<?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: João H. Capucho</title>
    <description>The latest articles on DEV Community by João H. Capucho (@hcapucho).</description>
    <link>https://dev.to/hcapucho</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%2F292515%2F5d99ebb3-0547-4474-9b1b-0a3dd6720f42.jpg</url>
      <title>DEV Community: João H. Capucho</title>
      <link>https://dev.to/hcapucho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hcapucho"/>
    <language>en</language>
    <item>
      <title>Thoughts on API Design</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Mon, 30 Jan 2023 18:56:46 +0000</pubDate>
      <link>https://dev.to/hcapucho/thoughts-on-api-design-3ag6</link>
      <guid>https://dev.to/hcapucho/thoughts-on-api-design-3ag6</guid>
      <description>&lt;p&gt;I really enjoy talking about REST API. Yes, for some people, REST is the past-generation stuff, and GraphQL is the cool kid in the block. Even though over the past months I've used GraphQL every day, REST still has my heart, and I have to be careful to avoid my bias toward it.&lt;/p&gt;

&lt;p&gt;If you had to use SOAP as a communication protocol, REST was most likely your savior from the deep trenches of old-school distributed systems. Sadly, even though I'm not that old in the area,  I've worked for an old bank, which exposed me to all kinds of ancient things you can imagine (yes, even COBOL).&lt;/p&gt;

&lt;p&gt;This article is not a extensive guide on best practices, is just some quick thoughts that might benefit beginners in the REST journey. If you're an experience developer, this will most likely be boring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goals
&lt;/h2&gt;

&lt;p&gt;One of the most important subjects to understand how to make your API comprehensive to your users/consumers is to have clear goals. In his book &lt;a href="https://apihandyman.io/about/" rel="noopener noreferrer"&gt;"The Design of Web API's"&lt;/a&gt; Arnaud Lauret defines five questions that one needs to answer to start reasoning on how to deliver a proper API.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who can use the API? 

&lt;ul&gt;
&lt;li&gt;Here's where you list the profiles of people who are going to use your API;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;What can they do?&lt;/li&gt;

&lt;li&gt;How do they do it?

&lt;ul&gt;
&lt;li&gt;Where you will decompose the previous question into steps&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;What do they need to do it?

&lt;ul&gt;
&lt;li&gt;What is needed in each step, and where does the input comes from&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;What they get in return

&lt;ul&gt;
&lt;li&gt;Which is where you state everything that is returned by each step and how it will be used;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Goals

&lt;ul&gt;
&lt;li&gt;Where you will combine the hows, inputs, and outputs into a concise objective&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Answering these questions will enable you to clarify what are the things your API must deliver. You can define a table where you fill those things, and you can run through a product manager and other colleagues to get feedback on any spots that you might be missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error handling
&lt;/h2&gt;

&lt;p&gt;Identify the possible errors of your API. Document all the cases, and error codes that you might return. A really nice to have is exhaustive errors. It's really annoying when you send a request, then the consumer receives an error. When the error is fixed and you re-submit the request, you get a new error. You can easily a &lt;code&gt;errors&lt;/code&gt; array and add all the issues into a single response, so the consumer can clearly see all the issues within the request. This is especially needed for API's that are used in forms.&lt;/p&gt;

&lt;p&gt;A good pattern I've found is to return something along these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;error_code:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;SOME_ERROR_CODE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;error_message:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Something&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;wrong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;right'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;validations:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;property:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'entity.created_at'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;code:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'INVALID_DATE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;message:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'whatever&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;message'&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Be predictable
&lt;/h2&gt;

&lt;p&gt;Lauret has a definition of consistent API's that I quite liked it. He splits into 4 levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistency within an API&lt;/li&gt;
&lt;li&gt;Consistency across an organization/company/team&lt;/li&gt;
&lt;li&gt;Consistency with the domain of an API.
How you represent the entities should be matching the domain experts' expectations&lt;/li&gt;
&lt;li&gt;Consistency with the rest of the world.
Meeting standards, like ISO's, RFC's, and protocols.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, be consistent wherever you can. Entity names, API responses (including error ones), path, headers, etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before I forget, it would be lovely if folks stopped using &lt;code&gt;X-&lt;/code&gt; for custom headers. There's an &lt;a href="https://www.rfc-editor.org/rfc/rfc6648" rel="noopener noreferrer"&gt;RFC&lt;/a&gt; deprecating this for around ten years now. I don't blame you, no one talks about this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Adaptability
&lt;/h2&gt;

&lt;p&gt;I loved when I worked in an API where we enabled our customers to get our reports in whichever format they wanted. JSON? You have it. PDF? Right now. CSV? Go crazy, just send me the header.&lt;/p&gt;

&lt;p&gt;Here you can also include localization, internationalization, etc. I mean, your users might still use a really old imperial system that doesn't make any sense at all. If you send them a response in meters they will be completely lost, so you could enable them to have the answer in yards.&lt;/p&gt;

&lt;p&gt;Your REST API can also enable lazy load to improve performance for your customers, they can easily expand the data sets they're interested at from a given entity. This is one of the main selling points for GraphQL from many folks, but can also be done in REST API's. &lt;a href="https://stripe.com/docs/api/expanding_objects" rel="noopener noreferrer"&gt;Stripe API&lt;/a&gt; for reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pagination
&lt;/h2&gt;

&lt;p&gt;Please, pretty please, don't return something that only gives the consumer the &lt;code&gt;next_page_token&lt;/code&gt;. This doesn't enable the consumer to go back and forth on the data.&lt;/p&gt;

&lt;p&gt;You can have a quite simple response and still be useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"pagination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"current_offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you know that the next page has the offset parameter as &lt;code&gt;current_offset + count&lt;/code&gt;. A good thing is to have a parameter to limit the number of elements returned as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;One of the main things, and often overlooked, is to have clear documentation. For me, one good example is the &lt;a href="https://stripe.com/docs/api" rel="noopener noreferrer"&gt;Stripe API&lt;/a&gt;. They provide not only clear documentation but easy-to-follow examples, with commands that you can copy and paste to try it out. From my humble perspective, this should start to be in place from the moment you start designing your API. Otherwise, details will often be overlooked later on.&lt;/p&gt;

&lt;p&gt;One other relevant portion of your documentation is that you should avoid the trap of only having it in an "engineer-oriented" format. It's always beneficial to have it in a human-friendly format (your JSON Schema is not so human-friendly).&lt;/p&gt;

&lt;h2&gt;
  
  
  Versioning
&lt;/h2&gt;

&lt;p&gt;When applying semantic versioning to your APIs, all that matters are two digits: &lt;code&gt;BREAKING_CHANGE.NON_BREAKING_CHANGE&lt;/code&gt;. However, your customers don't really care about the non breaking changes. So you can use the versioning only on the first value.&lt;/p&gt;

&lt;p&gt;There are many ways you can version your API. Path, domain, query parameters, custom headers, content negotiation. Pick your flavor. I honestly tend to prefer the version to be in the path, such as &lt;code&gt;/v1/users&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request tracing
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;correlation_id&lt;/code&gt;'s across your requests to enable yourself to trace the request flow across multiple services. If you're not familiar with the concept, you can read it in &lt;a href="https://microsoft.github.io/code-with-engineering-playbook/observability/correlation-id/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You will be thankful when debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idempotency Key
&lt;/h2&gt;

&lt;p&gt;Your customers could have retry operations when things fail, automatic reprocessing of messages. This could end up creating problems if there's no way to check if a operation has already been done. Idempotence is the property where an operation can be done multiple times without affecting the end result beyond the first application. Enabling your customers to take control over their idempotent requests is super useful. &lt;a href="https://stripe.com/docs/api/idempotent_requests" rel="noopener noreferrer"&gt;Stripe API&lt;/a&gt; has a good example on it if you want to dig further&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>crypto</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>5 books I'm happy that I've read in 2022</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Sun, 15 Jan 2023 10:32:36 +0000</pubDate>
      <link>https://dev.to/hcapucho/5-books-im-happy-that-ive-read-in-2022-4fao</link>
      <guid>https://dev.to/hcapucho/5-books-im-happy-that-ive-read-in-2022-4fao</guid>
      <description>&lt;p&gt;After a year goes by, it's always nice to take some to reflect on what we've done, and what we would like to do it differently for the next year.&lt;/p&gt;

&lt;p&gt;After a long time in my life focusing on reading mostly technical books, in 2021 and 2022 I've tried to read more on other topics. Specially around emotional health, career and productivity. I will state here in a few sentences what I've read that impacted me the most, the books I'm usually recommending to my friends.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Passionate Programmer - Chad Fowler
&lt;/h3&gt;

&lt;p&gt;This is my second read of this book. I've got this as a gift from a mentor back in 2015. I find it one of the best books regarding our career as software engineers. Specially for those ones that enjoy playing some instrument, the author who has been a jazz player, makes lots of connections on our software engineer lives and a musicians life. It's broken down in quite small chapters with easy to grasp action points we can start taking on our daily work lives to improve our deliveries, but also the value we aggregate in our careers. It's definitely one of my favorite books in IT.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laziness does not exist - Devon Price
&lt;/h3&gt;

&lt;p&gt;A must read for all of us who have been dedicating most of our lives to our jobs. Many are the reasons one can put their work life above everything else and sometimes we start becoming our careers. I took a serious step back past year, where I didn't want to be "João, software engineer" anymore. This shouldn't be the first thing people relate to me when they think about me. That's not how I want to live my life. This book gave me a better emotional foundation to create distance between my personal life and work life. It's helping me to pursue my hobbies, freeing myself from the constant and obsessive behavior that I should always be productive, that everything I do should be towards growing in my career.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atomic Habits - James Clear
&lt;/h3&gt;

&lt;p&gt;This book is most likely to cause the "urgh" reaction for most people that think that self-help books should be locked away. For me, it was a great complement on "The Power of Habit". It gives you more practical advice on how to keep a routine, how to introduce new habits in your daily life, and overall, made it easier for me to stick my routine. &lt;/p&gt;

&lt;p&gt;We all have routines, even if it's jumping on to the sofa after a full day of work. The main difference is on whether is the routine you want or not. Here I'm not going to preach on whether it's good for you or not. The only thing I care is if it's what you want. If you wanted to have a different routine in your life, this book might help you. &lt;/p&gt;

&lt;p&gt;One of the great things I've learnt here is habit tracking. It's quite nice to see how you're being able to stick to the new habits you want to introduce, until they're fully integrated in your life. &lt;/p&gt;

&lt;h3&gt;
  
  
  The sexual politics of meat - Carol Adams
&lt;/h3&gt;

&lt;p&gt;As a vegan person, looking vegetarianism and veganism through the lens of feminism was eye opening. This was the first classic vegetarianism book I've read in my life (after being a vegetarian for 3 years and vegan for 1). &lt;/p&gt;

&lt;p&gt;It's quite a journey through history, patriarchy and movements from distinct people, embracing a cruelty-free life. It's disturbing to see how women and animals are constantly reduced to body parts for consumption. The way we change our vocabulary to transform those into &lt;a href="https://caroljadams.com/the-absent-referent" rel="noopener noreferrer"&gt;absent referents&lt;/a&gt; "to keep the our 'meat' separated from any idea that she or he was once an animal...". Reading this solidified even more that this is not a life I want for myself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Focus - Daniel Goleman
&lt;/h3&gt;

&lt;p&gt;I really enjoyed reading Daniel Goleman's "Emotional Intelligence" book. It was what triggered my desire to have a deeper understanding on the subject and also pushed me towards seeing a therapist to heal myself. So, this book, was just a curiosity about what else the author could teach me. &lt;br&gt;
I honestly feel in love with the book because it confirmed me something I've lived practically. A meditative practice is substantial to being able to have the ability to focus. I've used the Headspace app since the beginning of the pandemic to help me cope with the period, and I've saw many advantages of that in my life. For this specific subject and reference, I wrote an &lt;a href="https://dev.to/hcapucho/the-zen-of-focus-5413"&gt;article called "The zen of focus"&lt;/a&gt; where I describe the journey with lots of references from this book. I highly recommend reading it if you want to understand the journey I had and how it helped me throughout the Covid-19 pandemic and still helps me to this day.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>contentwriting</category>
    </item>
    <item>
      <title>PostgreSQL - Partitioning &amp; Inheritance</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Sun, 30 Oct 2022 12:03:23 +0000</pubDate>
      <link>https://dev.to/hcapucho/postgresql-partitioning-inheritance-54np</link>
      <guid>https://dev.to/hcapucho/postgresql-partitioning-inheritance-54np</guid>
      <description>&lt;ul&gt;
&lt;li&gt;This article briefly exposes the basic concepts of how table partitioning and inheritance works in PostgreSQL. &lt;/li&gt;
&lt;li&gt;Some prior knowledge on basic queries and DDLs is necessary. &lt;/li&gt;
&lt;li&gt;There will be no deep dive in how the feature works under the hood, neither how to migrate your existing data to this solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Since university, PostgreSQL has had a special place in my heart. I was heavily influenced back then by this incredible a professor I had. Until this day in my career, I've never seen someone with SQL capabilities like hers.&lt;/p&gt;

&lt;p&gt;I can still recall this day, where after all her lectures about referential constraints and all sorts of integrity one can think about, she raises the question about what DB we used &amp;amp; liked the most. As we were a bunch of naïve young folks, breathing the LAMP (Linux, Apache, MySQL, PHP) era, the most common answer was MySQL. &lt;/p&gt;

&lt;p&gt;Then she explained all the issues MySQL had on enforcing some constraints (&lt;em&gt;I won't remember which ones since I never actually used MySQL professionally&lt;/em&gt;). Then, she took us to the lab and had made us test those constraints in both DBs. On that day, I feel in love with PostgreSQL.&lt;/p&gt;

&lt;p&gt;However, it's a love that I neglected for a long period of time. But over the last months, I've had lots of fun playing with it again. That's why I decided to write a little about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Partitioning your data
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://link.springer.com/referenceworkentry/10.1007/978-0-387-39940-9_688" rel="noopener noreferrer"&gt;Daniel Abadi&lt;/a&gt;, "Data Partitioning is the technique of distributing data across multiple tables, disks, or sites in order to improve query processing performance or increase database manageability".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to dive deeper into how to handle data-intensive architectures and the problems around them, I would highly recommend reading Martin's Kleppman "Design Data-Intensive Applications". It's definitely my reference book for system design nowadays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let's dig into how we can achieve partitioning at a table level using inheritance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using inheritance
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Wait, ain't inheritance an Oriented Object programming thing like those Java &lt;code&gt;public class Dog extends Animal&lt;/code&gt; type of stuff? Well, our folks working on PostgreSQL found a neat way to partition our data based on inheritance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's start with the following table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;year&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this table would grow too much (here we're not talking about indexes), and we want to optimize the search. A simple way is to partition the data into different tables. But then you would need to know which table to query from, right? Well, not exactly.&lt;/p&gt;

&lt;p&gt;If we use inheritance, we can sort of avoid that trap. Let's create a few tables that will inherit from &lt;code&gt;t_archive&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive_2021&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;INHERITS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_archive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive_2020&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;INHERITS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_archive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive_2019&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;INHERITS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_archive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all the tables have the same structure as follows:&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%2Fxrvpth93t2w8eek1oaxk.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%2Fxrvpth93t2w8eek1oaxk.png" alt="ERD Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/ck5JRWob7folZ7d97I/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/ck5JRWob7folZ7d97I/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you query the parent table, all child tables will also be scanned.&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%2Fql3iafnmi57zf8v9hpnp.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%2Fql3iafnmi57zf8v9hpnp.png" alt="Query Parent"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's try now with a filter based on the field we want?&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%2Fpp1dfqrtxhq44o33m6i8.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%2Fpp1dfqrtxhq44o33m6i8.png" alt="Query Parent with filter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, it wasn't as I expected. I would like to have a single table being looked at. We don't care about data in other years beside &lt;code&gt;2021&lt;/code&gt;, right? What we want here is to scan a single table. How to achieve that?&lt;/p&gt;

&lt;p&gt;In order to do so, we need to explicitly define checks on the table, so PostgreSQL can base itself on them when creating the query plan. Let's add a few checks to our tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive_2021&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2021&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive_2020&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive_2019&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we run the query, the data lookup will only check for the correct table.&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%2F08lds5m0sg5bh98m3wqt.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%2F08lds5m0sg5bh98m3wqt.png" alt="Query with checks"&gt;&lt;/a&gt;&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%2Fkq0zewraowg6mk7qy2js.gif" 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%2Fkq0zewraowg6mk7qy2js.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Changing parent table
&lt;/h3&gt;

&lt;p&gt;When altering the parent table, for instance, adding a column, all the changes will reflect in its child tables. By running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;t_archive&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result looks like this:&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%2Frisx7z1cfwvt6q26yalc.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%2Frisx7z1cfwvt6q26yalc.png" alt="ERD Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Hopefully with this brief exposure to the concept, you will be able to at least remember about it when the partition topic comes up at a design you're doing. Not that you would use it, but at least you would one more tool in your database Swiss army knife in case you need it.&lt;/p&gt;

&lt;p&gt;See you later :)&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>inheritance</category>
      <category>partition</category>
    </item>
    <item>
      <title>A Philosophy of Software Design - Review</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Wed, 31 Aug 2022 17:22:02 +0000</pubDate>
      <link>https://dev.to/hcapucho/a-philosophy-of-software-design-review-3aa2</link>
      <guid>https://dev.to/hcapucho/a-philosophy-of-software-design-review-3aa2</guid>
      <description>&lt;p&gt;by John Ousterhout&lt;/p&gt;

&lt;p&gt;tl;dr;&lt;/p&gt;

&lt;p&gt;Even for the more seasoned engineer, this book is a good reminder of design practices that needs some refreshing every once in a while. At a low cost (&amp;lt; $20 for a technical book), and easy to read, will provide you a pleasant read for 1-2 weeks. &lt;/p&gt;

&lt;p&gt;For the ones beginning their careers, is a good introduction to Software Design principles that won't require deep computer science knowledge, with guidelines that will improve your output.&lt;/p&gt;

&lt;p&gt;Overall: 7.5/10. &lt;br&gt;
If you wanna buy the book, click &lt;a href="https://amzn.to/3wDDbZ7"&gt;here :)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The book already starts defining what it wants to tackle: software complexity. The author defines complexity as "anything related to the structure of a software system that makes it hard to understand and modify the system.". From this point on, the author will go through the "complexity symptoms" and what practices software designers can apply to minimize the problem. &lt;/p&gt;

&lt;p&gt;One of the first things I've appreciated is that the author won't take the position from the software writer; instead, it will look through the software reader's eyes. These two are different personas, separated by time, context, and knowledge. The latter requires context that is potentially implicit in the written code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I've liked
&lt;/h2&gt;

&lt;p&gt;After setting the tone, the author will start describing his design philosophy based on his experience teaching at Stanford. These design principles are good practices, sometimes already detailed by other authors, but written in an easy-to-digest manner, even if you're a beginner in software development. &lt;br&gt;
In addition to his principles, the author will describe "red flags" that you can use to identify potential problems in your approach. John was also careful enough to create a summary at the end of the book with the red flags and which pages you can find more about them. He did the same for the Design Principles he distills in the book.&lt;/p&gt;

&lt;p&gt;Within his design philosophy, the author will also challenge the status quo defined by classic authors, especially R. Martin. This book will discuss a few things from Martin's "Clean Code" - how to write functions, modules, comments, etc. -. When I compare both, John's seems closer to our reality and more pragmatic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/mCOtW8spW64ocPdZcQ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/mCOtW8spW64ocPdZcQ/giphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I didn't like as much
&lt;/h2&gt;

&lt;p&gt;And what about what I didn't like as much? One thing that I'm not so sure whether I liked or not is that the author comes back to the same example too many times. Why don't I know if I liked it or not? When I saw it was the same example again, I would get annoyed. However, I will most likely remember the piece of code for the rest of my life. &lt;br&gt;
&lt;a href="https://i.giphy.com/media/cfMWrIWBKtYAX3LRze/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/cfMWrIWBKtYAX3LRze/giphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another thing that stuck with me was: that the author states that you shouldn't expose your internal data structures to the API consumers. I don't think we would disagree with that. However, later on, he mentions that you should not use implementations that are a mismatch from your variable interfaces. I found this piece a bit conflicting with the first statement. I can agree that you can do that for internal variables in your module. Yet, for exposed variables, I'm not so sure about it. This is what enables me to be free to do internal changes in my module without introducing breaking changes to my customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple takeaways
&lt;/h2&gt;

&lt;p&gt;The author goes through many things that I find valuable for any developer. Of course, they might impact you in different ways depending on at which point you're in your career. Among those, I will list a few (summarized, of course) that I find valuable to be reminded of even if you already know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complexity will always be present. It's a constant exercise to simplify code throughout a software lifecycle.&lt;/li&gt;
&lt;li&gt;Write deep modules with simple APIs, and design them as much as possible for common cases. Omit unimportant details.&lt;/li&gt;
&lt;li&gt;Do not fall under the temporal decomposition trap. Your code needs to reflect the knowledge required to perform tasks, not the execution order.&lt;/li&gt;
&lt;li&gt;Define errors out of existence, and make interfaces simple. &lt;/li&gt;
&lt;li&gt;Centralize error handling for simplicity.&lt;/li&gt;
&lt;li&gt;If pieces of code are related, think about whether you should bring them together&lt;/li&gt;
&lt;li&gt;Consistency is key for good readability. Don't start changing existing conventions without taking the effort to understand why they exist, and what value your new convention brings. Also, don't introduce yet another convention if you won't be able to remove the old one entirely.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In summary, this book is worth the time. Easy to understand, objective, and with small chapters that make it easy to assimilate things. For the more experienced engineer, many things could be a repetition of what you saw in other classics and already put into practice in your daily work. For you, the first chapters is where you will find the most valuable discussions.&lt;br&gt;
However, there are still valuable things that you most likely can take from it. For the ones who joined this journey more recently, I would definitely recommend it. Most likely it will improve your deliverables if you pay attention to the recommendations on your daily job.&lt;/p&gt;

&lt;p&gt;If you wanna buy the book, click &lt;a href="https://amzn.to/3wDDbZ7"&gt;here :)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>books</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Redis for beginners, part 1</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Sun, 31 Jul 2022 19:30:00 +0000</pubDate>
      <link>https://dev.to/hcapucho/redis-for-beginners-1n42</link>
      <guid>https://dev.to/hcapucho/redis-for-beginners-1n42</guid>
      <description>&lt;p&gt;There's no discussion that Redis is one of the most consolidated caching tools today. Whenever someone wants to introduce a cache layer in their systems, Redis will be one of the names on the table. &lt;/p&gt;

&lt;p&gt;For a while, I only associated Redis with caching solutions. However, I was missing a lot that I could get from this tool. About three and a half years ago was the first time I saw a solution that used Redis as a queue mechanism. As someone that had recently come from Java, I was having a hard time finding a solution where I could schedule jobs in Node.js. Talking about that with a few other teams with more experience in Node.js, I've come across "BullJS", a Redis-based queue for Node. This library introduced me to a few solutions based on Redis capabilities, like rate limiting, job priority, job delay &amp;amp; scheduler, among a few other things.&lt;/p&gt;

&lt;p&gt;By seeing the capabilities offered by this library, I started to wonder what other things I could get from Redis. I will likely write two (or three) articles on this to save you the trouble of reading them all at once. First, let's start with some concepts on Redis and a few relevant data structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redis
&lt;/h2&gt;

&lt;p&gt;Do you need a caching tool? Redis. Do you need a message broker? Redis. Do you need a database? Redis. Do you need a stream engine? Still, Redis. &lt;br&gt;
I'm not saying Redis is the perfect tool for all of the above, but depending on your use case, it might be the right fit. It includes transactions, pub/sub, failover mechanisms, and more.&lt;/p&gt;

&lt;p&gt;Redis Serialization Protocol (&lt;a href="https://redis.io/docs/reference/protocol-spec/"&gt;RESP&lt;/a&gt;) is what powers Redis behind the scenes. According to the docs, a simple to implement, fast to parse, and human-readable protocol, usually running over TCP (but not tied to it). It's aimed to be a request/response model. However, it contains two main exceptions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It allows clients to batch multiple commands. Which Redis refers to as Pipelining. &lt;/li&gt;
&lt;li&gt;When using a pub/sub subscription, the protocol will change its semantics to behave as a push protocol. Meaning that the server will push messages to the client as they arrive. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One curiosity on the protocol is that Redis keys are binary-safe. This means you can use strings, numbers, and binary values. Just keep in mind that they're also case-sensitive. One thing that struck me is that keys are allowed to be up to 512MB. I honestly have a hard time finding use cases for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Commands &amp;amp; Data Structures
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Deleting data
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/scan/"&gt;SCAN&lt;/a&gt;&lt;br&gt;
Iterates over a collection of elements. You must be careful with this command since it can return too many elements in production and degrade your performance. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use with caution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/keys/"&gt;KEYS&lt;/a&gt;&lt;br&gt;
Returns all keys matching a giving pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/exists/"&gt;EXISTS&lt;/a&gt;&lt;br&gt;
Returns a given key exists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/object-encoding/"&gt;OBJECT ENCODING&lt;/a&gt;&lt;br&gt;
Returns the internal encoding for the Redis object in a given key. This is used a lot internally to check if an operation is valid. For instance, Redis checking if the value is a number before doing a INCRBY or DECRBY operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/rename/"&gt;RENAME&lt;/a&gt;&lt;br&gt;
Rename a key. An error is returned if key doesn't exist.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/unlink/"&gt;UNLINK&lt;/a&gt;&lt;br&gt;
It follows the same idea as a delete command, however, it's a non-blocking operation, unlinking the key &amp;amp; freeing the memory associated with it in a separated thread. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/del/"&gt;DEL&lt;/a&gt;&lt;br&gt;
Removes key in a blocking operation&lt;/p&gt;

&lt;h3&gt;
  
  
  Expiring data / Time to Live (TTL)
&lt;/h3&gt;

&lt;p&gt;When setting expiration periods in your keys, you can mainly use three functions: &lt;a href="https://redis.io/commands/pexpire/"&gt;PEXPIRE&lt;/a&gt;, &lt;a href="https://redis.io/commands/expire/"&gt;EXPIRE&lt;/a&gt;, &lt;a href="https://redis.io/commands/expireat/"&gt;EXPIREAT&lt;/a&gt;. They will set the time to live in milliseconds, seconds, and Unix timestamps, respectively.&lt;/p&gt;

&lt;p&gt;If you're curious about the TTL for your key, you can check that using the TTL or PTTL commands. &lt;/p&gt;

&lt;p&gt;And if at some point you decided that the key/value pair you have are really important, you can make them persistent using the PERSIST command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hashes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/hget/"&gt;Command list&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mostly used to store objects, typically used for rate limiting and session stores. Data manipulation commands are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HGET - retrieves the hash field value. If the value is also passed, it returns a boolean informing whether the value is present or not&lt;/li&gt;
&lt;li&gt;HEXISTS - checks if a field exists in the hash&lt;/li&gt;
&lt;li&gt;HINCRBY - increments key value;&lt;/li&gt;
&lt;li&gt;HINCRBYFLOAT - increments field float value&lt;/li&gt;
&lt;li&gt;HSET - set key value&lt;/li&gt;
&lt;li&gt;HSETNX - only set field value if the key doesn't exist, if the key already exists, this command has no effect;&lt;/li&gt;
&lt;li&gt;HKEYS - return all keys in the hash;&lt;/li&gt;
&lt;li&gt;HVALS - return all values in the hash;&lt;/li&gt;
&lt;li&gt;HDEL - delete a field stored at a key;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lists
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/llen/"&gt;Command list&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An ordered collection of strings that enables you to add elements to the left &amp;amp; right, it can be used for stacks and queues. In lists, there's no nesting.&lt;br&gt;
Good use cases are activity streams and queues (producers, consumers).&lt;/p&gt;

&lt;p&gt;Data manipulation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLEN - list length&lt;/li&gt;
&lt;li&gt;LPUSH - add an element to the left&lt;/li&gt;
&lt;li&gt;RPUSH - add an element to the right&lt;/li&gt;
&lt;li&gt;LPOP - remove an element from the left&lt;/li&gt;
&lt;li&gt;RPOP - remove an element from the right&lt;/li&gt;
&lt;li&gt;LRANGE - retrieves elements from a list. It's used as (key, start, stop), where the key is the list, and start and stop are the indexes. In case you want to retrieve all elements, one can use a -1 as the stop index.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to use the list as a stack, you can limit yourself to using the LPUSH and LPOP commands. If you want to use it as a queue, you can use RPUSH and LPOP commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sets
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/sadd/"&gt;Command list&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sets are an unordered collection of strings, in which you can do difference, intersection, and union operations. The data cannot be nested. &lt;br&gt;
This is interesting for use cases like tag clouds, and unique visitors.&lt;/p&gt;

&lt;p&gt;Data manipulation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SADD - add an element to set&lt;/li&gt;
&lt;li&gt;SMEMBERS - returns all the members of a given set&lt;/li&gt;
&lt;li&gt;SISMEMBER - returns whether the element is present in the set&lt;/li&gt;
&lt;li&gt;SREM - removes an element from a given set&lt;/li&gt;
&lt;li&gt;SPOP - removes a random element from the given set&lt;/li&gt;
&lt;li&gt;SDIFF - returns the difference between two sets&lt;/li&gt;
&lt;li&gt;SDIFFSTORE - stores the diff between two sets into a new set&lt;/li&gt;
&lt;li&gt;SINTER - returns the intersection between two sets&lt;/li&gt;
&lt;li&gt;SINTERSTORE - stores the intersection between two sets into a new set&lt;/li&gt;
&lt;li&gt;SUNION - returns the union between two sets&lt;/li&gt;
&lt;li&gt;SUNIONSTORE - stores the union between two sets into a new set&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sorted sets
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://redis.io/commands/zrange/"&gt;Command list&lt;/a&gt;&lt;br&gt;
 Sorted sets contain a field called score, which will be used to sort your data. The elements in your sorted set cannot repeat, the score is not considered for the uniqueness of an element.&lt;/p&gt;

&lt;p&gt;For instance, let's say you want your elements sorted by time so you can have a time-series, you can ensure that by having the minute the element was added as the score, and this will enforce that your elements are always sorted by time. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your elements will always be sorted, with efficient inserts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Data manipulation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ZRANGE - returns the elements from start to stop, enabling you to ask in reverse order, also returning the scores.&lt;/li&gt;
&lt;li&gt;ZRANK - returns the rank of an element in the sorted set&lt;/li&gt;
&lt;li&gt;ZADD - adds the elements with the score to the sorted set&lt;/li&gt;
&lt;li&gt;ZCOUNT - how many elements the set has with scores between min and max parameters&lt;/li&gt;
&lt;li&gt;You will have lots of commands that look like the set commands, and a few extra ones due to the nature of the sorted sets. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Post image from: By Carlos Prioglio created the logo for the copyright owner Salvatore Sanfilippo, lead developer of Redis. - &lt;a href="http://redis.io/images/redis-logo.svg"&gt;http://redis.io/images/redis-logo.svg&lt;/a&gt;, Fair use, &lt;a href="https://en.wikipedia.org/w/index.php?curid=40127986"&gt;https://en.wikipedia.org/w/index.php?curid=40127986&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://redis.io/docs/"&gt;Redis docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Notes taken a long time ago from &lt;a href="https://university.redis.com/courses/ru102js/"&gt;Redis for Javascript Developers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Notes taken a long time ago from &lt;a href="https://university.redis.com/courses/ru101/"&gt;Introduction to Redis Data Structures&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>redis</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The zen of focus</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Thu, 30 Jun 2022 19:35:38 +0000</pubDate>
      <link>https://dev.to/hcapucho/the-zen-of-focus-5413</link>
      <guid>https://dev.to/hcapucho/the-zen-of-focus-5413</guid>
      <description>&lt;p&gt;After a long time without writing, I wrote an article in Portuguese regarding what changes I introduced in my life and the many attempts to improve it. In a quick summary of the article, I spoke about changes I've made in my routine, like waking up earlier, having a proper sleep routine, and whatnot. This article is somewhat a continuation of that, where I will talk about something I've spent quite some time and enjoyed a lot: &lt;em&gt;meditation&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The start of the journey
&lt;/h2&gt;

&lt;p&gt;Two years ago, I started my first attempts with it, using an app called &lt;em&gt;Headspace&lt;/em&gt;, I've tried for a few months, and the experience was great.&lt;/p&gt;

&lt;p&gt;I struggled in the beginning. I couldn't find a comfortable position to sit down without feeling pain in my back. Ten minutes felt like an eternity to me. &lt;/p&gt;

&lt;p&gt;I've always been a bit too anxious, and sitting down for ten minutes without doing anything? &lt;em&gt;Impossible&lt;/em&gt;, I said to myself. But would I be beaten by a ten minutes process in my day? Not a chance. I decided to trace a plan, one week doing 5 minutes, next week I should be able to do ten minutes without worries. And to my great surprise, everything went great! I could keep up with those 10 minutes a day for a long time.&lt;/p&gt;

&lt;p&gt;However, I wasn't finding the value for the cost I was having. I was paying around 12 euros per month, which was a bit too much. I tried a few playlists on Spotify, and even Headspace has some good guided meditations there. After a while, I gave up. But I got lucky, and the company I work for decided to start giving it to us as a benefit during the pandemic to help us cope with the lockdown. &lt;/p&gt;

&lt;p&gt;I picked up the routine again, going from 5 to 20 minutes a day of meditation. And I will be honest with you. Meditating helps me a lot to cope with reality. It helped me through the covid pandemic (two people living in a 30m2 apartment for one year and a half) and keeps helping me nowadays. When I have a streak without meditating, I can feel the difference: my patience and focus are jeopardized after just a couple days without practicing. It also reduces the quality of how I can process events that happen to me in a daily basis (according to my therapist).&lt;/p&gt;

&lt;p&gt;But the main question is, why I'm telling all these things? After around 100 hours of meditation, I was intrigued by what it was doing to me. Even my psychologist said I could reflect better and be more reasonable. So, I decided to study a bit about it.&lt;/p&gt;

&lt;p&gt;I picked an author I like a lot: Daniel Goleman. I picked him because he had a book on a subject that I felt that was directly impacted by meditating, my focus. So, I've dug up his "Focus - The hidden driver of excellence" book, which has some interesting explanations on mindfulness and meditation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learnings
&lt;/h2&gt;

&lt;p&gt;The so-called "mindfulness" practice can offer different benefits according to the author, which states: that it "boosts the classic attention network in the brain's frontoparietal system that works together to allocate attention. These circuits are fundamental in the basic movement of attention: disengaging your focus from one thing, moving it to another, and staying with that new object of attention".&lt;/p&gt;

&lt;p&gt;That's how it feels after a while. After practicing for some time, you start to be able to focus on your breath, isolating undesired thinking patterns, and avoiding scattered thoughts. Whenever I struggle with my brain being 100km/h, I know where I have to go: inhale, exhale.&lt;/p&gt;

&lt;p&gt;This is one of the things I've heard the most in my guided meditations. Whenever you feel your thoughts wandering, focus on your breathing. It's the key factor to calming down and going back to a place of attention.&lt;/p&gt;

&lt;p&gt;Yet, another benefit I'd never heard of before reading his book was "meta-awareness, attention to attention itself, as in the ability to notice that you are not noticing what you should and correcting your focus.". After reading this passage, I've reflected upon my own experience reading the book. How many pages did I "read" when I was thinking about something else? Maybe something that happened at work or a bill I had to pay? &lt;/p&gt;

&lt;p&gt;When I brought this subject to my therapist, she actually asked me to be mindful of doing basic things. For instance, paying attention to the flavor of whatever I ate, or when I was simply taking a shower. "Take your moment when chewing your food, appreciate it. When taking a shower, enjoy the water, the feeling of being clean after it.". &lt;/p&gt;

&lt;p&gt;The realization I had was that paying close attention to these small things will bring even more joy to life and will improve your overall happiness significantly. &lt;/p&gt;

&lt;p&gt;Of course, this article doesn't intend to state that you should be focused all day long. A wandering mind is a place of creativity, while it also "operates in the service of solving problems that matter for our lives.". &lt;/p&gt;

&lt;p&gt;This was a mere invitation for you to give it a shot. Five minutes the next couple of weeks before work or during your lunch break. See how it goes. The worst it could happen is feeling like you didn't watch one or two episodes of your favorite series. You can start with &lt;a href="https://open.spotify.com/track/7tnesh1ClZdJgJLP1H0ea3?si=1d0a5f35fb104940"&gt;this one&lt;/a&gt;, if you want. Here's a free &lt;a href="https://open.spotify.com/playlist/37i9dQZF1DWVS1recTqXhf?si=cf748c9281e14acd"&gt;playlist&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And always remember, focus on your breath :)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Goleman, Daniel. Focus: The Hidden Driver of Excellence. Bloomsbury, 2013. Print.&lt;/p&gt;

&lt;p&gt;"Zen" by Hipnosapo Peres is licensed under CC BY-NC-ND 2.0.  (Cover)&lt;/p&gt;

</description>
      <category>focus</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Rotina e sanidade, parte 1</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Tue, 31 May 2022 19:20:49 +0000</pubDate>
      <link>https://dev.to/hcapucho/rotina-e-sanidade-parte-1-le3</link>
      <guid>https://dev.to/hcapucho/rotina-e-sanidade-parte-1-le3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Em primeiro lugar, que fique claro que esse texto é uma exposição de ideias sobre o processo que venho fazendo, me&lt;br&gt;
utilizando de cobaia, para melhorar o que eu acredito ser essencial em &lt;strong&gt;minha&lt;/strong&gt; vida. Logo, esse artigo não tem a&lt;br&gt;
intenção de te convencer de que o que eu faço é a melhor forma de se fazer. Quero trazer apenas opções e razões do que&lt;br&gt;
fiz e que acredito ter melhorado minha vida. Espero que a partir disso você possa fazer suas reflexões e identificar o&lt;br&gt;
que é ou não aplicável ao seu processo. :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Acontecimentos recentes na minha vida me fizeram ter vontade de escrever sobre algo que vivo há pelo menos dois&lt;br&gt;
anos e meio. Um processo contínuo de transformar hábitos e processos que façam do meu dia-a-dia algo mais&lt;br&gt;
saudável. Esse processo teve início em meados de janeiro de 2020. Escreverei sobre isso em alguns posts, acredito eu,&lt;br&gt;
pois é algo que demandará um pouco de tempo para falar sobre o que fiz e os impactos que tenho percebido.&lt;/p&gt;

&lt;p&gt;Para eu conseguir explicar o que mudou, eu preciso explicar do que a minha vida consistia antes desse processo. Se&lt;br&gt;
você está lendo isso, provavelmente sabe que sou desenvolvedor de software. Assim como a maioria das pessoas que vivem&lt;br&gt;
nesse meio, minha vida poderia ser resumida em &lt;strong&gt;doses cavalares de café, dormir tarde, acordar o mais tarde possível de&lt;br&gt;
forma que eu ainda conseguisse chegar no escritório antes da Daily&lt;/strong&gt; (reunião diária de alinhamento do time, grosseiramente). &lt;br&gt;
Além disso, eu sempre tive o hábito de estudar após o trabalho, pelo menos 45 minutos, durante os dias de&lt;br&gt;
semana. O que acontecia frequentemente era estar muito cansado após o dia de trabalho (que frequentemente envolvia hora&lt;br&gt;
extra) para conseguir fazer isso com qualidade.&lt;/p&gt;

&lt;p&gt;No início da minha carreira profissional de software, priorizei muitas vezes as necessidades das empresas que&lt;br&gt;
trabalhei ao invés das minhas, e não posso dizer que isso foi de todo negativo, tive benefícios claros na minha&lt;br&gt;
trajetória graças a isso. Acredito que no início da sua carreira, dependendo das suas ambições e objetivos, diversos&lt;br&gt;
sacrifícios serão necessários. Entretanto, isso não é sustentável no longo prazo, e percebi nesse momento que eu havia&lt;br&gt;
chegado num ponto de inflexão, onde priorizar a minha vida e carreira não era mais opcional e sim uma necessidade (um bom&lt;br&gt;
livro sobre o assunto &lt;strong&gt;emprego vs. carreira&lt;/strong&gt;, é o livro do&lt;br&gt;
&lt;a href="https://www.amazon.com.br/Seja-ego%C3%ADsta-com-sua-carreira/dp/6588523343"&gt;Luciano Santos, "Seja egoísta com sua carreira"&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;O curso &lt;a href="https://pt.coursera.org/learn/learning-how-to-learn"&gt;Learning how to Learn&lt;/a&gt; abriu a minha mente sobre como o meu&lt;br&gt;
processo de aprendizado poderia ser melhorado, e cheguei a conclusão que eu precisava usar o meu melhor momento (pela manhã)&lt;br&gt;
para fazer tudo que fosse voltado para o meu crescimento pessoal e de carreira. E foi aí que veio o pivô da mudança, onde &lt;br&gt;
num belo dia em janeiro, olhando o dia frio lá fora, tomei a difícil decisão de&lt;br&gt;
passar a acordar cedo (6am). Usaria esse horário para estudar por uma hora, e ter a minha noite livre. Morando no Brasil &lt;br&gt;
talvez 6am nem seja tão cedo assim. Porém, morando na Suécia, o sol só aparece entre 8 e 9 da manhã em janeiro e o clima &lt;br&gt;
frio faz a cama ser muito mais convidativa, o que fez a decisão ser bem mais difícil para ser sincero.&lt;/p&gt;

&lt;p&gt;E qual foi o maior impacto dessa decisão? Percebi, com o tempo, que o nível de compreensão das coisas que eu fazia nesse&lt;br&gt;
período eram muito maiores e que eu conseguia fazer conexões mais sólidas do que eu aprendia. Porém, honestamente, esse&lt;br&gt;
não foi nem de longe o melhor ganho. O melhor ganho eu ainda estava para entender.&lt;/p&gt;

&lt;p&gt;Ao longo das semanas que se passavam, &lt;strong&gt;cada vez menos o meu primeiro pensamento do dia era sobre trabalho&lt;/strong&gt;. Não acordava&lt;br&gt;
pensando no que eu tinha que entregar, com quem eu precisava marcar reunião, quem eu precisava cobrar ou o que eu estava&lt;br&gt;
esquecendo. Como eu não estava correndo para me arrumar para trabalhar, tampouco eu me via pensando sobre trabalho. &lt;br&gt;
O meu foco passou a ser totalmente direcionado na minha vida, nos meus afazeres (nesse meio tempo passei a usar metodologias para organizar&lt;br&gt;
a minha vida que falarei no futuro, tentei algumas, como &lt;a href="https://gettingthingsdone.com/"&gt;GTD&lt;/a&gt;, &lt;br&gt;
&lt;a href="https://bulletjournal.com/"&gt;bullet journal&lt;/a&gt;, onde eu falhei diversas vezes e voltei mais vezes ainda para elas).&lt;/p&gt;

&lt;p&gt;Que tranquilidade foi passar a viver assim. Sou muito grato ao meu eu do passado que tomou essa decisão. Com a pandemia&lt;br&gt;
eu passei a trabalhar de casa, e por começar às 9 am, eu passei a ter aproximadamente 3 horas pela manhã para realizar as&lt;br&gt;
minhas coisas. Foi aí que o trabalho remoto ganhou meu coração.&lt;/p&gt;

&lt;p&gt;Conforme fui entendendo o tempo que tinha disponível para mim, comecei a acrescentar coisas nessas horas que faziam o meu&lt;br&gt;
dia melhor. Por exemplo, nunca fui de tomar café da manhã, sempre tive que sair correndo e não consigo sentir fome logo&lt;br&gt;
ao acordar. Ao passar a estudar e ficar mais de uma hora entretido estudando, meu apetite aparecia e passei a tomar café&lt;br&gt;
da manhã, o que fez com o que o resto da minha manhã fosse muito mais produtiva.&lt;/p&gt;

&lt;p&gt;Foi em janeiro também que voltei a malhar, deixava para malhar a noite, pois era quando eu não precisava mais de um&lt;br&gt;
raciocínio fino e poderia usar para descompressão do trabalho. Infelizmente, com o advento da pandemia, a&lt;br&gt;
academia teve um fim forçado que só teve retorno após as 3 doses da vacina (final de 2021), e tenho conseguido me manter&lt;br&gt;
consistente (+ de 4 vezes por semana) até então. Acredito fortemente que esse início e todas as mudanças inseridas durante&lt;br&gt;
o processo, foi um dos fatores fundamentais para eu conseguir viver o lockdown sem entrar em &lt;br&gt;
colapso, dado que eu passei mais de um ano trancafiado num apartamento de 30m2.&lt;/p&gt;

&lt;p&gt;As mudanças que enxergamos como positivas tendem a ter um efeito cascata. Quando você passa a enxergar os efeitos positivos de algo&lt;br&gt;
que fez, começa a procurar quais são as outras coisas que talvez façam sentido mudar que podem trazer-lhe algum&lt;br&gt;
benefício. Um subproduto da decisão de acordar cedo, foi construir uma rotina que fizesse com que eu dormisse bem, para&lt;br&gt;
conseguir levantar no horário.&lt;/p&gt;

&lt;p&gt;Decidi que as 10pm seria meu horário para dormir, e que a partir das 9pm eu não mexeria mais em telas. Uma das coisas&lt;br&gt;
mais úteis que fizemos foi comprar lâmpadas que você pode selecionar para ficar amarela, e durante as noites usávamos&lt;br&gt;
esse modo para estimular o nosso sono. O que fazer entre as 9pm e as 10pm, me perguntava. Bom, um hábito que havia&lt;br&gt;
ficado de lado desde o advento da Netflix na minha vida virou a melhor opção: ler.&lt;/p&gt;

&lt;p&gt;Passei então a trocar a tela da televisão pelos meus livros. Sempre foquei muito tempo nos meus estudos em tecnologia, porém&lt;br&gt;
com esse novo espaço, passei a dedicar parte do meu tempo com coisas que eu enxergava como essenciais para o meu futuro:&lt;br&gt;
a minha saúde emocional, a gestão da minha vida e das atividades que preciso fazer, minha carreira e eventuais livros &lt;br&gt;
de literatura. Além disso, nesse período também descobri que a cafeína tem um efeito estimulante de cerca de oito horas no seu corpo, o que&lt;br&gt;
me fez tomar com muito prazer o meu último cafezinho às 14h.&lt;/p&gt;

&lt;p&gt;Nas próximas vezes que eu me aventurar por essas terras quero falar mais a fundo sobre tudo que disse acima e sobre &lt;br&gt;
outras coisas que acrescentei e removi da minha vida durante esse período. Acredito que o mais importante que aprendi &lt;br&gt;
nesse processo é que uma rotina bem estabelecida me trouxe muita paz, mesmo em meio a momentos bastante delicados. Para muita gente ter uma vida assim pode parecer entediante, porém, eu descobri &lt;br&gt;
uma relação muito saudável com o famigerado “tédio da rotina”. Ter um direcionamento claro e palpável no meu dia-a-dia &lt;br&gt;
faz que eu consiga encontrar o meu norte quando a bússola começa a falhar. Evito questionamentos corriqueiros, tenho respostas simples &lt;br&gt;
e tangíveis para a maioria dos momentos no meu dia. &lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>Why are you using cronjobs?</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Wed, 12 Aug 2020 18:48:21 +0000</pubDate>
      <link>https://dev.to/hcapucho/why-are-you-using-cronjobs-ajj</link>
      <guid>https://dev.to/hcapucho/why-are-you-using-cronjobs-ajj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;There's an addendum in the end with a "fix" :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;You work for an e-commerce company. In this company, users will create their accounts. What is the most likely your feature will do when they sign up? That's right. Send an email with a confirmation token so you can be sure that you're creating the account for the right user. &lt;/p&gt;

&lt;p&gt;Ok, but what does this have to do with cronjobs? I will explain further down the road. &lt;/p&gt;

&lt;p&gt;Most likely, this token will have an expiration. It can be 3 hours, one day, it doesn't matter how long it will take, at some point in time in the future, it needs to be canceled. A common way to handle these scenarios where you need to perform something in the future is using cronjobs. &lt;/p&gt;

&lt;p&gt;The easy way? A cronjob that goes through the database table where you store the tokens, check the ones with more than 3 hours (if that's the expiration time for your company) and update or delete the tokens that are not valid anymore.&lt;/p&gt;

&lt;p&gt;You might ask me, what is the issue with this approach? Well, the first thing is that this approach is time and resource consuming. By using this approach, every hour or so, you will need to go through the whole table to find the elements you need and do an operation on them. If there's nothing to be canceled, the cronjob will still use the resources.&lt;/p&gt;

&lt;p&gt;Let's look through this with another set of lenses: scalability. The server that triggers the cronjob cannot scale up, otherwise, you could end up running the same process concurrently. For instance, if you're processing payments within a cronjob: two instances of the server triggering the same thing at the same time could end up paying a user twice if you're not careful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What can we do to improve it? The nature of the process is event-based. Why can't we use that in our favor?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of taking a time-based approach, let's think about how we can deal with this thinking asynchronously. First, when the user signs up, we process the event triggered by the "Sign up" button. This event, let's call it "CREATE_ACCOUNT". When you do so, another event is also triggered, which is "REVOKE_SIGN_UP_TOKEN". However, this event is to be processed in the future, how can we deal with that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous queues to the rescue
&lt;/h2&gt;

&lt;p&gt;Imagine you have a queue. Now imagine that in this queue you can say: "Hey, process this thing for me in 3 hours, please?". The queue properly stores the information you sent and later, will execute the code you want for the events stored in it.&lt;/p&gt;

&lt;p&gt;One may say: "Ok, this could be awesome. But how is it achievable? I have no idea on how to delay something for 3 hours". &lt;/p&gt;

&lt;p&gt;No worries, Redis is here to rescue you from the deep cronjob forest. If you are a happy developer that works with Node.js, I will show an amazing library that can help you on this journey.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/OptimalBits/bull"&gt;Bull&lt;/a&gt; is a queue tool for Node.js, based on Redis. By using it, you can implement asynchronous job processing, with delays, retries, priorities on your jobs, and much more. You may also use a &lt;a href="https://github.com/vcapretz/bull-board"&gt;dashboard&lt;/a&gt; to visualize in a nice way how your jobs are being handled. Remember, asynchronous processing can fail like any other piece of code. Keep in mind that you need to handle your failures.&lt;/p&gt;

&lt;p&gt;The libraries provide good examples of how to use it and what are the features they contain. I will leave to you to find what's the best approach for you using it. Adding examples here, it would only increase the time to read and would be really close to the documentation to keep it simple.&lt;/p&gt;

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

&lt;p&gt;I hope that this article brought a new perspective on how you can handle time-constrained events (or just events). I hope that the next time you see a cronjob handling an event-based process, you can think if it wouldn't be better to use an asynchronous process to do so.&lt;/p&gt;

&lt;p&gt;Stay safe, use a mask!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adendum
&lt;/h2&gt;

&lt;p&gt;After posting, a friend brought to my attention that we could use a DB that has a TTL feature. In this case, since we use Redis, it contains an EXPIRE command which you could indeed implement this specific feature more efficiently. Using this command you could tell the DB to remove the key after a given time window. Unfortunately, the example wasn't complex enough, but what I wanted to bring to attention are the scenarios where you have a complex operation that you must execute after a given time an event occurred. Hopefully, that can bring some ideas for you future projects =]&lt;/p&gt;

&lt;p&gt;Thanks @hkupty for bringing that to my attention and helping me improving the article :)&lt;/p&gt;

&lt;h5&gt;
  
  
  Image
&lt;/h5&gt;

&lt;p&gt;"My vintage watches" by penmanila is licensed under CC BY-NC-ND 2.0. To view a copy of this license, visit &lt;a href="https://creativecommons.org/licenses/by-nc-nd/2.0/"&gt;https://creativecommons.org/licenses/by-nc-nd/2.0/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
    </item>
    <item>
      <title>A quick guide to fix your Git mistakes :)</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Sun, 02 Aug 2020 14:35:13 +0000</pubDate>
      <link>https://dev.to/hcapucho/a-quick-guide-to-fix-your-git-mistakes-2a72</link>
      <guid>https://dev.to/hcapucho/a-quick-guide-to-fix-your-git-mistakes-2a72</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Git is a wonderful tool. It's the tool that is usually mentioned as the one every developer should have under its belt. However, git is not easy to understand as well. Most of us frequently face a really simple flow, doing commands like &lt;code&gt;pull, add, commit, push, merge&lt;/code&gt; and in some company flows you will use &lt;code&gt;rebase&lt;/code&gt;. However, once in a while we screw up.&lt;/p&gt;

&lt;p&gt;We know that sometimes &lt;del&gt;shit&lt;/del&gt; things happen in your commit history and you might find it easier to create a new branch, doing a revert, or creating a commit like &lt;code&gt;Fix typo&lt;/code&gt;. Making mistakes in Git is not so uncommon. However, knowing how to fix them is what makes me not bother when things like that happen. If you don't know the tools git provides to you, fixing mistakes can be painful. But if you do know the tools that allow you to fix your mistakes, it's like having a nice cup of coffee on a raining morning. Just delightful. &lt;/p&gt;

&lt;p&gt;This post will go through the &lt;code&gt;interactive rebase&lt;/code&gt; tool to enable you to fix your commits. &lt;/p&gt;

&lt;h2&gt;
  
  
  Basic rebase concepts
&lt;/h2&gt;

&lt;p&gt;If you never rebased a branch, I will go through a quick explanation on it and I'll leave this &lt;a href="https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase"&gt;article&lt;/a&gt;  so you can dig deeper into the subject if suitable for you. The goal here is not to go through the rebase itself, but without a basic understanding, it won't be possible to explain the interactive options. So, let's start with a quick explanation of rebasing.&lt;/p&gt;

&lt;p&gt;First, let's assume we have a main branch with the following commit history:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e2c_14tR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jquud05ytije1220nyyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e2c_14tR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jquud05ytije1220nyyr.png" alt="main"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From this &lt;code&gt;main&lt;/code&gt; branch, you create a new one called &lt;code&gt;button-feature&lt;/code&gt; and started your work while your colleagues kept merging their PR's into the &lt;code&gt;main&lt;/code&gt; branch. The times where a file was locked until your work is finished are long gone, thankfully. So your branches history will be a beautiful thing, looking like this now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5du68Tac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/60aaze4qwhk4tv8l67vh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5du68Tac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/60aaze4qwhk4tv8l67vh.png" alt="new-branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At some point, you will need to get the updated code from the &lt;code&gt;main&lt;/code&gt;, right?  Usually, people merge the &lt;code&gt;main&lt;/code&gt; branch into their development branch. However, you can also &lt;code&gt;rebase&lt;/code&gt; your branch from the one you created yours from.&lt;/p&gt;

&lt;p&gt;To do so, you will update the contents from &lt;code&gt;main&lt;/code&gt; by pulling the new contents and then, within your &lt;code&gt;button-feature&lt;/code&gt; branch you would run: &lt;code&gt;git rebase main&lt;/code&gt;. The result would be close to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FAAOa0f4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1ye0rlt295mm7dn7xnfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FAAOa0f4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1ye0rlt295mm7dn7xnfg.png" alt="rebased branches"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When doing so, the rebase command will add your commits on top of the latest commit from &lt;code&gt;main&lt;/code&gt;. Even though they still have the same content, they're not the same commit anymore. The history of those commits is rewritten now, new commit hashes are assigned to each one of them. That's the reason I've changed the colors of it. &lt;/p&gt;

&lt;p&gt;The main advantage here is that it allows the git history to keep a linear structure, making it easier to use operations like &lt;a href="https://git-scm.com/docs/git-bisect"&gt;&lt;code&gt;bisect&lt;/code&gt;&lt;/a&gt; to find issues within the code. &lt;/p&gt;

&lt;p&gt;Rewriting history is a powerful tool, and "with great powers, comes great responsibilities". You know that since you were a kid, right? So, be aware.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Changing commit history can be a problem if you rebase a branch that people branched of from, since the commit hashes won't be the same anymore, not being possible to track down the original changes. A deeper explanation can be seen &lt;a href="https://www.atlassian.com/git/tutorials/rewriting-history"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Interactive rebase to the rescue
&lt;/h1&gt;

&lt;p&gt;It's common for us developers to forget something when doing a commit, to name the commit inconsistently, forgetting to add some piece of code or we simply want to delete a commit we've added.&lt;/p&gt;

&lt;p&gt;These things among others can be helped if you know how to do an interactive rebase. I've separated three topics from it that at least in my development workflow are the most common to be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Renaming a commit
&lt;/h2&gt;

&lt;p&gt;In this scenario, I've added a commit with a name that doesn't follow the guideline that I should use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---x2YCxip--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hcel0g9r6ntqf0l6s3f4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---x2YCxip--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hcel0g9r6ntqf0l6s3f4.png" alt="gitlog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you take a closer look, you will see that the second commit is not consistent with the latest one, so let's fix that.&lt;/p&gt;

&lt;p&gt;First, we do a &lt;code&gt;git rebase -i HEAD~2&lt;/code&gt;, which means "I want to do the rebase operation on the latest two commits".&lt;/p&gt;

&lt;p&gt;After executing that command, you will see the following:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0pG-RW0e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p1avsebfx7o22h8gqcet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0pG-RW0e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p1avsebfx7o22h8gqcet.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rebase menu already shows you everything you can do. Read through it to see the possibilities if you don't remember from the top of your head. Let's choose the &lt;code&gt;reword&lt;/code&gt; option, or simply &lt;code&gt;r&lt;/code&gt;, to rename the commit we want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JnfuGI9m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/if9eq9fzdk075ghbtiej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JnfuGI9m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/if9eq9fzdk075ghbtiej.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every time you see this screen, to execute the operation, you will need to save and close the file. When doing so, the rebase process starts and the commit prompt is showed to me. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XmZFTsor--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/77zih26rk1m3ugueg67m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XmZFTsor--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/77zih26rk1m3ugueg67m.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I can change the text to whatever I want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vzX1J-Q8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kyqf79m7uth4vzof5htc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vzX1J-Q8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kyqf79m7uth4vzof5htc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new commit message is assigned to that commit I had. If I take a look into the log again, we'll see an updated message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gpT2ixHr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/at7bmd276hbauenm2gow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gpT2ixHr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/at7bmd276hbauenm2gow.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dropping a commit
&lt;/h2&gt;

&lt;p&gt;This one is for those cases you just want to test something and keep in your change history, but you want to delete later. You could stash, apply the stash later, but you can also simply commit it and later just delete it. I use this a lot when I have to do some tests, especially if I want the change to go through the pipeline. After testing everything I wanted, I can just delete the commit.&lt;/p&gt;

&lt;p&gt;Assume that I have a commit called &lt;code&gt;Remove this commit&lt;/code&gt; that I will delete it in the future as we can see in the following image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ol6rqjES--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k18hycf1p6l672ec4muo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ol6rqjES--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k18hycf1p6l672ec4muo.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can do a &lt;code&gt;git rebase -i HEAD~&lt;/code&gt;, which means we want to rebase the last commit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vay5MyZi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/myleyljve2iwpvyo6jr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vay5MyZi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/myleyljve2iwpvyo6jr2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you would just replace the &lt;code&gt;pick&lt;/code&gt; word with &lt;code&gt;d&lt;/code&gt; for &lt;code&gt;drop&lt;/code&gt;, after doing so, your commit should be long gone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MTDwPqiR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ku14xcso8o2c0ig3rm3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MTDwPqiR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ku14xcso8o2c0ig3rm3h.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Editing a commit
&lt;/h2&gt;

&lt;p&gt;If you ever had to face a commit where you forgot to add a piece of code,  or only after committing you saw a broken test (yeah, we know it's not always we do TDD). This is the tool to help you fix it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zR1hRgvl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7nripdzgo72owggao78v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zR1hRgvl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7nripdzgo72owggao78v.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The commit &lt;code&gt;Add message file&lt;/code&gt; contains a space that it shouldn't. You can see it in the green line with a &lt;code&gt;console.log(' message')&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kzQjj7Sc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/37qtyc0chr3x5dq0xtav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kzQjj7Sc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/37qtyc0chr3x5dq0xtav.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to fix this issue without creating a new commit? Let's make the magic happen. First, we will rebase to the point we want. So, let's do a &lt;code&gt;git rebase -i HEAD~2&lt;/code&gt; to rebase the latest two commits.&lt;/p&gt;

&lt;p&gt;Now, we will pick the option &lt;code&gt;e&lt;/code&gt; to &lt;code&gt;edit&lt;/code&gt; the commit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U6ZQBxLX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fawl3208ahsqnoazzj4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U6ZQBxLX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fawl3208ahsqnoazzj4i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what you will see when saving the file and closing the editor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_3AXaIKN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rwsmdipu6uiz4ay00lx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_3AXaIKN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rwsmdipu6uiz4ay00lx3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can edit the code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N1zlFuxZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o00vgq715emekoohuizz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N1zlFuxZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o00vgq715emekoohuizz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After this change, we can add the fix in the same commit using &lt;code&gt;git commit --amend&lt;/code&gt;. This will open the commit prompt for the commit you wanted to edit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8eVRNxp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/amqyrxk24ojjn3gspc4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8eVRNxp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/amqyrxk24ojjn3gspc4p.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can simply save it and close the editor. If there's nothing else to be done, after running a &lt;code&gt;git rebase --continue&lt;/code&gt; the operation will be done and your commit will be fixed :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xmqnz5sp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gikxna4ce58z4bibzsbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xmqnz5sp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gikxna4ce58z4bibzsbk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with remote
&lt;/h2&gt;

&lt;p&gt;If you do a rebase after your contents are already on remote (you pushed the contents), you will have to do force the push, since the history changed.&lt;/p&gt;

&lt;p&gt;To do so, the best idea is to use &lt;code&gt;git push --force-with-lease&lt;/code&gt;, since this command will check if no other new content was added to the branch by someone else :)&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;You can learn a lot on Git from &lt;a href="https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud"&gt;Atlassian tutorials&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing"&gt;Git manuals&lt;/a&gt; can be helpful. &lt;/li&gt;
&lt;li&gt;The most recommended book I've seen on Git is the &lt;a href="https://git-scm.com/book/en/v2"&gt;Pro Git&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Acknowledgments
&lt;/h1&gt;

&lt;p&gt;Thanks again, Martin Fieber. You've helped my growth a lot in the past year with your inputs. Especially reviewing my writings and giving great suggestions. :)&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Smooth Undefined - Maybe value, maybe not? </title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Wed, 29 Jul 2020 07:01:33 +0000</pubDate>
      <link>https://dev.to/hcapucho/smooth-undefined-maybe-value-maybe-not-55o2</link>
      <guid>https://dev.to/hcapucho/smooth-undefined-maybe-value-maybe-not-55o2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Functional programming (FP), for the ones used to it, is joyful, lovely, and a slice of heaven on earth. However, for mere mortals like me, it's painful to even try to understand those concepts. Weird symbols, crazy words without any meaning to my knowledge that people frequently talk about. It just feels like we're getting into a labyrinth. With no exit, to fight a minotaur, barehanded.&lt;/p&gt;

&lt;p&gt;For a while now, I've been trying to push myself to understand these concepts and applicabilities. However, materials are usually not so beginner-friendly, and from my perspective, you don't need to become a Jedi in FP concepts to get some benefit from it, even if it's with some hacks.&lt;/p&gt;

&lt;p&gt;In the end, I hope that you can add some basic concepts into your current codebase without much effort, neither having to change the programming paradigm you're currently using. The goal here is not to make you a functional programmer, but instead, to use a concept from it to improve your daily code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;If you're a JavaScript developer, I'm quite sure you faced or wrote a piece of code that checked if a variable was &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;, right?&lt;/p&gt;

&lt;p&gt;You probably have seen a lot of code that had this exact behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;parseNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&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;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&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;number&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// won't make it easy to you. Figure it out&lt;/span&gt;
  &lt;span class="c1"&gt;// if it's undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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



&lt;p&gt;And somewhere in the code, something like this is happening:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// now this returns undefined&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parseNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a10&lt;/span&gt;&lt;span class="dl"&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;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&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;// this will simply throw&lt;/span&gt;
&lt;span class="c1"&gt;// Uncaught TypeError: Cannot read property 'toFixed' of undefined.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And after someone added this piece of code, alarms start to fire, phones starts to ring. In the end, someone realizes that a simple check was missing. They change the code to the following and life goes back to normal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parseNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&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;number&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;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Maybe Container
&lt;/h2&gt;

&lt;p&gt;Now imagine the following scenario, instead of handing over to you the value you want or a possible undefined, you will be handed over a gift box. You won't know what's in that gift box until you open it. Now you have the &lt;a href="https://en.wikipedia.org/wiki/Schr%C3%B6dinger%27s_cat"&gt;Schrödinger's&lt;/a&gt; value. &lt;/p&gt;

&lt;p&gt;Let's give this gift box a name. Let's call it Maybe. This is what a really basic value container would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Maybe.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strict mode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&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="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;empty&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="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;isNothing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// this._value == undefined is equivalent&lt;/span&gt;
    &lt;span class="c1"&gt;// to this._value === null || this._value === undefined&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;isPresent&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isNothing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;value&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This code is not following the purist Functional principles since we're exposing the value and not providing some FP operators. I will add at the end of the article some references on how to get deeper into the Functional concepts, so you can explore if you desire to do so.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This simple piece of code can improve a lot your code design. Instead of allowing null and undefined values, now you have a way to enforce your function consumer to handle those weird scenarios.&lt;/p&gt;

&lt;p&gt;Let's refactor the code to use it. From now on, your function will return our gift box, a Maybe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// example.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strict mode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;maybeParseNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&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;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&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;Maybe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&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;Maybe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;empty&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 your code that calls this function will have to open the box before getting the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;maybeNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;maybeParseNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;9&lt;/span&gt;&lt;span class="dl"&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;maybeNumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPresent&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;maybeNumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&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;// prints 9.0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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



&lt;p&gt;&lt;code&gt;Maybe&lt;/code&gt; is what people call a Monad. However, a monad is something more complex than this, that won't expose the value as we're doing and will provide functions like &lt;code&gt;map, join, chain...&lt;/code&gt; so you don't need to retrieve the value from it like when we access &lt;code&gt;maybeNumber.value&lt;/code&gt;. If you want to get some deeper context into these concepts, I highly recommend this &lt;a href="https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/"&gt;book&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Still, from my viewpoint, these concepts can be a bit scary in the beginning and harder to introduce in a codebase that is not focused on the functional programming paradigm. Therefore, these small tweaks are a way to start introducing these nice concepts into your code while you get some familiarity with the ideas.&lt;/p&gt;

&lt;p&gt;Hopefully, this simple idea can help you out when making some decisions on what to return when you face a situation where you most likely will return &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; values. Since &lt;code&gt;null&lt;/code&gt; is considered the &lt;a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/"&gt;billion-dollar mistake&lt;/a&gt;, let's avoid it as much as we can.&lt;/p&gt;

&lt;p&gt;I will write a next post on how to provide a nice interface when handling asynchronous operations, stay tuned.&lt;/p&gt;

&lt;p&gt;Have a nice week, stay safe. Use a mask!&lt;/p&gt;

&lt;h4&gt;
  
  
  Credits
&lt;/h4&gt;

&lt;p&gt;"JavaScript Logo" by b0neskull is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit &lt;a href="https://creativecommons.org/licenses/by-nc-sa/2.0/"&gt;https://creativecommons.org/licenses/by-nc-sa/2.0/&lt;/a&gt; &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>functional</category>
    </item>
    <item>
      <title>TypeScript (patterns?)</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Wed, 24 Jun 2020 16:01:32 +0000</pubDate>
      <link>https://dev.to/hcapucho/typescript-patterns-2d8n</link>
      <guid>https://dev.to/hcapucho/typescript-patterns-2d8n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Throughout my journey with TypeScript, I've been impressed by its features. The v2 &lt;a href="https://www.typescriptlang.org/docs/home.html"&gt;documentation&lt;/a&gt; is a really good improvement to the learning resources. However, some patterns are not so easy to find documented in the common ground of TS materials. Therefore, I wrote this quick article with 3 interesting things in TS, that from my perspective, can make life a bit easier :).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We shall begin!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/iFxXouCf76ZencqIRP/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/iFxXouCf76ZencqIRP/giphy.gif" alt="Do it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Companion Object
&lt;/h2&gt;

&lt;p&gt;I've found this one when I read &lt;a href="https://www.amazon.com/Programming-TypeScript-Making-JavaScript-Applications/dp/1492037656"&gt;Programming TypeScript&lt;/a&gt;. It provides a simple and easy way to enable your module customers to import the type and a factory for that type in a single import. Hence, the name "Companion Object". &lt;/p&gt;

&lt;p&gt;It amazed me by how simple and useful this can be. This is how the module is presented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Currency.ts&lt;/span&gt;

&lt;span class="c1"&gt;// Here we will create a type and a variable &lt;/span&gt;
&lt;span class="c1"&gt;// with the same name&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EUR&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="s2"&gt;GBP&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="s2"&gt;JPY&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="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&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;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And this is how the module is consumed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// index.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Currency&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;./Currency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Use case 1: Used as type&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;amountDue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JPY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;83733.1&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// use case 2: Used as factory object&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;otherAmountDue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;330&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EUR&lt;/span&gt;&lt;span class="dl"&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;amountDue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;otherAmountDue&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we look at the &lt;code&gt;index.ts&lt;/code&gt; file, a single import of &lt;code&gt;Currency&lt;/code&gt; is declared. Yet, as you can see, it has two use cases. The first one as a type and the later as a factory object. By looking at the &lt;code&gt;Currency.ts&lt;/code&gt; file, it's possible to see that we also have a single export, which is valid for both variable and type.&lt;/p&gt;

&lt;p&gt;Consequently, &lt;strong&gt;with a single export and a single import, you gain a type and an object factory.&lt;/strong&gt;. This enables you to work with both smoothly. However, things can't be so easy. Since we usually opt-in for the &lt;code&gt;strict&lt;/code&gt; option in TS, this code throws an error:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;7022: 'Currency' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its initializer.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(If you want to understand a bit more on the compiler options, &lt;a href="https://www.typescriptlang.org/docs/handbook/compiler-options.html"&gt;this link&lt;/a&gt; provides an explanation to every option TypeScript contains.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/d2ZaChASUxF6xqWk/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/d2ZaChASUxF6xqWk/giphy.gif" alt="no"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, whenever we developers like an idea, we &lt;del&gt;smash the code until it works&lt;/del&gt; find a proper path to make it reasonable. In this particular case, it is possible to use this with the strict option, by doing a small tweak. Our module will look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;ValidCurrencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EUR&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="s2"&gt;GBP&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="s2"&gt;JPY&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="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// "Small tweak": Type that will be used on&lt;/span&gt;
&lt;span class="c1"&gt;// the variable that is used as constructor&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NotExposedCurrency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ValidCurrencies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;
  &lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ValidCurrencies&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Here we have the things we would like to export&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ValidCurrencies&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Type Constructor&lt;/span&gt;
&lt;span class="c1"&gt;// Here is where we use the tweak&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotExposedCurrency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&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;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

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



&lt;p&gt;By typing the factory with a private type, the variable won't have an &lt;code&gt;implicit any&lt;/code&gt; type. This won't impact our usage since we have no interest in the Factory type. Our interest is at the factory function return type. &lt;/p&gt;

&lt;p&gt;Applying this change, the &lt;code&gt;index.ts&lt;/code&gt; export was still the same and it enabled the feature usage even when the compiler is set to a strict mode. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/XbxZ41fWLeRECPsGIJ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/XbxZ41fWLeRECPsGIJ/giphy.gif" alt="happy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exceptions: Java, Go, and TypeScript?
&lt;/h2&gt;

&lt;p&gt;In my career, I've worked mostly as a Java Developer. In Java, you can add the Exceptions that might be thrown to your methods signatures, thus, enforcing the client to properly handle those cases. &lt;/p&gt;

&lt;p&gt;Such a simple thing, which I've never imagined how much I would miss. For those who might have never used Java or a language with this feature, here's a piece of code with an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ThisOneThrows&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// ThisOneThrows.java:4: error: &lt;/span&gt;
    &lt;span class="c1"&gt;// unreported exception Exception; &lt;/span&gt;
    &lt;span class="c1"&gt;// must be caught or declared to be thrown&lt;/span&gt;
    &lt;span class="c1"&gt;// ThisOneThrows.hereWeThrow();&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ThisOneThrows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hereWeThrow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;hereWeThrow&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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



&lt;p&gt;Java compiler will enforce you to declare that the &lt;code&gt;main&lt;/code&gt; function throws as well or that you need to wrap the call &lt;code&gt;ThisOneThrows.hereWeThrow()&lt;/code&gt; in a &lt;code&gt;try...catch&lt;/code&gt; block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ThisOneThrows&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// public static void main(String[] args) throws Exception {&lt;/span&gt;
    &lt;span class="c1"&gt;// ThisOneThrows.hereWeThrow();&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;

&lt;span class="c1"&gt;// OR&lt;/span&gt;

 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
         &lt;span class="nc"&gt;ThisOneThrows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hereWeThrow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;      
 &lt;span class="o"&gt;}&lt;/span&gt;


 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;hereWeThrow&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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



&lt;p&gt;Knowing this behavior upfront is always resourceful when dealing with error handling, and I've always missed that in TS. It's a really impressive type system, especially considering the environment it runs at, but not being able to know the possible errors I could expect bugged me for a while.&lt;/p&gt;

&lt;p&gt;However, the Go community has been dealing with this for a while. In Go, you don't have a &lt;em&gt;throws&lt;/em&gt; declaration, the solution? &lt;strong&gt;Return an actual error object to the function consumer&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;So, why not doing that in TS as well? &lt;em&gt;(This is a controversial pattern for many, but from my perspective, as long as it increases the chances of catching an issue before the client does, it brings value to the table)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here's one example of how you can do that in TS, again, from the book &lt;a href="https://www.amazon.com/Programming-TypeScript-Making-JavaScript-Applications/dp/1492037656"&gt;Programming TypeScript&lt;/a&gt;. I think I've done some really small tweaks to it, so I could make use of function return types as &lt;code&gt;Type Guards&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One example of how we could define the errors and &lt;code&gt;Type Guards&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// helpers.ts&lt;/span&gt;

&lt;span class="c1"&gt;// First Part: define the errors&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;InvalidDateFormatError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DateIsInTheFutureError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;// Type guard for the errors&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nb"&gt;Error&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;input&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// a helper functions for dates.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&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;[object Date]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTime&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;This is how we could define our logic to handle the errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// birthday.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;InvalidDateFormatError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;DateIsInTheFutureError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isValid&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="s1"&gt;./helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;birthday&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="nb"&gt;Date&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;InvalidDateFormatError&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;DateIsInTheFutureError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;birthday&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&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="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;InvalidDateFormatError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter a date in the form YYYY/MM/DD&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTime&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;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&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="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DateIsInTheFutureError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A what?&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="nx"&gt;date&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;birthday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt; &lt;span class="kr"&gt;number&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;possibleDate&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;birthday&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// step 1&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;isError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;possibleDate&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// step 2&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;possibleDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// step 3&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;possibleDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFullYear&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;Let's start with the &lt;code&gt;step 1&lt;/code&gt; part, inside the &lt;code&gt;getYear&lt;/code&gt; function. Here we call the &lt;code&gt;parse&lt;/code&gt; function. This function, as the signature states, tries to parse a string into a Date. The signature also shows that besides the Date we want, 2 errors could be returned from the validation conditions.&lt;/p&gt;

&lt;p&gt;By doing so, at the moment parse is executed and returns the value to the &lt;code&gt;possibleDate&lt;/code&gt; variable, TypeScript is exactly like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/X2iqesUkZULQs/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/X2iqesUkZULQs/giphy.gif" alt="Travolta"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is &lt;code&gt;possibleDate&lt;/code&gt; a Date or an Error? Since TypeScript can't figure it out at compile-time, it won't allow us to safely access any value. We will have to check the variable using a &lt;code&gt;Type Guard&lt;/code&gt;. Only after that, you will be able to access the value you want.&lt;/p&gt;

&lt;p&gt;In step two, we have our &lt;code&gt;Type Guard&lt;/code&gt;. If the call to &lt;code&gt;isError&lt;/code&gt; returns true, which has a return defined as &lt;code&gt;input is Error&lt;/code&gt;, TS knows that inside that if condition, we're dealing with an Error. Consequently, the compiler will allow access to the message attribute. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;(To see more on this Type Guards, take a look at &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#using-type-predicates"&gt;this link&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Moreover, by figuring that out on step 2, TypeScript also knows that the only possible type left for the &lt;code&gt;possibleDate&lt;/code&gt;, after executing the if condition, is the Date type. This is because both options are a subtype of Error.&lt;/p&gt;

&lt;p&gt;Now you're allowed to access the Date functions and attributes. :)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Some Functional Programming concepts can improve this error handling in a quite nice manner, I will write a post regarding that in the next few weeks. If you're curious about it already, I can recommend reading this &lt;a href="https://mostly-adequate.gitbooks.io/mostly-adequate-guide/"&gt;book&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Mostly Adequate Guide to Functional Programming is pleasant to read, with exercises so you can practice the concepts. I'm quite sure it will be a nice addition to your library. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Mapped Objects
&lt;/h2&gt;

&lt;p&gt;This one I don't recall where I've encountered for the first time, but it's a simple use of generics to improve a lot our safety. &lt;/p&gt;

&lt;p&gt;For instance, imagine you have an interface with the event types for a button, containing those events like: &lt;code&gt;click&lt;/code&gt;, &lt;code&gt;mouseover&lt;/code&gt;, etc.. Furthermore, imagine that you expose a client to that module, where users can subscribe to your events. Have you ever seen something like &lt;code&gt;.on('click', callbackFunction)&lt;/code&gt;? &lt;/p&gt;

&lt;p&gt;Maybe you also want to tell them the types they might expect in their callback functions. It would be way better if we had a type system that could provide this information, right?&lt;/p&gt;

&lt;p&gt;This pattern can help your module users a lot on those questions mentioned above. I can't stop thinking of a younger version of me while learning the JS basics. The countless number of times I had to look up on MDN which events were available on a given type of element.&lt;/p&gt;

&lt;p&gt;With this pattern, you can derive types that will improve your IntelliSense and autocomplete features by simply using &lt;a href="https://www.typescriptlang.org/docs/handbook/generics.html"&gt;Generics&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// redis.d.ts&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;
  &lt;span class="na"&gt;reconnecting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RedisClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// subscriber function&lt;/span&gt;
  &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
     &lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; 
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And this is how this would be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// redis.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Redis&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Create a new instance of a Redis client&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RedisClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Listen for a few events emitted by the client&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ready&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="o"&gt;=&amp;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;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Client is ready&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;If we take a look at our subscriber function in&lt;code&gt;redis.d.ts&lt;/code&gt;, TypeScript will realize that the event can only be one of the types &lt;code&gt;'read' | 'error' | 'reconnecting'&lt;/code&gt;, since the values are keys from the Event type. It will also add types and dynamically validate the function arguments since it will be based on the event type you select.&lt;/p&gt;

&lt;p&gt;This is also resourceful whenever you add a new key into that type, all your clients will be able to see the new addition, and if we didn't break anything, use that new event :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to say goodbye :)
&lt;/h2&gt;

&lt;p&gt;Hopefully, this article can bring some ideas to your future coding, even if it's to avoid using these concepts.&lt;/p&gt;

&lt;p&gt;Feel free to comment and bring your ideas to this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/9eM1SWnqjrc40/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/9eM1SWnqjrc40/giphy.gif" alt="Bye"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  References and Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://www.typescriptlang.org/docs/handbook/generics.html"&gt;TypeScript Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://www.amazon.com/Programming-TypeScript-Making-JavaScript-Applications/dp/1492037656"&gt;Programming TypeScript&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://frontendmasters.com/courses/typescript-v2/"&gt;FrontendMasters - TypeScript&lt;/a&gt;; Some material related to this one is presented for free in &lt;a href="https://github.com/mike-works/typescript-fundamentals"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://basarat.gitbook.io/typescript/"&gt;TypeScript Deep Dive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/understanding-typescript/"&gt;Udemy - Understanding TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Appreciation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Martin Fieber, that helped me a lot with my TypeScript learnings and had a lot (I mean, a LOT) of patience with me.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>patterns</category>
    </item>
    <item>
      <title>Apache Kafka 101 - Introduction</title>
      <dc:creator>João H. Capucho</dc:creator>
      <pubDate>Tue, 14 Apr 2020 07:28:23 +0000</pubDate>
      <link>https://dev.to/hcapucho/apache-kafka-101-introduction-567a</link>
      <guid>https://dev.to/hcapucho/apache-kafka-101-introduction-567a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Disclaimer: the intention behind this post is to do a brain dump of some understandings I have on Kafka and to make that useful by sharing it. I'm not a Kafka expert whatsoever, and if there's anything wrong in here, please, comment so I can fix it. Anything that can help improve this text is welcome. With that being said, let's start the journey :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Sync vs Async communication
&lt;/h2&gt;

&lt;p&gt;Before diving into Kafka, let's briefly go through the concepts of synchronous and asynchronous communication for the ones that never heard about it. &lt;em&gt;If you know the difference you can just skip this part&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To start off, let's take an example of synchronous communication that is a client app sending an HTTP request towards a REST API service. In this case, the client opens a connection with the server via the HTTP protocol and sends some data that will be received and processed by the server, which in turn will respond to the client with the result. If the client, by any chance, does not receive a response within an expected time, an error will be thrown (the beloved timeout). This architecture is quite simple and usually suits well the majority of the cases where a client needs to communicate with a server.&lt;/p&gt;

&lt;p&gt;However, imagine that you work for an e-commerce company and you have to implement the purchase button of the website. Would a regular synchronous request be enough to handle this case?&lt;/p&gt;

&lt;p&gt;If the customer clicks purchase you will probably need to check whether the warehouse has stock of the products, the user's credit card is valid, the delivery address exists, etc, but eventually a response will have to be given to the customer telling them that the purchase has been finished successfully. And even though you told the user so, the purchase process won't stop there. The logistics will need to separate all the items of the purchase and assemble the package, a delivery company will fetch them, and some tracking information will be sent to the user as the progress changes. And these things are naturally asynchronous. The user doesn't need to be waiting for all of them to happen before he knows his purchase is done. Otherwise, online shopping would be a huge pain.&lt;/p&gt;

&lt;p&gt;Here is where asynchronous communication enters the game. By using it you are able to leave things such as emails, logistic integrations, tracking, that don't need to be immediately taken care of for later, making sure that the user will receive the purchase feedback as soon as possible. &lt;/p&gt;

&lt;p&gt;Through messaging systems, we enable senders and receivers to communicate without the restriction that both must be available listening to the message at the same time. As the following image shows, the sender can produce a message and whenever the receiver is available, it will read and handle it.&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%2Fi%2Fz7rbpv62qn76242jtitd.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%2Fi%2Fz7rbpv62qn76242jtitd.png" alt="Messaging"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this mentioned scenario, imagine that instead of doing REST API calls to each system informing that an order was placed, you could just send a message to the queue saying "Hey, someone created an order, here's the information you might be interested in". Or even, "hey, the tracking position of that package has changed, you might want to do something about it".&lt;/p&gt;

&lt;p&gt;How beautiful would it be if all of your services that rely on this event could do whatever they need (and maybe even post follow-up messages?) whenever they're available to do it? Your email service would be really happy to be able to read this message calmly and send the update to the user when all its dependencies are available, isn't that so? That's what we want to achieve with asynchronous communication.&lt;/p&gt;

&lt;p&gt;So, what about this &lt;em&gt;Kafka&lt;/em&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Kafka?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kafka.apache.org/intro" rel="noopener noreferrer"&gt;Apache Kafka&lt;/a&gt; is a distributed streaming platform. It's built to be resilient and fault tolerant.&lt;/p&gt;

&lt;p&gt;You can achieve many use cases with Kafka, examples of it's usage could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Messaging&lt;/li&gt;
&lt;li&gt;Log gathering&lt;/li&gt;
&lt;li&gt;Stream processing&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kafka.apache.org/documentation/#uses" rel="noopener noreferrer"&gt;etc.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article we'll go through an overview of some Kafka core concepts to enable you to have some understanding of its main features with the focus on using it for messaging and distributed systems communication.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Topics&lt;/li&gt;
&lt;li&gt;Partitions&lt;/li&gt;
&lt;li&gt;Brokers&lt;/li&gt;
&lt;li&gt;Producers&lt;/li&gt;
&lt;li&gt;Consumers&lt;/li&gt;
&lt;li&gt;Consumer Groups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all these concepts, Kafka's proposition is to deliver a structure that enables horizontal scalability and high performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://kafka.apache.org/intro#intro_topics" rel="noopener noreferrer"&gt;Topics&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A topic is where your messages will be sent to (produced). Whoever wants to read this piece of information will read it (consume) from the topic.&lt;br&gt;
Inside Kafka, you may have as many topics as you want and each topic contains a given number of partitions (defined by you when creating the topic). So, whenever producing a message to a topic it will be written in a given partition of the topic, randomly selected unless a key is provided.&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%2Fi%2Fva82q85g0hqjc5g2ymvv.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%2Fi%2Fva82q85g0hqjc5g2ymvv.png" alt="Topic and Partitions"&gt;&lt;/a&gt;&lt;br&gt;
(image from Kafka &lt;a href="https://kafka.apache.org/intro" rel="noopener noreferrer"&gt;docs&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Within the topic, data is kept for some time. The default value is 7 days, but it can be extended. There are cases where these messages are kept on the topic for one year. One important thing here is that after a message is written in a given partition, you will no longer be able to change it. Being able to store the data for such a long period of time, enabling you to reprocess the messages, if necessary, is what makes Kafka reliable. After seeing some use cases for it in production, I can safely assure that this will be life-saving in some cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Partitions
&lt;/h3&gt;

&lt;p&gt;Within each partition the messages will be ordered, receiving an incremental id called offset in Kafka. A consumer is basically pointing to the last offset it was read, whenever a new message is consumed, this pointer moves forward to the next message. This process is an &lt;code&gt;offset commit&lt;/code&gt;, which is always incremental.&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%2Fi%2F9kq3ki1xsdcj1xg8f4lv.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%2Fi%2F9kq3ki1xsdcj1xg8f4lv.png" alt="Partitions and Offsets"&gt;&lt;/a&gt;&lt;br&gt;
(image from Kafka &lt;a href="https://kafka.apache.org/intro" rel="noopener noreferrer"&gt;docs&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Brokers
&lt;/h3&gt;

&lt;p&gt;When using Kafka, the infrastructure you will have is a Kafka Cluster. This cluster is basically a bunch of servers, in our case, the brokers. So, what is this broker for?&lt;/p&gt;

&lt;p&gt;Remember when we said that a topic consists of many partitions? To be more resilient and handle server failures, each broker will contain a certain topic partition.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When connecting to a broker (Bootstrap server), you're connected to the entire cluster. Every Kafka broker is a bootstrap server which knows about all brokers, topics and partitions. When the Kafka Client connects to a Broker, it will receive a list of all brokers and can eventually connect to one of them, if needed. Brokers are identified by an ID.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's imagine a cluster with 3 brokers and one topic (called A). To achieve resilience in the delivery of the messages, we need some replica of the information, right? Just in case something goes wrong in one of the servers.&lt;/p&gt;

&lt;p&gt;This is called &lt;code&gt;replication factor&lt;/code&gt; in Kafka and topics should have a replication factor &amp;gt; 1, usually between 2 and 3.&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%2Fi%2Ffqfpza7tlljsk2rhwhmr.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%2Fi%2Ffqfpza7tlljsk2rhwhmr.png" alt="Brokers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, we have a replication factor of 2, therefore, each partition is present in 2 brokers. So, in the case a broker becomes unavailable, you're still able to read the partition from another broker. However, if we had a replication factor of 3, we could afford even losing two brokers and we would still have the three partitions in one broker to work with.&lt;/p&gt;

&lt;h4&gt;
  
  
  How replication works?
&lt;/h4&gt;

&lt;p&gt;At any given point in time, one broker (and only one) can be a leader for a given partition. The other partitions are called &lt;code&gt;In Sync Replicas&lt;/code&gt; (ISR). When writing to a topic, only the leader can provide data for a partition and the brokers will need to sync the data.&lt;/p&gt;

&lt;h4&gt;
  
  
  Compression
&lt;/h4&gt;

&lt;p&gt;You can enable data compression in the Broker configuration to reduce the size of messages, see more in &lt;a href="https://kafka.apache.org/23/documentation.html#configuration" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Search for &lt;code&gt;compression.type&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://kafka.apache.org/intro#intro_producers" rel="noopener noreferrer"&gt;Producers&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To enable ourselves to use Kafka we need to be able to read and write messages to our loved topics, isn't that so? Therefore, we need to have an &lt;a href="https://kafka.apache.org/documentation/#producerapi" rel="noopener noreferrer"&gt;API&lt;/a&gt; that makes that possible.&lt;/p&gt;

&lt;p&gt;The producers are the ones responsible to write data to the topics (remember that this data will actually be written into a partition). If we want to summarise what a producer is, that would be it. However, if we only had this in the API it wouldn't be resilient.&lt;/p&gt;

&lt;p&gt;For that, a producer is able to detect a failure in the broker and recover from that producing to another broker. Like it has been said, keys can also be sent within the messages to enable ordering. If no key is present, the data will be sent to a partition on a round robin selection. However, with the key, a hash will be made out of that and the key will always be sent to the partition of that given hash.&lt;/p&gt;

&lt;p&gt;This is to enable order in messages. One thing to consider is that the number of partitions can never change otherwise the hashing mechanism will change and the guarantee won't be there for you anymore.&lt;/p&gt;

&lt;h4&gt;
  
  
  Acknowledgment
&lt;/h4&gt;

&lt;p&gt;It's possible to choose to receive acks when producing messages.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ack Value&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;No ack is needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Wait for leader to ack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;all&lt;/td&gt;
&lt;td&gt;Leader + replicas must ack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Something worth mentioning is that it is possible to configure retries in Kafka, with backoff configuration and timeout. But remember, with retries, Kafka could send messages out of order if you have that configured, be aware.&lt;/p&gt;

&lt;p&gt;Something else is that you can achieve idempotent producers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[...] The idempotent producer strengthens Kafka's delivery semantics from at least once to exactly once delivery. In particular producer retries will no longer introduce duplicates. [...]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://kafka.apache.org/24/javadoc/index.html?org/apache/kafka/clients/producer/KafkaProducer.html" rel="noopener noreferrer"&gt;Read more on it&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://kafka.apache.org/intro#intro_consumers" rel="noopener noreferrer"&gt;Consumers&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now we reached the point where we'll read the messages from a given topic. Consumers know which broker to read from and each consumer will read from a given partition (or multiple partitions as well, more on this later). By not having multiple consumers in the same partitions, Kafka ensures that the message will not be processed by two consumers. Here's the &lt;a href="https://kafka.apache.org/24/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html" rel="noopener noreferrer"&gt;API&lt;/a&gt; for reference.&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%2Fi%2F7xdqwom8ui74bq5q0t3b.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%2Fi%2F7xdqwom8ui74bq5q0t3b.png" alt="Consumers"&gt;&lt;/a&gt;&lt;br&gt;
(image from Kafka &lt;a href="https://kafka.apache.org/intro" rel="noopener noreferrer"&gt;docs&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;
  
  
  Consumer Groups
&lt;/h4&gt;

&lt;p&gt;Consumers are tied to a consumer group. As we can see in the image above, each server contains Partitions (P#, where # is the partition number) and each Consumer belongs to a given Consumer Group. Each consumer from Consumer Group A reads from two topics, but each consumer from Consumer Group B reads from a single partition. When each consumer reads from a single partition and you send messages with keys, you can ensure that consumers will read the message from the partition it reads from in an ordered manner. Important, if you have more consumers than partitions, some consumers will be inactive.&lt;/p&gt;

&lt;h4&gt;
  
  
  Offsets
&lt;/h4&gt;

&lt;p&gt;Consumer offsets are for a given consumer group and they're stored by Kafka when committed. This commit happens when the data received by the consumer is processed.&lt;/p&gt;

&lt;p&gt;Consumers choose when to commit these offsets. Three types are available:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Delivery&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;at most once&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;As soon as the message is received&lt;/strong&gt;, offset is committed. Process failures means lost messages.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;at least once&lt;/td&gt;
&lt;td&gt;Commits the offset when message is &lt;strong&gt;processed&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exactly once&lt;/td&gt;
&lt;td&gt;I'll leave a blog post from Confluence &lt;a href="https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it/" rel="noopener noreferrer"&gt;here&lt;/a&gt; since it's a bit more complex.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One thing to be aware of is that when using &lt;code&gt;at least once&lt;/code&gt; configuration, you may read the message more than once, so be prepared for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;p&gt;So, I've been working for the past year with Node; therefore, the library we use is &lt;a href="https://kafka.js.org/docs/getting-started" rel="noopener noreferrer"&gt;KafkaJS&lt;/a&gt;. An open-source library, with some really good features and easy to start working with. If you want to get started with the basics, check it out! :)&lt;/p&gt;

&lt;p&gt;Also, follow this &lt;a href="https://kafka.js.org/docs/running-kafka-in-development" rel="noopener noreferrer"&gt;doc&lt;/a&gt; to enable yourself to run Kafka locally (with Docker) and be happy :)&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kafka.apache.org/intro" rel="noopener noreferrer"&gt;https://kafka.apache.org/intro&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kafka.apache.org/documentation/" rel="noopener noreferrer"&gt;https://kafka.apache.org/documentation/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kafka.apache.org/24/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html" rel="noopener noreferrer"&gt;https://kafka.apache.org/24/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kafka.apache.org/24/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html" rel="noopener noreferrer"&gt;https://kafka.apache.org/24/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JS Library&lt;/strong&gt;: &lt;a href="https://kafka.js.org/docs/getting-started" rel="noopener noreferrer"&gt;https://kafka.js.org/docs/getting-started&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Appreciations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Túlio Ornelas, for having a lot of patience when helping me while I was building some communications using Kafka.&lt;/li&gt;
&lt;li&gt;Gabriel Gomes, for doing such a neat review on this text and helping me improve the readability (also fixing my English mistakes hahaha). &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kafka</category>
      <category>distributedsystems</category>
      <category>messaging</category>
    </item>
  </channel>
</rss>
