<?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: Davide Silva</title>
    <description>The latest articles on DEV Community by Davide Silva (@davidesilva_).</description>
    <link>https://dev.to/davidesilva_</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%2F345781%2F7439747b-fe93-4853-9133-483f7f0d4fe3.jpg</url>
      <title>DEV Community: Davide Silva</title>
      <link>https://dev.to/davidesilva_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidesilva_"/>
    <language>en</language>
    <item>
      <title>Storing custom structs in Cairo 1</title>
      <dc:creator>Davide Silva</dc:creator>
      <pubDate>Mon, 29 May 2023 23:00:00 +0000</pubDate>
      <link>https://dev.to/finiam/storing-custom-structs-in-cairo-1-54hf</link>
      <guid>https://dev.to/finiam/storing-custom-structs-in-cairo-1-54hf</guid>
      <description>&lt;p&gt;Let's imagine you are writing a Starknet smart contract in Cairo 1 and you want to store some complex data as the value of a map in your contract's storage. You probably want to use a custom struct to save that complex data but you'll find a small surprise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Struct
&lt;/h2&gt;

&lt;p&gt;You might define your custom struct like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Drop,&lt;/span&gt; &lt;span class="nd"&gt;Serde)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;CustomStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&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 use it on the Storage struct like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LegacyMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;felt252&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, so good. This makes perfect sense and it's the correct way of doing it.&lt;br&gt;
However, depending on your Cairo version, and at the time of writing, when you attempt to compile your contract, you might get the following error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;Detailed&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Trait&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;storage_access&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;StorageAccess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;hello_starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hello_starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HelloStarknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;
            &lt;span class="nn"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;StorageAccess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                     &lt;span class="o"&gt;^**^&lt;/span&gt;

&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Trait&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;storage_access&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;StorageAccess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;hello_starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hello_starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HelloStarknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;
            &lt;span class="nn"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;StorageAccess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                     &lt;span class="o"&gt;^***^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's the problem here? What this means is simply the StorageAccess Trait has no implementation of the &lt;code&gt;write&lt;/code&gt; and &lt;code&gt;read&lt;/code&gt; functions needed to access your CustomStruct in the Storage struct. For native types, this is automatically derived but since you defined your own CustomStruct, the compiler has no idea what to do.&lt;/p&gt;

&lt;p&gt;Note: this is a temporary problem and in newer versions of Cairo we no longer need to manually derive the implementation. This &lt;a href="https://github.com/starkware-libs/cairo/pull/3062"&gt;PR&lt;/a&gt; adds that functionality for custom structs used in Storage and is already available if you are using the &lt;code&gt;main&lt;/code&gt; branch of the Cairo compiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;So, while we wait for a proper release to include this functionality, how can we fix this? Let's take a look at a possible implementation.&lt;/p&gt;

&lt;p&gt;We start by defining a new implementation of the &lt;code&gt;StorageAccess&lt;/code&gt; for our &lt;code&gt;CustomStruct&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;CustomStructStorageAccess&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nn"&gt;StorageAccess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside, we define two functions, a &lt;code&gt;write&lt;/code&gt; function and a &lt;code&gt;read&lt;/code&gt; function. As you can see from the signatures, the &lt;code&gt;write&lt;/code&gt; funtion receives, amongst other parameters, a &lt;code&gt;CustomStruct&lt;/code&gt; that we want to save in our Storage space, and the &lt;code&gt;read&lt;/code&gt; function returns a stored &lt;code&gt;CustomStruct&lt;/code&gt; wrapped on a &lt;code&gt;SyscallResult&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StorageBaseAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;SyscallResult&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StorageBaseAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;SyscallResult&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Write
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;write&lt;/code&gt; function implementation could look something like this. We receive a &lt;code&gt;CustomStruct&lt;/code&gt; and we make use of the &lt;a href="https://docs.starknet.io/documentation/architecture_and_concepts/Contracts/system-calls-cairo1/#storage_write"&gt;&lt;code&gt;storage_write_syscall&lt;/code&gt; function&lt;/a&gt; to write each individual value to our storage space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StorageBaseAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;SyscallResult&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;storage_write_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;storage_address_from_base_and_offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0_u8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="py"&gt;.value_a&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;storage_write_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;storage_address_from_base_and_offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1_u8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="py"&gt;.value_b&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;storage_write_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;storage_address_from_base_and_offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2_u8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="py"&gt;.value_c&lt;/span&gt;&lt;span class="nf"&gt;.into&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing to take into consideration is the use of the &lt;code&gt;storage_address_from_base_and_offset&lt;/code&gt; function. This function is responsible for generating the address of our storage space where we are saving our element. Since our struct has three elements, the second parameter of the function goes from &lt;code&gt;0_u8&lt;/code&gt; to &lt;code&gt;2_u8&lt;/code&gt;, so that we have a unique spot for each element.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;read&lt;/code&gt; function is what we need in order to retrieve the stored data of our &lt;code&gt;CustomStruct&lt;/code&gt;. This function makes use of the &lt;a href="https://docs.starknet.io/documentation/architecture_and_concepts/Contracts/system-calls-cairo1/#storage_read"&gt;&lt;code&gt;storage_read_syscall&lt;/code&gt; function&lt;/a&gt; to retrieve each of our elements from the storage space. We also need to provide the same offset as we did for the &lt;code&gt;write&lt;/code&gt; function and we simply construct a &lt;code&gt;CustomStruct&lt;/code&gt; instance with the data retrieved. We wrap our struct in a &lt;code&gt;Result::Ok&lt;/code&gt; due to the function signature expected from the &lt;code&gt;StorageAccess&lt;/code&gt; trait.&lt;/p&gt;

&lt;p&gt;One possible implementation would be something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StorageBaseAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;SyscallResult&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;CustomStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;value_a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;storage_read_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;storage_address_from_base_and_offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0_u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'not&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;value_b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;storage_read_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;storage_address_from_base_and_offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1_u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'not&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;value_c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;storage_read_syscall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;address_domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;storage_address_from_base_and_offset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2_u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;'not&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="err"&gt;'&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;After adding this implementation, our contract should compile without any problem. For reference, &lt;a href="https://gist.github.com/DavideSilva/2c3f604bca6df00551c711eecfaf687f"&gt;here&lt;/a&gt; is the full implementation of a contract that uses a custom struct using this manual implementation approach.&lt;/p&gt;

&lt;p&gt;Once again, this is only needed at the time of writing, and if we are using tagged release versions. On the &lt;code&gt;main&lt;/code&gt; branch, we no longer need to provide the &lt;code&gt;impl&lt;/code&gt; block to use this functionality, simply defining the struct is enough.&lt;/p&gt;

&lt;p&gt;That's pretty much it. This was just a short post to show how we can manually implement the &lt;code&gt;read&lt;/code&gt; and &lt;code&gt;write&lt;/code&gt; function for custom defined types.&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

</description>
      <category>cairo</category>
      <category>starknet</category>
      <category>development</category>
    </item>
    <item>
      <title>A look into Cairo 1.0 traits</title>
      <dc:creator>Davide Silva</dc:creator>
      <pubDate>Fri, 28 Apr 2023 10:56:30 +0000</pubDate>
      <link>https://dev.to/finiam/a-look-into-cairo-10-traits-4aph</link>
      <guid>https://dev.to/finiam/a-look-into-cairo-10-traits-4aph</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.starknet.io/documentation/starknet_versions/upcoming_versions/"&gt;Starknet Regenesis&lt;/a&gt; is currently underway. There's been an effort from Starkware into improving not only the Cairo language but the entire ecosystem. We are currently in the transition period but there is already some new language features that we can play with. Let's look at some of the new features of Cairo 1.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o-X0IbeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/67MtrLF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o-X0IbeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/67MtrLF.png" alt="Regenesis" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cairo likes Rust
&lt;/h2&gt;

&lt;p&gt;If you have been following the updates from the Starkware team, you probably already know that the new Cairo 1 syntax is going to be very similar to Rust. Not only in terms of syntax but also some of the concepts introduced by Rust are being ported to Cairo, with Traits now being present in Cairo 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  Traits
&lt;/h3&gt;

&lt;p&gt;What are traits? Traits are a concept in Rust that allow sharing a certain behaviour across types. It's very similar to &lt;em&gt;interfaces&lt;/em&gt; in traditional OO languages, but with some key differences. In Cairo, traits don't behave exactly like you would expect if you are familiar with Rust, but it will feel similar.&lt;/p&gt;

&lt;p&gt;In Cairo, we can define a trait by using the &lt;code&gt;trait&lt;/code&gt; keyword followed by the name of the trait. In the &lt;code&gt;trait&lt;/code&gt; block, we specify the signature of the functions that we want that specific trait to implement. Let's look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;SuperComputer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;the_ultimate_question&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;felt&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;We defined our Trait, &lt;code&gt;SuperComputer&lt;/code&gt;, and we said that every type that uses this trait needs to implement the &lt;code&gt;the_ultimate_question&lt;/code&gt; function.&lt;br&gt;
If a type wants to implement our trait, it will need to implement all the functions declared by our trait definition. Otherwise, the compiler will throw out an error saying &lt;code&gt;Not all trait items are implemented&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A Trait implementation is defined by the &lt;code&gt;impl&lt;/code&gt; keyword followed by the name of our implementation and the trait that we are implementing for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;DeepThought&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;SuperComputer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;the_ultimate_question&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;felt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="mi"&gt;42&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 we now define a new implementation, &lt;code&gt;Marvin&lt;/code&gt;, that also uses the &lt;code&gt;SuperComputer&lt;/code&gt; trait, we are enforced by the compiler to implement the function &lt;code&gt;the_ultimate_question&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Marvin&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;SuperComputer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;the_ultimate_question&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;felt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Generics
&lt;/h2&gt;

&lt;p&gt;The previous example was simply to introduce the concept of Traits. We can also make use of generics in order to make our Trait accept any type we want. We just need to implement our Trait for every type that uses it.&lt;/p&gt;

&lt;p&gt;Let's imagine we want to represent a color in our Cairo program. We can follow the widely used RGB color model to define our color. We can have a struct that stores the value of red, green, and blue that make up our color. However, there are also other color models, like the CMYK color model, that use different attributes to represent the same color.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;RGB&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;CMYK&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cyan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&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 we wanted to have a way to find the color representation of the color red, using either color model, we could have a &lt;code&gt;ColorModelTrait&amp;lt;T&amp;gt;&lt;/code&gt; that would accept any type &lt;code&gt;T&lt;/code&gt;, in order to enforce a function &lt;code&gt;red&lt;/code&gt; that would return, either a RGB or CMYK struct, with that representation. Like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;ColorModelTrait&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;red&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;RGBImpl&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nn"&gt;ColorModelTrait&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RGB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;red&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;RGB&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;RGB&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;CMYKImpl&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nn"&gt;ColorModelTrait&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CMYK&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;red&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CMYK&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;CMYK&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;cyan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="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;With this in place, we can now use our ColorModelTrait to get a struct that will represent the color red. The &lt;code&gt;T&lt;/code&gt; in the trait definition represents any possible type so we can specify if we want the RGB or CMYK type when calling our trait.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rgb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ColorModelTrait&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;RGB&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;red&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cmyk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ColorModelTrait&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;CMYK&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;red&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This brief post aims to show how we can use traits in Cairo. Obviously, there are many more concepts and new syntax to delve into. We are on a learning journey and are excited to share and exchange knowledge with you.&lt;/p&gt;

&lt;p&gt;We are currently building a community for anyone interested in Cairo and Starknet in particular. Whether you're an experienced developer or just starting out, join our &lt;a href="https://t.me/starknetportugal"&gt;Starknet Portugal on Telegram&lt;/a&gt; and &lt;a href="https://www.meetup.com/starknet-portugal"&gt;Starknet Portugal on Meetup&lt;/a&gt; groups. Don't forget to also follow our socials where we will share more events soon.&lt;/p&gt;

</description>
      <category>cairo</category>
      <category>starknet</category>
      <category>programming</category>
    </item>
    <item>
      <title>Developer Productivity</title>
      <dc:creator>Davide Silva</dc:creator>
      <pubDate>Wed, 13 Apr 2022 15:42:01 +0000</pubDate>
      <link>https://dev.to/finiam/developer-productivity-4oam</link>
      <guid>https://dev.to/finiam/developer-productivity-4oam</guid>
      <description>&lt;p&gt;I like to think that I am a productivity oriented person. If there is a faster or more efficient way of doing a task, I tend to incorporate that as part of my workflow. This can be small things like being able to jump directly to a certain application without having to do the &lt;code&gt;CMD+Tab&lt;/code&gt; dance or being able to run a test without having to leave my editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DvClXrsx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/38138fcd778521977ce64e68ba85ae0e798141fc-750x942.png%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DvClXrsx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/38138fcd778521977ce64e68ba85ae0e798141fc-750x942.png%3Fw%3D450" alt="image" width="450" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a long time Vim user, I also like to avoid using my mouse as much as possible.&lt;br&gt;
Therefore, my current development setup is optimized so that I can perform most of my tasks using only the keyboard. I'll try to be as much editor agnostic as I can because it is not so much about a specific editor configuration, as it is more about the general workflow, but the examples I'll give will be in &lt;a href="https://neovim.io/"&gt;Neovim&lt;/a&gt; as that is my preferred text editor.&lt;/p&gt;

&lt;h1&gt;
  
  
  What to improve
&lt;/h1&gt;

&lt;p&gt;There are a few things that I consider any developer should focus in order to improve their development workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic file navigation&lt;/li&gt;
&lt;li&gt;Jump to definitions or references&lt;/li&gt;
&lt;li&gt;Run a test&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic file navigation
&lt;/h2&gt;

&lt;p&gt;Being able to quickly navigate a codebase, of any size, is a crucial skill for any developer. There are basically two phases of understanding a new codebase. There's the "everything is new and I don't know where anything is" phase and the "I know this codebase like the palm of my hand" phase. The method for navigating a codebase should also change with your increased understanding. &lt;/p&gt;

&lt;h3&gt;
  
  
  Tree based navigation
&lt;/h3&gt;

&lt;p&gt;When we first start navigating a new codebase, we can make some educated guesses of where some of the logic is but we don't yet know exactly how the files are called or how the project is structured. If we are using a framework, we can expect some structure already, but this is not true for all the cases.&lt;br&gt;
Surprisingly enough, the best way to become more familiar with the codebase is by looking through it. Seeing where things are in relation to another, how is the folder structure organized, any filename that might be worth having a deep dive, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RZLKRzIR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/24d8a9d7f8c95eb1730bd60fa63d03e222d6c342-321x267.png%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RZLKRzIR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/24d8a9d7f8c95eb1730bd60fa63d03e222d6c342-321x267.png%3Fw%3D450" alt="image" title="tree view of the project structure" width="450" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is nothing new as file tree explorers have been a crucial part of most text editors, either natively or via a plugin, for a while. However, one feature that people seem to not know exists, is being able to show the location of a file in the tree.&lt;br&gt;
Let's say that we need to make a change but we don't know exactly where the actual logic is. We know of a place to start but, as we are still very new to the codebase, we need to start jumping to function definitions or opening other files until we finally arrive at our destination. We finally found the file at the end of the chain but now we realize that our file explorer is closed and we have no idea of where we are. Most file tree explorers have a functionality that allows us to open our tree but instead of showing the root folder, opening the tree showing the current path until our current folder. &lt;br&gt;
Voilà! We now know exactly where we are and the path we took.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TA6UrBe5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/503d4933e0fba64858f5dfc07e610be4635c0c45-1920x1080.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TA6UrBe5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/503d4933e0fba64858f5dfc07e610be4635c0c45-1920x1080.png%3Fw%3D840" alt="image" title="the file that we don't know where it is" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gQT05kI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/918b751af64c4a6e379fc643c036b9404011a945-1920x1080.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gQT05kI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/918b751af64c4a6e379fc643c036b9404011a945-1920x1080.png%3Fw%3D840" alt="image" title="the tree view with the opened folders until our file" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: some editors may do this automatically or just require a keyboard combination or running a command. In others, you might have to configure something first.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fuzzy finders
&lt;/h3&gt;

&lt;p&gt;Tree based navigation is very useful and in some situations even superior to fuzzy finding. When we are looking through a folder to find a file but we don't really know its name or just when we want to have a sense of the size of the project. However, when we already know exactly where we want to go, having to navigate through the file tree is slower than just opening a prompt and typing the name of the file we want to open.&lt;br&gt;
Fuzzy finding is just better because we don't need to fully type the name of the file we want. We can just start typing some of the characters that are part of the name of the file and we can usually get to the file very quickly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7QJEaBtE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/432a0515cf60dbc60e9e30508589fce751a4761b-1920x1080.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7QJEaBtE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/432a0515cf60dbc60e9e30508589fce751a4761b-1920x1080.png%3Fw%3D840" alt="image" title="file finder prompt" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rj6KFYIU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/ca7f51f7eedb31fd3dbab826c038034c0abe5f53-1920x1080.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rj6KFYIU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/ca7f51f7eedb31fd3dbab826c038034c0abe5f53-1920x1080.png%3Fw%3D840" alt="image" title="our file after typing a few characters of the filename" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Jump to definitions or references
&lt;/h2&gt;

&lt;p&gt;Now that we know how to navigate our project quickly, we find a function that we don't know what it does or where it is defined. Having to stop our mental process to go find the file and scroll through to the function declaration is wasted time. Even more so if the function calls another function that calls another function.&lt;br&gt;
What we really want is to put our cursor on top of the function call and, with a shortcut, jump to the function declaration. That way, we don't have to do the cognitive shift from reading code, to finding code, and back.&lt;br&gt;
Another useful shortcut is showing all the places where a function is referenced. Let's say that we need to add a new parameter to a function. We will need to find all the places where the function is called to add the new parameter. Doing that so manually, is considerably slower than having our editor just compile a list that we can scroll through.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0iKRqN0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/87f839d2bb9f00d9cd868aa57610ba7d6ab50a41-1920x1080.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0iKRqN0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/87f839d2bb9f00d9cd868aa57610ba7d6ab50a41-1920x1080.png%3Fw%3D840" alt="Function Call" title="hovering &amp;lt;br&amp;gt;
over the function call" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7oeToK8s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/1cb86a8c56975c82c60d1af7e5d7016dcf89c2f5-1920x1080.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7oeToK8s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/1cb86a8c56975c82c60d1af7e5d7016dcf89c2f5-1920x1080.png%3Fw%3D840" alt="Function Definition" title="jump to function definition after a keystroke" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to the &lt;a href="https://microsoft.github.io/language-server-protocol/"&gt;Language Server Protocol&lt;/a&gt;, we can now do just that. The installation varies from editor to editor, so I won't give any instructions here on how to install or configure it, but finding the appropriate installation instructions for your editor is just a matter of asking Google. The LSP also provides other functionalities that you should probably look into, like showing the documentation for a function or code formatting, and many more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run a test without leaving the editor
&lt;/h2&gt;

&lt;p&gt;Here, at finiam, we follow a TDD approach when developing. Having to switch from the editor to the terminal to run the tests is wasted time, even if the terminal is incorporated in our editor.&lt;br&gt;
Let's say we are writing a new test file. Having a shortcut to automatically start and run the test for us is a major time saver. We can even have different shortcuts to either run that specific test or run the entire test file or even the test suite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kq3IPaZN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/5b3aa1d4f933708435d9be5a258f79b488ff80f4-1920x1080.png%3Fw%3D840" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kq3IPaZN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/5aprln8a/production/5b3aa1d4f933708435d9be5a258f79b488ff80f4-1920x1080.png%3Fw%3D840" alt="Test" title="running a test with a keystroke" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's another implicit advantage of being able to run the tests from our editor. If the barrier for running a test is just a simple keystroke combination away, we are more likely to run the tests when writing our code. If, for instance, running the tests is a process that forces us to switch from our editor to a terminal and typing the command to run the tests, we are more prone to skip them because we don't want to lose our focus. I am also guilty of this. I was once in a project that had a test configuration that forced us to start a Docker container to run the tests. I wasn't able to do my shortcuts to run the tests and, more times than I'd like to admit, I'd skip running the tests locally. The CI ends up having to do extra work when we open a PR for something that breaks the tests that we could have found locally, had we just run the tests. Eventually, we refactored that project enough that we didn't have to use Docker locally and I was back to using my shortcuts.&lt;/p&gt;

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

&lt;p&gt;These small time save improvements end up compounding without you even noticing. The motivation is not to just be quicker at doing things but to shift the mental load of doing some repetitive tasks to muscle memory.&lt;br&gt;
If every time we want to run a test or open a new file, we need to stop what we are doing and focus on doing that task instead, we lose track of that mental model that we spent so long building and we need to start again. &lt;/p&gt;

&lt;p&gt;Take those boring tasks and make them so easy and so repeatable to do that eventually they become muscle memory and we don't even need to actively think about what we are doing. &lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Ruby vs Elixir: a brief comparison</title>
      <dc:creator>Davide Silva</dc:creator>
      <pubDate>Wed, 19 May 2021 09:22:22 +0000</pubDate>
      <link>https://dev.to/finiam/ruby-vs-elixir-a-brief-comparison-58fj</link>
      <guid>https://dev.to/finiam/ruby-vs-elixir-a-brief-comparison-58fj</guid>
      <description>&lt;p&gt;In the world of tech startups, time is an essential factor in the success of a company. Who can deliver the best work in the shortest amount of time gains a competitive edge over the competition. Not only that but in a world in constant evolution, the need to quickly change gears and pivot a business idea into another opportunity is of great importance.&lt;/p&gt;

&lt;p&gt;A minimum viable product (MVP) is a great way of testing and learning new insights of a potential new product, without having to spend precious time and money on the development of a product that might not have a demand in the market. The &lt;em&gt;Lean Startup&lt;/em&gt; book defines an MVP at its core as "a version of a new product which allows a team to collect the maximum amount of validated learning about customers with the least effort".&lt;/p&gt;

&lt;p&gt;Therefore, the time of development of an MVP would, ideally, be the shortest possible. In order to achieve that, a software development team must choose a framework that would allow the rapid prototyping of the MVP as well as allow a sudden need of pivoting or scaling.&lt;br&gt;
The constant evolution of software methodologies and web frameworks means that choosing one framework over another is not always a trivial choice.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ruby on Rails
&lt;/h2&gt;

&lt;p&gt;Since its release in 2004, Ruby on Rails attracted a lot of attention from the tech startup world as it caused a shift in the way web applications are developed. The sensible defaults provided by the framework, the active community providing the necessary tooling that helps speed up development even further, being an open-source framework and the ease of scalability of a Rails application make Ruby on Rails a prime candidate for the rapid prototyping of a web application. Developers spend most of their time implementing actual features instead of debating over design choices of little to no impact to the end-user.&lt;/p&gt;

&lt;p&gt;Many of the notorious and largest tech startups of today, Twitter, GitHub, Shopify, to name a few, did their first steps with Ruby on Rails. And while Ruby on Rails is an obvious choice for bootstrapping an application, there is also concrete proof that it performs well under heavy load and in scale. &lt;a href="https://news.shopify.com/shopify-merchants-break-records-with-51-billion-in-worldwide-sales-over-black-fridaycyber-monday-weekend-354749"&gt;Shopify reported&lt;/a&gt; "sales of $5.1+ billion from the more than one million Shopify-powered brands around the world" during the Black Friday and Cyber Monday of 2020. At the peak of Black Friday, they were able to process $102+ million in sales during an hour. They achieved this using a monolithic Ruby on Rails application. Like Shopify, GitHub also runs Ruby on Rails in their production environment, having spent considerable time and effort into upgrading both Rails and Ruby to the latest stable versions available.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ruby on Rails downsides
&lt;/h2&gt;

&lt;p&gt;Despite these and many other success cases, Rails interest has been declining over the last few years.&lt;br&gt;
One possible reason for the decline in popularity seen recently in Rails is directly related to the fact that it brings lot of opinionated tools and makes choices for the developer that will work perfectly as long as you use the framework as it is. Changing these tools for other alternatives requires extra work, that might not always be trivial. The Convention over Configuration doctrine is good for most use cases but when some custom configuration is needed, Rails makes it harder than it should to change its defaults. After a few years as the de facto web framework used by most tech startups, and despite still being a perfectly valid choice for a rapid prototype or as a web framework by itself, companies and developers are starting to move away from Rails in search of valid alternatives. Many tech startups started to look closely into Elixir, and its web framework Phoenix, as a possible substitute to Rails.&lt;/p&gt;
&lt;h2&gt;
  
  
  Elixir
&lt;/h2&gt;

&lt;p&gt;Elixir started to make waves in the tech world by promising the fault-tolerance, highly scalable and easily distributed properties of the Erlang VM with a Rails- like syntax and an active community. The creator of Elixir, José Valim, is a former Ruby/Rails core contributor and brought many of the good practices and positives of Ruby/Rails to Elixir. The appearance of a new language that promises the better parts of Rails, without its most known downsides, and that is built upon a battle-tested language like Erlang has caused a buzz in the tech startup world. Despite the fairly recent release of Elixir, being first released in 2011, it builds on top of the Erlang VM that has been around since the 1980s and is used by some of the largest telecommunication companies in the world, like Ericsson, Cisco, Samsung, and WhatsApp.&lt;/p&gt;

&lt;p&gt;One of the things that made programmers very excited about Elixir is that building distributed systems in Elixir is a very pleasant experience. Everything in Elixir consists of processes that send messages to one another. The code in each process runs sequentially and we don't need to worry about race conditions or locks while building our system. If a process wants to send a message to another process, that message is put in the mailbox of the receiver process and the sender might enter a sleep state while it awaits for a response or simply carry on with its execution. The receiver process iterates over its mailbox and processes each message one at a time. If you want a more in-depth explanation of Elixir processes and how you can better use &lt;a href="https://blog.finiam.com/blog/genserver-agent-task"&gt;GenServers, Agents, and Tasks&lt;/a&gt;, Resende has got you covered.&lt;/p&gt;

&lt;p&gt;Pattern matching and the pipe operator are also two big factors why developers seem to like Elixir so much. This often leads to functional, prettier code that is also easier to reason and maintain. With the pipe operator, &lt;code&gt;|&amp;gt;&lt;/code&gt;, we can treat a series of function calls or data transformations as a single chain of operations. Instead of wrapping function calls with another, we use the pipe operator to pass our data to the first argument of the next function. The following snippet shows two ways of writing the same logic, but one is easier to read than the other:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello world! "&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="s2"&gt;"Hello world! "&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike Ruby, Elixir is also a language that has everything figured out. It has an &lt;a href="https://hexdocs.pm/mix/master/Mix.Tasks.Format.html"&gt;official built-in linter&lt;/a&gt; that is part of the core of the language. There is also an &lt;a href="https://hexdocs.pm/mix/Mix.Tasks.Release.html"&gt;official release manager&lt;/a&gt; that is also built-in in the language. A &lt;a href="https://hexdocs.pm/ex_unit/ExUnit.html"&gt;unit testing framework&lt;/a&gt; is also shipped with Elixir, meaning there is no need to install third-party dependencies just to get some basic quality of life tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elixir downsides
&lt;/h2&gt;

&lt;p&gt;Being a very recent language, the Elixir ecosystem is lacking in the resources and libraries one would find in the Rails ecosystem, as well as the scale of the existing community. The number of Elixir developers pales in comparison to the number of Ruby/Rails developers but the existing community is very active and responsive, always striving to improve the ecosystem. Another factor that might cause some resistance in adopting Elixir is the fact that it is a functional programming language. Instead of calling a method on an object, in Elixir, we call a function of a module and you pass the data to that function. This is not a problem with the language itself, but this shift in thinking might deter some programmers who are more comfortable with imperative or object-oriented programming. Coming from one of those paradigms to Elixir without having a background or some experience in functional programming might take some time to get used to. As a very quick example, here's how to get the length of a string in both languages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#ruby&lt;/span&gt;
&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;#elixir&lt;/span&gt;
&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, in Ruby we call the &lt;code&gt;length&lt;/code&gt; method on an instance of the &lt;code&gt;String&lt;/code&gt; object that contains the phrase "Hello world!" while in Elixir we call the &lt;code&gt;length&lt;/code&gt; function of the &lt;code&gt;String&lt;/code&gt; module and we pass our "Hello World!" phrase as an argument to that function. It's similar but involves a shift in the way you think about a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;If this sparked your interest and you want to see a more concrete example of Elixir being used, you can take a look at Diogo and his &lt;a href="https://blog.finiam.com/blog/simulations-with-elixir-and-the-actor-model/"&gt;Simulations with Elixir&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the end, the positives and negatives of a language/framework are something that should always be considered before picking one for building an MVP. We shouldn't blindly pick the new shiny thing simply because it might not be the best solution for the problem we are trying to solve. This doesn't mean that we should always pick the same tools to solve any problem we are faced with. If the restraints of the problem align with our tools of choice, then the decision is easy. But if the problem asks for another tool set, there are plenty more to choose from. The important bit is to do some research beforehand and carefully weigh the pros and cons before making a decision.&lt;/p&gt;

&lt;p&gt;Stay safe!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>elixir</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Refactoring or: How We Learned to Stop Worrying and Live with Chaos</title>
      <dc:creator>Davide Silva</dc:creator>
      <pubDate>Tue, 01 Dec 2020 17:12:17 +0000</pubDate>
      <link>https://dev.to/finiam/refactoring-or-how-we-learned-to-stop-worrying-and-live-with-chaos-2ic0</link>
      <guid>https://dev.to/finiam/refactoring-or-how-we-learned-to-stop-worrying-and-live-with-chaos-2ic0</guid>
      <description>&lt;p&gt;I will be completely transparent and start by saying that this blogpost itself has been rewritten a couple of times since its original idea. Given the topic we are going to discuss, it seems fitting that that happened.&lt;/p&gt;

&lt;p&gt;In the beginning of 2019, we took over a Rails project. On the surface, it looked like a typical Rails app with an integration to a payment service. The fun began when we started to take a closer look at the codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mocking an API
&lt;/h2&gt;

&lt;p&gt;Let's say we want to mock a request that makes a payment. Normally, we'd use something like &lt;a href="https://github.com/bblimke/webmock" rel="noopener noreferrer"&gt;webmock&lt;/a&gt; or &lt;a href="https://github.com/vcr/vcr" rel="noopener noreferrer"&gt;VCR&lt;/a&gt; in order to fake that interaction with the real API and have an expected result that we can use in our tests. Something that would allow the code to run exactly as it would run in the production environment, with the only difference being the return value we get from the request. We don't need to write code in the controller to check what environment we are on. The code is the same, the output of the HTTP call is what's different. If you want to know how to do this, the folks from Thoughtbot have a &lt;a href="https://thoughtbot.com/blog/how-to-stub-external-services-in-tests" rel="noopener noreferrer"&gt;great post about that&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, the codebase at that time didn't have any automated tests and the development team opted for another approach to testing. Any time they had any major updates, they would have someone from their team run through a list of tests and manually assert that everything is working as it should or report any regressions they would find.&lt;/p&gt;

&lt;p&gt;So, how did they mock the external API? In short, for every endpoint of the external API, they added a Dummy and an Impl class. You can probably guess from the naming, but to be perfectly clear, the Dummy class version is the mock and the Impl is the actual implementation of the endpoint. Ok, now we have two classes for the same endpoint. One that handles the mock for the development environment and another that handles production. &lt;/p&gt;

&lt;p&gt;It's a bit of unnecessary indirection but at least we have a complete separation of the implementations. Except, not really. Something I haven't mentioned yet is that both Dummy and Impl classes were inheriting from a common Abstract class. The Abstract classes mostly served to ensure that both versions had the same methods implemented, but, in some cases, actual logic was in the Abstract ****class. This coupled with the fact that for each endpoint we would have a Service class, that served as the main entrypoint to that service, that itself would inherit from an AbstractService, just to return the Impl class, added up to be a lot of indirection.&lt;/p&gt;

&lt;p&gt;All this is difficult enough to actually follow when looking at the code, let alone just reading some vague description. Here's a diagram to help visualize 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%2Fbmfoh2f2c0s75i62rhod.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%2Fbmfoh2f2c0s75i62rhod.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a simplified version of the actual structure. The diagram doesn't show the models used in each class and we had this for each request in the API. Sometimes, trying to find where a particular method was defined, was like trying to find a needle in an haystack.&lt;/p&gt;

&lt;p&gt;This strategy worked at the time it was needed and there was nothing particulary wrong with it. It served its purpose but trying to maintain it was proving to be challenging. Especially now that we no longer need the Dummy classes. We had inheritance between two classes when it would be fine to merge everything into a single class. We've since refactored this and removed a lot of that indirection.&lt;/p&gt;

&lt;p&gt;Chances are you are familiar with the Donald Knuth quote: "&lt;em&gt;premature optimization is the root of all evil&lt;/em&gt;". In this case, it wasn't optimization that caused the "evil", it was trying to write DRY code when it would be perfectly okay having code duplication. Sometimes, it is encouraged to write the same code twice. Or maybe, the problem was using a Java pattern in a Rails codebase.&lt;/p&gt;

&lt;p&gt;That was one of the pains we felt when we started working in this codebase. Another was having to do with accessing our users's email inboxes. With their permission, obviously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing our user's emails
&lt;/h2&gt;

&lt;p&gt;One of the features of this product has to do with reading the user's email inbox and parsing the email attachments, looking for PDF attachments, in particular. This feature was implemented back in the days where neither Google nor Microsoft had yet to release their API's to allow access to the Gmail and Outlook inboxes, respectively. So, this was implemented using IMAP. It was what was available at the time so it was the only option. It was still perfectly working when we decided to refactor it. Why did we decide to refactor something that works? Well, for one, the implementation, while it worked, was not ideal. The method responsible for crawling the inboxes was generic in the sense that it would crawl either the Gmail inbox or the Outlook inbox, depending on the user's preferred email service. That caused the method to be quite long in order to handle the differences between the two services, since it needed to differentiate between the two. And while long methods don't bother us enough to refactor an entire feature, there was some logic scattered between multiple methods that could perfectly live together in the same place. For instance, we had multiple occurences of this code snippet scattered throughout the codebase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"google"&lt;/span&gt;
  &lt;span class="c1"&gt;# do something related to Google&lt;/span&gt;
&lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"microsoft"&lt;/span&gt;
  &lt;span class="c1"&gt;# do something related to Microsoft&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the perfect example to counterpoint the first problem I've talked about. This is where abstraction is welcome. Instead of checking in each method that composes the crawler for the provider, we can abstract this into a higher level. We start by implementing a Gmail crawler and an Outlook crawler. Then we go to the highest point of the crawler method we can and do that same check, only now we are only doing it once and calling the appropriate crawler. Each crawler now only has to worry about their respective implementation of how to get emails from an inbox.&lt;/p&gt;

&lt;p&gt;The main motivator behind the refactoring was simply to convert to the new REST API that Google and Microsoft provide. We could get rid of some of that indirection, aggregate the logic in a more meaningful sense while we converted to a REST API and got rid of the IMAP implementation. And that's what we did. Now, the method responsible for crawling the user's inbox either calls the Gmail or the Outlook crawler, depending on the user's email service. Everything related to crawling Gmail is in one place, everything related to crawling Outlook is in another. With this we have a more structured and cleaner code, that's easier to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to refactor
&lt;/h2&gt;

&lt;p&gt;There were other major refactors that we did during this last year but there is still more to be done. Refactoring code is not something that you do once and call it a day. Some of the current best practices may change in the future. There might be some new language features or external services that your product could use to simplify something. I'm not trying to say that you should always be refactoring code to be using the new, shiny things. If it works, and the hassle of refactoring would only cause minimal benefits, it should probably stay that way. If you find code that you want to refactor, but there is no real need for that, make a note of that somewhere. The next time you would need to touch some of that code, then consider refactoring. We always try to leave the codebase in a better state than when we first found it. That's the rule of thumb we tend to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;One thing to have in mind, always, but especially when refactoring code, is that you shouldn't judge the person by the quality of their code. It doesn't matter who wrote it. It doesn't matter why they wrote it that way. It is very easy to judge past code and think less of the person who wrote it but that does not help you with the task of refactoring it. &lt;/p&gt;

&lt;p&gt;What matters is how we can make this code better, so that in the future, someone who happens to come across the same code doesn't have the same frustrations as you did. And chances are it might be your future self that has to refactor the code you are now refactoring, so be kind.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>refactorit</category>
    </item>
  </channel>
</rss>
