<?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: Luis Felipe Ciochetta</title>
    <description>The latest articles on DEV Community by Luis Felipe Ciochetta (@ciochetta).</description>
    <link>https://dev.to/ciochetta</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%2F407822%2F2c7f8f29-5748-4419-bdcf-00b2fd94c6d8.jpeg</url>
      <title>DEV Community: Luis Felipe Ciochetta</title>
      <link>https://dev.to/ciochetta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ciochetta"/>
    <language>en</language>
    <item>
      <title>Idempotence - what is and how to implement</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Tue, 14 Feb 2023 12:24:52 +0000</pubDate>
      <link>https://dev.to/woovi/idempotence-what-is-and-how-to-implement-4bmc</link>
      <guid>https://dev.to/woovi/idempotence-what-is-and-how-to-implement-4bmc</guid>
      <description>&lt;p&gt;In the context of development, idempotence means that calling a certain function once or multiple times should have the same effect on the system's state.&lt;/p&gt;

&lt;p&gt;Being idempotent does not mean the return value is always the same, but that the function, if it has changed the system state, does not make any further changes if it is immediately called again with the same parameters.&lt;/p&gt;

&lt;p&gt;So, for example, a function that returns the balance of an account is idempotent, even if it returns different values, because other functions may have changed the system state between one call and another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idempotence in our APIs
&lt;/h2&gt;

&lt;p&gt;When using our APIs, to ensure idempotency in calls, we use the pattern known as &lt;code&gt;Idempotence-Key&lt;/code&gt;, which means that when making a call to our API, it is important to specify an ID that your system understands as corresponding to the operation.&lt;/p&gt;

&lt;p&gt;The way we implement Idempotence-Key in our system is through the a property named "correlationID" inside the body. &lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You want to use our API to create a charge&lt;/p&gt;

&lt;p&gt;In your system, you should have a table/collection that represents the creation of the charge, create a document and get its ID&lt;/p&gt;

&lt;p&gt;In the call to our API, add a correlationID property with that ID.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When using our webhooks, it is necessary to ensure that the route that handles the webhooks is idempotent, as it is common practice to resend webhooks to ensure that at least one of them has arrived and been processed. At the end of this document, there are examples of how you can implement this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is idempotence relevant?
&lt;/h2&gt;

&lt;p&gt;A recurring problem in event-driven systems is duplicating events, which can occur for many reasons, such as communication failures, parallel invocations of the functions that generate the events, etc.&lt;/p&gt;

&lt;p&gt;Resilient systems are built taking into consideration that these problems can and will frequently happen, and preparing adequately so that communication failures do not cause a bad internal state.&lt;/p&gt;

&lt;p&gt;So, the main importance of idempotence is to make your system resilient and reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should a function be idempotent?
&lt;/h2&gt;

&lt;p&gt;As with everything in development, it heavily depends on the project goal and business rules.&lt;/p&gt;

&lt;p&gt;However, there are some patterns:&lt;/p&gt;

&lt;h3&gt;
  
  
  REST APIs
&lt;/h3&gt;

&lt;h4&gt;
  
  
  PUT routes
&lt;/h4&gt;

&lt;p&gt;All routes with the PUT verb, which make changes to entities.&lt;/p&gt;

&lt;p&gt;For example: A route that serves to change the address of a client.&lt;/p&gt;

&lt;p&gt;As long as the new address is the same, it shouldn't matter to the system state how many times that route is called.&lt;/p&gt;

&lt;h4&gt;
  
  
  GET routes
&lt;/h4&gt;

&lt;p&gt;All routes with the GET verb, which are meant to read information.&lt;/p&gt;

&lt;p&gt;For example: A route that serves to read the current balance of a bank account.&lt;/p&gt;

&lt;p&gt;Even if the balance changes over time, it is safe to call this route multiple times without causing changes to the system state.&lt;/p&gt;

&lt;h4&gt;
  
  
  DELETE routes
&lt;/h4&gt;

&lt;p&gt;All routes with the DELETE verb, which are meant to delete entities.&lt;/p&gt;

&lt;p&gt;For example: A route that serves to delete a charge.&lt;/p&gt;

&lt;p&gt;Once called, the function will delete the bank account, subsequent calls should not delete other accounts, but return a message saying that this account has already been deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Idempotence
&lt;/h2&gt;

&lt;p&gt;These are some patterns for implementing idempotence:&lt;/p&gt;

&lt;h3&gt;
  
  
  GetOrCreate Pattern
&lt;/h3&gt;

&lt;p&gt;The idea behind this pattern is to check if the entity that the function is trying to create already has an equivalent created in the database.&lt;/p&gt;

&lt;p&gt;Assuming this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="c1"&gt;// Model validation&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Creating the account in the database&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Applying this pattern, it can be rewritten as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getOrCreateCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="c1"&gt;// Before making creation validations, we can look for the most important parameters in our database and return an already existing account&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;bankId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bankId&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;existingCustomerBankAccount&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;existingCustomerBankAccount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Model validation&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Creating the account in the database&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;h3&gt;
  
  
  Call History Pattern
&lt;/h3&gt;

&lt;p&gt;The idea behind this pattern is to save all calls made to the route that deals with events and upon receiving a new call, check if there is not a similar call that was made previously.&lt;/p&gt;

&lt;p&gt;Assuming this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="c1"&gt;// Model validation&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Creating the account in the database&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Applying this pattern, it can be rewritten as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&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;newRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&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;existingRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&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="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newRequest&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;existingRequest&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="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Model validation&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Creating the account in the database&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;// Saving the event for future calls&lt;/span&gt;
    &lt;span class="nx"&gt;db&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="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({...&lt;/span&gt;&lt;span class="nx"&gt;newRequest&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;Or, we can use hashing to save storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&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;newRequestHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MD5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&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;existingRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&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="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newRequestHash&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;existingRequest&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="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Model validation&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Creating the account in the database&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;db&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="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newRequestHash&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;h3&gt;
  
  
  Idempotence-Key Pattern
&lt;/h3&gt;

&lt;p&gt;The idea behind this pattern is to use a key to represent an operation, and upon receiving a duplicate key, not repeat the operation.&lt;/p&gt;

&lt;p&gt;We use a similar pattern to this in our APIs through the correlationID property.&lt;/p&gt;

&lt;p&gt;Assuming this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="c1"&gt;// Model validation&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Creating the account in the database&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Applying this pattern, it can be rewritten as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCustomerBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;idempotenceKey&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Check if the user sent an idempotence key&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;idempotenceKey&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;existingBankAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nx"&gt;idempotenceKey&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="c1"&gt;// Checking if there is any registered account with this key and returning it if we find&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;existingBankAccount&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;existingBankAccount&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="c1"&gt;// Model validation&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="c1"&gt;// Creating the account in the database&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerBankAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;If you want to work in a startup in its early stages, This is your chance. &lt;a href="https://woovi.com/jobs/" rel="noopener noreferrer"&gt;Apply today&lt;/a&gt;!&lt;/p&gt;




&lt;p&gt;&lt;a href="https://woovi.com/" rel="noopener noreferrer"&gt;Woovi&lt;/a&gt; is a Startup that enables shoppers to pay as they please. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.&lt;/p&gt;

&lt;p&gt;If you want to work with us, &lt;a href="https://woovi.com/jobs/" rel="noopener noreferrer"&gt;we are hiring&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>career</category>
      <category>cloudcomputing</category>
      <category>cloudpractitioner</category>
    </item>
    <item>
      <title>Learning Observability (w/ OpenTelemetry and Jaeger)</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Thu, 16 Dec 2021 23:41:03 +0000</pubDate>
      <link>https://dev.to/ciochetta/learning-observability-w-opentelemetry-and-jaeger-1kjb</link>
      <guid>https://dev.to/ciochetta/learning-observability-w-opentelemetry-and-jaeger-1kjb</guid>
      <description>&lt;p&gt;Hey folks, there has been a long time since I have last posted anything here and I wanted to start writing again.&lt;/p&gt;

&lt;p&gt;A quick disclaimer, as always, I am learning as I write this article, so I may get something wrong, I would love some feedback if you catch anything&lt;/p&gt;

&lt;p&gt;My idea here is to make some projects to teach myself how to create highly observable services&lt;/p&gt;

&lt;h3&gt;
  
  
  First Project: Fibonacci
&lt;/h3&gt;

&lt;p&gt;To start, I've decided to follow the golang  &lt;a href="https://opentelemetry.io/docs/instrumentation/go/getting-started/"&gt;OpenTelemetry tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And used the &lt;a href="https://github.com/open-telemetry/opentelemetry-go/blob/main/example/jaeger/main.go"&gt;jaeger example&lt;/a&gt; to create the tracer provider.&lt;/p&gt;

&lt;p&gt;The result for this project is a simple program that calculates Fibonacci based on the input you provide and sends the data about each individual operation to jaeger&lt;/p&gt;

&lt;p&gt;It looks like this in the jaeger UI: &lt;/p&gt;

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

&lt;p&gt;The important concepts behind this project are traces, spans, and tracer providers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Traces
&lt;/h4&gt;

&lt;p&gt;Traces are an abstraction for an operation or call inside your system, and they are composed by spans.&lt;/p&gt;

&lt;p&gt;Traces can track the life-cycle of a operation through many processes (I will probably get there in the next project).&lt;/p&gt;

&lt;p&gt;In the case of this program, this is the trace strucutre:&lt;/p&gt;

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

&lt;p&gt;Specifically in golang, the context library is used to create this structure, so you will need a context for each separate trace.&lt;/p&gt;

&lt;h4&gt;
  
  
  Spans
&lt;/h4&gt;

&lt;p&gt;Spans are the subdivisions of a trace, the way I see it, they are meant to represent each function execution inside a given trace.&lt;/p&gt;

&lt;p&gt;Each span can contain attributes, that are key/value pairs that should represent the state of that function when they're called.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tracer Provider
&lt;/h4&gt;

&lt;p&gt;Tracer providers are configurations for the project about where to send the tracing data and how to send it.&lt;/p&gt;

&lt;p&gt;In the case of this project, that would be jaeger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second Project: Square
&lt;/h3&gt;

&lt;p&gt;The second project was customized, I did not write the steps for it in as much detail as these documentations, but it's fairly simple code (the link for the repositories is at the end of the post).&lt;/p&gt;

&lt;p&gt;The idea was to create two services and a trace that would have spans in both services.&lt;/p&gt;

&lt;p&gt;So I have created this two services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API: has an http server that receives requests and calls the other service&lt;/li&gt;
&lt;li&gt;Square: squares the number sent to it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how a request looks like for the user &amp;gt;&lt;/p&gt;

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

&lt;p&gt;And this is how it looks on jaeger &amp;gt;&lt;/p&gt;

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

&lt;p&gt;And the structure for the trace &amp;gt;&lt;/p&gt;

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

&lt;p&gt;And as a nice side effect, you also get this graph that shows the dependencies for your services and the number of requests sent from a service to another &amp;gt;&lt;/p&gt;

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

&lt;p&gt;And for this second project there was a single new relevant concept: propagators &lt;/p&gt;

&lt;h4&gt;
  
  
  Propagators
&lt;/h4&gt;

&lt;p&gt;Propagators are the tool used to share context;&lt;/p&gt;

&lt;p&gt;The metadata is injected in the headers for the request, then the server receiving the request extracts it and adds to it's own spans.&lt;/p&gt;

&lt;p&gt;The result is this graphic where you know how much time the trace spent in each service and in each operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Words
&lt;/h3&gt;

&lt;p&gt;So, I covered the basics of observability, and I can see how this would be relevant on onboarding members to your team and also to debugging&lt;/p&gt;

&lt;p&gt;Next I will probably try to learn other observability tools like prometheus and grafana&lt;/p&gt;

&lt;h3&gt;
  
  
  Repositories
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ciochetta"&gt;
        ciochetta
      &lt;/a&gt; / &lt;a href="https://github.com/ciochetta/learn-jaeger"&gt;
        learn-jaeger
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      repository for learning jaeger
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ciochetta"&gt;
        ciochetta
      &lt;/a&gt; / &lt;a href="https://github.com/ciochetta/go-square"&gt;
        go-square
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      square service for my learning jaeger article 
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Useful links
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://opentelemetry.io/docs/concepts/what-is-opentelemetry/"&gt;https://opentelemetry.io/docs/concepts/what-is-opentelemetry/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.jaegertracing.io/docs/1.29/getting-started/"&gt;https://www.jaegertracing.io/docs/1.29/getting-started/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/open-telemetry/opentelemetry-go"&gt;https://github.com/open-telemetry/opentelemetry-go&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/open-telemetry/opentelemetry-go/blob/main/example/jaeger/main.go"&gt;https://github.com/open-telemetry/opentelemetry-go/blob/main/example/jaeger/main.go&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>todayilearned</category>
      <category>go</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Book notes: Hooked - Chapter 1</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Wed, 07 Apr 2021 11:32:43 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-hooked-chapter-1-153l</link>
      <guid>https://dev.to/ciochetta/book-notes-hooked-chapter-1-153l</guid>
      <description>&lt;h3&gt;
  
  
  Chapter 1 - The Habit Zone
&lt;/h3&gt;

&lt;p&gt;This chapter is a 22 pages long sales pitch. I was really annoyed by it. If you plan to extract value from reading this book, you can just skip chapter one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Habits are formed from solving our needs, our brain starts to associate actions with pleasant experiences (solving problems) and this might become a behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Habit-making products increase the amount of cash you can generate from a single customer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;People are less sensitive to the price of products that are part of their day-to-day life.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leaving a product you have formed a habit around is very difficult. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ Say you want to stop using Instagram, then you would have to think of another way to store and share your photos with your friends that also use Instagram and think of new ways of contacting them. So Instagram, for being a habit-forming product has you hooked to it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To use habit-forming as a strategy you have to focus on increasing the frequency of use of your product and the value you generate each time. Some behaviors are bound to not repeat as much as others, then you would need to focus more on delivering value.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>design</category>
    </item>
    <item>
      <title>Book notes: Hooked - Introduction</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Mon, 05 Apr 2021 11:40:10 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-hooked-introduction-26da</link>
      <guid>https://dev.to/ciochetta/book-notes-hooked-introduction-26da</guid>
      <description>&lt;p&gt;Hey folks&lt;/p&gt;

&lt;p&gt;I've decided I should probably read some of the books I've bought in the last years before I bought any new, so I am starting today the reading of "Hooked: how to build habit-forming products". &lt;/p&gt;

&lt;p&gt;As far as I was told, this is a book mostly about design, not coding or anything related.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Habits are behaviors we have but don't think much about.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Companies should focus on creating habit-forming products.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hook model is made of four parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;1 - trigger: what starts the action, can be divided into external (ads, emails etc) and internal (psychological needs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;2 - action: the thing people do to interact with a product (click a button). Actions should be easy to do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3 - variable reward: the result of the action. This result must change in order to get people hooked, the reward must not be predictable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;4 - investment: the user puts something into the product (money, time, data, etc) and that improves his experience for his next hook cycle.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>design</category>
    </item>
    <item>
      <title>Learning Event-Driven Architecture</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Mon, 15 Mar 2021 12:49:34 +0000</pubDate>
      <link>https://dev.to/ciochetta/learning-event-driven-architecture-4en2</link>
      <guid>https://dev.to/ciochetta/learning-event-driven-architecture-4en2</guid>
      <description>&lt;p&gt;Hello folks!&lt;/p&gt;

&lt;p&gt;I've been studying event-driven architecture for about a month now, and I wanted to write about it so I can better fix the knowledge in my head.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick disclaimer
&lt;/h2&gt;

&lt;p&gt;I am using Apache Kafka in my studies because that is what we use in the company I work with, but I am sure that most concepts I've learned can be applied to other tools.&lt;/p&gt;

&lt;p&gt;Also, as I have mentioned, I am a beginner in this subject, I could be very wrong about some things, and if I am, I would love some feedback about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What
&lt;/h3&gt;

&lt;p&gt;Event-driven architecture is a way of thinking about software architecture where things (events) happen in the business and our system reacts to it.&lt;/p&gt;

&lt;p&gt;This architecture has three main components: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;event emitters&lt;/strong&gt; (aka producers, aka publishers) that are responsible for capturing and sending events to the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;event listeners&lt;/strong&gt; (aka consumers, aka subscribers) that react to the events applying business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;brokers&lt;/strong&gt; which are the glue that receives the events from the emitters and sends them to the listeners. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As far as I know, event-driven architecture is always based on microservices, meaning, each of these components is a separate service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why
&lt;/h3&gt;

&lt;p&gt;Event-driven architecture solves the problem of having a huge volume of data that needs to be asynchronously processed while supporting future change in the system.&lt;/p&gt;

&lt;p&gt;Most of the examples I've found talk about payment processing, where you can have N orders being processed by different services so the information can come out of order and have multiple outcomes that need to be handled in a unique way.&lt;/p&gt;

&lt;p&gt;Maybe you want to have systems that both notify the user about a failed payment and send information to a business dashboard; &lt;/p&gt;

&lt;p&gt;You achieve this with both monolithic and regular microservices architectures, however, this will lead to more dependency between your modules or services.&lt;/p&gt;

&lt;p&gt;But if you have an event-driven architecture you could easily just write a new service that handles this exact same data (let's say you also need a client dashboard now) without interfering with how the other two systems work.&lt;/p&gt;

&lt;h3&gt;
  
  
  How
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;I will grossly over-simplify the process of implementing this architecture but I intend to make other posts on the subject explaining it better.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1 - Pick a message software.
&lt;/h4&gt;

&lt;p&gt;There is plenty of message queue software out there, do some research on their pros and cons.&lt;/p&gt;

&lt;p&gt;Pick the one that makes more sense to your needs.&lt;/p&gt;

&lt;h4&gt;
  
  
  2 - Map your business needs and business events add them to your architecture.
&lt;/h4&gt;

&lt;p&gt;Like in the example in the previous section, you have both events and business needs, add them to your design. so it should look like this &amp;gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Item purchase&lt;/em&gt; &amp;gt; ? &amp;gt; &lt;em&gt;Notifiying customer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You will need to do something like this process for each of your business needs. In this case, the business need is to have customers notified of their successful purchases.&lt;/p&gt;

&lt;h4&gt;
  
  
  3 - Design a path in which the data is transformed from events to fulfilling your needs.
&lt;/h4&gt;

&lt;p&gt;Now is time to design the services that you will need to make this event into a notification.&lt;/p&gt;

&lt;p&gt;In this case, we should need only two more steps, one to validate the order and one to notify the customer.&lt;/p&gt;

&lt;p&gt;So our project would look something like this &amp;gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Item purchase event&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Order validation service acts upon this event, generating another event for validated order (or invalid).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notifying services acts upon this event and send the notification to the user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4 - Set communication interfaces for the services.
&lt;/h4&gt;

&lt;p&gt;For each of these events, we need a (preferably documented) data structure that represents what happened, so other services can later act upon the events.&lt;/p&gt;

&lt;h4&gt;
  
  
  5 - Done, start coding.
&lt;/h4&gt;

&lt;p&gt;The architecture phase is done, you can move to develop the system.&lt;/p&gt;




&lt;p&gt;Once you finished doing all of this work, you will most likely have a lot of new ideas on how to improve your architecture, and that's why you should always keep in mind that can and will occur, your systems and data structures should be easy to alter.&lt;/p&gt;

</description>
      <category>eventdriven</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Book notes: Clean Code - Chapter 9</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Thu, 11 Mar 2021 01:03:39 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-clean-code-chapter-9-30bi</link>
      <guid>https://dev.to/ciochetta/book-notes-clean-code-chapter-9-30bi</guid>
      <description>&lt;h3&gt;
  
  
  Chapter 9 - Unit Tests
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We should try to write &lt;em&gt;clean&lt;/em&gt; tests, meaning that we should make the tests as easy to maintain as the functions they are testing. If the functions are changing as business needs evolve, so should the tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Test code is just as important as production code. It is not a second-class citizen. It requires thought, design, and care. It must be kept as clean as production code. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Tests enable bold changes to the code base.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ This is kinda obvious, but I'm keeping it here to remember myself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean tests should be as elegant as clean production code. They should be designed to be read.&lt;/li&gt;
&lt;li&gt;Tests should follow the BUILD-OPERATE-CHECK pattern.&lt;/li&gt;
&lt;li&gt;There are things you can do in a testing environment that you cannot in production. But they are not related to code cleanliness, but to resource usage.&lt;/li&gt;
&lt;li&gt;We should try to minimize the assert statements per test.&lt;/li&gt;
&lt;li&gt;We should have one concept per test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;F.I.R.S.T. rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast: Tests should run fast, so people always want to run them.&lt;/li&gt;
&lt;li&gt;Independent: You should be able to run any test independently.&lt;/li&gt;
&lt;li&gt;Repeatable: Tests should run in any environment.&lt;/li&gt;
&lt;li&gt;Self-validating: Tests should have a boolean output, you should not have to think or investigate to know if it passed.&lt;/li&gt;
&lt;li&gt;Timely: Tests should be written just before production code.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
    </item>
    <item>
      <title>Book notes: Clean Code - Chapter 8</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Tue, 09 Mar 2021 10:25:07 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-clean-code-chapter-8-1556</link>
      <guid>https://dev.to/ciochetta/book-notes-clean-code-chapter-8-1556</guid>
      <description>&lt;h3&gt;
  
  
  Chapter 8 - Boundaries
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We can and should keep third party code abstracted so we have control over which properties and methods are accessible&lt;/li&gt;
&lt;li&gt;We should create tests for third-party code so we create a better understanding of it and how we can use it on our application. This would also make us sure that if these libraries update in the future, that portion we are using in our code did not broke.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ I don't think this is very practical, most libraries are not that easy to write relevant tests on. I can see why this is good and will try to do this in a future project but I am not optimistic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When writing code that will integrate with code that doesn't yet exists and have no interface, we can create a class that has the interface we wish we had to mock that integration. Once we have the real code, we can adapt this class and abstract the implementation of the newly written module.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
    </item>
    <item>
      <title>Book notes: Clean Code - Chapter 7</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Mon, 08 Mar 2021 23:58:33 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-clean-code-chapter-7-305j</link>
      <guid>https://dev.to/ciochetta/book-notes-clean-code-chapter-7-305j</guid>
      <description>&lt;h3&gt;
  
  
  Chapter 7 - Error Handling
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Error handling is important, but if it obscures logic, it’s wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Exceptions are better than returning error codes. When using exceptions we can just follow the logic path until the end, and if there is an exception it will be caught later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ So, he mentions this in a previous chapter, I have also included this here just so I can find it later&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When writing our tests, we should try to create tests that generate exceptions. This will force us to put all the correct logic inside the try block for our function.&lt;/li&gt;
&lt;li&gt;We should provide meaningful context to our exceptions&lt;/li&gt;
&lt;li&gt;We should not return null if something went wrong, if we return null, then we will have to check for null in every interaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ Ouch, can't count on my fingers the amount of times I wrote a function that returns null last month&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passing null as an argument is even worst than returning it. &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
    </item>
    <item>
      <title>Book notes: Clean Code - Chapter 6</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Mon, 08 Mar 2021 00:36:25 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-clean-code-chapter-6-37mk</link>
      <guid>https://dev.to/ciochetta/book-notes-clean-code-chapter-6-37mk</guid>
      <description>&lt;h3&gt;
  
  
  Chapter 6 - Objects and Data Structures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keeping implementation of functions private is a matter of abstraction. The user of a class does not need to know the details on how the command issued will be taken care of. &lt;/li&gt;
&lt;li&gt;The worst option is to just create getters and setters, we should think about the best way to expose the data and how it will be used.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Hybrids between objects and data structures are bad. they make adding new data and new functions hard. In order to avoid creating such hybrids, we can create data structures and then encapsulate these data structures within objects that have functions.&lt;/li&gt;
&lt;li&gt;We can add commands to objects that call commands on their internal properties to avoid making chain calls.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
    </item>
    <item>
      <title>Book notes: Radical Candor - Part 1, Chapter 1</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Wed, 03 Feb 2021 02:03:50 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-radical-candor-50dn</link>
      <guid>https://dev.to/ciochetta/book-notes-radical-candor-50dn</guid>
      <description>&lt;p&gt;Hello folks&lt;/p&gt;

&lt;p&gt;I was about to finish my reading of "Radical Candor" when I realized that I should have documented my whole study process like I am doing with other subjects I am studying.&lt;/p&gt;

&lt;p&gt;So I am starting the book over and this time I will write notes and publish them here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: if you never heard of this book, it is a book about managing people, it is not a technical book about programming&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Part 1 - A new management philosophy
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Chapter 1 - Build radically candid relationships
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is not babysitting, it's called management and it is your job" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;^ So this is one of the first things she says in the book and well, I am someone that has complained in the past about having to babysit adults because they just could not focus.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Emotional labor (aka babysitting) is a huge part of management.&lt;/li&gt;
&lt;li&gt;Bosses have three responsibilities: guidance, team-building, and results.&lt;/li&gt;
&lt;li&gt;Good relationships are the key to good management.&lt;/li&gt;
&lt;li&gt;There is a direct correlation between a manager's responsibilities and relationships with his direct reports. good guidance, team building, and achieving results make for better relationships, and failing to fulfill these responsibilities leads to bad relationships.&lt;/li&gt;
&lt;li&gt;There are two dimensions that can predict good relationships, "caring personally" and "challenging directly".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ These two dimensions are very important, they are the foundation from where the Radical Candor framework emerges.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caring personally here means that you should know people who work with you on a personal level, not caring only about what affect their job.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ Ironically, if this framework is correct, caring about the stuff that is not job-related has a big impact on the contributor's job;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Challenging directly here means telling the truth, delivering feedback about bad situations, making hard choices, firing people. Basically, not being afraid to piss people off.&lt;/li&gt;
&lt;li&gt;When you have a relationship with someone where you care personally and challenge directly, you have a radically candid relationship.&lt;/li&gt;
&lt;li&gt;Radically candid relationships make for better communication, trust, and group cohesion.&lt;/li&gt;
&lt;li&gt;The job of a boss doesn't need to go in the direction of crushing his direct report's souls, it can be to mitigate the misery and bring joy to the work.&lt;/li&gt;
&lt;li&gt;People do not become bosses because they don't care about other people, and yet, this is how lots of people feel about their bosses.&lt;/li&gt;
&lt;li&gt;There is a fear of caring personally because it does not seem professional. Being professional should not mean hiding your feelings or thoughts, neither changing your personality. People are not comfortable doing those things. So you should not hide who you are and create a safe space for other people to do the same. &lt;/li&gt;
&lt;li&gt;You, as a boss, should not feel superior to your direct reports, being the boss is a job, not a value judgment. &lt;/li&gt;
&lt;li&gt;Challenging people is to embrace conflict as a way to grow, to give people the chance to correct themselves.&lt;/li&gt;
&lt;li&gt;Conflict may lead to hurt feelings, do not dismiss or disrespect the feelings of other people, instead, show them you care personally, and that's the source of the conflict.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"The hardest part of building trust is to invite people to challenge you just as directly as you are challenging them." &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;You should encourage people to challenge you in the same intensity, the one that can lead to hurt feelings. This can be hard, but it will lead you to learn about yourself.&lt;/li&gt;
&lt;li&gt;Radical candor is not about being rude or front-stabbing people. This would not be caring personally. Nor is it about talking about everything that comes to mind, it's about meaningful conversations.&lt;/li&gt;
&lt;li&gt;Both caring personally and challenging directly are different from person to person. Not everyone feels comfortable with the same levels of intimacy and conflict. &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>management</category>
      <category>leadership</category>
    </item>
    <item>
      <title>Book notes: Clean Code - Chapter 5</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Fri, 29 Jan 2021 16:54:25 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-clean-code-chapter-5-3pbl</link>
      <guid>https://dev.to/ciochetta/book-notes-clean-code-chapter-5-3pbl</guid>
      <description>&lt;p&gt;I will jump right into the notes, the description for the note formatting is in the first post of this series&lt;/p&gt;

&lt;h3&gt;
  
  
  Chapter 5 - Formatting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Good formatting is good for communication, and we should strive to have good communication&lt;/li&gt;
&lt;li&gt;Small files are better to understand (and therefore better to work with) when compared to big files &lt;/li&gt;
&lt;li&gt;Vertically close lines of code should have a close logical relation&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Variables should be declared as close to their usage as possible&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Functions that are called by another function in the same file should be right below the caller&lt;/li&gt;
&lt;li&gt;Big lines of code are bad, 120 characters/line is fine, more than that is not&lt;/li&gt;
&lt;li&gt;The team has the final word on the formatting rules for the codebase&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
    </item>
    <item>
      <title>Book notes: Clean Code - Chapters 1-4</title>
      <dc:creator>Luis Felipe Ciochetta</dc:creator>
      <pubDate>Wed, 27 Jan 2021 02:31:42 +0000</pubDate>
      <link>https://dev.to/ciochetta/book-notes-clean-code-chapters-1-4-2g5c</link>
      <guid>https://dev.to/ciochetta/book-notes-clean-code-chapters-1-4-2g5c</guid>
      <description>&lt;p&gt;Hello folks! &lt;/p&gt;

&lt;p&gt;I am starting a new series of posts about the books I am reading, these will be my notes on the book&lt;/p&gt;

&lt;p&gt;I thought about reading the entire book before publishing any notes, but I think this would take a long time, and if anyone has feedback, it would make the cycle bigger than it could be.&lt;/p&gt;

&lt;p&gt;So I will publish my notes as I read the book.&lt;/p&gt;

&lt;p&gt;The book I am currently reading is Clean Code, an absolute must-read in our profession, I am sure most people that will read this have already read the book, but I hope I can help these people remember its content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;p&gt;This is how I've structured my notes &lt;/p&gt;

&lt;h4&gt;
  
  
  Notes
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;first note&lt;/li&gt;
&lt;li&gt;second note&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n note&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Direct quotes
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a quote (not really)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Others
&lt;/h4&gt;

&lt;p&gt;Everything that is not a quote or a not is a personal thought &lt;/p&gt;

&lt;h3&gt;
  
  
  Notes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Chapter 1 - Clean Code
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Good code matters (obviously)&lt;/li&gt;
&lt;li&gt;It's our &lt;strong&gt;responsibility&lt;/strong&gt; as developers to communicate the risks of having a bad code to business people&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Code, without tests, is not clean. No matter how elegant it is"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;We should leave the code cleaner than when we've checked it out&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Chapter 2 - Meaningful Names
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Avoid meaningless names like "a", "a1", "b"&lt;/li&gt;
&lt;li&gt;Avoid noise words like "Data" or "Info"&lt;/li&gt;
&lt;li&gt;The length of a variable name should correspond to the size of its scope&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"There can be no worse reason for using the name &lt;em&gt;c&lt;/em&gt; than because &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt; were already taken."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;I laughed hard at this^&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand."&lt;/p&gt;

&lt;p&gt;"Classes and objects should have noun or noun phrase names like &lt;em&gt;Customer&lt;/em&gt;, &lt;em&gt;WikiPage&lt;/em&gt;, &lt;em&gt;Account&lt;/em&gt;, and &lt;em&gt;AddressParser&lt;/em&gt;"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Pick one word per concept, don't use "get" and "fetch" for the same thing&lt;/li&gt;
&lt;li&gt;Pick one concept per word, don't use "get" for both fetching and retrieving properties&lt;/li&gt;
&lt;li&gt;People who will read our code are programmers, so we should use technical names over domain names; Ideally, the name will express both technical usage and domain&lt;/li&gt;
&lt;li&gt;Add meaningful context; Using prefixes, namespaces, objects to hold information and with the name of other variables&lt;/li&gt;
&lt;li&gt;Don't add meaningless context; Don't prefix every single variable in your application with its name&lt;/li&gt;
&lt;li&gt;Shorter names are better when they are clear enough&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Chapter 3 - Functions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Functions should be small, as small as possible&lt;/li&gt;
&lt;li&gt;Functions should not hold nested structures; if, else and loops should have only one line, and if more is necessary, this should be a function call with a descriptive name&lt;/li&gt;
&lt;li&gt;Functions should only do one thing and deal with abstraction only one level below its name; &lt;/li&gt;
&lt;li&gt;If a function does only steps one level below of abstraction, it is only doing one thing; After all, we write functions to decompose large concepts&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Functions that do one thing cannot be reasonably divided into sections"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Functions should as few arguments as possible, having a lot of arguments make a function trickier to test&lt;/li&gt;
&lt;li&gt;Monadic functions (functions with 1 argument) should have two forms, you either ask a question to a function with its argument, and it has a return value that is that argument transformed, or you should have no return value and the function should change the state of the system&lt;/li&gt;
&lt;li&gt;Passing booleans to a monadic is a bad practice, if you are doing it, you probably should split that function in two&lt;/li&gt;
&lt;li&gt;When a function &lt;strong&gt;needs&lt;/strong&gt; more than two arguments, you can likely wrap then into an object &lt;/li&gt;
&lt;li&gt;Functions should have no side effects&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Side effects are lies. Your function promises to do one thing, but it also does other hidden things."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Functions should either do something or return something but not both&lt;/li&gt;
&lt;li&gt;We should use exceptions instead of returning error codes; When we return errors, we have to deal with them immediately, when we throw exceptions, we can deal with them later&lt;/li&gt;
&lt;li&gt;Try/catch blocks should each call their own functions&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Error handling is one thing"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Therefore, if we want our functions to do one thing, a function that handles errors should do only that&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 4 - Comments
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;"Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Before writing a comment, we should before try to better express ourselves through code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;^ This thing he says about comments is very important, he comes back to it a lot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a comment is not maintained with the code, sooner or later, it will be lying about the nature of the function or class it is talking about&lt;/li&gt;
&lt;li&gt;Lying comments are worst than no comment at all&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"It is possible to make the point that programmers should be disciplined enough to keep the comments in a high state of repair, relevance, and accuracy. I agree, they should. But I would rather that energy go toward making the code so clear and expressive that it does not need the comments in the first place."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;It is fine to write comments warning other developers of the possible consequences of using or changing a function&lt;/li&gt;
&lt;li&gt;It is fine to leave some TODO comments. But you should regularly try to eliminate them (implementing the changes they describe)&lt;/li&gt;
&lt;li&gt;Redundant comments are bad //&lt;em&gt;and useless&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Mandated comments are bad, don't tell other programmers to write huge comment headers for each function if the functions themselves are expressive and clear enough&lt;/li&gt;
&lt;li&gt;Journal/log comments are bad, this kind of comment should be kept in commit messages&lt;/li&gt;
&lt;li&gt;Comments announcing the start or the end of a subject are bad, unless you use them rarely and meaningfully &lt;/li&gt;
&lt;li&gt;Comments announcing the end of a subject or a function are bad&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commented-out code is bad&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Comments should be located near the code they talk about, this makes the maintaining of such comment easier&lt;/li&gt;
&lt;li&gt;Comments should not have a lot of information&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
    </item>
  </channel>
</rss>
