<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jessica Alves</title>
    <description>The latest articles on DEV Community by Jessica Alves (@alvesjessica).</description>
    <link>https://dev.to/alvesjessica</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F878228%2F4efb1777-bd4c-436c-bd14-c9e2e9d3c5c0.jpg</url>
      <title>DEV Community: Jessica Alves</title>
      <link>https://dev.to/alvesjessica</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alvesjessica"/>
    <language>en</language>
    <item>
      <title>Editing a message of a pushed commit</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Fri, 04 Aug 2023 20:27:33 +0000</pubDate>
      <link>https://dev.to/alvesjessica/editing-a-message-of-a-pushed-commit-3lc6</link>
      <guid>https://dev.to/alvesjessica/editing-a-message-of-a-pushed-commit-3lc6</guid>
      <description>&lt;p&gt;This is a quick post for those situations where you just pushed a commit to your branch and then realized the commit message is not clear, or there's some misspelling. Whatever is the reason you want to edit it, here are two quick steps.&lt;/p&gt;

&lt;p&gt;Make sure you're in the intended branch and first run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git commit --amend -m "Your new commit message"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git push --force&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Done.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;git log&lt;/code&gt; you'll be able to check your updated commit message.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don’t amend public commits&lt;/strong&gt;&lt;br&gt;
"Amended commits are actually entirely new commits and the previous commit will no longer be on your current branch. This has the same consequences as resetting a public snapshot. Avoid amending a commit that &lt;strong&gt;other developers&lt;/strong&gt; have based their work on. This is a confusing situation for developers to be in and it’s complicated to recover from."&lt;br&gt;
(&lt;em&gt;Atlassian's tutorial&lt;/em&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  See more
&lt;/h2&gt;

&lt;p&gt;Read the &lt;a href="https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/changing-a-commit-message"&gt;GitHub docs&lt;/a&gt; for more information or &lt;a href="https://www.atlassian.com/git/tutorials/rewriting-history"&gt;this tutorial from Atlassian&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My experience deploying a Next.js application on Netlify (using Next App Router)</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Thu, 29 Jun 2023 21:59:36 +0000</pubDate>
      <link>https://dev.to/alvesjessica/my-experience-deploying-a-nextjs-application-on-netlify-using-next-app-router-3k1b</link>
      <guid>https://dev.to/alvesjessica/my-experience-deploying-a-nextjs-application-on-netlify-using-next-app-router-3k1b</guid>
      <description>&lt;h2&gt;
  
  
  My motivation to write this article
&lt;/h2&gt;

&lt;p&gt;A few weeks ago I built a Next.js application and deployed it on Netlify.&lt;br&gt;
I enjoyed working with Next.js but a few issues came up after the deploy on Netlify - main issues that will definitely be considered for future projects - and I decided to share them with the community in case someone’s been facing similar problems. So feel free to comment and share any thoughts/suggestions that can help me to have a better understanding of these issues :)&lt;/p&gt;

&lt;p&gt;I had already created the project using the Pages Router when I decided to create a &lt;code&gt;layout&lt;/code&gt; component and other server side components, and then I realized that the new App Router would be a better approach for what I was building. The App Router (or app directory) is still in &lt;strong&gt;experimental&lt;/strong&gt; stages so clearly there’s a list of improvements to be done. But since I believe the idea is at some point having the old pages directory overridden by the app directory in a near future - so it made even more sense to me to use its latest features instead of sticking to the old pages router.&lt;/p&gt;

&lt;p&gt;So I made the migration to the App Router and deployed on Netlify. Well, a few “surprises” along the way. Here are the challenges I faced.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue #1: 500 Internal Server Error
&lt;/h2&gt;

&lt;p&gt;After migrating from Pages to App Router and deploying on Netlify that was the first issue I got. When trying to access specific URLs typing them directly instead of accessing them by navigating on the interface and clicking on the respective links, I started to get a 500 error. Or if I refreshed that page I also got the error. All the rest was working fine apparently but when trying to debug I found &lt;a href="https://answers.netlify.com/t/server-edge-not-defined-error-on-nextjs-ssr-functions-cause-site-to-return-500-errors/91793" rel="noopener noreferrer"&gt;this discussion on Netlify Support forum&lt;/a&gt; describing a possible cause for what I was getting. After implementing &lt;a href="https://answers.netlify.com/t/server-edge-not-defined-error-on-nextjs-ssr-functions-cause-site-to-return-500-errors/91793/31" rel="noopener noreferrer"&gt;the workaround suggested by the community&lt;/a&gt;, which is a prebuild script to set the env var &lt;code&gt;__NEXT_PRIVATE_PREBUNDLED_REACT&lt;/code&gt;, the 500 error was gone.&lt;/p&gt;

&lt;p&gt;It's not clear for me yet if the issue is related to Next.js, Netlify or even to React (see the discussion &lt;a href="https://github.com/vercel/next.js/issues/49169#issuecomment-1542220461" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue #2: Trailing Slash
&lt;/h2&gt;

&lt;p&gt;Next.js has a &lt;code&gt;trailingSlash&lt;/code&gt; option in &lt;code&gt;next.config.js&lt;/code&gt; which we can set to &lt;code&gt;true&lt;/code&gt; so that the URLs without trailing slashes are redirected to their counterparts with trailing slashes. And that worked for me running locally, it worked building locally, but it didn’t work properly when I deployed the application on Netlify. Even setting the &lt;code&gt;trailingSlash&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt; in Next.js and having the 'Pretty URLs' enabled on Netlify, it didn’t work for me for all pages. So I started to search about the issue and figured out that other people were having the same issue on Netlify and making a long story short: &lt;a href="https://github.com/netlify/next-runtime/issues/1329#issuecomment-1157654958" rel="noopener noreferrer"&gt;"it's a behaviour resulting from the logic on the Netlify CDN aimed at keeping site performance high by maximizing the cache hit rate".&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So &lt;a href="https://github.com/netlify/next-runtime/issues/1448" rel="noopener noreferrer"&gt;adding an edge function was the only workaround I found&lt;/a&gt;. Apparently it's an issue they're working on and I think it should be set as &lt;strong&gt;high priority&lt;/strong&gt; since trailing slashes matter for &lt;strong&gt;SEO&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;a href="https://github.com/netlify/next-runtime/issues/1448#issuecomment-2072212793" rel="noopener noreferrer"&gt;Netlify solved the issue on &lt;code&gt;v5&lt;/code&gt; release of Next.js runtime.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue #3: The 'prefetch' issue when using Next Link
&lt;/h2&gt;

&lt;p&gt;This was from far the most annoying issue I faced during this project. Not only spent hours trying to debug and figure out what exactly was going on but also couldn’t find related issues or someone describing exactly the same issue I was having. Except for &lt;a href="https://github.com/vercel/next.js/discussions/50958" rel="noopener noreferrer"&gt;this discussion here&lt;/a&gt; that helped me a lot to understand on how to reproduce the bug. So basically I was on the home page and after clicking on a link, going to another page, clicking to go back to the home page, I was being kicked to the previous page that I just clicked after scrolling the home page. And I was so sure it was related to scrolling the page that it took me a long time to figure out that what was actually triggering the kicking behaviour was hovering any Next Link (or showing a Next Link in the viewport as I saw later in the Github discussion I found).&lt;/p&gt;

&lt;p&gt;After many different tries I disabled the prefetch for all Next Links and that made the problem go away. But since I wasn't sure about the side effects of having &lt;code&gt;prefetch={false}&lt;/code&gt; for the Next Links I decided it wasn't a viable solution. So I gave up on that approach and ended up removing the &lt;code&gt;generateStaticParams&lt;/code&gt; for one of my page components. Issue was gone as well as generating static pages for that component on the server side which made me rethink about the point of using Nextjs. 😑&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue #4: Preloaded CSS files not used within a few seconds
&lt;/h2&gt;

&lt;p&gt;When importing a font from &lt;code&gt;'next/font/google'&lt;/code&gt; and using it in the &lt;code&gt;layout&lt;/code&gt; component, the console in the browser starts triggering several warnings - and I mean it: several - saying &lt;code&gt;'The resource &amp;lt;URL&amp;gt; was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate&lt;/code&gt;as&lt;code&gt;value and it is preloaded intentionally'&lt;/code&gt;. I realized removing the mentioned &lt;code&gt;import&lt;/code&gt; made the warning go away. The warning was coming not only in dev but also in prod environment. And you can also find it on &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js website&lt;/a&gt;, if you open the console you'll see the warnings coming. So I found a &lt;a href="https://github.com/vercel/next.js/discussions/49607" rel="noopener noreferrer"&gt;discussion on GitHub&lt;/a&gt; and an &lt;a href="https://github.com/vercel/next.js/issues/51524" rel="noopener noreferrer"&gt;open issue&lt;/a&gt; related to it. Apparently there's no solution for that yet but I believe they're working on it considering the open issue progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  My final impression and considerations
&lt;/h2&gt;

&lt;p&gt;After all that buggy journey I found myself at the final week of the project rethinking my decision about migrating to the Next App Router. Or using Netlify instead of Vercel. And it's been a bit frustrating to be honest because I thought creating this simple application would be a smooth journey - and perhaps it would have been if the decisions along the way had been different. Because of all that I'm not sure if I'll use Nextjs + Netlify while the App Router is still in experimental stages. Or maybe not even to consider using the two technologies together in another project again.  I had a great time learning and using Next.js but there's still a lot to be improved for the App Router and maybe it's more reliable to use it only when deploying on their ecosystem (Vercel), at least for now.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>netlify</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using `git bisect` to find the faulty commit</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Sat, 13 May 2023 21:46:21 +0000</pubDate>
      <link>https://dev.to/alvesjessica/using-git-bisect-to-find-the-faulty-commit-25gf</link>
      <guid>https://dev.to/alvesjessica/using-git-bisect-to-find-the-faulty-commit-25gf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Yesterday I was working on a task and I made changes in a few files. When committing the changes, right before pushing them to a remote branch, I added a couple of more small changes, created a few more commits and done, pushed all the commits. When running the application again I got an error, which I couldn't identify which of the changes or commits was related to.&lt;br&gt;
And that's when &lt;code&gt;git bisect&lt;/code&gt; came across while I was trying to debug.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the &lt;code&gt;git bisect&lt;/code&gt; command do?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git bisect&lt;/code&gt; is a command in &lt;a href="https://git-scm.com/docs/git-bisect"&gt;Git&lt;/a&gt; that helps find the commit that introduced a bug or caused a regression in your codebase. It uses a binary search algorithm to efficiently narrow down the range of commits to be examined. By marking specific commits as “good” or “bad”, &lt;code&gt;git bisect&lt;/code&gt; automatically selects the next commit for testing until it identifies the exact commit that introduced the issue. This process helps identify the faulty commit more quickly and efficiently, enabling developers to pinpoint and fix the problem more effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example on how to use it
&lt;/h2&gt;

&lt;p&gt;Using the &lt;a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens"&gt;GitLens extension in VSCode&lt;/a&gt; I picked one of the previous commits guessing it didn’t contain any errors (you can use &lt;code&gt;git log&lt;/code&gt; to do that as well), and to make sure it was working fine I checked out to that commit and ran the application from that point, checking if the error was there or not. Once it hasn’t any errors I decided to pick that commit to start to bisect.&lt;/p&gt;

&lt;p&gt;So I &lt;strong&gt;started&lt;/strong&gt; the &lt;code&gt;git bisect&lt;/code&gt; with the flawed commit id - which was my last commit - to indicate it’s a bad commit:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git bisect start &amp;lt;flawed_commit_id&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Git will mark it as a bad commit and then expect for the id of a good commit. So I copied and pasted the id of that commit I ran previously to make sure it wasn’t broken in order to run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git bisect good &amp;lt;good_commit_id&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Git will now automatically checkout a commit in the middle of the range between the known good commit and the bad commit. This commit represents the midpoint of the binary search. So I was able to run my application using the returned commit to test if the application was already crashed or not, so that I could tell Git to mark the commit as good or bad using &lt;code&gt;git bisect good&lt;/code&gt; or &lt;code&gt;git bisect bad&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repeat the process:&lt;/strong&gt; Git will continue selecting commits for testing based on the binary search algorithm. You repeat the previous step by testing the code and telling Git to mark it as good or bad commit until you narrow down to the exact commit that introduced the bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finish the bisect:&lt;/strong&gt; Once you identify the faulty commit, you can run &lt;code&gt;git bisect reset&lt;/code&gt; to exit the bisect mode and return to the latest commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By systematically cutting down the range of commits through binary search, &lt;code&gt;git bisect&lt;/code&gt; helps efficiently locate the faulty commit in your code history.&lt;/p&gt;

</description>
      <category>git</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Array.sort(): defining the sort order</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Sun, 26 Mar 2023 23:41:10 +0000</pubDate>
      <link>https://dev.to/alvesjessica/arraysort-defining-the-sort-order-4efg</link>
      <guid>https://dev.to/alvesjessica/arraysort-defining-the-sort-order-4efg</guid>
      <description>&lt;h2&gt;
  
  
  The sort() method in JavaScript
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.", according to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort"&gt;MDN Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Defining the sort order
&lt;/h2&gt;

&lt;p&gt;Let's say you want to sort some data, a list of users for example, based on the &lt;code&gt;status&lt;/code&gt; of each user (if they're &lt;code&gt;online&lt;/code&gt; or &lt;code&gt;offline&lt;/code&gt;), and based on the alphabetical order of the user's first name and last name, in that order respectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rafael&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Nadal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fernando&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alonso&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Daniel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ricciardo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Daniel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Brühl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To do that we can use an optional &lt;code&gt;sort()&lt;/code&gt; parameter &lt;code&gt;compareFn&lt;/code&gt; which takes a function as an argument to define the sort order. This function has two parameters (&lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;) that take the two elements of comparison as arguments. The return value &lt;code&gt;r&lt;/code&gt; depends on the comparison result between the elements, according to the following logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// r &amp;gt; 0 if a &amp;gt; b&lt;/span&gt;
&lt;span class="c1"&gt;// returns a number greater than zero if a &amp;gt; b&lt;/span&gt;

&lt;span class="c1"&gt;// r = 0 // a === b&lt;/span&gt;
&lt;span class="c1"&gt;// returns zero if a === b&lt;/span&gt;

&lt;span class="c1"&gt;// r &amp;lt; 0 // a &amp;lt; b&lt;/span&gt;
&lt;span class="c1"&gt;// returns a number less than zero if a &amp;lt; b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if we want to write a function to sort our list considering the two mentioned elements (status and alphabetical order), we could write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortUsersByStatusAndName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortUsersByStatusAndName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* expected output:
[{
  "firstName": "Daniel",
  "lastName": "Brühl",
  "status": "online"
}, {
  "firstName": "Daniel",
  "lastName": "Ricciardo",
  "status": "online"
}, {
  "firstName": "Rafael",
  "lastName": "Nadal",
  "status": "online"
}, {
  "firstName": "Fernando",
  "lastName": "Alonso",
  "status": "offline"
}] 
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we want to sort by bringing &lt;strong&gt;first&lt;/strong&gt; all the &lt;code&gt;online&lt;/code&gt; users (in &lt;strong&gt;alphabetical order&lt;/strong&gt;), and &lt;strong&gt;finally&lt;/strong&gt; the &lt;code&gt;offline&lt;/code&gt; users (in &lt;strong&gt;alphabetical order&lt;/strong&gt; as well).&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>algorithms</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Using uuid in Knex.js and PostgreSQL</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Fri, 17 Mar 2023 19:44:03 +0000</pubDate>
      <link>https://dev.to/alvesjessica/using-uuid-in-knexjs-and-postgresql-1o46</link>
      <guid>https://dev.to/alvesjessica/using-uuid-in-knexjs-and-postgresql-1o46</guid>
      <description>&lt;p&gt;I've been working on a personal project using &lt;a href="https://nodejs.org/en/about" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; and &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;. I also decided to use &lt;a href="https://knexjs.org/" rel="noopener noreferrer"&gt;Knex.js&lt;/a&gt; (a SQL query builder) to run migrations and build schemas. So when creating a table which I wanted to replace a simple incremental &lt;code&gt;id&lt;/code&gt; with &lt;code&gt;uuid&lt;/code&gt; I had to search a little bit more than just reading Knex and Postgres documentation. I found a few comments on GitHub issues and Stack OverFlow answers that were very helpful and decided to share this short post in case someone faces the same situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scrolling the documentation
&lt;/h2&gt;

&lt;p&gt;So that's the relevant piece of documentation from Knex related to using uuid when creating a schema in Knex migrations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw7w62tp5w84pjqk49av.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw7w62tp5w84pjqk49av.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although there is no example of how to use it, I also found the &lt;a href="https://www.postgresql.org/docs/current/uuid-ossp.html" rel="noopener noreferrer"&gt;documentation related to the &lt;code&gt;uuid-ossp&lt;/code&gt; extension in Postgres&lt;/a&gt;, which has a function called &lt;code&gt;uuid_generate_v4()&lt;/code&gt;. And that's the extension and function you should use to write your schema in Knex when creating a table that has an uuid column.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;So after creating a new Knex migration, let's say you want to create a new table whose &lt;code&gt;primary key&lt;/code&gt; will be a &lt;code&gt;uuid&lt;/code&gt; column.&lt;br&gt;
Here's an example of how to do it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Knex&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;knex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Knex&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CREATE EXTENSION IF NOT EXISTS "uuid-ossp"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;table_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;defaultTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uuid_generate_v4()&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;//scheme continuation...&lt;/span&gt;

    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; as stated in &lt;a href="https://knexjs.org/guide/schema-builder.html#uuid" rel="noopener noreferrer"&gt;Knex documentation&lt;/a&gt; you can set the &lt;code&gt;useBinaryUuid&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; so that &lt;code&gt;binary(16)&lt;/code&gt; is used instead of the default &lt;code&gt;char(36)&lt;/code&gt;.&lt;br&gt;
Like that:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;useBinaryUuid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;defaultTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uuid_generate_v4()&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Also note that the &lt;code&gt;notNullable()&lt;/code&gt; is not necessary in this case since we're setting the &lt;code&gt;primaryKey&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt;, which in Postgres doesn't allow nullable values.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>postgres</category>
      <category>database</category>
    </item>
    <item>
      <title>Abstraction, reusability and flexibility in software design</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Tue, 14 Mar 2023 14:51:32 +0000</pubDate>
      <link>https://dev.to/alvesjessica/abstraction-reusability-and-flexibility-in-software-design-3k7g</link>
      <guid>https://dev.to/alvesjessica/abstraction-reusability-and-flexibility-in-software-design-3k7g</guid>
      <description>&lt;p&gt;These three concepts are very important to keep in mind as well as good practices to have when it comes to software design. In programming we should be always trying to increase the level of all these design principles when writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstraction
&lt;/h2&gt;

&lt;p&gt;Abstraction is the opposite of concrete. So trying to increase the abstraction of your code means trying to keep it as generic as possible in terms of complexity and readability. Abstracting code can make it easier to read and understand, as it can help to eliminate unnecessary details and focus on the core functionality.&lt;/p&gt;

&lt;p&gt;Below is an example of a not very abstract code vs a more abstract code. Let's say you want to calculate the area of a rectangle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# not very abstract code
&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;area&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;area&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# more abstract code
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;area&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;area&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculate_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So keeping the code abstract helps to make it more modular, readable, maintainable, reusable and flexible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reusability
&lt;/h2&gt;

&lt;p&gt;Reusability refers to the ability to reuse existing code in different contexts, rather than writing new code every time a similar task needs to be performed. Reusable code saves time and effort (which in turn increases productivity in most cases), facilitates collaboration once you're not the only one that can reuse the code, and avoids code repetition.&lt;/p&gt;

&lt;p&gt;As an example we can think in a visual component such as a React component that will be used in many different pages or components. The idea is to make this component just once and reuse it wherever is needed, right? So keeping the code reusable also helps to make it more modular and maintainable since if a change is requested you can change it in just one place, in one piece that will reflect in the other pieces that are being reused.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flexibility
&lt;/h2&gt;

&lt;p&gt;The idea here is trying to go against practices that make your code highly coupled and trying to make good use of the previously mentioned practices above, because they are also responsible for increasing the code's flexibility. This one allows us to make changes to software without having to completely rewrite it from scratch, which saves time and effort especially when there are new user needs or new business requirements. It's an important aspect of programming that can help ensure that software remains adaptable, scalable, integrable, maintainable, and user-friendly over time.&lt;/p&gt;

&lt;p&gt;Good practices to increase the flexibility of your code: avoiding hard-coded code (which means using variables and constants), using functions to help modularize the code, increasing the cohesion, increasing the abstraction and the reusability as mentioned above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In software design, abstraction, reusability, and flexibility are closely related concepts that are essential for building &lt;strong&gt;high-quality&lt;/strong&gt;, &lt;strong&gt;scalable&lt;/strong&gt;, &lt;strong&gt;adaptable&lt;/strong&gt; and &lt;strong&gt;maintainable&lt;/strong&gt; software.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>design</category>
    </item>
    <item>
      <title>Cohesion in software design</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Sun, 12 Mar 2023 00:59:54 +0000</pubDate>
      <link>https://dev.to/alvesjessica/cohesion-in-software-design-559l</link>
      <guid>https://dev.to/alvesjessica/cohesion-in-software-design-559l</guid>
      <description>&lt;h2&gt;
  
  
  What is cohesion in programming?
&lt;/h2&gt;

&lt;p&gt;Cohesion in software design is a term used to describe the degree to which the elements of a module or component are related to each other and serve a common purpose. In simple words is keeping related things together and unrelated things out.&lt;/p&gt;

&lt;p&gt;Usually in programming you want to increase cohesion. And what does that mean? It means when designing a program if you organize the code in a high cohesive way it's much better to manage it, finding the source of bugs and locate what you want based on the functionalities organization you defined.&lt;/p&gt;

&lt;p&gt;For example, let's say you create two different modules or components and each of them is responsible for a different functionality in your program. So increasing the cohesion of your software would be to concentrate everything related to a specific functionality within the module or component responsible for that functionality.&lt;/p&gt;

&lt;p&gt;In small programs the cohesion might not seem so relevant but as the scale changes and the code becomes larger, so does the importance of having a cohesive code. Keeping the cohesion in your code is also an important habit even when writing small pieces of code such as naming a function or a variable that is related to what the function actually does or to what the variable actually stores.&lt;/p&gt;

&lt;p&gt;Once cohesion can exist in many different levels that can be related based on distinct criteria, following are some examples of different types of cohesion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of cohesion
&lt;/h2&gt;

&lt;p&gt;The types are ordered by strength or weakness of cohesion forms, with the strongest at the top of the list and the weakest at the bottom of the list.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Functional:&lt;/strong&gt; this one is related specifically to functions and it comes to writing functions with no side effects. An example of that is writing functions respecting the function scope and not using global keywords, such as global variables. This is the highest level of cohesion and is generally considered to be the most desirable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layer&lt;/strong&gt;: this type of cohesion refers to the situation where elements are organized into layers or tiers. It's often used in software design to organize complex systems into manageable parts, where each layer is responsible for a specific aspect of the system's functionality and it has its related services. For example, the concept of having models, views and controllers in a program can be considered layer cohesion, once we have a strong hierarchy between each layer where high level features access low level features, never the opposite - it's a one way flow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Communicational&lt;/strong&gt;: what acts on the same data should be kept together, so the elements are related by the data they share. An example of that are classes or instances of a class, and they all have methods acting on the same data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sequential:&lt;/strong&gt; this type of cohesion occurs when elements are arranged together in a specific order and depend on each other to complete a task. The output of one element is typically the input to the next element. An example of that could be processing some data before using it (such as a big text block or a spreadsheet of numbers), and let's say that requires many steps of data treatment and formatting. So the result of each step is an input for the next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Procedural&lt;/strong&gt;: this case is similar to sequential once the elements are related by the sequence in which they are executed, but they do not necessarily perform a single, well-defined computation. They're not necessarily working on the same data (as in the sequential example) yet the procedures order is still relevant and the reason why we should group them all together.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporal&lt;/strong&gt;: this is considered a weaker form of cohesion (in comparison to the previous ones) and the elements are related by the time at which they are executed. For example, &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Utility&lt;/strong&gt;: finally when you have some unrelated code and it's hard to find some relation to group them, you can try to group them by utility, which means if they don't have anything in common and they're not directly related to anything or to each other, so this is already something they have in common. So you can group them, such as helper functions you group in a &lt;code&gt;utils&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Cohesion in software design can exist on many different levels (such as modules, classes, files, functions, etc) and have different types depending on the criteria that was chosen to relate them.&lt;/p&gt;

&lt;p&gt;A high cohesion is an important aspect of creating &lt;strong&gt;maintainable&lt;/strong&gt;, &lt;strong&gt;reusable&lt;/strong&gt;, and &lt;strong&gt;understandable&lt;/strong&gt; code.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>design</category>
      <category>computerscience</category>
      <category>programming</category>
    </item>
    <item>
      <title>Divide and Conquer approach</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Sat, 11 Mar 2023 15:24:57 +0000</pubDate>
      <link>https://dev.to/alvesjessica/divide-and-conquer-approach-3k83</link>
      <guid>https://dev.to/alvesjessica/divide-and-conquer-approach-3k83</guid>
      <description>&lt;p&gt;Image from &lt;a href="https://unsplash.com/photos/B-x4VaIriRc"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking the problem into smaller pieces
&lt;/h2&gt;

&lt;p&gt;The idea behind the divide and conquer concept is breaking down a problem into smaller sub-problems, solving each sub-problem independently, and then combining the solutions to obtain the final solution to the original problem. The concept is based on the idea that if we can break down a problem into smaller pieces, it becomes easier to solve each sub-problem individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Divider and conquer algorithm
&lt;/h2&gt;

&lt;p&gt;This technique is useful and powerful for solving problems that are too large or complex to solve using traditional brute-force methods. By dividing the problem into smaller sub-problems, we can reduce the amount of computation needed to solve the problem, making it more manageable.&lt;/p&gt;

&lt;p&gt;So it's more efficient in comparison to brute-force methods and it's usually easier to understand and maintain. It can also be used to solve a wide variety of problems, from simple sorting problems to complex optimization problems. Some well-known algorithms are based on the divide and conquer approach, such as &lt;strong&gt;sorting algorithms&lt;/strong&gt; and &lt;strong&gt;binary search&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The steps in a practical example
&lt;/h2&gt;

&lt;p&gt;Let's say we want to sort an array of integers whose length can be a very large number. We can use a sorting algorithm to do that. Once this algorithm is based on the divide and conquer approach, the main steps would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Dividing the problem into smaller sub-problems: finding the base case, breaking the input into subarrays (sub-problems) instead of trying to sort a long array (original problem) at once. In other words, finding smaller instances of the same problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conquering the sub-problems: sorting the subarrays recursively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Combining the solutions to the sub-problems: merging the sorted subarrays in a sorting problem to get the final sorted array. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Divide and conquer approach is a powerful technique that can be used to solve complex problems efficiently.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>design</category>
      <category>algorithms</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>A short explanation of compilers and interpreters in Python code</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Thu, 02 Mar 2023 17:12:54 +0000</pubDate>
      <link>https://dev.to/alvesjessica/a-short-explanation-of-compilers-and-interpreters-in-python-code-2pm0</link>
      <guid>https://dev.to/alvesjessica/a-short-explanation-of-compilers-and-interpreters-in-python-code-2pm0</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Compilers and interpreters are part of the implementation of a programming language, and compilation and interpretation are two stages that make up the &lt;strong&gt;code execution process&lt;/strong&gt;. This article is about compilers and interpreters in Python context.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is a compiler?
&lt;/h1&gt;

&lt;p&gt;It's a program that takes your code (the code you, human, wrote it), a high level language, and turns it into another language, in Python's case, into bytecode (or a lower level language). Compilers are going to make sure the syntax of your code is correct, that it's formatted properly, that Python's indentation is perfect. Once all checks are done, that means the code is translated and compilers are making sure the code is ready to be run and executed by the interpreter.&lt;/p&gt;

&lt;h1&gt;
  
  
  And what is an interpreter?
&lt;/h1&gt;

&lt;p&gt;It's a program that will read the compiled code and execute it line by line. In summary, the interpreter is also converting the compiled code into a language that CPUs can understand so that your code can be executed and run by the machine. It translates code into target machine code during execution. Or in simple words, the interpreter is enabling your code to be run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compilation errors x runtime errors
&lt;/h2&gt;

&lt;p&gt;Compilation errors are errors that happen during the compilation stage, the first stage I described above. That means while the compiler was trying to "translate" your code to bytecode it found an error, e.g. syntax errors, formatting errors or indentation errors, so it crashes.&lt;/p&gt;

&lt;p&gt;The runtime errors happen during the interpretation stage, the second stage I described above. They are errors that happen during the execution process of the code, e.g. errors in the logic of a function, or logic errors in an if statement, or zero division errors, or type errors (trying to divide an integer by a string), etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The process described above is usually what happens for most modern languages, including Python. You can find some differences like in &lt;em&gt;Java&lt;/em&gt; ou &lt;em&gt;C++&lt;/em&gt;, where the compilation stages are much more complex and advanced than in Python. That's why you hear people saying that Java and C++ are &lt;em&gt;compiled languages&lt;/em&gt; and Python is an &lt;em&gt;interpreted language&lt;/em&gt;. That doesn't mean Python doesn't have a compilation step, but in Python most of the effort is being done during the interpretation stage.&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>LeetCode Daily Challenge: House Robber solution using dynamic programming</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Fri, 16 Dec 2022 13:00:25 +0000</pubDate>
      <link>https://dev.to/alvesjessica/leetcode-daily-challenge-house-robber-solution-using-dynamic-programming-2k01</link>
      <guid>https://dev.to/alvesjessica/leetcode-daily-challenge-house-robber-solution-using-dynamic-programming-2k01</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is an article to discuss a LeetCode challenge solution.&lt;br&gt;
If you want to see the full challenge description with examples click on the following link:&lt;br&gt;
&lt;a href="https://leetcode.com/problems/house-robber/description/" rel="noopener noreferrer"&gt;198. House Robber&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.&lt;br&gt;
Given an integer array &lt;code&gt;nums&lt;/code&gt; representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Using dynamic programming over recursion
&lt;/h2&gt;

&lt;p&gt;I first solved this problem using a recursive function. However when submitting the solution there was a time limit exceeded for longer inputs. So I had to optimize my solution using dynamic programming. My recursive solution looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:]),&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The solution above consists on checking and treating the base cases (when there is no houses to rob or when there's only one house in the list) and, if the list includes more than one house, we get the max amount between including the first house and not doing it.&lt;/p&gt;

&lt;p&gt;When using dynamic programming to optimize the solution above, the logic behind it consists of creating a table which we can store the max amount for each position from start to the &lt;code&gt;Nth&lt;/code&gt; position (we're gonna call this variable &lt;code&gt;moneyBag&lt;/code&gt;). So we iterate over the input list and for each iteration we calculate the max amount the robber can get from the first position until that current position. To do that we need to consider the max amount from start to two houses (positions) before the current position, and the max amount from start to the previous position. To calculate the max amount for the current position we get the max between &lt;em&gt;the max from two positions before plus the current value&lt;/em&gt; and &lt;em&gt;the max from the previous position&lt;/em&gt;.&lt;br&gt;
The max possible amount the robber can get will be last element of the &lt;code&gt;moneyBag&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;moneyBag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;moneyBag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;moneyBag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;moneyBag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;moneyBag&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to optimize even more this solution you can replace the &lt;code&gt;moneyBag&lt;/code&gt; list with two variables (here we're gonna call them &lt;code&gt;bag1&lt;/code&gt; and &lt;code&gt;bag2&lt;/code&gt;) once we're only using the two previous positions in each iteration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;bag1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;bag2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;currentBag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bag1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bag2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;bag1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bag2&lt;/span&gt;
            &lt;span class="n"&gt;bag2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;currentBag&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bag2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The runtime complexity for this last solution is O(n) and the space complexity is O(1) which makes it the optimal solution.&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>learning</category>
      <category>community</category>
    </item>
    <item>
      <title>LeetCode solution: Determine if Two Strings Are Close</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Fri, 02 Dec 2022 17:45:58 +0000</pubDate>
      <link>https://dev.to/alvesjessica/leetcode-solution-determine-if-two-strings-are-close-3kb9</link>
      <guid>https://dev.to/alvesjessica/leetcode-solution-determine-if-two-strings-are-close-3kb9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I was developing a solution for LeetCode today's challenge and decided to write this article to present a Python solution for the problem: &lt;a href="https://leetcode.com/problems/determine-if-two-strings-are-close/" rel="noopener noreferrer"&gt;1657. Determine if Two Strings Are Close&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Two strings are considered &lt;strong&gt;close&lt;/strong&gt; if you can attain one from the other using the following operations:&lt;br&gt;
Operation 1: Swap any two &lt;strong&gt;existing&lt;/strong&gt; characters.&lt;br&gt;
For example, &lt;code&gt;'abcde' -&amp;gt; 'aecdb'&lt;/code&gt;.&lt;br&gt;
Operation 2: Transform &lt;strong&gt;every&lt;/strong&gt; occurrence of one &lt;strong&gt;existing&lt;/strong&gt; character into another &lt;strong&gt;existing&lt;/strong&gt; character, and do the same with the other character.&lt;br&gt;
For example, &lt;code&gt;'aacabb' -&amp;gt; 'bbcbaa'&lt;/code&gt; (all &lt;code&gt;a's&lt;/code&gt; turn into &lt;code&gt;b's&lt;/code&gt;, and all &lt;code&gt;b's&lt;/code&gt; turn into &lt;code&gt;a's&lt;/code&gt;).&lt;br&gt;
You can use the operations on either string as many times as necessary.&lt;br&gt;
Given two strings, &lt;code&gt;word1&lt;/code&gt; and &lt;code&gt;word2&lt;/code&gt;, return &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;word1&lt;/code&gt; and &lt;code&gt;word2&lt;/code&gt; are close, and &lt;code&gt;false&lt;/code&gt; otherwise."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Check the link in the Introduction section if you want to see the complete problem statement with examples.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Note
&lt;/h2&gt;

&lt;p&gt;Reading the problem statement might lead you to think that you need to implement the two operations to solve the challenge. However there are a few checks you can do instead of starting to implement and execute the operations described in the problem statement.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to check to solve the problem
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The first check is simple and easy: you need to make sure both strings &lt;code&gt;word1&lt;/code&gt; and &lt;code&gt;word2&lt;/code&gt; have the same length as neither operation would work correctly if they had different lengths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second check is: you need to check if the occurrences of each characters frequency are the same for both strings.&lt;br&gt;
For example, &lt;code&gt;word1 = 'aabbcccc'&lt;/code&gt; and &lt;code&gt;word2 = 'aabcbcaa'&lt;/code&gt; have the same number of occurrences in their character frequencies or, in other words, the same frequency of frequencies:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# word1
&lt;/span&gt;    &lt;span class="c1"&gt;# chars frequency:
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;c&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;# frequency of frequencies:
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# word2
&lt;/span&gt;    &lt;span class="c1"&gt;# chars frequency:
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;c&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;# frequency of frequencies:
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The third and last check is that all existing characters in one string must also exist in the other string.&lt;br&gt;
For example, &lt;code&gt;word1 = 'aabbzzzz'&lt;/code&gt; and &lt;code&gt;word2 = 'aabcbcaa'&lt;/code&gt; attend the second check related to the chars frequency. However the strings are not composed of the same characters (&lt;code&gt;'z'&lt;/code&gt; doesn't exist in &lt;code&gt;word2&lt;/code&gt; just as &lt;code&gt;'c'&lt;/code&gt; doesn't exist in &lt;code&gt;word1&lt;/code&gt;) and this is something that none of the operations described in the problem statement can solve.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  My first solution
&lt;/h2&gt;

&lt;p&gt;Following is the first solution I wrote to solve the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;closeStrings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        
        &lt;span class="n"&gt;dict1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;dict2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;dict1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dict1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;dict2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dict2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cleaning up and optimizing the solution
&lt;/h2&gt;

&lt;p&gt;I did a few optimizations and also cleaned the code a little bit including the &lt;code&gt;Counter&lt;/code&gt; module in my solution and tried to replace the &lt;code&gt;sorted&lt;/code&gt; (which turns the complexity of the code into a &lt;em&gt;nlog(n)&lt;/em&gt;) with some other way to improve the runtime complexity.&lt;br&gt;
So I managed to optimize a little bit by rewriting it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;closeStrings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        
        &lt;span class="n"&gt;dict1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;dict2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; 
                &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; 
                &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to go a little further and try to turn the solution into something even shorter, you can try this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;closeStrings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;           
        &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt;
            &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt;
            &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Doing those changes improve the code runtime complexity which now is &lt;em&gt;O(n)&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To see more details about runtime and space complexity check out this same solution published on &lt;a href="https://wingkwong.github.io/leetcode-the-hard-way/solutions/1600-1699/define-if-two-strings-are-close-medium" rel="noopener noreferrer"&gt;LeetCode The Hard Way&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>A short summary of my first Hacktoberfest 🎃 🎉</title>
      <dc:creator>Jessica Alves</dc:creator>
      <pubDate>Fri, 04 Nov 2022 17:02:44 +0000</pubDate>
      <link>https://dev.to/alvesjessica/a-short-summary-of-my-first-hacktoberfest-109b</link>
      <guid>https://dev.to/alvesjessica/a-short-summary-of-my-first-hacktoberfest-109b</guid>
      <description>&lt;p&gt;&lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; ended earlier this week and it was the first time I registered for the challenge as well as the first time I made open source contributions. This post is for all open source beginners contributors :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I found projects to contribute 👾
&lt;/h2&gt;

&lt;p&gt;There's not much of a secret on how to find open source projects to contribute. Probably many of the softwares and technologies you use are open source and you can pick one of them to contribute. Specifically for Hacktoberfest challenge you can search for "hacktoberfest" or "hacktoberfest-2022" topic on &lt;a href="https://github.com/topics/hacktoberfest"&gt;GitHub Topics page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the effective ways I've also found to search for projects to contribute was the &lt;a href="https://discord.com/invite/hacktoberfest"&gt;Hacktoberfest Discord channel&lt;/a&gt;. I think this option was even better than the first one because there were so many people sharing their projects - from small projects to bigger ones - and looking for contributors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing to open source for the first time 🌱
&lt;/h2&gt;

&lt;p&gt;As I said that was my first time contributing to open source. And that can be kinda intimidating at first especially because in almost all cases you're not familiar with the project and the code. Or even when you want to contribute to a repository because you use or like the product but you never used the programming language they've chosen to write their code. Or you just find open issues that are not good first issues.&lt;br&gt;
All that can make the experience seem even more intimidating, but you can start contributing to super easy and simple tasks such as translations and documentations. And this is what I did.&lt;/p&gt;

&lt;p&gt;I found a few repos needing Portuguese translations and made my first contribution. Then I also found a cool repository whose purpose is to contain all possible solutions to LeetCode challenges so I decided to contribute writing a few solutions while learning to solve such problems.&lt;br&gt;
Then I contributed to a few more projects from creating PR template to doing more translations. Simple but still a contribution :)&lt;/p&gt;

&lt;h2&gt;
  
  
  My impressions and learnings from this experience 💭
&lt;/h2&gt;

&lt;p&gt;Overall the experience of contributing was very positive. And it made me feel motivated to do it more often and not just during October. The event organization was good, the Discord channel was very helpful as I said already. I know that the motivation of many people comes from getting the swags, t-shirts, stickers, etc. But for me it was more about doing it for the first time. In my opinion the Holopin's digital badges were a nice idea of a simple effort recognition and progress tracking. You can find more about Holopin badges in this post: &lt;a href="https://dev.to/elenalape/introducing-holopin-the-digital-badge-platform-for-developers-2hlk"&gt;Introducing Holopin - The Digital Badge Platform for Developers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aside from all the positive matters related to the experience, the only note I would make is: don't get frustrated if your PR is not approved in time to complete the challenge. I mean some of the contributions I made in addition to those required to complete the challenge were approved after the challenge ended and one of them hasn't been reviewed yet. Not all repositories have maintainers that can dedicate a lot of time reviewing all PRs and issues so be patient. Everyone is doing their best to contribute ;)&lt;/p&gt;

&lt;p&gt;The experience was really nice and for those who have never participated, or never contributed to open source I strongly recommend that you do. Looking forward to the next one!&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>github</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
