<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[In Search of Pie]]></title><description><![CDATA[Rides bikes]]></description><link>https://edumats.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 07 Oct 2026 15:53:12 GMT</lastBuildDate><atom:link href="https://edumats.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Understanding Big O Notation: A Beginner's Guide]]></title><description><![CDATA[Why should I learn about Big O Notation?
Because it is commonly asked in tech interviews, one can say.
The reason that many tech companies test their candidate's knowledge of big O notation is to check if the candidate can write efficient code and is...]]></description><link>https://edumats.dev/understanding-big-o-notation-a-beginners-guide</link><guid isPermaLink="true">https://edumats.dev/understanding-big-o-notation-a-beginners-guide</guid><category><![CDATA[#big o notation]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[software development]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Mon, 04 Sep 2023 14:16:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/qDY9ahp0Mto/upload/a33828524083b59d7fef87a952f2a63d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-why-should-i-learn-about-big-o-notation">Why should I learn about Big O Notation?</h2>
<p>Because it is commonly asked in tech interviews, one can say.</p>
<p>The reason that many tech companies test their candidate's knowledge of big O notation is to check if the candidate can write efficient code and is aware of what kinds of code are expensive to run, both in terms of actual money and resources, such as computer memory or processing time.</p>
<p>It is important to write code that runs without errors and outputs the expected result, but there is a third component in it, which is efficiency.</p>
<p>A company that hosts its services on cloud servers, such as AWS or Google Cloud, can save millions just by replacing an inefficient code with an efficient one. With optimization, it is possible to do the same work on a much cheaper server or spend less computing time. This is just an example where just by changing a piece of code it is possible to save millions of dollars, so no wonder it is essential for companies to search for programmers that can write efficient code.</p>
<p>Even if you are writing just simple scripts, a skill that empowers you to look at a piece of code and lets you know which parts of it are critical to performance will empower you to always make the best decisions to build a fast program that can serve millions of users or process huge loads of data in no time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685994508497/d6153c9a-744c-472e-b661-d6679fc86272.gif" alt="emperor palpatine making lightning" class="image--center mx-auto" /></p>
<p>So let's learn about big O notation!</p>
<h2 id="heading-what-is-big-o-notation">What is Big O Notation?</h2>
<p>Big O notation is always pessimistic. Suppose I have a list that contains thousands of names:</p>
<pre><code class="lang-python"><span class="hljs-comment"># I have a long list of names</span>
names = [<span class="hljs-string">'Ed'</span>, <span class="hljs-string">'Karl'</span>, <span class="hljs-string">'Sam'</span>, <span class="hljs-string">'Ana'</span>, thousands of names, <span class="hljs-string">'Boris'</span>]
</code></pre>
<p>Imagine that I have a program that searches for a name in the <code>names</code> list. One way for a computer to search a list is by checking one item at a time. If the name to be found is "Sam", as humans we can just look at the above list and find it, but with computers, the process goes like this:</p>
<ul>
<li><p>First item at index 0 is Ed. Is Ed equal to Sam? No</p>
</li>
<li><p>Second item at index 1 is Karl. Is Karl equal to Sam? No</p>
</li>
<li><p>Third item at index 2 is Sam. Is Sam equal to Sam? Yes</p>
</li>
<li><p>Sam was found at index 2</p>
</li>
</ul>
<p>The same process happens in the following Python code:</p>
<pre><code class="lang-python"><span class="hljs-comment"># For each name in names list</span>
<span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> names:
  <span class="hljs-comment"># If name is equal to 'Sam'</span>
  <span class="hljs-keyword">if</span> name == <span class="hljs-string">'Sam'</span>:
    <span class="hljs-comment"># Returns True</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
<span class="hljs-comment"># If 'Sam' was not found in the list, return False</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p>The best-case scenario is finding "Ed". Ed is the first item on the list, so it will be found very fast, regardless of the list size. But as programmers, we always need to think in terms of the worst-case scenario, because they are the ones responsible for problems.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685994804801/b3df2117-0c39-4c9c-a48f-87c11d06cbb1.gif" alt="Homer with a sign written &quot;The end is near&quot;" class="image--center mx-auto" /></p>
<p><strong>The worst-case scenario is a name that is not on the list. A computer will have to check all names in this huge list, one by one, only to tell us that the name is not on the list.</strong></p>
<blockquote>
<p>Big O notation is interested only in the worst-case scenario. In simple terms, it gives a grade to the performance of a task in the worst-case possible.</p>
</blockquote>
<p>The process I described here to find a name on a list can be defined as an algorithm. Do not let its fancy name deceive you.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685978391248/b2a642d7-8f2d-4e11-bf39-14e77c2db191.webp" alt="a very confused woman looking at math equations" class="image--center mx-auto" /></p>
<p><strong>An algorithm is just a list of steps that are needed to solve a problem</strong>. You can think of these real-world examples that are equivalent to an algorithm:</p>
<ul>
<li><p>Directions from home to a bakery: From your home, turn right, walk 500 meters, turn left, cross a bridge, and walk 50 meters. You will reach the bakery.</p>
</li>
<li><p>A recipe for fried egg: Take a frying pan and put one tablespoon of oil on it. Place it on medium heat. Break one egg in the frying pan. Cook until the egg yolk becomes solid. You have a fried egg!</p>
</li>
</ul>
<p>From now on, instead of saying a task, a program or code, I will use "algorithm".</p>
<h2 id="heading-when-does-efficiency-matter">When does efficiency matter?</h2>
<p>If my algorithm is dealing with a small input, like a list with 10 items, it will not benefit from optimization, as any algorithm will complete the task in some milliseconds, with no notable difference between the top and worst performers. An algorithm that orders a list of numbers with only 10 items will not benefit much from optimization, as it will be done in a very short time, regardless of its performance.</p>
<p>Most users would be satisfied with a process that takes less than a second to complete, but as the size of the list increases, performance can suffer to a point that even a human can feel.</p>
<p>Below you can find a comparison between an okay algorithm and a bad one. It shows how many operations are needed as we increase the size of a list.</p>
<p>You will see later what O(n) and O(n<sup>2</sup>) mean.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td>Number of operations</td><td>Number of operations</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Size of the list</strong></td><td><strong>Ok algorithm: O(n)</strong></td><td><strong>Bad algorithm: O(n<sup>2</sup>)</strong></td></tr>
<tr>
<td>2</td><td>2</td><td>4</td></tr>
<tr>
<td>10</td><td>10</td><td>100</td></tr>
<tr>
<td>1.000</td><td>1.000</td><td>1.000.000</td></tr>
<tr>
<td>10.000</td><td>10.000</td><td>10.0000.000</td></tr>
</tbody>
</table>
</div><p>When the size of the list is small, the number of operations in the worst case remains small. But when the size begins to increase from 1.000 onwards, the discrepancies between an okay algorithm and a bad algorithm become very evident.</p>
<p>Some algorithms can take months or thousands of years to complete a task if an inefficient algorithm is used because they have to deal with huge amounts of data, think about big data or machine learning. Or it will not have practical applicability if a result cannot be found in a very short time, think about calculating a route in Google Maps or giving product recommendations at Amazon. Google would not have a viable product if returning a route from point A to point B would take 15 minutes.</p>
<h2 id="heading-the-types-of-efficiency-from-best-to-worst">The types of efficiency, from best to worst</h2>
<h3 id="heading-constant-time-the-gold-standard">Constant Time: The Gold Standard</h3>
<blockquote>
<p>Representation: O(1)</p>
</blockquote>
<p>This is the most efficient algorithm. An algorithm that has a constant time takes the same amount of time to get the task done, regardless of the size of the input. By input, here I mean the length of the list. Normally as the length increases, the time required to do a certain task increases, but not when we are dealing with a constant time algorithm.</p>
<p>I will list some operations that are done in constant time:</p>
<pre><code class="lang-python">names[<span class="hljs-number">-1</span>] <span class="hljs-comment"># Gets the last item of a list</span>
<span class="hljs-comment"># Returns Boris</span>

names[<span class="hljs-number">-1</span>] = <span class="hljs-string">'Clara'</span> <span class="hljs-comment"># Sets the last item as Clara</span>

names.append(<span class="hljs-string">'Marcus'</span>) <span class="hljs-comment"># Appends 'Marcus' to the end of the list</span>

names.pop() <span class="hljs-comment"># Removes the last item from the list</span>
</code></pre>
<p>All these operations take the same time, regardless if a list has one name or thousands of names. Also, there is no difference between best-case and worst-case here.</p>
<p>This may look strange because I have said previously that a computer must look for all items on a list when searching for a value. But when the index of the item is known or we know that we are dealing with the last item, there is no need to hop from item to item. When using <code>append()</code> or <code>pop()</code> we don't have to go through the items on the list because we only want to change the end of the list and we know where the last item is located.</p>
<p>If we create a graph with the time needed for the algorithm to complete versus the volume of data, the result will be this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685726194356/f9d36fd1-7940-4b4a-973e-6456a3dff0fe.png" alt class="image--center mx-auto" /></p>
<p>The time remains the same, regardless of the input size. The number of operations of O(1) is 1, meaning only a single operation is needed to finsih the algorithm.</p>
<h3 id="heading-logarithmic-divide-and-conquer">Logarithmic: Divide and conquer</h3>
<blockquote>
<p>Representation: O(log n), where n is the size of the list</p>
</blockquote>
<p>Remember that we were searching for a name on a list? If the list was sorted alphabetically, it would be possible to search more efficiently. Suppose I am searching for the name "Hagar", which begins with "H":</p>
<pre><code class="lang-python"><span class="hljs-comment"># We have sorted the list alphabetically</span>
sorted_names = [<span class="hljs-string">'Ana'</span>, <span class="hljs-string">'Boris'</span>, <span class="hljs-string">'Ed'</span>, <span class="hljs-string">'Karl'</span>, <span class="hljs-string">'Sam'</span>, thousands of sorted names, <span class="hljs-string">'Zara'</span>]
<span class="hljs-comment"># size of the list: 10.000</span>

<span class="hljs-comment"># Get to the middle of the list, divide the list in two</span>
<span class="hljs-comment"># Is the letter H in the left list or in the right list?</span>
divided_names = [<span class="hljs-string">'Ana'</span>, ..., <span class="hljs-string">'Marcus'</span>] + [<span class="hljs-string">'May'</span>, ..., <span class="hljs-string">'Zara'</span>]
<span class="hljs-comment"># size of left list: 5.000</span>
<span class="hljs-comment"># size of right list: 5.000</span>

<span class="hljs-comment"># As H is between A and M, we can safely discard the right list, reducing the problem in half!</span>
sorted_names = [<span class="hljs-string">'Ana'</span>, ..., <span class="hljs-string">'Marcus'</span>]
<span class="hljs-comment"># size of the list: 5.000</span>

<span class="hljs-comment"># We again get the middle of the list and divide it in two, repeating the process</span>
divided_names = [<span class="hljs-string">'Ana'</span>, ..., <span class="hljs-string">'Fred'</span>] + [<span class="hljs-string">'Frodo'</span>, ..., <span class="hljs-string">'Marcus'</span>]
<span class="hljs-comment"># size of left list: 2.500</span>
<span class="hljs-comment"># size of right list: 2.500</span>

<span class="hljs-comment"># H should be on the right list, we again reduced the problem in half!</span>
sorted_names = [<span class="hljs-string">'Frodo'</span>, ..., <span class="hljs-string">'Marcus'</span>]
<span class="hljs-comment"># size of the list: 2.500</span>

<span class="hljs-comment"># Continues until there is one name left in the list</span>
</code></pre>
<p><strong>The worst-case situation would be not finding a name on the list.</strong></p>
<p>As you can see, by dividing the list size by half, we are also dividing the size of the problem by half. This is much more efficient than checking all the items one by one.</p>
<p>This makes sense if we think of real-life examples. The contacts list on our phones is organized by name and as a result, we can quickly find the contact name we want. Searching for a contact in the contacts list is a very common task, so the programmers of the phone book app already sorted the contact list alphabetically for us. It would be much harder to find a contact if the contacts were sorted by the date they were added or if they were shown in a random order.</p>
<p>If we apply this principle to code, if we know that a list will be searched many times, we can optimize the time needed to do these searches by sorting the list beforehand. Sorting is a costly process in terms of time, but this cost is only paid once, so it is worthwhile in cases where we know that we are going to do multiple searches.</p>
<p>The graph of a logarithmic algorithm will be:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685729084265/95cbb5c4-c37f-4d15-8b56-73518d714906.png" alt class="image--center mx-auto" /></p>
<p>It starts to increase, but as the input size gets larger, the execution time begins to flatten. It gets more efficient as the input size gets larger.</p>
<p>O(log n) means that the number of operations needed in the worst case is log n. For example, log(4) is 2, which is just half, but log(100) is 6.644 and log(1000) is 9.966. You can see that the number of operations remains small even with a list with a huge size.</p>
<h3 id="heading-linear-the-predictable-algorithm">Linear: The predictable algorithm</h3>
<blockquote>
<p>Representation O(n), where n is the size of the list</p>
</blockquote>
<p>The process I described when trying the find a name on a list is classified as a linear algorithm. It checks for every item on a list in its worst case, so the time needed to do this depends on the size of the list.</p>
<p>The code below is equivalent to the example I refer to above:</p>
<pre><code class="lang-python"><span class="hljs-comment"># For each name in names list</span>
<span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> names:
  <span class="hljs-comment"># If name is equal to 'Sam'</span>
  <span class="hljs-keyword">if</span> name == <span class="hljs-string">'Sam'</span>:
    <span class="hljs-comment"># Returns True</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
<span class="hljs-comment"># If 'Sam' was not found in the list, return False</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p>Sometimes a single line of code has the same complexity as the code above:</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> <span class="hljs-string">'Sam'</span> <span class="hljs-keyword">in</span> names:
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p>The part <code>'Sam' in names</code> has a time complexity of O(n), despite being a single line. The underlining process is the same: <strong>it still has to go through all items in the list if the name is not on the list.</strong></p>
<p>When analyzing a piece of code, always think about the principles of how a computer completes the task. To look for the name Sam in the <code>names</code> list, it still has to search one name at a time, despite being a one-liner and inside an if condition.</p>
<p>The graph below shows what a linear algorithm looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685728330847/96b7416d-36a7-4cc1-88aa-65ae761c1d1d.png" alt class="image--center mx-auto" /></p>
<p>As the size of the list increases, the time needed follows together.</p>
<h3 id="heading-danger-zone-things-could-start-to-get-slow-from-here"><mark>Danger Zone: Things could start to get slow from here</mark></h3>
<h3 id="heading-quadratic">Quadratic:</h3>
<blockquote>
<p>Representation: O(n<strong>²</strong>)</p>
</blockquote>
<p>Imagine that I want to check if there is a duplicate name in the list of names.</p>
<pre><code class="lang-python"><span class="hljs-comment"># I have a long list of names</span>
names = [<span class="hljs-string">'Ed'</span>, <span class="hljs-string">'Karl'</span>, <span class="hljs-string">'Sam'</span>, <span class="hljs-string">'Ana'</span>, thousands of names, <span class="hljs-string">'Boris'</span>]

<span class="hljs-comment"># For each name in names list</span>
<span class="hljs-keyword">for</span> index1, name1 <span class="hljs-keyword">in</span> enumerate(names):
  <span class="hljs-comment"># Loop through the list again</span>
  <span class="hljs-keyword">for</span> index2, name2 <span class="hljs-keyword">in</span> enumerate(names):
    <span class="hljs-comment"># Only make a comparison when indexes are different</span>
    <span class="hljs-keyword">if</span> index1 != index2:
      <span class="hljs-comment"># If names are equal, print message with the duplicate name</span>
      <span class="hljs-keyword">if</span> name1 == name2:
        print(<span class="hljs-string">f'A duplicate name was found: <span class="hljs-subst">{name1}</span>'</span>)
</code></pre>
<p>Here <code>enumerate()</code> allows me to keep track of indexes of the list without needing to use <code>range()</code> and <code>len()</code> allowing me to write a simpler and cleaner code.</p>
<p>This algorithm starts almost the same as a linear algorithm, with a for loop, but it has an important difference. There is another for loop inside the first loop! It means that: <strong>For each name in the list, we have to loop through all names in the list!</strong></p>
<p>The worst-case scenario would be any run because this time the algorithm continues to run until the end of the list even if a duplicate was found. Even I can feel the amount of work that the poor computer would need to perform!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685981623380/c6a687ef-dbaf-4df8-a958-1a67348408be.png" alt class="image--center mx-auto" /></p>
<p>The graph looks like an inverted logarithmic graph: As the input size gets larger, the execution time increases drastically.</p>
<h3 id="heading-exponential">Exponential</h3>
<blockquote>
<p>Representation O(2ˆ<strong>n</strong>)</p>
</blockquote>
<p>I have a list with a single name and I want to generate all the possible combinations. There would be two possible combinations:</p>
<ul>
<li><p>One with the name "Ed"</p>
</li>
<li><p>One empty list, without the name "Ed"</p>
</li>
</ul>
<pre><code class="lang-python">name = [<span class="hljs-string">'Ed'</span>]

ed_present = [<span class="hljs-string">'Ed'</span>]
ed_absent = []

<span class="hljs-comment"># Let's combine all possibilities</span>

scenario1 = [<span class="hljs-string">'Ed'</span>]
scenario2 = []
</code></pre>
<p>Now, what if I wanted all combinations from a list with two names?</p>
<p>The process would be the same, for each name, the name can be included or excluded:</p>
<pre><code class="lang-python">names = [<span class="hljs-string">'Ed'</span>, <span class="hljs-string">'John'</span>]

<span class="hljs-comment"># Ed can be present or absent</span>
ed_present = [<span class="hljs-string">'Ed'</span>]
ed_absent = []

<span class="hljs-comment"># John can be present or absent</span>
john_present = [<span class="hljs-string">'John'</span>]
john_absent = []

<span class="hljs-comment"># Let's combine all possibilities</span>
scenario1 = [<span class="hljs-string">'Ed'</span>, <span class="hljs-string">'John'</span>] <span class="hljs-comment">#combining ed_present + john_present</span>
scenario2 = [<span class="hljs-string">'Ed'</span>] <span class="hljs-comment">#combining ed_present + john_absent</span>
scenario3 = [<span class="hljs-string">'John'</span>] <span class="hljs-comment">#combining ed_absent + john_present</span>
scenario4 = [] <span class="hljs-comment">#combining ed_absent + john_absent</span>
</code></pre>
<p>We can see a pattern here, we can multiply the resulting 2 possibilities of Ed with the 2 possibilities of John so we get 4.</p>
<pre><code class="lang-python">names = [<span class="hljs-string">'Ed'</span>, <span class="hljs-string">'John'</span>, <span class="hljs-string">'Maria'</span>]

<span class="hljs-comment"># Ed can be present or absent</span>
ed_present = [<span class="hljs-string">'Ed'</span>]
ed_absent = []

<span class="hljs-comment"># John can be present or absent</span>
john_present = [<span class="hljs-string">'John'</span>]
john_absent = []

<span class="hljs-comment"># Maria can be present or absent</span>
maria_present = [<span class="hljs-string">'Maria'</span>]
maria_absent = []
</code></pre>
<p>With 3 elements, the total combinations would be 2 x 2 x 2, which would result in 8.</p>
<p>To calculate the necessary steps to go through all combinations, we can calculate 2 to the power of the length of the list, or 2 ˆ &lt;list_length&gt;, as we saw in the previous examples:</p>
<ul>
<li><p>With a list of length 1: <strong>2 ^ 1 = 2</strong></p>
</li>
<li><p>With a list of length 2: <strong>2 ^ 2 = 4</strong></p>
</li>
<li><p>With a list of length 3: <strong>2 ^ 3 = 8</strong></p>
</li>
</ul>
<p>This can get ugly very fast, as with a length of 20 you will be returning 1,048,576 combinations and with a length of 63, it will return a whooping 9,223,372,036,854,775,808 combinations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1693836265091/f139e97f-9014-4b85-91b1-f52ff64f7f69.png" alt class="image--center mx-auto" /></p>
<p>As you can see, the rate of growth of an algorithm with exponential complexity is very steep and it is very slow.</p>
<h2 id="heading-conclusions">Conclusions</h2>
<p>Although some algorithms are better than others, some problems are not possible to be solved with a good algorithm and we need to stick with a bad algorithm, as it is our only option. If we need to search for an item on a list, there is no way we can achieve this in a constant time or O(1).</p>
<p>As we saw, there are creative ways to increase efficiency, by transforming a linear algorithm <code>O(n)</code> to a logarithmic <code>O(log n)</code> by sorting the list before searching and then dividing the problem in half. In this case, it will be worth it if you plan to do multiple searches on the list, as there is a cost for sorting the list.</p>
<p>In this article, I gave examples related only to lists, but any input is applicable here. It could be integers, dictionaries, and so on, but I chose lists because most of my readers would be more comfortable with them.</p>
<p>When trying to determine the complexity of an algorithm you wrote, keep the big picture. Keep an eye out for loops as they are the main cause of increases in complexity. However spotting a loop can be a challenge, as it can be disguised as something else:</p>
<pre><code class="lang-python"><span class="hljs-comment"># This line below appears to be simple, but has a complexity of O(n)</span>
<span class="hljs-keyword">if</span> <span class="hljs-string">'Kenya'</span> <span class="hljs-keyword">in</span> names:
  print(<span class="hljs-string">'Found Kenya'</span>)
</code></pre>
<p>In the example above, it appears that this is only an if cause, which can be safely ignored, but if you think about it, it needs to iterate a list to find the name "Kenya". It does the same as :</p>
<pre><code class="lang-python"><span class="hljs-comment"># This loop has a complexity of O(n)</span>
<span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> names:
  <span class="hljs-keyword">if</span> name == <span class="hljs-string">'Kenya'</span>:
    print(<span class="hljs-string">'Found Kenya'</span>)
</code></pre>
<h3 id="heading-final-considerations">Final Considerations</h3>
<p>When writing an algorithm for the first time, you should not aim for performance. Instead, aim for an algorithm that does the job correctly. Then, if the need arises, you should start optimizing it to go faster. Remember: <a target="_blank" href="https://stackify.com/premature-optimization-evil/">Premature optimization is the root of all evil</a></p>
<p>Hope you liked this article! If you have questions or comments, please write them in the comments section :)</p>
]]></content:encoded></item><item><title><![CDATA[Use localStorage to power up your apps]]></title><description><![CDATA[What is localStorage?
Web pages do not persist data by default. If you reload the page while writing a long text, the text is gone forever. This lack of persistence could be very annoying in situations like:

Setting the page to dark mode, but having...]]></description><link>https://edumats.dev/use-localstorage-to-power-up-your-apps</link><guid isPermaLink="true">https://edumats.dev/use-localstorage-to-power-up-your-apps</guid><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Tue, 09 May 2023 15:54:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/TluMvvrZ57g/upload/79c2c77c51c0f3002cb7335048936a33.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-what-is-localstorage">What is localStorage?</h3>
<p>Web pages do not persist data by default. If you reload the page while writing a long text, the text is gone forever. This lack of persistence could be very annoying in situations like:</p>
<ul>
<li><p>Setting the page to dark mode, but having it revert to light mode on return.</p>
</li>
<li><p>Spending time choosing products for a shopping cart, only to find it empty when you return.</p>
</li>
<li><p>Writing a lengthy blog post, being logged off, and losing all progress when the post is submitted</p>
</li>
</ul>
<p>Using <code>localStorage</code> enables your apps to save information without the need for a backend server. This means no need for storage infrastructure and no costs for you since the data is being stored on your user's computer instead of a server you manage.</p>
<p>It also can be used for static pages to have data persistence. Imagine you built a simple ToDo app that is hosted on Github Pages. It is fast to load and can be hosted for free, but it is useless because when the user leaves the page, all his tasks are gone. <code>localStorage</code> can solve this issue by saving the tasks in the user's machine.</p>
<h3 id="heading-heres-how-to-use-localstorage">Here's how to use localStorage</h3>
<ul>
<li><p><code>setItem</code> saves data to the user's browser</p>
</li>
<li><p><code>getItem</code> retrieves the saved data from the user's browser</p>
</li>
<li><p><code>removeItem</code> removes the saved data from the user's browser</p>
</li>
</ul>
<h3 id="heading-example-1-dark-mode">Example 1: Dark mode</h3>
<p>Suppose I have a webpage that has a dark mode option. I would want the webpage to remember the user's preference. Notice that when retrieving data from localStorage, <code>getItem()</code> always returns the data as a string, so you need to convert it to the actual data type that you originally saved using <code>JSON.parse()</code> to avoid using true as a string in a comparison, which could lead to errors in the app:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Store the user's preference</span>
<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'darkMode'</span>, <span class="hljs-literal">true</span>)

<span class="hljs-comment">// Retrieve the user's preference from localStorage </span>
<span class="hljs-comment">// getItem() always returns a string</span>
<span class="hljs-keyword">const</span> darkModeData = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'darkMode'</span>) <span class="hljs-comment">// returns a string: 'true' </span>

<span class="hljs-comment">// Convert string to a Boolean value</span>
<span class="hljs-keyword">const</span> darkMode = <span class="hljs-built_in">JSON</span>.parse(darkModeData) <span class="hljs-comment">// returns a bollean: true</span>
</code></pre>
<h3 id="heading-example-2-a-static-page">Example 2: A static page</h3>
<p>In the second example, I have a To-Do app and I want to save my list of tasks to do. I can save the array in localStorage, but when saving complex data structures like objects and arrays, I need to convert them to a string using <code>JSON.stringify()</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> tasks = [
    <span class="hljs-string">'Go to gym'</span>,
    <span class="hljs-string">'Prepare dinner'</span>,
    <span class="hljs-string">'Go to supermarket'</span>,
]

<span class="hljs-comment">// Array tasks gets converted to a string</span>
arrayAsString = <span class="hljs-built_in">JSON</span>.stringify(tasks)

<span class="hljs-comment">// Store the array as a value of the key tasks</span>
<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'tasks'</span>, arrayAsString)
</code></pre>
<h3 id="heading-why-do-i-need-jsonstringify">Why do I need JSON.stringify()?</h3>
<p>You could be thinking that <code>localStorage.setItem()</code> saves the value as a string anyways, so why the need to convert the value to a string beforehand using <code>JSON.stringify()</code> ?</p>
<p>That is because behind the curtains <code>localStorage.setItem()</code> uses <code>toString()</code> which gives some unexpected results compared to <code>JSON.stringfy()</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/* With booleans, integers and float the result is the same */</span>
<span class="hljs-keyword">const</span> boolExample = <span class="hljs-literal">true</span>

boolExample.toString() 
<span class="hljs-comment">// Returns 'true'</span>

<span class="hljs-built_in">JSON</span>.stringify(<span class="hljs-literal">true</span>) 
<span class="hljs-comment">// Returns 'true'</span>

<span class="hljs-comment">/* When using objects, the results are very different */</span>

<span class="hljs-keyword">const</span> product = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'ice cream'</span>,
  <span class="hljs-attr">price</span>: <span class="hljs-number">1.20</span>,
  <span class="hljs-attr">quantity</span>: <span class="hljs-number">2</span>
}

product.toString()
<span class="hljs-comment">// Returns '[object Object]'</span>

<span class="hljs-built_in">JSON</span>.stringify(product) 
<span class="hljs-comment">// Returns '{"name":"ice cream","price":1.2,"quantity":2}'</span>

<span class="hljs-comment">/* With arrays, there are unexpected differences */</span>

<span class="hljs-keyword">const</span> users = [<span class="hljs-string">'Paul'</span>, <span class="hljs-string">'Maria'</span>, <span class="hljs-string">'Ken'</span>]

users.toString()
<span class="hljs-comment">// Returns 'Paul,Maria,Ken'</span>

<span class="hljs-built_in">JSON</span>.stringify(users)
<span class="hljs-comment">// Returns '["Paul","Maria","Ken"]'</span>
</code></pre>
<p>In summary, <code>JSON.stringify</code> converts objects and arrays into strings in a way that it is possible to easily convert them back to their original forms. On the other hand, <code>toString()</code> removes their original data structure, making it difficult or impossible to convert back to their original form.</p>
<h3 id="heading-example-3-a-shopping-cart">Example 3: A shopping cart</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> cartItems = [
    {
        <span class="hljs-attr">product</span>: <span class="hljs-string">'ice cream'</span>,
        <span class="hljs-attr">flavour</span>: <span class="hljs-string">'vanilla'</span>,
        <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span>    
    },
    {
        <span class="hljs-attr">product</span>: <span class="hljs-string">'hamburger'</span>,
        <span class="hljs-attr">toppings</span>: [<span class="hljs-string">'picles'</span>, <span class="hljs-string">'cheese'</span>],
        <span class="hljs-attr">quantity</span>: <span class="hljs-number">2</span>
    }
]

<span class="hljs-comment">// Same as before, convert the array of object into a string</span>
arrayAsString = <span class="hljs-built_in">JSON</span>.stringify(shoppingCart)

<span class="hljs-comment">// Store the array of objects converted to string</span>
<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'cartItems'</span>, arrayAsString)

<span class="hljs-comment">// Deletes the cart</span>
<span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-string">'cartItems'</span>)
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p><code>localStorage</code> is a great way to store data without the need to set and maintain databases. You are transferring the responsibility of storing data from your servers to your users, so you can power up your static websites or can expand your page's capabilities without touching your database servers.</p>
<p>The data stored at <code>localStorage</code> will not expire and will remain as long as the user does not clean the browser's cache. Depending on the browser, it can store up to 5MB of data or an unlimited amount.</p>
<p>You should never use <code>localStorage</code> for storing sensitive data, such as passwords, login sessions or credit card information, because the data stored in <code>localStorage</code> is not encrypted and can be accessed by a malicious hacker or even someone who has access to the browser can just use the browser's developer tools and see what is stored there.</p>
<p>Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Use ChatGPT as your free programming teacher]]></title><description><![CDATA[Programming is complex and hard. Feeling overwhelmed by a bug is something that newbies and experienced programmers can relate to. If only you could ask someone more experienced...
Stack Overflow is a great resource, but it requires to search through...]]></description><link>https://edumats.dev/use-chatgpt-as-your-free-programming-teacher</link><guid isPermaLink="true">https://edumats.dev/use-chatgpt-as-your-free-programming-teacher</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Wed, 22 Feb 2023 21:01:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/g29arbbvPjo/upload/16cf1ce4e90449c37a215530c5203773.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Programming is complex and hard. Feeling overwhelmed by a bug is something that newbies and experienced programmers can relate to. If only you could ask someone more experienced...</p>
<p><a target="_blank" href="https://stackoverflow.com/">Stack Overflow</a> is a great resource, but it requires to search through the answers to find the best solution or to visit multiple related questions to find the answer to a specific problem. Its moderation rules are very strict, so open-ended questions are banned, and questions that are considered similar to already existing ones are quickly closed. It is intended to use a simple and direct input =&gt; output style forum, where a users inputs a question and the community answers the question and the most up-voted answer becomes the standard answer for the question.</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/ChatGPT">ChatGPT</a> was released in 2022 and caused a great uproar, as it is an AI that can produce answers in many domains of knowledge, in a very human and smart way. It is not perfect, but it is expected to do huge leaps of evolution since it is constantly learning from its 100 millions of users and the ever growing data on the Internet. You can test it for free on its <a target="_blank" href="https://openai.com/blog/chatgpt/">official page</a>.</p>
<p>The launch to the general public of such polished AI for free created huge shockwaves across the tech industry and <a target="_blank" href="https://www.theverge.com/2023/1/20/23563851/google-search-ai-chatbot-demo-chatgpt">caused Google to panic</a>, as ChatGPT was integrated into Microsoft's search engine Bing, creating a much more intelligent and human like search experience, threatening Google's search business, which is the main source of revenue for the tech giant.</p>
<h2 id="heading-examples-of-use">Examples of use</h2>
<p>ChatGPT can answer in a detailed way almost all kinds of programming questions:</p>
<blockquote>
<p><strong>Me</strong>: I have an array of objects in Javascript in which each object has a boolean value. How do I filter objects based on this value?</p>
<p><strong>ChatGPT</strong>: To filter an array of objects in JavaScript based on a boolean property, you can use the <code>filter()</code> method along with a conditional statement that checks the value of the property. Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myArray = [
  { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">true</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">false</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">true</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">false</span> }
];

<span class="hljs-keyword">const</span> trueValues = myArray.filter(<span class="hljs-function"><span class="hljs-params">object</span> =&gt;</span> object.value === <span class="hljs-literal">true</span>);
<span class="hljs-keyword">const</span> falseValues = myArray.filter(<span class="hljs-function"><span class="hljs-params">object</span> =&gt;</span> object.value === <span class="hljs-literal">false</span>);

<span class="hljs-built_in">console</span>.log(trueValues);
<span class="hljs-built_in">console</span>.log(falseValues);
</code></pre>
<p>In this example, we have an array of objects with an <code>id</code> property and a <code>value</code> property that contains a boolean value. We want to filter the objects that have a value of <code>true</code> and the objects that have a value of <code>false</code>.</p>
<p>We use the <code>filter()</code> method twice, once to filter the objects that have a value of <code>true</code>, and once to filter the objects that have a value of <code>false</code>.</p>
<p>In each call to <code>filter()</code>, we pass a callback function that takes an object as its parameter. The callback function checks the <code>value</code> property of the object using a conditional statement, and returns <code>true</code> if the value matches the condition, and <code>false</code> otherwise.</p>
<p>The <code>filter()</code> method returns a new array that contains the objects that match the condition. We store the two resulting arrays in separate variables and log them to the console.</p>
</blockquote>
<p>You can refer to its previous answer to ask new questions:</p>
<blockquote>
<p><strong>Me</strong>: Is it possible to filter the value in a single loop?</p>
<p><strong>ChatGPT</strong>: Yes, it is possible to filter an array of objects based on a boolean property using a single loop. Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myArray = [
  { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">true</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">false</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">true</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">false</span> }
];

<span class="hljs-keyword">const</span> trueValues = [];
<span class="hljs-keyword">const</span> falseValues = [];

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; myArray.length; i++) {
  <span class="hljs-keyword">const</span> object = myArray[i];
  <span class="hljs-keyword">if</span> (object.value === <span class="hljs-literal">true</span>) {
    trueValues.push(object);
  } <span class="hljs-keyword">else</span> {
    falseValues.push(object);
  }
}

<span class="hljs-built_in">console</span>.log(trueValues);
<span class="hljs-built_in">console</span>.log(falseValues);
</code></pre>
<p>In this example, we initialize two empty arrays, <code>trueValues</code> and <code>falseValues</code>, to store the objects that match the condition.</p>
<p>We then use a <code>for</code> loop to iterate over the array of objects. For each object, we check the <code>value</code> property using a conditional statement, and push the object to the corresponding array based on its value.</p>
<p>The <code>for</code> loop allows us to filter the array in a single pass, without having to call the <code>filter()</code> method twice. We store the resulting arrays in separate variables and log them to the console.</p>
</blockquote>
<p>It is well aware of the context in which the questions are asked and it is not just a database of answers of StackOverflow:</p>
<blockquote>
<p><strong>Me</strong>: Which solution is the most efficient?</p>
<p><strong>ChatGPT</strong>: In terms of performance, the two solutions have different tradeoffs, and the most efficient approach will depend on the specific use case.</p>
<p>Using the <code>filter()</code> method is a more concise and expressive way to filter an array of objects based on a property. It can make the code easier to read and maintain, especially for more complex filtering conditions.</p>
<p>However, the <code>for</code> loop approach can be more efficient in terms of performance, especially for large arrays. This is because it only iterates over the array once, whereas the <code>filter()</code> method creates a new array and iterates over it.</p>
<p>Additionally, using the <code>for</code> loop approach allows you to immediately store the objects in separate arrays, which can be more efficient than creating a new array for each filtering condition using the <code>filter()</code> method.</p>
<p>Overall, if performance is a critical concern and the array is very large, using a <code>for</code> loop to filter the array in a single pass is likely to be the most efficient approach. If the array is small or performance is not a critical concern, using the <code>filter()</code> method can provide a more concise and expressive solution.</p>
</blockquote>
<p>It is possible to paste a particular piece of code and ask it if there is an error. Or ask an open-ended question like:</p>
<blockquote>
<p><strong>Me</strong>: Could you create HTML and CSS code for an app that allows animal shelters to show which animals are available for adoption and show their photo, age, characteristics and current location?</p>
<p><strong>ChatGPT</strong>: Sure, here is an example HTML and CSS code for an app that allows animal shelters to show which animals are available for adoption, with their photo, age, characteristics, and current location:</p>
<p>HTML Code:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Animal Adoption App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"style.css"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Animal Adoption<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"animal-list"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Available Animals<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Cat"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Fluffy<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 2 years<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Characteristics: Playful, friendly<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Current location: Cat House 1<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"adopt-btn"</span>&gt;</span>Adopt Me!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Dog"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Buddy<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 3 years<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Characteristics: Energetic, loyal<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Current location: Dog House 2<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"adopt-btn"</span>&gt;</span>Adopt Me!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://via.placeholder.com/150"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Rabbit"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Bugsy<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: 1 year<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Characteristics: Cute, cuddly<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Current location: Rabbit House 1<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"adopt-btn"</span>&gt;</span>Adopt Me!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">footer</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;copy;</span> 2023 Animal Adoption App. All rights reserved.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>CSS Code:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-selector-tag">header</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#008CBA</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">36px</span>;
}

<span class="hljs-selector-tag">main</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.animal-list</span> {
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.animal-list</span> <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.animal-list</span> <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(auto-fit, minmax(<span class="hljs-number">250px</span>, <span class="hljs-number">1</span>fr));
    <span class="hljs-attribute">grid-gap</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.animal-list</span> <span class="hljs-selector-tag">li</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
    <span class="hljs-attribute">justify-content</span>: space-between;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.animal-list</span> <span class="hljs-selector-tag">img</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.adopt-btn</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f44336</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span> <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<p>This code creates a simple app with one section, "Available Animals". The section displays a list of available animals with their photo, name, age, characteristics, current location, and an "Adopt Me!" button. The animals are displayed in a grid format with a responsive design.</p>
</blockquote>
<p>I did not ask for the page to be mobile-friendly, but Chat GPT did it anyways by using CSS Grid. If you are curious to see how it looks, check it out on CodePen <a target="_blank" href="https://codepen.io/edumats/pen/dyqMEPW">here</a>. It does not look impressive at first sight, but you can certainly give ChatGPT some directions on how to improve it!</p>
<h2 id="heading-problems">Problems</h2>
<p>I noticed that if I asked ChatGPT for a solution and on top of it, added an constraint that it is not possible to fullfill, it can occasionaly produce wrong answers because it is too focused in trying to produce a valid answer:</p>
<blockquote>
<p><strong>Me</strong>: How can I write a function that converts a float into an integer?</p>
<p><strong>ChatGPT</strong>: You can use the <code>Math.floor</code> function to convert a float to an integer. This function will round down to the nearest integer.</p>
<p>Here's an example function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">floatToInt</span>(<span class="hljs-params">floatNum</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor(floatNum);
}
</code></pre>
<p>You can call this function and pass in your float as an argument. The function will return the integer equivalent of the float.</p>
<p><strong>Me</strong>: Can your write another option that does not lose precision?</p>
<p><strong>ChatGPT</strong>: Sure! You can also convert a float to an integer without losing precision by using the <code>Math.trunc</code> method. <code>Math.trunc</code> simply removes the decimal portion of a number without performing any rounding.</p>
<p>Here's an example function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">floatToInt</span>(<span class="hljs-params">floatNum</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.trunc(floatNum);
}
</code></pre>
<p>You can call this function and pass in your float as an argument. The function will return the integer equivalent of the float without losing precision.</p>
</blockquote>
<p><code>Math.trunc</code> does not make any rounding, but still loses precision, as it simply cuts the decimal parts of a float, but ChatGPT does not see a problem in it.</p>
<p>Curiously, it admits the error when confronted:</p>
<blockquote>
<p><strong>Me</strong>: In the last response, using Math.trunc still loses precision, as it simply cuts the decimal</p>
<p><strong>ChatGPT</strong>: You're right, I apologize for my mistake. When truncating a float to an integer, it will always lose the decimal portion of the number, and hence lose precision. The <code>Math.trunc</code> function only removes the decimal portion without performing any rounding, but this still results in the loss of the decimal information.</p>
<p>If you need to preserve the decimal information, you can convert the float to a string and then use the <code>parseInt</code> function to extract the integer part of the number.</p>
<p>Here's an example function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">floatToInt</span>(<span class="hljs-params">floatNum</span>) </span>{
  <span class="hljs-keyword">const</span> floatString = floatNum.toString();
  <span class="hljs-keyword">const</span> integerString = floatString.split(<span class="hljs-string">'.'</span>)[<span class="hljs-number">0</span>];
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">parseInt</span>(integerString, <span class="hljs-number">10</span>);
}
</code></pre>
<p>In this example, we first convert the float to a string using the <code>toString</code> method. Then we split the string on the decimal point and keep only the integer part of the number. Finally, we use the <code>parseInt</code> function to convert the integer string back to an integer.</p>
<p>You can call this function and pass in your float as an argument. The function will return the integer equivalent of the float, with the decimal portion discarded, but without losing precision.</p>
</blockquote>
<p>But its answer still presents a contradiction, as its solution is still discarding the decimal information while saying that it is preserving it.</p>
<h2 id="heading-disadvantages">Disadvantages</h2>
<ul>
<li><p>It can produce completely wrong answers, so the user must have some level of knowledge to be able to filter down the wrong ones</p>
</li>
<li><p>Can create a bad habit of just copying and pasting its answers, instead of understanding the why's</p>
</li>
</ul>
<h2 id="heading-advantages">Advantages</h2>
<ul>
<li><p>Free of charge</p>
</li>
<li><p>Can be a very helpful assistant for developers, from begginers to experienced ones</p>
</li>
<li><p>The experience is very close to having a human mentor</p>
</li>
<li><p>Can understand most programming languages, libraries or frameworks</p>
</li>
</ul>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>AI is not able to produce a beautiful app or a revolutionary startup just yet, but it can become a valuable tool in a programmer's tool box, just like Google or Stack Overflow. We can surely expect more mind blowing surprises from ChatGPT and its competitors in the coming years. The AI wars have just begun!</p>
<p>Have you tried ChatGPT? Feel free to share your impressions about it.</p>
]]></content:encoded></item><item><title><![CDATA[Don't use float to represent currency. Here is why]]></title><description><![CDATA[So you are building an e-commerce system or a personal expense tracker or whatever system that makes calculations using currency values, like calculating the total amount of dollars with taxes included or simply calculating the total price by multipl...]]></description><link>https://edumats.dev/dont-use-float-to-represent-currency-here-is-why</link><guid isPermaLink="true">https://edumats.dev/dont-use-float-to-represent-currency-here-is-why</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[floating point arithmetic]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Fri, 10 Feb 2023 16:12:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1zO4O3Z0UJA/upload/3c7291b7258c030cd6fc51ea61159fc8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So you are building an e-commerce system or a personal expense tracker or whatever system that makes calculations using currency values, like calculating the total amount of dollars with taxes included or simply calculating the total price by multiplying. And for that, the most obvious choice for a beginner is to represent money as a float, as integers seem not fit for this task.</p>
<h2 id="heading-the-problem">The Problem</h2>
<p>I will be using Python in these examples, but most programming languages would yield similar results.</p>
<p>Let's calculate the total price for 3 burgers which costs $1.1 each:</p>
<pre><code class="lang-python">burger_price = <span class="hljs-number">1.1</span>
amount = <span class="hljs-number">3</span>
total = burger_price * amount
<span class="hljs-comment"># Expected 3.3, but got 3.3000000000000003 :(</span>
</code></pre>
<p>What is happening here? This result would look awful on a shopping cart!</p>
<p>Even a simple addition leads to a strange result:</p>
<pre><code class="lang-python">base_bonus = <span class="hljs-number">0.2</span>
additional_bonus = <span class="hljs-number">0.1</span>
total_bonus = base_bonus + additional_bonus
<span class="hljs-comment"># Expected 0.3, but got 0.30000000000000004 :(</span>
</code></pre>
<p>You might be thinking that the solution is really simple, just cut off after two digits!</p>
<pre><code class="lang-python">total_bonus = <span class="hljs-number">0.1</span> + <span class="hljs-number">0.2</span>
<span class="hljs-comment"># 0.30000000000000004</span>
corrected_total_bonus = round(total_bonus, <span class="hljs-number">2</span>)
<span class="hljs-comment"># 0.3</span>
</code></pre>
<p>That might work for something really simple, but if you keep making these floating point calculations and rounding off repeatedly, small rounding errors will accumulate and lead to a large calculation error. This will not be acceptable for an application that needs precision and also, rounding can lead to errors like this:</p>
<pre><code class="lang-python">party_minimum = <span class="hljs-number">5.0</span>
party_result = <span class="hljs-number">4.97</span>
party_result = round(party_result, <span class="hljs-number">1</span>)
<span class="hljs-comment"># 5.0</span>
<span class="hljs-keyword">if</span> party_result &gt;= party_minimum:
    print(<span class="hljs-string">'You can seat in the Parlament'</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">'You cannot seat at Parlament anymore'</span>)

<span class="hljs-comment"># You can seat in the Parlament</span>
</code></pre>
<blockquote>
<p>In German parliamentary elections, a party with less than 5.0% of the vote cannot be seated. The Greens appeared to have a cliff-hanging 5.0%, until it was discovered (after the results had been announced) that they really had only 4.97%. The printout was to two figures, and the actual percentage was rounded to 5.0%.</p>
</blockquote>
<p>Disasters already happened due to float precision:</p>
<blockquote>
<p>On February 25, 1991, during the Gulf War, a Patriot missile defense system let a Scud get through. It hit a barracks, killing 28 people. The problem was in the differencing of floating point numbers obtained by converting and scaling an integer timing register.</p>
</blockquote>
<p>You can even fail a simple automated test and spend hours trying to figure out why:</p>
<pre><code class="lang-python"><span class="hljs-keyword">assert</span> <span class="hljs-number">0.1</span> + <span class="hljs-number">0.2</span> == <span class="hljs-number">0.3</span>
<span class="hljs-comment"># Raises AssertionError!</span>
</code></pre>
<h2 id="heading-why-does-this-happen">Why does this happen?</h2>
<p>Computers use zeros and ones to represent numbers. A bit can be a zero or a one. Modern computers usually use up to 64 bits to represent information, which means you can have up to 16 digits after the decimal point, which is a lot, but there is still a hard limit on the values that it is possible to represent.</p>
<p>As humans, we can easily understand the concept of <code>0.1</code>. It is one tenth of something or <code>10%</code> of something. But computers using zeros and ones will represent <code>0.1</code> as:</p>
<blockquote>
<p>0.0001100110011...</p>
</blockquote>
<p>In which the 0011 part will be repeating infinitely.</p>
<p>But a 64-bit computer will cut the repeating part, so it will have just 16 digits after the decimal point. In this process of cutting to the allowed precision digits, it loses precision. So <code>0.1</code> that was fitted into 64-bit data will be just close enough to <code>0.1</code>.</p>
<p>If we reveal the 20 digits that follow the decimal sign in a float:</p>
<pre><code class="lang-python">decimal_one = <span class="hljs-number">0.1</span>
print(<span class="hljs-string">f'<span class="hljs-subst">{decimal_one:<span class="hljs-number">.20</span>f}</span>'</span>) <span class="hljs-comment"># 0.10000000000000000555</span>
decimal_two = <span class="hljs-number">0.2</span>
print(<span class="hljs-string">f"<span class="hljs-subst">{decimal_two:<span class="hljs-number">.20</span>f}</span>"</span>) <span class="hljs-comment"># 0.20000000000000001110</span>
</code></pre>
<p>We can see that we are indeed getting only the approximate value of a decimal number. And that is why you can see those unexpected results using floats.</p>
<h2 id="heading-solution-1-use-the-decimal-module">Solution 1: Use the Decimal module</h2>
<p>Python has a module called <code>Decimal</code> and it behaves like how a human would do Math:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> decimal <span class="hljs-keyword">import</span> Decimal

burger_price = Decimal(<span class="hljs-string">'1.1'</span>)
amount = <span class="hljs-number">3</span>
total = burger_price * amount <span class="hljs-comment"># Decimal('3.3')</span>
print(total)
<span class="hljs-comment"># 3.3</span>
</code></pre>
<p>Note that it is possible to do Math operations with those Decimal objects:</p>
<pre><code class="lang-python">Decimal(<span class="hljs-string">'0.1'</span>) + Decimal(<span class="hljs-string">'0.2'</span>)
<span class="hljs-comment"># Decimal('0.3')</span>
</code></pre>
<p>When creating Decimal objects, the float value should be passed as a string, otherwise, you would suffer again from precision issues that we wanted to avoid:</p>
<pre><code class="lang-python">Decimal(<span class="hljs-number">0.1</span>)  <span class="hljs-comment"># Decimal('0.1000000000000000055511151231257827021181583404541015625')</span>

Decimal(<span class="hljs-string">'0.1'</span>) <span class="hljs-comment"># Decimal('0.1')</span>
</code></pre>
<p>When creating Decimal objects, it is possible to customize the level of precision, rounding rules, etc.</p>
<h2 id="heading-solution-2-use-integers">Solution 2: Use integers</h2>
<p>It is possible to use integers to store the values and do the calculations. Only when there is a need to show the results for a human it would be divided by 100:</p>
<pre><code class="lang-python">burger_price = <span class="hljs-number">110</span>
amount = <span class="hljs-number">3</span>
total = burger_price * amount <span class="hljs-comment"># 330</span>
print(total/<span class="hljs-number">100</span>)
<span class="hljs-comment"># 3.3</span>
</code></pre>
<p>This way will keep us in the safe realm of integers.</p>
<p>The downside is when calculating a number with a large number of digits. Float is represented as scientific notation so it is fast doing calculations, but using integers expect slower speeds.</p>
<p>Hope you find this article useful and happy decimal calculations!</p>
]]></content:encoded></item><item><title><![CDATA[Learn  about Artificial Intelligence for free at Harvard University]]></title><description><![CDATA[Harvard University is one of the best universities in the world and it offers free online courses for anyone willing to learn. CS50 is the largest course on the university's campus and is also the one that receives the most funding. It is also no coi...]]></description><link>https://edumats.dev/learn-about-artificial-intelligence-for-free-at-harvard-university</link><guid isPermaLink="true">https://edumats.dev/learn-about-artificial-intelligence-for-free-at-harvard-university</guid><category><![CDATA[AI]]></category><category><![CDATA[Python]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Tue, 10 Jan 2023 21:00:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/0E_vhMVqL9g/upload/8fb4db308f99e602e7e80f9b71671a5f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Harvard University is one of the best universities in the world and it offers free online courses for anyone willing to learn. CS50 is the largest course on the university's campus and is also the one that receives the most funding. It is also no coincidence that it has an incredible 4.2 million students enrolled to date:scream::scream::scream:</p>
<p>In CS50 there are many courses and one of them is <a target="_blank" href="https://cs50.harvard.edu/ai/2020/">Introduction to Artificial Intelligence with Python</a>, or CS50AI, which is indicated for those who managed to finish <a target="_blank" href="https://cs50.harvard.edu/x/2023/">Introduction to Computer Science</a> (CS50X) or have 1 year of experience in Python and want to have a general understanding of what is Artificial Intelligence (AI). CS50AI gives you a certificate issued by the CS50 institution for free if you manage to complete all the projects, and there is also the possibility of paying for the certificate provided by Edx or acquiring a professional certification, which includes other CS50 courses, but honestly only the CS50 certificate is enough.</p>
<h2 id="heading-what-is-needed-before-starting-the-course">What is needed before starting the course?</h2>
<p><code>- [ ]</code> Know advanced math or statistics</p>
<p><code>- [ ]</code> Have excellent grades in math</p>
<p><code>- [ ]</code> Be a genius</p>
<p><code>- [x]</code> Be comfortable with Python so you don't have to learn two things at once</p>
<p><code>- [x]</code> Be resilient and always be willing to make an effort to learn</p>
<p><code>- [x]</code> Know English, as the course is entirely in English</p>
<p>In 2021 I managed to finish the course, after completing the CS50X and <a target="_blank" href="https://cs50.harvard.edu/web/2020/">Introduction to Web Development</a> (CS50W) and I will tell you... it was INTENSE! :cold_sweat: :cold_sweat:</p>
<p>Following the CS50 tradition, CS50AI is difficult for those who have never had contact with the subject of AI, but with effort and dedication, you can finish it. In all courses, they aim to make you "comfortable with discomfort", that is:</p>
<blockquote>
<p>Even if you feel helpless and confused when faced with a problem that you don't know how to solve immediately, the idea is that everything is fine and eventually you will be able to arrive at a solution, which is the representation of the day-to-day life of many programmers.</p>
</blockquote>
<h2 id="heading-what-will-i-learn-in-cs50ai">What will I learn in CS50AI?</h2>
<p>The CS50AI is divided into 7 modules, which are the main areas in the field of AI:</p>
<ol>
<li><p>Search: Finding a solution to a problem, such as a navigation program that needs to find the best route from source to destination</p>
</li>
<li><p>Knowledge: How to represent information and draw inferences from it</p>
</li>
<li><p>Uncertainty: How to handle events that have uncertainty using probability</p>
</li>
<li><p>Optimization: Finding not just the right way to solve a problem, but better ways, or the best way, to solve a problem</p>
</li>
<li><p>Learning: Improve performance by having access to data and past experience. For example, your email can differentiate spam from past experience.</p>
</li>
<li><p>Neural Networks: A structure inspired by the human brain that can efficiently perform tasks</p>
</li>
<li><p>Language: Process natural language, which is produced and understood by humans</p>
</li>
</ol>
<p>All modules have a long and dense class, of about 1h30, which must be rewatched whenever there are doubts. Then there is a not-so-easy quiz on the topics covered and finally, one or two projects, which must be coded by the student and sent via Git to the course repository.</p>
<p>Each project is tested to verify that the student's code meets all requirements and is then approved or rejected. It is possible to resend a project as many times as necessary and whenever the project is disapproved, a small note of why it was rejected is also sent.</p>
<p>It's amazing to see how the CS50 team managed to give opportunities for all students, even those who are not paying for the certificate, to be able to code their projects and still receive feedback, even if limited. I noticed that many of the projects are corrected by humans, probably Harvard students, as it is not possible to automate certain assessments and the only way to check the final result is to watch a video recorded by the student, showing how the final solution behaves. I imagine the amount of work this must take and only a giant institution like Harvard can make it available worldwide for free to any student.</p>
<h2 id="heading-what-is-it-like-to-take-the-course">What is it like to take the course?</h2>
<p>In short, the course is <strong>DIFFICULT</strong>. It's made for the elite American students, so it is blood, sweat and tears from beginning to end:under::under:</p>
<p>In the second project, the game of tic-tac-toe, I was stuck for a good few weeks, because my version was very slow and I wanted to implement a solution that made the AI to be more efficient and faster when making moves. It didn't help that I got confusing feedback about what was wrong with my code, something like "your AI's movement patterns are inconsistent". After taking a sabbatical from the course, I took a few days to rethink the problem and managed to move forward:grinning:</p>
<p>What is most required to complete the projects is time and dedication to completely understand the content shown in the video, in addition to reading the documentation in modules that introduced tools related to AI and also taking the time to research any errors and bugs that appear along the way.</p>
<h2 id="heading-what-did-i-learn-at-the-end-of-cs50ai">What did I learn at the end of CS50AI?</h2>
<p>What was very rewarding was going from a superficial view of what AI is to a very solid understanding of what an AI problem is, what kind of strategies can I use to solve a problem and what tools are available to help me.</p>
<p>The course demystified some myths, such as having to know a lot of Math or statistics to create a solution that uses AI, as there are already tools and frameworks that do most of the heavy lifting, such as neural networks already trained for certain tasks. The developer should see the problem from a more macro perspective: finding a problem to be solved, thinking about the best solution, connecting the parts and refining the process to have the best final result. Mathematics and statistics are important for the area, especially for those who do research and develop AI related tools, but it is also possible to use AI as a framework and not get involved with lower layers of abstraction, as when someone uses a web framework or a module that makes the developer's life easier: it is not necessary to understand what is behind it to be able to use and benefit from it.</p>
<p>The course introduces you to tools that are part of the toolkit that is commonly used to work with AI:</p>
<ul>
<li><p><a target="_blank" href="https://scikit-learn.org/stable/">Scikit-learn</a>: Machine Learning tool for data analysis</p>
</li>
<li><p><a target="_blank" href="https://www.tensorflow.org/">TensorFlow</a>: Used to create neural networks capable of classifying images</p>
</li>
<li><p><a target="_blank" href="https://www.nltk.org/">NLTK</a>: Tool to analyze human language</p>
</li>
</ul>
<p>I was very proud of several projects that I managed to complete, in particular, three of them:</p>
<ol>
<li><p>When I created an <a target="_blank" href="https://cs50.harvard.edu/ai/2020/projects/0/tictactoe/">invincible tic-tac-toe player</a></p>
</li>
<li><p>When I created a <a target="_blank" href="https://cs50.harvard.edu/ai/2020/projects/3/crossword/">crossword puzzle generator that creates a crossword puzzle only using a list of words as input</a></p>
</li>
<li><p>When I created an <a target="_blank" href="https://cs50.harvard.edu/ai/2020/projects/1/minesweeper/">AI that can play minesweeper</a></p>
</li>
</ol>
<h2 id="heading-final-thoughts-on-the-cs50ai">Final thoughts on the CS50AI</h2>
<p>I recommend the course to everyone curious about AI, but never had the courage/opportunity/guidance to start studying it. It's an area with tough problems, many still unresolved, so don't expect a smooth, stress-free journey.</p>
<p>On the other hand, solutions that use AI leave non-technical persons and programmers awestruck. It's amazing to see behaviors that human beings deem to be "intelligent" being done by programs and electronic devices:alien::alien:</p>
<p>Only a small portion of the problems and potential areas of AI have been explored, which is an incredible opportunity for those who possess the knowledge, not only about training and building an AI but also identifying situations that could benefit from it! Imagine what could happen if all cameras could analyze images like humans or if computers could understand a person's mood from what they say and write.</p>
<p>Good journey and happy learning!:smiley:</p>
]]></content:encoded></item><item><title><![CDATA[As a developer, don't reinvent the wheel. An advice for developers and entrepreneurs]]></title><description><![CDATA[As developers, we earn money, reputation and experience by being builders. We take pride in building unique solutions or solving difficult problems. Recreating common algorithms that already exists makes us understand basic principles and give us a g...]]></description><link>https://edumats.dev/as-a-developer-dont-reinvent-the-wheel-an-advice-for-developers-and-entrepreneurs</link><guid isPermaLink="true">https://edumats.dev/as-a-developer-dont-reinvent-the-wheel-an-advice-for-developers-and-entrepreneurs</guid><category><![CDATA[Entrepreneurship]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Startups]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Mon, 09 Jan 2023 19:36:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/3coKbdfnAFg/upload/v1669215233525/C3aySLBNE.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As developers, we earn money, reputation and experience by being builders. We take pride in building unique solutions or solving difficult problems. Recreating common algorithms that already exists makes us understand basic principles and give us a great amount of knowledge.</p>
<p>On the other hand, many problems already have been solved by others and we should take advantage of this fact. We use modules, frameworks and higher-level abstractions built by others to make our lives easier, be able to make more with less time and be free to focus on solving our unique problems.</p>
<h2 id="heading-more-code-more-problems">More code, more problems</h2>
<p>I have heard and seen many cases where small and medium businesses, when confronted with a problem that can be solved with technology, choose the path of hiring a developer or a software company and embarking on a journey of building the solution themselves, instead of searching for a service provider or a platform that could provide a ready-made solution.</p>
<p>For a business that is not tech-centric, deciding to build the code themselves, usually means a lot of time and wasted money.</p>
<blockquote>
<p>In Science, we stand on the shoulders of giants to take one further step ahead. The first step in scientific research is to search for work that already has been done in a particular field of study, so it is possible to improve or extend the existing knowledge.</p>
</blockquote>
<p>Especially in startups, we should take a similar approach to one taken by Science, by searching for solutions that already exist, instead of immediately proceeding to build our solution. This allows us to:</p>
<h3 id="heading-go-to-market-fast">Go to market fast.</h3>
<p>Instead of waiting for an application to be planned, created, and tested, use a solution that is ready to be used and was proven both by tests and real-world usage.</p>
<h3 id="heading-avoid-common-pitfalls-that-can-eat-a-lot-of-time-and-money">Avoid common pitfalls that can eat a lot of time and money</h3>
<p>Not many understand how hard is to build something, as it is not only a technical challenge. When creating something new, there should be considerations on the market, its users, usability, and costs, just to cite a few. Even if it is a technical product, a developer will feel overwhelmed, as skills like design, entrepreneurial skills, and user interface are necessary to be successful. It is possible that many iterations are necessary before finally reaching the desired result and those take a lot of time.</p>
<h3 id="heading-change-fast">Change fast</h3>
<p>As a new business, the initial assumptions can change dramatically. It is easy to unsubscribe from an online platform, but it is painful to throw away months of developer work, as well as time, and resources that were invested in it. This can lead to a situation where a business <a target="_blank" href="https://www.investopedia.com/terms/s/sunkcost.asp">continues to invest in a failing strategy because it does not want to lose the resources already invested</a>.</p>
<blockquote>
<p>You cannot ask for a refund from your developers if your product is not what is needed by your customers.</p>
</blockquote>
<h3 id="heading-delegating-maintenance-and-improvements-to-someone-else">Delegating maintenance and improvements to someone else.</h3>
<p>Not many entrepreneurs realize that a website, platform or tool will need constant improvements and fixes throughout its lifetime. If developers build an e-commerce website, it will have the requested features, but as time passes, an integration to marketplaces will appear to be necessary to increase revenue and analytics will show that a shorter sign-up process will decrease cart abandonment. None of that was considered when building the first version of the website and that is expected as no one can predict the future. When using a platform, for example, these needs have been already addressed, as they listen to the needs of thousands of customers and already have iterated their product thousands of times.</p>
<p>Common problems, such as selling over the Internet, building a business website or storing files are so common that large platforms already exist to solve problems for millions of users. They usually provide customization so they can serve a large number of use cases and it does not make much sense to build a custom solution unless you have a very specific problem that cannot be addressed by these platforms.</p>
<h2 id="heading-a-personal-example">A personal example</h2>
<p>When I was building my startup, we needed a platform to connect end customers with service providers, a typical marketplace. So we were confronted with two options:</p>
<ol>
<li><p>Hire developers to build the platform with everything we thought we needed. It would have taken 5 months to make a functional version and it would eat months of resources that would give more months to our startup to stay afloat.</p>
</li>
<li><p>Use a platform as a service. It did not have all the necessary features that we needed, nor would give the best user experience, but it could work. We would pay only the monthly fee to them and could cancel anytime.</p>
</li>
</ol>
<p>I am glad that we chose the second option, as we discovered a few months after that we needed to pivot our business strategy from B2C (business to consumer) to B2B (business to busines), focusing more on serving business than end-consumers, as serving businesses has lower customer acquisition cost, operational costs were far lower and we generated more revenue. We avoided the difficult decision of throwing away time and money directed toward end users, as I could simply cancel our subscription to the platform when the time came and that was as easy as canceling a Spotify plan.</p>
]]></content:encoded></item><item><title><![CDATA[6 lessons I have learned in my path to become a developer]]></title><description><![CDATA[Instead of boring you by detailing personal achievements or publishing generic articles made by bots, I will write a very sincere review of what I have learned in the year 2022. There were many stressful months, because of Covid, prostate cancer and ...]]></description><link>https://edumats.dev/6-lessons-i-have-learned-in-my-path-to-become-a-developer</link><guid isPermaLink="true">https://edumats.dev/6-lessons-i-have-learned-in-my-path-to-become-a-developer</guid><category><![CDATA[#DevRetro2022]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Thu, 05 Jan 2023 00:00:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/a0e079d0100220b3380604de540e762a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Instead of boring you by detailing personal achievements or publishing generic articles made by bots, I will write a very sincere review of what I have learned in the year 2022. There were many stressful months, because of Covid, prostate cancer and noisy neighbors, but there were also many "a-ha" moments and other situations where I felt proud to be relied upon as a programmer that can solve problems that ordinary people cannot.</p>
<h2 id="heading-the-background">The background</h2>
<p>Since 2019 I have been rustling to become a developer and not any developer, but a self-employed one. It is not the easiest nor the shortest path, since I majored in Psychology and never excelled in hard sciences, but I have been enjoying the learning process and overcoming the hurdles. I have been self-studying and this has many advantages, such as:</p>
<ul>
<li><p>Learning at a fast pace: No bullshit, gets directly where I want to go<code>:rocket:</code></p>
</li>
<li><p>Becoming more independent and self-motivated: I am the only one responsible for my learning<code>:muscle:</code></p>
</li>
<li><p>Learning exactly what I want or taking the time to go deeper into a subject: Makes the act of studying very enjoyable and interesting<code>:smiley:</code></p>
</li>
<li><p>Be able to experiment different paths and plan my career<code>:chart_with_upwards_trend:</code></p>
</li>
<li><p>Have a deep understanding of a subject instead of just studying to pass a test and forgetting everything months later<code>:books:</code></p>
</li>
<li><p>Study for free or very little cost: There are tons of free, high-quality materials for self-study and many high-quality courses that are much better than an actual university class and cost nothing or just a few dollars<code>:moneybag:</code></p>
</li>
</ul>
<p>But also has many disadvantages:</p>
<ul>
<li><p>Easy to be distracted by life: Creating and maintaining the habit of studying and practicing every day is mandatory for self-study<code>:persevere:</code></p>
</li>
<li><p>Difficult to be held accountable for progress: No lectures to attend, no hard deadlines for delivering projects<code>:date:</code></p>
</li>
<li><p>Progress is not being validated by peers or teachers<code>:100:</code></p>
</li>
<li><p>Impostor Syndrome can creep in, as there is no external validation, like diplomas, grades or certifications<code>:confounded:</code></p>
</li>
</ul>
<p>I had a hard time achieving <a target="_blank" href="https://en.wikipedia.org/wiki/Flow_(psychology)">flow</a> in 2022 as in my home I was getting constantly interrupted by ringing doorbells, noisy neighbors, dogs barking all the time, hunting mosquitos and sweaty, hot days. This improved when I started to go to public coworking spaces where I could work in a silent environment, without interruptions<code>:relieved:</code></p>
<h2 id="heading-why-code">Why code?</h2>
<p>In 2016 I have built a startup called <a target="_blank" href="https://bike123.com.br/">Bike123</a> with a friend and ex-coworker. It solves the problem of finding a qualified mechanic that can fix your bicycle without the need of bringing it yourself to a bike shop. We did not have any background in tech, but we were very motivated and we had extensive knowledge of the bicycle industry. Turns out that trying to build a scalable startup without a programmer on the team is like running a marathon using only one leg: it is possible but will be hard<code>:running::running::dizzy_face:</code></p>
<p>I was considering leaving the startup in 2018 when it became clear that it would be very hard to scale it in a way that could financially sustain ourselves and the final decision was made when my mother passed away unexpectedly, leaving a lot of unfinished issues to be solved, but I am still proud that I have helped to build a very lean startup that was validated as a business and it is still in operation to this day.</p>
<p>If you need to fix a bicycle in Brazil, you could consider checking <a target="_blank" href="https://bike123.com.br/">Bike123's website</a> to find a trusted mechanic that will fix your bicycle in no time.</p>
<h2 id="heading-lesson-0-failures-are-necessary-for-a-journey">Lesson 0: Failures are necessary for a journey</h2>
<p><img src="https://media.giphy.com/media/3ohs4qw8hkPShGeanS/giphy.gif" alt class="image--center mx-auto" /></p>
<p>Looking back on what I did up to this day, the experience of running a startup without tech skills opened my eyes to a career in programming. I felt extremely handicapped and hopeless as most of the necessary improvements that our business needed were associated with technical skills, such as creating an API or eliminating manual work with technology and automation.</p>
<p>After researching more about the tech world, I could already envision building a small tech company that can sell services anywhere in the world, without the need for spending capital to buy goods or store them. If needed, the company could be incredibly lean and have one or very few team members that can leverage technology to get to millions of customers.</p>
<p>That thought lead me to try to start some small online programming courses. I liked the experience and slowly I devoted more and more time to learning about algorithms, JavaScript, Python, and enrolled in <a target="_blank" href="https://cs50.harvard.edu/x">CS50</a>, until I was devoting my full-time to learning programming.</p>
<h2 id="heading-lesson-1-body-and-mind-are-one">Lesson 1: Body and mind are one</h2>
<p><img src="https://media.giphy.com/media/l1KVaj5UcbHwrBMqI/giphy.gif" alt class="image--center mx-auto" /></p>
<p>Fast forward to 2022 and my body was tired after so many years and months of Coronavirus, sitting down all day and maintaining social distancing. Especially my lumbar was killing me, I could barely sit for a couple of hours without pain. On top of that, I got my first corona infection in January and felt sick for many weeks. My father was just diagnosed with prostate cancer and a decision was needed regarding what treatment to take, so I had very little time to exercise and was not sleeping well at all.</p>
<p>Those were very stressful months and as a result, I was not able to think right, let alone have new ideas or be creative. Coding was a frequent struggle and I felt that for every new concept that I managed to learn, another one that I have already learned was being forgotten. I was constantly forgetting common words and had a hard time recalling things that I have done.</p>
<p>My body was not well and this reflected in my ability to do intellectual work.</p>
<h2 id="heading-lesson-2-diversity-brings-creativity">Lesson 2: Diversity brings creativity</h2>
<p><img src="https://media.giphy.com/media/26BoEeFJkz2eZUBcQ/giphy.gif" alt class="image--center mx-auto" /></p>
<p>In April, I was worried about my dwindling mind and noticed that my weekly routine barely changed. I stayed home most of the days, chatting only with my girlfriend and going out to the same places. To counter this, I started to actively seek new experiences, such as:</p>
<ul>
<li><p>Seeking friends that I haven't seen in a long time</p>
</li>
<li><p>Going to places in the city that I haven't been to for a long time</p>
</li>
<li><p>Going to art expositions</p>
</li>
<li><p>Studying in libraries and going to a coworking to see new faces</p>
</li>
<li><p>Trying foods and new places for the first time</p>
</li>
</ul>
<p>After some months, I slowly began having new ideas and even started writing again, a habit that I have distanced myself from. This leads me to start this very blog on Hashnode.</p>
<p>And by reconnecting with friends, I got a freelance job! A friend needed help replacing a buggy scheduling tool with better usability for his business. I was glad that I could solve a problem that would make a difference for his business and this experience made me think about what can I do to help small businesses like his.</p>
<h2 id="heading-lesson-3-take-it-as-medicine">Lesson 3: Take it as medicine</h2>
<p>When (re)starting a new habit outside the comfort zone, inevitably there will be resistance in form of laziness or well-thought excuses. I used to cycle a lot, meaning +150km a week, but with the pandemic, I was using a static roller and was only doing 3 times a day, meaning 30km a week at best. This is more than the average person rides, but it was not enough for me. As a result, I got a couple of kilos and my skills and reflexes on a bicycle greatly decreased.</p>
<p>I wanted to start cycling with my friends, but I have to admit now that I was fearful and insecure, so I made excuses in form of "I think cycling is kinda dangerous" or "I need more free time to dedicate to that".</p>
<p>One day I remembered something my father used to say when I was little and I was refusing to eat greens:</p>
<blockquote>
<p>You don't have to enjoy it, take it as a medicine</p>
</blockquote>
<p>So I just did it, I took cycling as medicine for countering back pain and my extra kilos. On the first rides, it tasted like a bitter pill. I was fearful, my back hurt, and my body was protesting. At first, it was bad, but then I felt good. Today I am glad that I took the medicine, my lumbar is almost cured and I feel much better about myself and my progress.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672849257456/33b6204a-8804-4f78-ada5-70fb130eab18.jpeg" alt class="image--center mx-auto" /></p>
<p>This is me, in a hill climbing race, organized by my cycling club. I managed to get a third place!</p>
<h2 id="heading-lesson-4-one-step-a-day-makes-you-go-farther-away">Lesson 4: One step a day makes you go farther away</h2>
<p><img src="https://media.giphy.com/media/fhAwk4DnqNgw8/giphy.gif" alt class="image--center mx-auto" /></p>
<p>In school or university, there is a tendency to work in bursts. Like studying for a test, the test has a deadline, so the students will have a week or some days of intense work, which culminates on the day of the test. After that, most of the students will not touch a book until the next exam.</p>
<p>In the real life, things are not like that. The path to becoming a good programmer does not involve taking tests and studying the bare minimum to pass them. When learning to drive a car, for example, the key is to practice a little every day, feel the feedback from the pedals, noises and vibrations, and not pass exams about how to drive a car.</p>
<p>This year I managed to code almost every day, some days I was very productive, and others were a struggle, but I did it, nonetheless. Just like climbing a high mountain, at first, the progress is negligible, but after some time, you forget about the progress and just enjoy the adventure. You finally reach a clearing and it is possible to see that you have climbed a lot and you see for the first time the path you have taken from above. It is very rewarding, but it only comes after a long effort.</p>
<p><img src="https://media.giphy.com/media/KTb1vC1gsPuNdrXXLc/giphy.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-lesson-5-build-your-toolkit-and-your-specialty">Lesson 5: Build your toolkit and your specialty</h2>
<p>As a freelance programmer, it is not productive to try to adjust your skills for every customer's demand. When I started freelancing I tried to grab every opportunity that I assumed that I could deal with my skills. Wrong! This resulted in long hours of research, frustrating problem-solving sessions and stressing out, as the deadline was approaching, but in the end, I was getting very little money for all that effort and I was not satisfied with the final product. This <a target="_blank" href="https://www.freecodecamp.org/news/freelance-web-developer-guide/#freelance-developers-must-decide-which-niche-they-are-going-to-serve">article</a> explains more why you should focus on a niche segment, instead of trying to serve everyone<code>:weary:</code></p>
<blockquote>
<p>If you are a freelancer, think about yourself as a restaurant. Have you ever seen a place where you could sit and ask anything you like? A place where you could order a burger or some sushi or maybe some french food. I doubt it.</p>
</blockquote>
<p>That happens because it is uneconomical to do so. Yeah, everything is under the umbrella of "cooking", but the cook has to dedicate himself to some genre of cooking, otherwise:</p>
<ul>
<li><p>his dishes would be terrible as he would not get enough time to get good at making a particular dish</p>
</li>
<li><p>he would take a long time to make even a simple dish as there is no way to make preparations beforehand</p>
</li>
<li><p>there will be a lot of wasted ingredients that would not be used and would spoil</p>
</li>
</ul>
<p>So why programming would be any different? Find a niche, build a product using a tech stack you are comfortable and serve a large range of customers without changing too much from your basic product template. That will be the path to making a sustainable business</p>
<p>In 2022, to consolidate my tech stack, I decided to go all in on:</p>
<ul>
<li><p>Python, which I find clean, flexible and enjoyable to work with<code>:snake:</code></p>
</li>
<li><p>AWS, which allows me to launch projects at a low cost and in a scalable way<code>:arrow_double_up:</code></p>
</li>
<li><p>AWS Chalice, which allows me to glue together my business logic and AWS services, such as authentication and database<code>:stuck_out_tongue_closed_eyes:</code></p>
</li>
<li><p>AWS CDK, which allows me to call my complete infrastructure stack with a single command<code>:smile:</code></p>
</li>
</ul>
<h2 id="heading-closing-thoughts">Closing thoughts</h2>
<p>This year I am becoming more confident in my developer skills, as I have expanded my programmer toolkit and, as a result, can take a variety of jobs. Also, having more experience freelancing, I can avoid common pitfalls, such as creating an application from scratch that has a low probability to be reused.</p>
<p>Another good news is that my father is cured of cancer, having been treated with radiotherapy and hormone therapy and having no lasting side effects at all. If you know someone that has been diagnosed with prostate cancer, be sure to get as much information as possible to be able to help them make the best decision. The Prostate Cancer Research Institute helped us a lot, be sure to check their Youtube <a target="_blank" href="https://www.youtube.com/@ThePCRI">channel</a>.</p>
<p>I think I am slowly returning to my pre-pandemic performance and I feel that body, mind and habits are set in a way that 2023 will be a much better year.</p>
<p>This was Dev Retro 2022!</p>
<h2 id="heading-achievements">Achievements</h2>
<ul>
<li><p>My <a target="_blank" href="https://edumats.dev/a-path-to-hosting-personal-projects-for-free-on-the-cloud">article about hosting personal projects for free using AWS</a> got featured on Hashnode!</p>
</li>
<li><p>Passed <a target="_blank" href="https://www.credly.com/badges/89dc2c48-0390-4046-bef3-e7f9da63a4ad/public_url">AWS Cloud Practitioner certification</a>! Check <a target="_blank" href="https://edumats.dev/how-i-passed-the-aws-cloud-practitioner-certification">my blog post</a> about the experience</p>
</li>
<li><p>Built a <a target="_blank" href="https://github.com/edumats/flexible-price-tracker">scrapper</a> that tracks prices on e-commerces, so you can get a nice deal. You can use it too and make pull requests, check it on my GitHub</p>
</li>
<li><p>Completed <a target="_blank" href="https://cs50.harvard.edu/python/2022/">Harvard University's course in Python</a>. Check out <a target="_blank" href="https://edumats.dev/a-review-of-cs50p-introduction-to-programming-with-python">my review of it</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How I passed the AWS Cloud Practitioner Certification]]></title><description><![CDATA[First things first: Why the cloud is important?
Companies like Amazon, Google and Microsoft spend huge amounts of money buying computers and infrastructure to power their numerous digital services. One day they realized that it is possible to sell so...]]></description><link>https://edumats.dev/how-i-passed-the-aws-cloud-practitioner-certification</link><guid isPermaLink="true">https://edumats.dev/how-i-passed-the-aws-cloud-practitioner-certification</guid><category><![CDATA[Web Development]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Fri, 23 Dec 2022 00:47:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/c62f08a8b3db9fbbd1b72af5919f27f6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-first-things-first-why-the-cloud-is-important">First things first: Why the cloud is important?</h2>
<p>Companies like Amazon, Google and Microsoft spend huge amounts of money buying computers and infrastructure to power their numerous digital services. One day they realized that it is possible to sell some of their unused computer capacity to other companies, so they can earn more while providing an invaluable service to companies that are not tech-centric or do not have pockets so deep but need to offer digital services or rely on them to maintain their operations. Think about Coca-Cola, the BBC TV or the Government.</p>
<p>When a company ditches its in-house servers and moves to cloud-based services, it gets rid of many pains, while getting many advantages over competitors:</p>
<ul>
<li><p>Avoid the hassle of buying and managing expensive servers</p>
</li>
<li><p>Do not need to hire expensive employees to take care of their servers</p>
</li>
<li><p>Avoid having expensive servers that most of the time work below 20% of their total capacity</p>
</li>
<li><p>Avoid having expensive downtimes and poor user experience during peak time due to insufficient server capacity</p>
</li>
<li><p>Can react to sudden changes in demand. You can add more cloud servers at any time, but you cannot do the same with in-house servers that need to be bought, configured and maintained. Think about peaks in e-commerce during Black Friday sales</p>
</li>
<li><p>Developers can focus on the business part of the application, avoiding undifferentiated work, like applying updates, checking the health of servers or managing backups</p>
</li>
</ul>
<p>For a startup, cloud services are even more important:</p>
<ul>
<li><p>Do not need to commit huge amounts of cash before starting the business. They can pay for what they use in a gradual manner</p>
</li>
<li><p>Do not need to guess what will be the demand for their servers</p>
</li>
<li><p>Can deploy an entire infrastructure very fast, with some mouse clicks or a simple command in a terminal</p>
</li>
<li><p>One single developer can manage a complex infrastructure</p>
</li>
</ul>
<h2 id="heading-why-have-a-certification">Why have a certification?</h2>
<p>Currently, there are more than 300 services on AWS and the number keeps growing. Their combined documentation has thousands of pages so it takes a great deal of time and effort to learn the inner workings. So, while knowledge of cloud services is in high demand, it is difficult to assert the level of knowledge a person has. Certifications can fix this issue, by attesting that a developer has a good understanding of a particular field in the cloud.</p>
<p>For me, having a certification is important because:</p>
<ul>
<li><p>Many job postings have AWS as a requirement and a certification is an important differentiator</p>
</li>
<li><p>As I am doing freelance work, my customers can rest assured that I know AWS services</p>
</li>
<li><p>It is a good opportunity to do an in-depth study of the AWS services otherwise, I would not be so keen to go deep into the AWS ecosystem</p>
</li>
</ul>
<h2 id="heading-why-i-chose-the-cloud-practitioner-certification">Why I chose the Cloud Practitioner certification?</h2>
<p><a target="_blank" href="https://aws.amazon.com/certification/">There are many certifications to choose from</a> and they are divided into levels, from generalist to specialist:</p>
<ul>
<li><p>Foundational</p>
</li>
<li><p>Associate</p>
</li>
<li><p>Professional</p>
</li>
<li><p>Specialty</p>
</li>
</ul>
<p>Cloud Practitioner certification should be your first certification, as it is situated at the Foundational level and evaluates the general understating of AWS, without going too deep. Other certifications assume that you are specializing in a role, such as:</p>
<ul>
<li><p>SysOps</p>
</li>
<li><p>Networking</p>
</li>
<li><p>Data Analytics</p>
</li>
<li><p>Database</p>
</li>
<li><p>Machine Learning</p>
</li>
<li><p>Security</p>
</li>
<li><p>SAP</p>
</li>
</ul>
<h2 id="heading-how-i-prepared-for-the-exam">How I prepared for the exam</h2>
<p>The Cloud Practitioner certification exam asks for a general understanding of AWS and its most important services, so they will not ask for coding a solution or open-ended questions, just multiple-choice questions, but do not be fooled: <strong>it is not an easy exam</strong>. Some questions are tricky as they thoroughly test if you have a good grip on the topic or just a shallow understanding.</p>
<p>I am not a fan of buying courses and I don't find it necessary at all to pass the certification exam. There is plenty of content on Youtube and AWS Skill Builder. I would recommend reading the <a target="_blank" href="https://aws.amazon.com/certification/certified-cloud-practitioner/">Cloud Practitioner exam page</a>, carefully reading the exam guide and studying each of the required topics. There are many things to study and you could feel overwhelmed, but keep in mind that they will always ask for general understanding, not specifics. I studied every day for about 3 weeks and I learned the most when doing hands-on tutorials and trying to get the bigger picture instead of trying to memorize names or parts of the documentation.</p>
<p>AWS Skill Builder is a great tool for learning, unfortunately, it is not easy to use, as most of its valuable free courses are hidden by paid courses. Here are the most helpful ones I completed for my preparations for the Cloud Practitioner certification:</p>
<ul>
<li><p><a target="_blank" href="https://explore.skillbuilder.aws/learn/course/11458/aws-cloud-quest-cloud-practitioner">AWS Cloud Quest: Cloud Practitioner</a> (a nice 3D game for learning AWS)</p>
</li>
<li><p><a target="_blank" href="https://explore.skillbuilder.aws/learn/course/9449/exam-prep-aws-certified-cloud-practitioner-clf-c01">Exam Prep: AWS Certified Cloud Practitioner (CLF-C01</a></p>
</li>
<li><p><a target="_blank" href="https://explore.skillbuilder.aws/learn/course/12483/aws-certified-cloud-practitioner-official-practice-question-set-clf-c01-english">AWS Certified Cloud Practitioner Official Practice Question Set (CLF-C01 - English)</a></p>
</li>
<li><p><a target="_blank" href="https://explore.skillbuilder.aws/learn/course/134/aws-cloud-practitioner-essentials">AWS Cloud Practitioner Essentials</a></p>
</li>
</ul>
<h2 id="heading-the-exam-day">The exam day</h2>
<p>I was a little skeptical of the seriousness of the exam, as I opted for the online version. Do they care about my ID or if I am possibly reading the answers in another browser tab? I wondered.</p>
<p>Yes, they care.</p>
<p>I got into my first trouble when I tried to log into the exam page at the scheduled time. Before taking the exam it is necessary to install proprietary software that blocks others browsers during the exam. Although I tested beforehand if my Ubuntu laptop would meet the requirements of the exam, the link for installing the software was not working, despite changing from Firefox to Chrome. I changed to a Macbook and managed to complete the installation of the software.</p>
<p>The second trouble happened when they wanted to check my ID. My bedroom does not have good lighting and the examiner could not read my ID data. After more than 30 minutes of struggle, I got redirected to technical support. Luckily I managed to get more lights into the room and another document and they managed to</p>
<p>Some tips for the exam:</p>
<ul>
<li><p>Be well-rested and have a good night's sleep</p>
</li>
<li><p>Make sure that the name you used to register on the AWS Certification website matches the name on your ID</p>
</li>
<li><p>If you chose the online exam option, pick a location and time with no chance for interruptions or background noise</p>
</li>
<li><p>Be in a well-lit room and use a good-quality webcam</p>
</li>
<li><p>Have at least two types of identification documents. Make sure both are in good condition and legible when using your webcam</p>
</li>
<li><p>They will ask for moving your webcam to check if you are the only person in the room or if you have study material on your desk or below it, so organize your desk and room before the exam for the process to go smoothly</p>
</li>
</ul>
<h2 id="heading-the-day-after">The day after</h2>
<p>Having passed the certification I received some perks:</p>
<ul>
<li><p>Access to AWS Certified Global Comunity, where other people who managed to get certified can connect</p>
</li>
<li><p>Access to AWS Subject Matter Expert, where you can help create and validate questions for AWS Certification exams</p>
</li>
<li><p>Access to AWS Certified Store, where you can buy AWS Certified goods</p>
</li>
<li><p>A digital base that can be shared on social media</p>
</li>
<li><p>A 50% discount voucher that can be used in any other exam</p>
</li>
</ul>
<h2 id="heading-next-steps">Next steps</h2>
<p>As I am a web developer, I plan to get to the Associate level, by going after the Developer Associate and the Solutions Architect Associate certifications, as they are a perfect fit for my current role. In the long term, I would go for the Database Specialty certification, but other certifications would go way off course.</p>
<p>I will keep you updated about my progress and happy coding!<code>:smiley:</code></p>
]]></content:encoded></item><item><title><![CDATA[A path to hosting personal projects for free on the cloud]]></title><description><![CDATA[Having created a series of personal projects, I was excited to start building a number of projects of mine, but after being orphaned by the discontinuation of Heroku's free plans, the first challenge was to host them. To start my search, I had some p...]]></description><link>https://edumats.dev/a-path-to-hosting-personal-projects-for-free-on-the-cloud</link><guid isPermaLink="true">https://edumats.dev/a-path-to-hosting-personal-projects-for-free-on-the-cloud</guid><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[AWS]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Tue, 29 Nov 2022 20:21:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/L85a1k-XqH8/upload/v1669746990561/rVIVv2vfR.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Having created a series of personal projects, I was excited to start building a number of projects of mine, but after being orphaned by the <a target="_blank" href="https://blog.heroku.com/next-chapter">discontinuation of Heroku's free plans</a>, the first challenge was to host them. To start my search, I had some prerequisites:</p>
<ul>
<li><p><strong>Reliability first</strong>. I want to sleep well at night and not worry if my applications are down because of an unstable cloud provider</p>
</li>
<li><p><strong>Use managed services instead of DIY solutions</strong>, so I could focus on my code. Instead of being dragged down by a lot of manual labor and spending a huge amount of time doing things like applying updates to my server's OS or doing manual backups of my database, I would rather think about the problem that I am trying to solve and the code that is unique to my application</p>
</li>
<li><p><strong>Have the lowest cost possible</strong>, as I live in Brazil and paying in dollars really hurts my wallet</p>
</li>
<li><p><strong>Use industry standards</strong>. I do not want to invest my time learning about platforms that are only used by hobbyists or a small niche, I would rather learn a single platform that could be used to power either a simple personal project or a large, enterprise-grade solution</p>
</li>
<li><p>The solution should be <strong>able to do back-end tasks</strong>: it should be capable of doing authentication, user sign-in/sign-up, a persistent database for storing user data, as well as static page hosting and be able to create APIs with ease.</p>
</li>
</ul>
<h2 id="heading-a-little-surprise">A little surprise</h2>
<p>So I looked over the cloud provider options and all of them offered similar services. AWS has the largest market share, so it was the natural first choice. At the very basic, I needed a place to run my server code and a database. On the server hosting, I could get going for a fully managed solution like <a target="_blank" href="https://aws.amazon.com/lightsail/">AWS Lightsail</a> on containers for $7/month.</p>
<p>On the database side, things did not look great. Even if I start with a single project with very little database use, the cheapest <a target="_blank" href="https://aws.amazon.com/rds/">AWS RDS</a> instance would charge about $30/month. Another option would be the managed database provided by AWS Lightsail, resulting in a $15/month cost.</p>
<p>Still, I would have to spend at least $22 per month. Some of the readers from developed countries may find it strange that I making a big fuss over 20 dollars, but here in Brazil, it is expensive, especially when those are only experimental projects with no plans in the short term for revenue. On top of that, it is not even an ideal solution, as most of the time the database server would be sitting doing nothing, meaning wasted dollars. And it is not very scalable either, as spinning another project using the same kind of resources quickly adds more dollars to the monthly cost.</p>
<h2 id="heading-going-serverless">Going serverless</h2>
<p>Going back and forth in <a target="_blank" href="https://calculator.aws">AWS Pricing Calculator</a>, I discovered that serverless services are mostly free when there is only light usage (thanks to their <a target="_blank" href="https://aws.amazon.com/free/">Free Tier</a>) and, even with some respectable loads, they are very inexpensive, meaning a monthly cost that wouldn't top the $5 or $10 mark. On top of that, those are managed services, meaning I would only focus on code that matters to me, no time wasted managing or monitoring the infrastructure.</p>
<p>Before continuing, I would like to clarify that serverless is not a type of service that does not use servers, but rather a <strong>totally</strong> managed service, meaning that everything is taken care of by AWS: thinking about how to balance the traffic load between servers or to create a private network between a server and an API is not needed because AWS takes care of the servers, the overall infrastructure, the way it scales up or down, the way it handles traffic and other low-level configurations. In general, It is possible to create resources that would receive zero requests and would stay available for free or they can receive millions or billions of requests and AWS takes care of everything.</p>
<h2 id="heading-what-if-i-use-aws-services-to-replace-my-current-web-framework">What if I use AWS services to replace my current web framework?</h2>
<p>At a first glance, AWS services seemed to be a bunch of services that would need to be manually created, configured and connected together, going back and forth on their webpage. But going a bit deeper, it became clear that is not the only way that it is meant to be used.</p>
<p><a target="_blank" href="https://spiegelmock.com/2021/05/29/frameworkless-web-applications-aws-cdk/">AWS services can be used as an entire framework</a>, like Django or Flask, and <a target="_blank" href="https://mitelman.engineering/blog/amazon-api-gateway-with-lambda-is-a-next-generation-of-web-frameworks/">it may even be the next generation of web frameworks</a>, so I would write application code in my favorite programming language and also infrastructure code, describing that I need authentication, API, storage, for example, and a very brief configuration for each of these services. Then I would be able to test the code, store it in version control and deploy all the infrastructure, back-end and front-end code using a single command. If I need to add a new service, it would be just like adding a new feature in my application code: change the code, test it, send it to version control and deploy it.</p>
<p>All of this is possible thanks to AWS CDK. It can generate AWS resources with very little code because it uses sensible defaults, so it is not necessary the describe all the details, like in <a target="_blank" href="https://aws.amazon.com/cloudformation/">AWS Cloudformation</a>. CDK generates an AWS Cloudformation template, which is <strong>MUCH</strong> more verbose and has all the necessary details that are not specified in the original CDK code, then the template is used to deploy the services at AWS. Here is an AWS CDK code that is describing an API that uses a Lambda function to process the requests:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> constructs <span class="hljs-keyword">import</span> Construct
<span class="hljs-keyword">from</span> aws_cdk <span class="hljs-keyword">import</span> (
    Stack,
    aws_lambda <span class="hljs-keyword">as</span> _lambda,
    aws_apigateway <span class="hljs-keyword">as</span> apigw,
)


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CdkWorkshopStack</span>(<span class="hljs-params">Stack</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, scope: Construct, id: str, **kwargs</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        super().__init__(scope, id, **kwargs)

        <span class="hljs-comment"># Creates a AWS Lambda resource and points where the Python code is located</span>
        my_lambda = _lambda.Function(
            self, <span class="hljs-string">'HelloHandler'</span>,
            runtime=_lambda.Runtime.PYTHON_3_7,
            code=_lambda.Code.from_asset(<span class="hljs-string">'lambda'</span>),
            handler=<span class="hljs-string">'hello.handler'</span>,
        )

        <span class="hljs-comment"># Defines the my-lambda instance as endpoint for the API</span>
        apigw.LambdaRestApi(
            self, <span class="hljs-string">'Endpoint'</span>,
            handler=my_lambda,
        )
</code></pre>
<p>That's it! Deploying this code will result in a simple API being deployed, ready to receive requests. Doing the same thing on the AWS Console page would mean a bunch of clicking, scrolling, configuring all the permissions and doing all the work again for each different AWS region. In this example, all necessary authorizations for the services to interact with each other are automatically created and defaults are applied automatically if the developer does not mention it in the CDK code.</p>
<p>For those that are already familiar with a framework called Flask, a serverless AWS equivalent is available as <a target="_blank" href="https://aws.github.io/chalice/">AWS Chalice</a> and is <strong>very</strong> similar to Flask in terms of syntax. By using it, it is possible to integrate authentication or a database as one would have done if using Flask, writing a line or two of code. The snippet below creates with a few lines an API with GET and POST routes that create Users and Profiles. Both routes use a database, provided by DynamoDB, and the POST routes use AWS Cognito to provide authentication and sign-in/sign-out flows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">from</span> chalice <span class="hljs-keyword">import</span> Chalice, CognitoUserPoolAuthorizer


app = Chalice(app_name=<span class="hljs-string">'cdkdemo'</span>)
dynamodb = boto3.resource(<span class="hljs-string">'dynamodb'</span>)
dynamodb_table = dynamodb.Table(os.environ.get(<span class="hljs-string">'APP_TABLE_NAME'</span>))

<span class="hljs-comment"># Creates an Cognito Authorizer for the API</span>
authorizer = CognitoUserPoolAuthorizer(
    <span class="hljs-string">'cdk-test-pool'</span>,  <span class="hljs-comment"># Name of authorizer</span>
    [os.environ.get(<span class="hljs-string">'USER_POOL_ID'</span>)] <span class="hljs-comment"># Gets User Pool ARN</span>
)


<span class="hljs-meta">@app.route('/users', methods=['POST'], authorizer=authorizer)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_user</span>():</span>
    <span class="hljs-string">""" Creates or updates a user in DynamoDB Table """</span>
    <span class="hljs-comment"># Gets json payload in request body</span>
    request = app.current_request.json_body

    <span class="hljs-comment"># Creates an item</span>
    item = {
        <span class="hljs-string">'PK'</span>: <span class="hljs-string">f'User#<span class="hljs-subst">{request[<span class="hljs-string">"username"</span>]}</span>'</span>,
        <span class="hljs-string">'SK'</span>: <span class="hljs-string">f'Profile#<span class="hljs-subst">{request[<span class="hljs-string">"username"</span>]}</span>'</span>,
    }

    <span class="hljs-comment"># Item is created or updated in database</span>
    dynamodb_table.put_item(Item=item)

    <span class="hljs-comment"># Return empty dictionary</span>
    <span class="hljs-keyword">return</span> {}


<span class="hljs-meta">@app.route('/users/{username}', methods=['GET'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>(<span class="hljs-params">username</span>):</span>
    <span class="hljs-string">""" Gets a user from DynamoDB Table """</span>
    <span class="hljs-comment"># Creates a key to search for</span>
    key = {
        <span class="hljs-string">'PK'</span>: <span class="hljs-string">f'User#<span class="hljs-subst">{username}</span>'</span>,
        <span class="hljs-string">'SK'</span>: <span class="hljs-string">'Profile#{username}'</span>,
    }

    <span class="hljs-comment"># Gets key from db</span>
    item = dynamodb_table.get_item(Key=key)[<span class="hljs-string">'Item'</span>]

    <span class="hljs-keyword">return</span> item
</code></pre>
<p>AWS Chalice automatically creates everything that is needed for the application to run in the AWS cloud and can neatly integrate into AWS CDK. Sure, it is possible to achieve the same result using only Lambda functions, but it can make the writing of application code much more convenient.</p>
<h2 id="heading-code-organization">Code Organization</h2>
<p>Some of you could be wondering how to organize the infrastructure and the application code. Both should be part of the same repository and be separated into different folders, like in the example below:</p>
<pre><code class="lang-plaintext">├── infrastructure
│   ├── app.py #AWS infrastructure definitions are here
│   ├── requirements.txt #Requirements used by infrastructure definition
├── runtime
│   ├── app.py #Chalice code is here
│   ├── requirements.txt #Requirements used by Chalice app
└── requirements.txt #Contains pointers to both requirements
</code></pre>
<p>Each infrastructure and runtime should have its own tests, but they should share the same virtual environment. To install all dependencies you only use the root folder requirements.txt file, it only contains pointers to the other 2 requirements files.</p>
<h2 id="heading-summing-up">Summing up</h2>
<p>Learning and using AWS services has been a long journey for me. I had a fair share of frustration and despair when I came across unexpected errors and confusing documentation from AWS and it adds a ton of complexities over something like Heroku. Thinking back on what I have experienced so far, I could sum up a few downsides when working with AWS:</p>
<h3 id="heading-cons">Cons</h3>
<ul>
<li><p>Learning the inner workings of many AWS services and their relationships have a steep learning curve.</p>
</li>
<li><p>It has a very different logic compared to traditional, non serverless frameworks that take some time to get used to it</p>
</li>
<li><p>Vendor lock-in. Using multiple AWS services and investing time to learn them means that it will be harder to move to another cloud provider, also moving data and users that are already stored in AWS to other equivalent services could be very painful. Think about moving from Apple to Android or vice versa</p>
</li>
<li><p>The costs of serverless can be high if the services are not configured properly and end up consuming more server time than they should or if they receive very high loads</p>
</li>
<li><p>The AWS documentation, besides being bland, sometimes is outdated or is not very polished. Information about AWS Cognito, for example, is spread between different AWS websites: in documentation, CDK documentation and articles.</p>
</li>
</ul>
<p>But the advantages outweigh the disadvantages:</p>
<h3 id="heading-pros">Pros</h3>
<ul>
<li><p>Serverless is a modern way of creating infrastructure with flexibility and low costs</p>
</li>
<li><p>After overcoming the learning curve, it becomes easy to build or replicate complex infrastructure that has proven itself in production in very little time</p>
</li>
<li><p>AWS services have seamless integration, especially if using AWS CDK</p>
</li>
<li><p>Zero cost or little cost, but is able to respond to spikes in demand and manage huge loads</p>
</li>
<li><p>AWS is used by many companies, has a large community and knowledge of serverless is in high demand</p>
</li>
<li><p>AWS has plenty of free or paid learning resources like videos, tutorials and articles, created by AWS or other third parties</p>
</li>
<li><p>Instead of paying a full salary for a DevOps or database specialist, you paid a little monthly fee for AWS that can be reduced or canceled at any time, no hard feelings</p>
</li>
</ul>
<p>That's all for today! If you have some comments or questions, feel free to ask in the comments below.</p>
]]></content:encoded></item><item><title><![CDATA[Learn to write better and stress-free code by using linters]]></title><description><![CDATA[The Problem
As a developer, it's a common experience to be bogged down by syntax errors that could be very time consuming. Sometimes it's just a missing comma, a mismatched parenthesis or a simple mistype in a variable name that throws errors that ar...]]></description><link>https://edumats.dev/learn-to-write-better-code-by-using-linters</link><guid isPermaLink="true">https://edumats.dev/learn-to-write-better-code-by-using-linters</guid><category><![CDATA[Linter]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Wed, 23 Nov 2022 13:34:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668726303148/EcbPzvZbb.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-the-problem">The Problem</h2>
<p>As a developer, it's a common experience to be bogged down by syntax errors that could be very time consuming. Sometimes it's just a missing comma, a mismatched parenthesis or a simple mistype in a variable name that throws errors that are not always so obvious. Someone would say that such simple mishaps are very easy to debug, but it can be very frustrating if you are tired at the end of the day and end up being stuck for some minutes up to some days trying to catch a syntax error in a line that looks perfectly fine only to find out that the mismatched parenthesis that is causing the error is a few lines above.
Being told to be more focused or cautious when writing code does not help, as we are not always in the perfect mood or energy level when coding. It would be perfect if every developer had enjoyed 8 hours of sleep, had some physical workouts before starting to code and have a calm, happy mood, but this does not happen very often in the real world.</p>
<h2 id="heading-style-stuck">Style stuck</h2>
<p>Another point of frustration is following style guides that are certainly helpful and make your code cleaner, more readable and more professional, but are quite lengthy and they change depending on the particular language you are using, company that enforces them and even individual preferences step in.
As someone who is learning a particular style, it is helpful if someone could point to us what parts of our code need more attention. By correcting our mistakes at the same time we write code, it is possible to gradually learn the new ways on the fly instead of simply reading the style guides, which is certainly uninteresting and unproductive, as most of the effort will be dissolved by our forgetful minds in the long run.</p>
<h2 id="heading-the-solution">The Solution</h2>
<p>I find surprising that I do not hear much about linters, especially when they can save countless of hours of debugging and rewriting code. Imagine writing a pretty complicated essay without the aid of auto-correct in your text editor. Sure, if you are a professional writer or someone who majored in English, you may think these kind of helpers as a nuisance, but for the rest of us, it surely brings some benefits.
Linters are pretty much like the text editor's auto-correct, but key one difference is that they are not activated by default in the code editors and one linter only covers a particular language. You cannot use the same linter of writing Python and Javascript, for example.
Having a fast feedback that highlights problems on the fly also helps the learning process as you don't have to run the code or rely on tests to receive an error. Also, using linters is the first line of defense for avoiding bugs, a complement of running tests.</p>
<h2 id="heading-my-experience-with-linters-in-python">My experience with linters in Python</h2>
<p>There are many linters that could be used with Python, but two popular ones are flake8 and pylint. They not only pick style errors, but also <a target="_blank" href="https://en.wikipedia.org/wiki/Anti-pattern">anti-patterns</a> like:</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
  <span class="hljs-comment"># Do something that could throw an error</span>
<span class="hljs-keyword">except</span>:
  <span class="hljs-comment"># What to do if an error appears</span>
</code></pre>
<p>Which could hide errors that are very difficult to debug, as the except will catch any kind of error, not only the error that you were thinking in the first place. This could lead to a situation where your except statement hides an unexpected error and causing strange behavior that does not raise an exception, instead of simply raising the error and prompting you to fix it. The code above can be improved by specifying the error type that you intend to catch and leaving other errors to appear:</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
  <span class="hljs-comment"># Do something that could throw an ImportError</span>
<span class="hljs-keyword">except</span> ImportError:
  <span class="hljs-comment"># What to do if an ImportError is raised, other errors will still be raised</span>
</code></pre>
<p>It is like having a mentor for yourself, pointing out what could be improved in your code and training you to be a better developer!</p>
<h2 id="heading-closing-thoughts">Closing thoughts</h2>
<p>Do not despair if a linter throws a lot of problems the first time it is activated. It is not mandatory to solve every single problem, but it is worthwhile to take a look on the most urgent ones. The problems are categorized by importance, so a styling issue will not have the same weight as something that could prevent you code to run, like a module that does not exist, but it is being imported.
You could also include linters in your CI process by using them to check your code before pushing new code to a repository. This will further guarantee the you can produce reliable code consistently and effortlessly, by using automated processes.</p>
]]></content:encoded></item><item><title><![CDATA[A review of CS50P: Introduction to Programming with Python]]></title><description><![CDATA[Having completed CS50X, CS50W and CS50AI, I was extremely excited when I learned that there was a fresh new course from CS50 which covers Python in great detail. For those who are not familiar with CS50 (it stands for Computer Science 50), it is the ...]]></description><link>https://edumats.dev/a-review-of-cs50p-introduction-to-programming-with-python</link><guid isPermaLink="true">https://edumats.dev/a-review-of-cs50p-introduction-to-programming-with-python</guid><category><![CDATA[Python]]></category><category><![CDATA[python beginner]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Eduardo Matsuoka]]></dc:creator><pubDate>Thu, 09 Jun 2022 14:46:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652722760592/nPAqn8Yln.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Having completed <a target="_blank" href="https://www.edx.org/course/introduction-computer-science-harvardx-cs50x">CS50X</a>, <a target="_blank" href="https://www.edx.org/course/cs50s-web-programming-with-python-and-javascript">CS50W</a> and <a target="_blank" href="https://www.edx.org/course/cs50s-introduction-to-artificial-intelligence-with-python">CS50AI</a>, I was extremely excited when I learned that there was a <a target="_blank" href="https://www.edx.org/course/cs50s-introduction-to-programming-with-python">fresh new course from CS50</a> which covers Python in great detail. For those who are not familiar with CS50 (it stands for Computer Science 50), it is the largest on-campus course taught at Harvard University and it is also available to students that are not enrolled in Harvard via its online version.</p>
<h2 id="heading-the-difference-between-cs50x-and-cs50p">The difference between CS50X and CS50P</h2>
<p>Being an introductory course, what differentiates itself from CS50X is that it is a "introduction to programming" not a "introduction to computer science", so it does not mess with pointers, file structure, memory management, data structures which are common themes in computer science. Instead, it focuses on core functionalities of Python language, like its syntax, loops, functions, data structures, classes and also features that almost always comes with the language like Object Oriented Programming, testing and regular expressions.
It is intended for beginner programmers, those are making its first steps in Python or even those who have no prior programming experience at all. It will certainly be a challenge, but a doable one, if one takes its time.</p>
<h2 id="heading-the-lectures">The lectures</h2>
<p>In 2022, partly due to restriction imposed by COVID-19, CS50's team decided to take a different approach in regards to the launch of the program. It has turned to a online only course, releasing the lessons in live videos on social media and by doing so, allowed viewers that are not students from Harvard to watch the lectures, ask questions and reply to the lecturer. It is a very innovative approach for a program still rooted in a traditional learning environment.
This approach, although inclusive, was not free from shortcomings, as sometimes the student asking questions were inaudible or difficult to understand due to its English pronunciation. Sometimes their audio was choppy or they couldn't be heard at all. As the lectures will be edited before they are available in their final version, I believe most of these problems won't be noticed by future students of this course.</p>
<h2 id="heading-problem-sets">Problem sets</h2>
<p>After each lecture, there is a opportunity to practice what was learned by completing a problem set. In the past programs, it consisted of one or two exercises, which were lengthy, required an extensive research and some hard work to pass all the required tests. When I was taking CS50X, despite being advertised as a beginner course, it was really challenging to tackle these exercises, even with the helper lectures and the possibility to ask for directions (not copy and paste answers) in the social media forums. On the other hand, I really learned so much by researching, learning from other sources and acquiring additional skills. But in the end, my feeling is that many students were lost to frustration, because of the steep learning curve.
CS50P greatly alleviates this pain by having around five exercises in each problem set, the first requiring the basic concepts presented in the lecture in order to solve it and the others adding a bit more complexity in each step, which makes the learning curve more gentle. The subsequent problem sets uses the concepts from the previous ones, so it further helps to harden the freshly acquired concepts.
Instead of the dull "find the prime numbers of X" or "sort this array" types of problem, there are fun problems, like a program that <a target="_blank" href="https://cs50.harvard.edu/python/2022/psets/4/bitcoin/">converts Bitcoins to US Dollars</a> or <a target="_blank" href="https://cs50.harvard.edu/python/2022/psets/4/figlet/">converting regular text to ASCII art</a>. It is quite difficult to design creative and engaging problems, while also making sure that the difficulty and the required skills are adequate to beginners, so thumbs up for the team!
For the gran finale there is a final project that is about creating your own program that you can potentially share, so other programmers can solve problems or just have fun, complete with instructions, tests for ensuring reliability and with all requirements listed in a file!  </p>
<h2 id="heading-summing-up">Summing up</h2>
<p>If you are new to Python, take the course. Even if you are in an intermediate level, you may learn some new things and have a great time practicing your skills. Don't rush for the certificate, trying to complete everything at the shortest time possible, instead take your time, do your research and try to learn as much as possible from the problems and the modules that are presented during the course. I am sure that it will be the foundational knowledge for any future developer that wants to solve problems with the Python language.</p>
]]></content:encoded></item></channel></rss>