<?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: senyo</title>
    <description>The latest articles on DEV Community by senyo (@senyeezus).</description>
    <link>https://dev.to/senyeezus</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%2F394310%2F5d2897b6-d56e-4a0d-a3e8-28ff07feaafe.jpg</url>
      <title>DEV Community: senyo</title>
      <link>https://dev.to/senyeezus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/senyeezus"/>
    <language>en</language>
    <item>
      <title>Embedded systems with Rust video course</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Mon, 02 Sep 2024 09:12:47 +0000</pubDate>
      <link>https://dev.to/senyeezus/embedded-systems-with-rust-video-course-4co4</link>
      <guid>https://dev.to/senyeezus/embedded-systems-with-rust-video-course-4co4</guid>
      <description>&lt;p&gt;Hello folks! This is just a post to say I've got a new course out with &lt;a href="https://learning.linkedin.com/" rel="noopener noreferrer"&gt;LinkedIn Learning&lt;/a&gt; on embedded systems programming with Rust.&lt;/p&gt;

&lt;p&gt;It covers the basics of embedded systems and how to write Rust programs targeted for them. If you're interested in this field, check it out, I hope you find it valuable!&lt;/p&gt;

&lt;p&gt;Course: &lt;a href="https://www.linkedin.com/learning/introduction-to-embedded-systems-with-rust" rel="noopener noreferrer"&gt;Introduction to embedded systems with Rust&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>embeddedsystems</category>
    </item>
    <item>
      <title>ecto's cast/4 function explained</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Mon, 20 May 2024 17:00:00 +0000</pubDate>
      <link>https://dev.to/senyeezus/ectos-cast4-function-explained-p2e</link>
      <guid>https://dev.to/senyeezus/ectos-cast4-function-explained-p2e</guid>
      <description>&lt;p&gt;The typical changeset in Ecto is created via the &lt;a href="https://hexdocs.pm/ecto/3.11.2/Ecto.Changeset.html#cast/4" rel="noopener noreferrer"&gt;&lt;code&gt;cast/4&lt;/code&gt;&lt;/a&gt;function.&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="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permitted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&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;I've hardly found its usage intuitive.&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="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;register_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;registration_changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;registration_changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;validate_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;validate_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why are we casting with an empty &lt;code&gt;User&lt;/code&gt;? What do we actually use &lt;code&gt;attrs&lt;/code&gt; for?&lt;/p&gt;

&lt;p&gt;As it turns out, it's not even mildly confusing. The purpose of the &lt;code&gt;cast/4&lt;/code&gt; function is as the name says on the box: to cast data from one type into the other. It's necessary as we may receive data from external sources with the wrong type i.e an integer sent as a string from a form. Keep in mind though, we're still dealing with a changeset, whose sole purpose is to track changes to fields in our data.&lt;/p&gt;

&lt;p&gt;Per the function signature, &lt;code&gt;cast/4&lt;/code&gt; casts the fields of &lt;code&gt;params&lt;/code&gt; into the expected types specified by &lt;code&gt;data&lt;/code&gt;, while tracking changes to the &lt;code&gt;data&lt;/code&gt;. The only changes that are tracked are those specified by the atoms passed via &lt;code&gt;permitted&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Take this Ecto schema&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="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And say we do this&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="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameter &lt;code&gt;age&lt;/code&gt; is a string. The &lt;code&gt;cast/4&lt;/code&gt; function will convert it into an integer. And since we've passed in an empty &lt;code&gt;User&lt;/code&gt;, we'll get a changeset reflecting the changes we've made i.e adding a parameter age with the value of 0.&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="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;
&lt;span class="c1"&gt;#Ecto.Changeset&amp;lt;&lt;/span&gt;
  &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;changes:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;# type is cast to an integer&lt;/span&gt;
  &lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="ss"&gt;data:&lt;/span&gt; &lt;span class="c1"&gt;#User&amp;lt;&amp;gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;valid?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll see this fail if our data cannot be converted into an integer with no changes applied.&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="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; 
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;
&lt;span class="c1"&gt;#Ecto.Changeset&amp;lt;&lt;/span&gt;
  &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;changes:&lt;/span&gt; &lt;span class="p"&gt;%{},&lt;/span&gt;
  &lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"is invalid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;type:&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;validation:&lt;/span&gt; &lt;span class="ss"&gt;:cast&lt;/span&gt;&lt;span class="p"&gt;]}],&lt;/span&gt;
  &lt;span class="ss"&gt;data:&lt;/span&gt; &lt;span class="c1"&gt;#User&amp;lt;&amp;gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;valid?:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we already have a populated &lt;code&gt;User&lt;/code&gt; type and we pass in valid data, we get our change tracking as expected and the data is cast if need be.&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="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; 
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;
&lt;span class="c1"&gt;#Ecto.Changeset&amp;lt;&lt;/span&gt;
  &lt;span class="ss"&gt;action:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;changes:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="ss"&gt;data:&lt;/span&gt; &lt;span class="c1"&gt;#User&amp;lt;&amp;gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;valid?:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More writing
&lt;/h2&gt;

&lt;p&gt;For more of my writing, check out my newsletter: &lt;a href="https://offthewire.substack.com" rel="noopener noreferrer"&gt;off the wire&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>ecto</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Earning the right to write software 'the right way'</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Wed, 10 May 2023 19:59:50 +0000</pubDate>
      <link>https://dev.to/senyeezus/earning-the-right-to-write-software-the-right-way-2hpo</link>
      <guid>https://dev.to/senyeezus/earning-the-right-to-write-software-the-right-way-2hpo</guid>
      <description>&lt;p&gt;Originally posted on my blog at &lt;a href="https://senyosimpson.com/posts/earning-the-right" rel="noopener noreferrer"&gt;https://senyosimpson.com/posts/earning-the-right&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;As technologists, we're often captivated by the technical details of software. It’s not long before we want to understand database internals, the intricacies of our operating system or the best paradigms for writing software. We’re arbitrarily motivated to do deep dives into areas that are filled with high degrees of complexity or to spend hours figuring out how to optimise the performance of some software. We’re invested in the technology itself; it is the end, not a means to it. Over time, I’ve come to realise that while this inclination has been central to my growth as a software engineer, in the context of my professional career, it comes with a hefty downside — being caught up in the technology even when its not valuable to the customer. If you’re obsessed with implementation details, you need a high level of pragmatism to be and remain successful at work.&lt;/p&gt;

&lt;p&gt;The central goal of any company is &lt;del&gt;growth&lt;/del&gt; to generate profit. Well, at least that’s the goal of any &lt;em&gt;reasonable&lt;/em&gt; company. Generating profit means we get to care about everything else because without profit there is no company. To generate profit, we need to create value.&lt;/p&gt;

&lt;p&gt;Software, in the context of a &lt;a href="https://www.vice.com/en/article/5d3naz/openai-is-now-everything-it-promised-not-to-be-corporate-closed-source-and-for-profit" rel="noopener noreferrer"&gt;for-profit company&lt;/a&gt;, is a means to an end and that end is creating value. There’s a saying, “It's better to go slowly in&lt;br&gt;
the right direction than go speeding off in the wrong direction”. If you exert energy in the wrong direction, it doesn’t matter how great of a job you’ve done in creating something, it’s value to your customers is marginal. That's the potential downside of obsessing over implementation details. All the time and energy that you put into producing the "perfect" code amounts to nothing if you're going in the wrong direction. In and of itself, great code is not valuable. It doesn’t matter if its performant and &lt;a href="https://news.ycombinator.com/item?id=25326446" rel="noopener noreferrer"&gt;scales to handling millions of queries per second&lt;/a&gt; or that is has 100% test coverage and a beautiful integration test suite or that its written in a purely functional programming language or that it has best-in-class observability. To care about writing software and software systems "the right way™️", you have to earn the right.&lt;/p&gt;

&lt;p&gt;To “earn the right” means to create a successful product. At that point, it is justifiable to care about the technical details&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. If millions of customers are using your product each day, you start running into many fun problems: &lt;a href="https://discord.com/blog/why-discord-is-switching-from-go-to-rust" rel="noopener noreferrer"&gt;optimising&lt;/a&gt; the &lt;a href="https://www.notion.so/blog/sharding-postgres-at-notion" rel="noopener noreferrer"&gt;performance&lt;/a&gt; of your software systems, &lt;a href="https://fly.io/blog/carving-the-scheduler-out-of-our-orchestrator/" rel="noopener noreferrer"&gt;rearchitecting systems&lt;/a&gt; to handle increasing load and &lt;a href="https://dropbox.tech/infrastructure/atlas--our-journey-from-a-python-monolith-to-a-managed-platform" rel="noopener noreferrer"&gt;improve developer velocity&lt;/a&gt; and improving &lt;a href="https://stripe.com/blog/migrating-to-typescript" rel="noopener noreferrer"&gt;developer&lt;/a&gt; &lt;a href="https://stripe.com/blog/sorbet-stripes-type-checker-for-ruby" rel="noopener noreferrer"&gt;productivity&lt;/a&gt;. At this stage, the company, the team and you have earned the right to care about the details&lt;sup id="fnref2"&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;At the beginning of this post, I mentioned that if you’re captivated by implementation details, you need a high level of pragmatism to be successful. The reason is summarised nicely in a quote we’ve all heard before, “premature optimisation is the root of all evil”. It’s so easy to get wrapped up&lt;br&gt;
in improving the performance of your code or how well it’s encapsulates behaviour or any of the other 1000 things we all want to care about before we've even proven its useful to our customers. At this point, it's not subject to the type of constraints that necessitate the level of detail we all care about. And then, we have to ask ourselves, "is it really worth it?". It’s fine shipping it if it gets the job done. When you have enough customers, your systems will let you know they need some love. You’ve earned the right to care.&lt;/p&gt;

&lt;p&gt;the best way to structure your repos and code or the programming paradigm are mostly a distraction. You'll undoubtedly run into challenges no matter which way you go, engineering is a bunch of trade-offs after all. And by the time you get to that point, you can just &lt;a href="https://www.computerenhance.com/p/performance-excuses-debunked" rel="noopener noreferrer"&gt;rewrite it anyway&lt;/a&gt;.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;For the sake of nuance, this isn't as applicable to infrastructure products (e.g databases) where the novelty of the solution is the selling point of the software. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Not all technical details are created equal. Even in the early stages, worrying about adequate test coverage, choosing good design patterns or how to write generally readable and maintainable code makes sense. Worrying about the scalability properties of your system, the performance of your software, ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>development</category>
      <category>devjournal</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Pointer Fu: An adventure in the Tokio code base</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Mon, 25 Oct 2021 16:13:14 +0000</pubDate>
      <link>https://dev.to/senyeezus/pointer-fu-an-adventure-in-the-tokio-code-base-120f</link>
      <guid>https://dev.to/senyeezus/pointer-fu-an-adventure-in-the-tokio-code-base-120f</guid>
      <description>&lt;p&gt;This post was originally posted on my &lt;a href="https://senyosimpson.com/short-forms/pointer-fu-tokio/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;In an effort to understand the internals of asynchronous runtimes, I've been spending time reading &lt;a href="https://tokio.rs/" rel="noopener noreferrer"&gt;Tokio&lt;/a&gt;'s source code. I've still got a long way to go but it has been a great journey so far.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1450127351917027332-304" src="https://platform.twitter.com/embed/Tweet.html?id=1450127351917027332"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1450127351917027332-304');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1450127351917027332&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Raw pointers are used all over Tokio. In one particular instance, the way they used them really blew my mind 🤯. So here I am, writing about it. Buckle in 💺.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting the scene
&lt;/h2&gt;

&lt;p&gt;We have a type &lt;code&gt;Cell&lt;/code&gt; that is defined as (taken directly from Tokio source)&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;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&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;Cell&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="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/// Hot task state data&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cd"&gt;/// Either the future or output, depending on the execution stage.&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Core&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cd"&gt;/// Cold data&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;trailer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Trailer&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;It's used when initialising a struct &lt;code&gt;RawTask&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;struct&lt;/span&gt; &lt;span class="n"&gt;RawTask&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NonNull&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This is pseudocode&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;RawTask&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;new&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;RawTask&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;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// returns a raw pointer to a Cell&lt;/span&gt;

        &lt;span class="c1"&gt;// Cast pointer to one that points to a Header&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;header_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Header&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;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NonNull&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header_ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
        &lt;span class="n"&gt;RawTask&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ptr&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;
  
  
  What is so interesting?
&lt;/h2&gt;

&lt;p&gt;First, a necessary detour! Rust can represent structs in memory in multiple ways. It's covered in detail in the &lt;a href="https://doc.rust-lang.org/reference/type-layout.html#representations" rel="noopener noreferrer"&gt;The Rust Reference&lt;/a&gt;. By default, Rust offers &lt;em&gt;no guarantee&lt;/em&gt; on the memory layout of your struct; it is free to modify the layout however it wants. From a developer perspective, it means you cannot write any code that makes assumptions on the memory layout of your struct. To change the representation of the struct, you can use the &lt;code&gt;repr&lt;/code&gt; attribute (as shown in the above definition of &lt;code&gt;Cell&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Now, here's where it gets good! I omitted the comment for the &lt;code&gt;Cell&lt;/code&gt; struct, which is&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="cd"&gt;/// The task cell. Contains the components of the task.&lt;/span&gt;
&lt;span class="cd"&gt;///&lt;/span&gt;
&lt;span class="cd"&gt;/// It is critical for `Header` to be the first field as the task structure will&lt;/span&gt;
&lt;span class="cd"&gt;/// be referenced by both *mut Cell and *mut Header.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully some alarm bells started ringing in your head 🚨. &lt;code&gt;Header&lt;/code&gt; has to be the first field in the struct, so that you can dereference a pointer to &lt;code&gt;Cell&lt;/code&gt; into either a &lt;code&gt;Cell&lt;/code&gt; or a &lt;code&gt;Header&lt;/code&gt; (if this doesn't make sense to you, check out the addendum). However, Rust's default representation provides no guarantee that &lt;code&gt;Header&lt;/code&gt; will remain the first struct field! Instead, as you can see, they've changed the representation to the &lt;code&gt;C&lt;/code&gt; layout. In &lt;code&gt;C&lt;/code&gt;, struct fields are stored in the order they are declared. This gives us the guarantee we need. Now we can go around dereferencing the pointer to &lt;code&gt;Header&lt;/code&gt; without any worry!&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;cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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;cell_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Cell&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;header_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cell_ptr&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Header&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;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;header_ptr&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Addendum
&lt;/h2&gt;

&lt;p&gt;View in &lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=147f74ccb012c0ef292ffe6e781c685a" rel="noopener noreferrer"&gt;Rust playground&lt;/a&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="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&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="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Core&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;y&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="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy)]&lt;/span&gt;
&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Core&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;main&lt;/span&gt;&lt;span class="p"&gt;()&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;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&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;core&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Core&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Create raw pointer to task&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;task_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Cast pointer to point to Header&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;header_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task_ptr&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Dereference header_ptr&lt;/span&gt;
    &lt;span class="c1"&gt;// We expect this to give us our Header struct as defined above.&lt;/span&gt;
    &lt;span class="c1"&gt;// Because Header is the first field and the pointer is pointing&lt;/span&gt;
    &lt;span class="c1"&gt;// to the beginning of the Task struct, it is valid to perform&lt;/span&gt;
    &lt;span class="c1"&gt;// this dereference&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;header_from_ptr_deref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;header_ptr&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Dereference task_ptr&lt;/span&gt;
    &lt;span class="c1"&gt;// We expect this to give us our Task struct as defined above&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;task_from_ptr_deref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;task_ptr&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Header from deref: {:#?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header_from_ptr_deref&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task from deref: {:#?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_from_ptr_deref&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Bonus: we can also cast task_ptr into a pointer to Core&lt;/span&gt;
    &lt;span class="c1"&gt;// However, because its struct member is a u8 and Header's member&lt;/span&gt;
    &lt;span class="c1"&gt;// is storing 256, which u8 cannot represent, dereferencing&lt;/span&gt;
    &lt;span class="c1"&gt;// core_ptr will produce a corrupted Core struct&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;core_ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task_ptr&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Core&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;core_from_ptr_deref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;core_ptr&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Core from deref: {:#?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;core_from_ptr_deref&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;The output of running this is shown below. Note that &lt;code&gt;Core&lt;/code&gt; we obtained from dereferencing has &lt;code&gt;y=0&lt;/code&gt; instead of &lt;code&gt;y=10&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Header from deref: Header {
    x: 256,
}

Task from deref: Task {
    header: Header {
        x: 256,
    },
    core: Core {
        y: 10,
    },
}

Core from deref: Core {
    y: 0,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Shoutouts to &lt;a href="https://twitter.com/a_hoverbear" rel="noopener noreferrer"&gt;Ana&lt;/a&gt; for reviewing this post.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tokio</category>
      <category>programming</category>
    </item>
    <item>
      <title>Designing state machines in Rust</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Thu, 16 Sep 2021 14:50:15 +0000</pubDate>
      <link>https://dev.to/senyeezus/designing-state-machines-in-rust-252k</link>
      <guid>https://dev.to/senyeezus/designing-state-machines-in-rust-252k</guid>
      <description>&lt;p&gt;This post was originally posted on my &lt;a href="https://senyosimpson.com/short-forms/rust-state-machines/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;In Rust, you often hear about state machines. Futures are state machines! I thought it would be cool to read more about it. I came across &lt;a href="https://hoverbear.org/blog/rust-state-machine-pattern/" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; (funnily enough, by a friend and mentor of mine) which really helped me! I highly recommend reading it. In this post, I'm just noting the part I found relevant. The example here is from her blog post.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;P.S.A: Go and read that post 😆&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  State Machines
&lt;/h2&gt;

&lt;p&gt;Rust is able to represent state machines quite elegantly. Due to its type system, you can make sure invariants are upheld. To use a real life example, we can do some basic modeling of &lt;a href="https://raft.github.io/" rel="noopener noreferrer"&gt;Raft&lt;/a&gt; (no knowledge needed for this post). A node in a Raft cluster can be in one of 3 states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Candidate&lt;/li&gt;
&lt;li&gt;Follower&lt;/li&gt;
&lt;li&gt;Leader&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The possible transitions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follower -&amp;gt; Candidate&lt;/li&gt;
&lt;li&gt;Candidate -&amp;gt; Leader&lt;/li&gt;
&lt;li&gt;Candidate -&amp;gt; Follower&lt;/li&gt;
&lt;li&gt;Leader -&amp;gt; Follower&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore the only invalid state transition is: Follower -&amp;gt; Leader.&lt;/p&gt;

&lt;p&gt;Now we can start modeling this. We have a struct &lt;code&gt;Node&lt;/code&gt; that represents a node in the cluster&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;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;S&lt;/code&gt; is a generic parameter over the possible states. Our states are also structs&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;Follower&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// In reality, these are likely to hold some data&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Candidate&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;Leader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Raft, all nodes start in the &lt;code&gt;Follower&lt;/code&gt; state. We can define a function &lt;code&gt;new&lt;/code&gt; for that state &lt;em&gt;only&lt;/em&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;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Follower&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;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&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;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Follower&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Follower&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;We can initialise this 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;let&lt;/span&gt; &lt;span class="n"&gt;follower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Node&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;Follower&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;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important thing is that we can't do this for other states! If we do&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;leader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Node&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;Leader&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;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we will get an error because we haven't defined the function &lt;code&gt;new&lt;/code&gt; for &lt;code&gt;Node&amp;lt;Leader&amp;gt;&lt;/code&gt;. This is super sweet!&lt;/p&gt;

&lt;p&gt;The next thing we need to be able to do is have state transitions enforceable by the compiler. We can do this using the &lt;code&gt;From&lt;/code&gt; trait. If we want to transition from &lt;code&gt;Follower&lt;/code&gt; to &lt;code&gt;Candidate&lt;/code&gt; we can implement &lt;code&gt;From&lt;/code&gt; for it.&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="nb"&gt;From&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Follower&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Candidate&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;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Follower&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;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Candidate&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;let&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="o"&gt;..&lt;/span&gt;
      &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Candidate&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;candidate&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 can use it as such&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;follower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Follower&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;candidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Node&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;Candidate&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;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;follower&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we've gotten the type system on our side! If we don't implement &lt;code&gt;From&lt;/code&gt; for Follower -&amp;gt; Leader, doing&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;leader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Node&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;Leader&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;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;follower&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will cause a compilation error. Nice!&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;On using this design, one issue I came across was implementing general behaviours across all states. Since each &lt;code&gt;impl&lt;/code&gt; block is dedicated to a particular state (e.g &lt;code&gt;Node&amp;lt;Follower&amp;gt;&lt;/code&gt;, &lt;code&gt;Node&amp;lt;Leader&amp;gt;&lt;/code&gt;), you have to duplicate any methods you use across them. We can get around this using our favourite feature: traits! We could have something like&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;Follower&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;Candidate&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;Leader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;NodeState&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;NodeState&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Follower&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;NodeState&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Candidate&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;NodeState&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Leader&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NodeState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Generic methods&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've added the trait bound &lt;code&gt;NodeState&lt;/code&gt;. All states &lt;code&gt;S&lt;/code&gt; that implement &lt;code&gt;NodeState&lt;/code&gt; will have the functionality in the &lt;code&gt;impl&lt;/code&gt; block.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
      <category>design</category>
    </item>
    <item>
      <title>Expectations of senior+ engineers from a not so senior engineer</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Fri, 03 Sep 2021 14:29:25 +0000</pubDate>
      <link>https://dev.to/senyeezus/expectations-of-senior-engineers-from-a-not-so-senior-engineer-4a34</link>
      <guid>https://dev.to/senyeezus/expectations-of-senior-engineers-from-a-not-so-senior-engineer-4a34</guid>
      <description>&lt;p&gt;Senior(+) engineer. One of the most coveted titles in our field. There are endless articles on the expectations of these engineers. Naturally, these are written by other senior+ engineers. On realising this, I had a thought&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What would the expectations of a senior+ engineer look like from a non-senior+ engineer?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fitting the bill of that description, I decided, I should write about it! Turns out, they're not so different from what is already in the public domain. However, I thought I would motivate them from my perspective. I can't speak for everyone but I think the themes will be largely applicable. I hope you&lt;br&gt;
find it valuable.&lt;/p&gt;
&lt;h2&gt;
  
  
  Know it all
&lt;/h2&gt;

&lt;p&gt;I'm only trolling you 😆 There is no expectation on you to know everything. All of us are on a learning journey. If you don't know the answer to something, that's perfectly fine. Pointing me in the right direction is often good enough. The best part? I have an opportunity to teach you something. We all grow together.&lt;/p&gt;
&lt;h2&gt;
  
  
  An uncanny sixth sense
&lt;/h2&gt;

&lt;p&gt;At the core of being a senior engineer is having good intuition. Developed through a mix of experience and the ability to critically evaluate past successes and mistakes, it's an important piece of what separates seniors from the rest. Remember that time you avoided a sub-optimal design decision because you started seeing all kinds of red flags? That's your intuition saving the day. You're able to evaluate trade-offs, have a good feel for why certain designs will/won't work given the context you're operating in, base your decisions off decent assumptions in the face of incomplete information and so on. These all help in aiding your decision making process and guide yourself and your team to make more informed decisions.&lt;/p&gt;

&lt;p&gt;This is one trait I appreciate immensely. Anyone who knows me knows I love asking technical questions: Why do our APIs follow this specific design, why do we use microservices, why don't monorepos suit us, when should we trade off quality for speed and so on. These kind of technical questions have no definitive answer. As I've said before&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1363729866194116608-485" src="https://platform.twitter.com/embed/Tweet.html?id=1363729866194116608"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1363729866194116608-485');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1363729866194116608&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;They are all contextual. However, as someone who hasn't seen enough of this play out through my own experiences, it is great to be able to ask and get back well justified answers. I've found this to be one of the most valuable ways of learning for me. It helps me bootstrap my own intuition and opinions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep thought enables great work
&lt;/h2&gt;

&lt;p&gt;Keeping the tweets flowing, we have another one by yours truly&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1336008654693281792-324" src="https://platform.twitter.com/embed/Tweet.html?id=1336008654693281792"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1336008654693281792-324');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1336008654693281792&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I hold the belief that the art of writing code is more a function of design than anything else. Once you have a design, e.g an API interface, a suitable distributed algorithm, etc, the act of actually implementing it in code is often rather straightforward. Even for complex pieces of software this applies. We've gotten better at writing concurrent software because we've designed better concurrent primitives, as an example. This is to all say, at the heart of great engineering is thoughtfulness. Engineers (and teams) that spend significant portions of their time thinking through their solutions tend to produce higher quality work. This makes sense - barely ever is the first idea we have the best one. Being able to take a step back, conjure up and evaluate alternative solutions and then pick the best one given the constraints and context is such a valuable skill. All too often, we find ourselves mashing our keyboards without even thinking about the soundness of our API interfaces.&lt;/p&gt;

&lt;p&gt;I find this trait valuable for the same reason I find the first valuable: I get to ask questions and learn from your thinking. It's always a great learning experience when something is implemented differently to the way I would have imagined it. Being able to talk through your thinking and getting justifications/opinions that challenge my own help me develop my thinking. In fact, one of the most important lessons I've learned is that there doesn't &lt;em&gt;always&lt;/em&gt; have to be a strong justification for making a certain decision. Sometimes, "it's easy and it works" is really enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  A human message broker
&lt;/h2&gt;

&lt;p&gt;Much ink has been spilled on why it is necessary for engineers to learn to communicate effectively. At staff+ levels, this is likely to be one of the biggest expectations outside of technical skills. As technical people, this is often a really difficult skill to pick up and improve. Computers are simple. Humans, not so much. However, it cannot be underestimated how valuable a skill it is. Unfortunately, it's not as simple as putting words on paper or speaking about the matter at hand. This is what I believed initially. Over time, I've realised there's more to it: being able to build consensus on ideas/topics, being clear on outcomes and what they mean (we underestimate how often people have different ideas of the same thing), being clear on what success looks like, being able to storytell, being able to articulate the reasoning behind certain decisions and so on. These are all facets of being able to communicate effectively.&lt;/p&gt;

&lt;p&gt;This is particularly relevant for me because I've been trying to learn how to communicate better within a technical context. I've found this to be rather challenging, however, I have grown considerably by watching how seniors (and even execs) communicate their ideas and concerns. To give a concrete example, one mistake I used to make routinely is vouching for a certain practice, for example, using type annotations in Python, in the name of "best practice". Best in class open source projects are using type annotations, we should too! This is &lt;em&gt;poor&lt;/em&gt; communication. It doesn't even answer the first question you should ask yourself in this situation&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What problem does using type annotations solve for us?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's easy to have good ideas. It is significantly more difficult to &lt;em&gt;justify&lt;/em&gt; them. Being able to communicate effectively is a necessary piece of being a great engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  May the force be with you
&lt;/h2&gt;

&lt;p&gt;Part of seniority is enabling others to do their best work. People who do this are &lt;em&gt;force multipliers&lt;/em&gt;. This is especially relevant at staff+ but even at senior. There are countless ways of doing force multiplying work: mentoring juniors/mids, bridging communication with the business and technical teams, delegating work, leading teams/projects, amplifying others work, helping team members get promoted, driving initiatives across teams, being involved in hiring. These have a large impact on your team and the organisation at large. It is often this work that moves people up into more senior positions, especially when it has organisation wide impact.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As an aside, check out the &lt;a href="https://podcast.staffeng.com/" rel="noopener noreferrer"&gt;StaffEng podcast&lt;/a&gt;. It is one of the best places to gain insight into real-life stories of the journey to staff+ engineer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From a personal perspective, it's great having force multipliers in the team. The best part for me is actually just witnessing it. It is amazing to see senior+ engineers doing great work, caring about the org and making a positive impact. It's simply just inspiring.&lt;/p&gt;




&lt;p&gt;Shoutouts to &lt;a href="https://twitter.com/a_hoverbear" rel="noopener noreferrer"&gt;Ana&lt;/a&gt; and &lt;a href="https://twitter.com/wasimlorgat" rel="noopener noreferrer"&gt;Wasim&lt;/a&gt; for reviewing this&lt;/p&gt;

</description>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ergonomic error handling with Rust</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Wed, 31 Mar 2021 09:02:10 +0000</pubDate>
      <link>https://dev.to/senyeezus/ergonomic-error-handling-with-rust-13bj</link>
      <guid>https://dev.to/senyeezus/ergonomic-error-handling-with-rust-13bj</guid>
      <description>&lt;p&gt;Prior to learning Rust, I never knew error handling was actually a big deal. It never struck me that there are alternative ways to handling errors, that error messages should be as informative as possible, or even that you should take time to write robust error handling logic in your code. It's obvious in retrospect, but in Python-land, there isn't as big a chorus on error handling.&lt;/p&gt;

&lt;p&gt;Rust's story is still developing and as a result there are conversations about every aspect of the language. With a strong emphasis on making developing in Rust enjoyable, there is plenty of healthy debate going on. Error handling is an ongoing and important discussion in the community. The language attempts to make error handling ergonomic and I think they've done a great job of it so far. As I started to read more about it, I realised there was so much I had never considered. Writing good errors and having robust&lt;br&gt;
error handling logic are core features of writing good software. Alongside this, they contribute immensely to developer experience. The central theme threaded throughout this post is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Error handling is about communication&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We strive to write robust code with good error handling logic and informative errors so that we can accurately describe what happened and how we resolved it. Without further ado, let's jump into the world of error handling.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why you should learn about distributed systems
&lt;/h2&gt;

&lt;p&gt;In distributed systems, if there is anything you can be certain of, it is that your system &lt;em&gt;will&lt;/em&gt; fail. Failure is normal. These systems must be built to be fault-tolerant. In learning more about them, one idea really stuck with me and shaped my thinking: build for failure. This thinking&lt;br&gt;
is applicable in most aspects of software development. How many times have you used software and it returns the world's most unhelpful error messages? It once took me about a full working day to debug an error that was fixed by using a jpg image instead of a png. The error message had absolutely nothing to do with the image format and so I wasted countless hours researching and debugging. The application was not built to handle (reasonable) failures.&lt;/p&gt;

&lt;p&gt;Error handling is such an important part of development precisely because it allows us to handle failure. It improves our ability to reason about our software; we understand the myriad ways it may fail. When we encounter failures, great error messages help us diagnose problems efficiently. This in turn boosts productivity and leads to an improved developer experience.&lt;/p&gt;
&lt;h2&gt;
  
  
  Shifting paradigms
&lt;/h2&gt;

&lt;p&gt;Languages like Rust and Go have returned to ways of ancient past by returning errors instead of using exceptions. Being accustomed to exceptions, I did not understand the benefits of returning errors. Through researching it, I came across justifications for its use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Returning errors is explicit. In Python, any function &lt;em&gt;could&lt;/em&gt; throw an exception. Short of reading the source code or the documentation, you're left for dead. If errors are returned, e.g &lt;code&gt;obj, err = func()&lt;/code&gt;, they are pushed onto the developer explicitly. She is at least aware that the function may result in an error. It is still left to her to decide to handle or ignore it but she does so consciously. Without the explicitness, it is too easy to miss areas of code that should have exception handling, purely because you do not even know exceptions are raised. In fairness, statically typed languages with exceptions can solve this problem. For example, Java function signatures declare the exceptions they throw and the compiler enforces exceptions. Fortunately for all Java developers, there is a loophole out of that requirement; one that is used all &lt;a href="https://www.overops.com/blog/ignore-checked-exceptions-all-the-cool-devs-are-doing-it-based-on-600000-java-projects/" rel="noopener noreferrer"&gt;too often&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Exceptions are often misused. They should only be used in &lt;em&gt;exception&lt;/em&gt;-al cases. This is one of those dogmatic phrases in tech but there is some merit behind it. Exceptions do not need to be raised in situations where errors are expected. For example, if we need to read a file and know that there is a possibility that the file may not exist, an exception should not be raised. We expected this and should write our code to handle that situation or propagate that information back to the caller. It's not an exceptional situation. However, if we need to read a file and expect the file to be there and it is not, an exception can be raised. It's a situation we did not expect and possibly one we do not know how to handle. This was the original thinking behind exceptions - in most circumstances, we have logic to handle known, expected failure cases but when we run into truly exceptional situations, we raise exceptions. In reality, exceptions are used freely. One horror story I came across was from a developer who complained about an HTTP client library he had tried using. It threw exceptions for every single non 2xx and 3xx response. That's a great example of misusing exceptions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wiki.c2.com/?PokemonExceptionHandling" rel="noopener noreferrer"&gt;Pokemon exception handling&lt;/a&gt;. In Java and Python, it's possible to catch all exceptions by using syntax like &lt;code&gt;catch Exception&lt;/code&gt; since all exceptions subclass &lt;code&gt;Exception&lt;/code&gt;. This makes debugging failure modes extremely difficult. If your code starts producing weird outputs, it's impossible to tell because errors are caught silently by the catch all statement. In reality, this is the fault of the developer but developers are lazy and will find loopholes if the system allows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After reading that list, you'd be inclined to think that returning errors is hands down the better option. Returning errors has a critical flaw: it is &lt;em&gt;easy&lt;/em&gt; to ignore them. For example in Go, you can write &lt;code&gt;value, _ := func()&lt;/code&gt;. In the event that &lt;code&gt;func&lt;/code&gt; errors, &lt;code&gt;value&lt;/code&gt; will be left in an invalid state but execution will continue uninhibited. With exceptions, a key benefit is that program will crash immediately. Returning errors requires significant discipline from developers, who as we mentioned before, are lazy.&lt;/p&gt;

&lt;p&gt;Rust takes returning errors to the next logical level by enforcing errors are handled. It takes inspiration from the &lt;a href="https://en.wikipedia.org/wiki/ML_(programming_language)" rel="noopener noreferrer"&gt;ML family of languages&lt;/a&gt;. These languages have a strong type system, embedding the notion of a fallible computation into the type system in a unique way.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Rust does error handling
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Result type
&lt;/h3&gt;

&lt;p&gt;In the ML family of languages, one of the common constructs is the &lt;code&gt;Result&lt;/code&gt; type. A &lt;code&gt;Result&lt;/code&gt; is an enum that has two possible states: the value of the computation or an error. To get the value, you have to unwrap &lt;code&gt;Result&lt;/code&gt;. The compiler enforces that &lt;code&gt;Result&lt;/code&gt; is unwrapped before it is &lt;em&gt;used&lt;/em&gt; anywhere else. For example, if we have a function &lt;code&gt;do_something(s: String)&lt;/code&gt; and our input variable is currently a &lt;code&gt;Result&amp;lt;String&amp;gt;&lt;/code&gt;, we have to unwrap it to get the &lt;code&gt;String&lt;/code&gt; in order to pass it into the function. In the event &lt;code&gt;Result&lt;/code&gt; contains an error, we have to handle it. This enforces the handling of errors. There is no way to circumvent it due to it being embedded in the type system. This is why error handling in Rust is great. Let's take a look at basic error handling.&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="c1"&gt;// This is the result type in the standard library. It either contains&lt;/span&gt;
&lt;span class="c1"&gt;// the value of the computation Ok(T) where T is the value or an error&lt;/span&gt;
&lt;span class="c1"&gt;// Err(E) where E is the error&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nb"&gt;Result&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E&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;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&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;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="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&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="s"&gt;"ferris.txt"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Returns Result&amp;lt;File&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// To unwrap we match on the enum variants&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;f&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;f&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;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"File could not be created"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.write_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi Ferris"&lt;/span&gt;&lt;span class="p"&gt;)&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not write to file"&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;Rust has several convenience methods/syntax such as &lt;code&gt;unwrap&lt;/code&gt;, &lt;code&gt;expect&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt; which help to remove some of the boilerplate. We will discuss these later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Panicking
&lt;/h3&gt;

&lt;p&gt;In Rust, irrecoverable errors are signaled using the &lt;code&gt;panic!&lt;/code&gt; macro. When a panic is invoked, the developer is essentially saying, "program execution cannot continue any further after encountering this error". Panicking is a terminal state; the program crashes as a result. It is normally used when&lt;br&gt;
a bug is encountered. They are meant to be infrequent, with standard error handling taking care of most cases. We've already seen panic being used in Rust in the above 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;match&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.write_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi Ferris"&lt;/span&gt;&lt;span class="p"&gt;)&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not write to file"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// If this branch executes, program crashes&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bubbling errors
&lt;/h3&gt;

&lt;p&gt;In many cases, we do not want an error to be handled at the location it is generated. Instead, we would prefer to have that error be handled by the caller of the function, giving it the power to decide how to proceed. In programming parlance, we want to "bubble" the error to the caller. In Rust, we can achieve this using matching.&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="c1"&gt;// () is the unit type and is used when there is no meaningful&lt;/span&gt;
&lt;span class="c1"&gt;// value to return&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;File&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="s"&gt;"ferris.txt"&lt;/span&gt;&lt;span class="p"&gt;)&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;f&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;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// returns an error to the caller&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.write_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi Ferris"&lt;/span&gt;&lt;span class="p"&gt;)&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(()),&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The executable code&lt;/span&gt;
&lt;span class="c1"&gt;// Caller of function gets error and then panics on failure&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not initialise"&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;
  
  
  Making it ergonomic
&lt;/h2&gt;

&lt;p&gt;As I mentioned earlier, Rust has a number of convenience methods/syntax to reduce boilerplate. There are three that are commonly used: &lt;code&gt;unwrap&lt;/code&gt;, &lt;code&gt;expect&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try
&lt;/h3&gt;

&lt;p&gt;When bubbling errors, you can imagine that writing the above match statement becomes cumbersome. It's boilerplate that the language can handle for you. A similar problem exists in Go. If you ask Gophers what line of code they write the most, they'll answer: &lt;code&gt;if err != nil {}&lt;/code&gt;. The Rust language designers took care of matching boilerplate by introducing the &lt;code&gt;?&lt;/code&gt; syntax. This replaced the &lt;code&gt;try!&lt;/code&gt; macro as a more convenient syntax. Its purpose is to automatically bubble the error to the caller on an error occuring.&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="c1"&gt;// Before we would write code like this&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;File&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="s"&gt;"ferris.txt"&lt;/span&gt;&lt;span class="p"&gt;)&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;f&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;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.write_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi Ferris"&lt;/span&gt;&lt;span class="p"&gt;)&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(()),&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// With the `?` operator, we can write it as&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&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="s"&gt;"ferris.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.write_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi Ferris"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see from the above example, our code is significantly less verbose while being functionally identical. This is one of those small quality of life improvements that makes a world of difference when writing Rust. It highlights the commitment to a friendly developer experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  unwrap
&lt;/h3&gt;

&lt;p&gt;There are often scenarios where you want to opt out of error handling. This may be when you're prototyping and don't want to go through the effort of setting up robust error handling or when you know that a function won't fail (e.g if you need to read a file that you know will always exist). To get out of it, you can use the &lt;code&gt;unwrap()&lt;/code&gt; method. &lt;code&gt;unwrap&lt;/code&gt; returns the &lt;code&gt;Ok&lt;/code&gt; variant with it's value if the computation succeeds or will panic on 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="c1"&gt;// Notice how we don't need the return type anymore&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We use `unwrap()` to panic if it fails otherwise execution continues&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&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="s"&gt;"ferris.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.write_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi Ferris"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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 try create a file in a location we do not have permission to access, the code will panic, causing the program to crash. An example of a panic message&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os {
code: 13, kind: PermissionDenied, message: "Permission denied" }',
src/main.rs:4:36
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how Rust does not give us a get out of jail free card with error handling. Either we write error handling logic or we accept our code will panic and subsequently crash (most likely unknowingly to the developer). Extensive &lt;code&gt;unwrap&lt;/code&gt;ing is not recommended for production code. There are cases where it is permissible (as with everything), for example if we can guarantee it won't fail or we want execution to panic at that location. One issue with &lt;code&gt;unwrap&lt;/code&gt; is that error messages can be uninformative. We can do one better by using &lt;code&gt;expect&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  expect
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;expect()&lt;/code&gt; method is identical to &lt;code&gt;unwrap()&lt;/code&gt; but it allows you to set an error message. This conveys your intent and makes debugging easier.&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;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Write to a location we do not have permission&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;File&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="s"&gt;"/var/ferris.txt"&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="s"&gt;"Could not create file `ferris.txt`"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.write_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi Ferris"&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="s"&gt;"Could not write to file"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates the message&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;thread 'main' panicked at 'Could not create file `ferris.txt`: Os {
code: 13, kind: PermissionDenied, message: "Permission denied" }',
src/main.rs:4:36
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, Rust has a strong focus on making error handling a frictionless experience for the developer. There are other functions that I have not gone through here: &lt;code&gt;map_err&lt;/code&gt;, &lt;code&gt;map_or_else&lt;/code&gt;, &lt;code&gt;unwrap_or&lt;/code&gt;, &lt;code&gt;unwrap_or_else&lt;/code&gt; and many more. If you're new to Rust, I encourage you to give them a look. I certainly will as I improve the quality of my error handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it informative
&lt;/h2&gt;

&lt;p&gt;Writing good errors means making them highly informative. Without good error messages, debugging is significantly more difficult. To reiterate, error handling and error reporting is about communication. By providing highly informative errors, we paint the full picture of what has happened. We want to guide the developer directly to the problem. Rust has made good error reporting a core emphasis of the language and the larger ecosystem. Arguably, unintentionally.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1303107711928643584-24" src="https://platform.twitter.com/embed/Tweet.html?id=1303107711928643584"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1303107711928643584-24');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1303107711928643584&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The Rust compiler really is a gold standard in error reporting. There's still work to do but it is one of the most human friendly pieces of software I have used. As an example&lt;/p&gt;

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

&lt;p&gt;I quite like how this tweet puts it :)&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1348669062528774148-95" src="https://platform.twitter.com/embed/Tweet.html?id=1348669062528774148"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1348669062528774148-95');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1348669062528774148&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Focusing on good error messages has permeated throughout the community. There's even the &lt;a href="https://github.com/rust-lang/project-error-handling" rel="noopener noreferrer"&gt;Error Handling Project Group&lt;/a&gt; if you weren't convinced how committed the language designers are to getting this right. There are a number of techniques we can use to make our errors more informative. Along the way, we will discuss the crates that can help.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are we writing?
&lt;/h3&gt;

&lt;p&gt;The first question we have to ask is&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are we writing an application or a library?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I had never considered that your approach to structuring error handling is different depending on whether you are writing an application or library. This &lt;a href="https://nick.groenen.me/posts/rust-error-handling/" rel="noopener noreferrer"&gt;article&lt;/a&gt; illuminated this difference to me. I encourage you to go read it. I will mention the points I found particularly insightful with some insight of my own.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As far as possible, libraries should use meaningful custom error types. This has several benefits:

&lt;ul&gt;
&lt;li&gt;Applications can easily differentiate between various errors. A simple example are the
various &lt;a href="https://doc.rust-lang.org/std/io/enum.ErrorKind.html" rel="noopener noreferrer"&gt;IO errors&lt;/a&gt; defined in the Rust standard library.&lt;/li&gt;
&lt;li&gt;Errors can be wrapped into a custom error defined by the library. Without this, it would be impossible to differentiate between errors from different libraries. An IO error in &lt;code&gt;Foo&lt;/code&gt; would be indistinguishable from an IO error in &lt;code&gt;Bar&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It increases the cardinality of errors at the application level. High cardinality data allows us to answer very specific questions, giving us the insights we need. This helps when you need to understand error rates across your system, find areas that need some extra maintenance, debug production issues and so on.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;When defining custom errors, they should always implemented the standard library &lt;code&gt;Error&lt;/code&gt; trait, &lt;code&gt;std::error::Error&lt;/code&gt;. This is to mitigate compatibility issues with errors from other libraries.&lt;/li&gt;

&lt;li&gt;Libraries should never panic. From the application programmer's point of view, panics are undefined behaviour; there is no expectation that a library call will crash an application. Errors should be bubbled up to the caller.&lt;/li&gt;

&lt;li&gt;Applications consume errors and make informed decisions on how to handle them. There is often not a huge need for custom errors at the application level. Additionally, at this level, panicking may be the best option and is therefore reasonable.&lt;/li&gt;

&lt;li&gt;Applications are responsible for deciding how errors are formatted and displayed to users.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;As we can see, there are subtly different requirements depending on which one you are writing. Rust being Rust has crates for both these use cases. The most popular of these are &lt;a href="https://docs.rs/anyhow/1.0.39" rel="noopener noreferrer"&gt;anyhow&lt;/a&gt; and &lt;a href="https://docs.rs/thiserror/1.0.24/thiserror/" rel="noopener noreferrer"&gt;thiserror&lt;/a&gt;. &lt;code&gt;anyhow&lt;/code&gt; is used for error reporting in applications while &lt;code&gt;thiserror&lt;/code&gt; is used for creating custom errors for libraries (and applications). I will go through their use cases in context of important aspects of error handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  It depends
&lt;/h3&gt;

&lt;p&gt;A while ago, I tweeted this&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1363729866194116608-877" src="https://platform.twitter.com/embed/Tweet.html?id=1363729866194116608"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1363729866194116608-877');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1363729866194116608&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;As (not) funny as it may be, the truth is that most technical decisions (and arguably most life decisions) come down to &lt;em&gt;context&lt;/em&gt;. If you operate outside of context, you're likely to make a whole host of sub-optimal decisions; not because they are inherently incorrect, they're just not applicable to the situation. Similarly, if error messages are missing the context in which they are generated, they're likely to send you down a spiral of debugging. Most of that time might unfortunately be spent exploring dead ends. For errors to be informative, they need to include additional context. Taking a simple example, imagine you are trying to open a file and it does not exist. If we printed the error, we would get&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No such file or directory (os error 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is barely useful. We know that we have an IO error but no idea what generated it. We also do not know which file or directory is the culprit. Now imagine our error message was like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Failed to read file /path/to/directory/ferris.txt

Caused by:
    No such file or directory (os error 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Much better! We know which file we are missing and where it's located. If we let our imagination run unbounded, we can think of additional context we could add - like a stack backtrace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Failed to read file /path/to/directory/ferris.txt

Caused by:
    No such file or directory (os error 2)

Stack backtrace:
   0: std::backtrace_rs::backtrace::libunwind::trace
             at /rustc/f5f33ec0e0455eefa72fc5567eb1280a4d5ee206/library/std/src/../../...
      std::backtrace_rs::backtrace::trace_unsynchronized
   ...
   ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, adding additional context makes our errors so much more informative. This aids us whenever we need to debug our code.&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, I said I'd talk about the relevant crates as we go over various topics. &lt;code&gt;anyhow&lt;/code&gt; allows us to add additional context to our error messages. The above two error reports are produced by &lt;code&gt;anyhow&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;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Context&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;main&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;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&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;let&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ferris.txt"&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;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&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="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.with_context&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read file {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;
  
  
  Be like Mansory
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Mansory" rel="noopener noreferrer"&gt;Mansory&lt;/a&gt; is a luxury car modification company. Their cars are something to behold and I'm not even that into cars. In the same way they make crazy custom cars, we should strive to make crazy custom errors. Okay, maybe not &lt;em&gt;too&lt;/em&gt; crazy. Libraries should have their own set of custom errors that are meaningful given the domain they operate within. In other cases, they should wrap standard errors. As mentioned, this ensures we can differentiate between similar classes of errors between libraries. You can also take the approach &lt;a href="https://docs.rs/tokio/1.4.0/tokio/" rel="noopener noreferrer"&gt;tokio&lt;/a&gt; took and &lt;a href="https://docs.rs/tokio/1.4.0/tokio/io/index.html#reexports" rel="noopener noreferrer"&gt;re-export types&lt;/a&gt; so they are accessible through your library but still differentiated from another library. Once again, when you strip it down to its core essence, the point of all of this is communication. We want our libraries to faithfully communicate to the developer what type of error was encountered when things go wrong.&lt;/p&gt;

&lt;p&gt;Rust requires a bit of ceremony to &lt;a href="https://learning-rust.github.io/docs/e7.custom_error_types.html" rel="noopener noreferrer"&gt;define custom types&lt;/a&gt;. It is worth digging into before using a library to do the heavy lifting for you. &lt;code&gt;thiserror&lt;/code&gt; is a library used for creating custom errors. I've found it enjoyable to use, albeit I have not had to do anything advanced. Imagine we have a library &lt;code&gt;beatmaker&lt;/code&gt; that generates music using midi. The errors we care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The notes are invalid music notes i.e they are not between A &amp;amp; G&lt;/li&gt;
&lt;li&gt;The format of the file containing the notes is invalid&lt;/li&gt;
&lt;li&gt;The instrument is invalid - it's not in the set of instruments we have&lt;/li&gt;
&lt;li&gt;IO errors e.g the file is missing. For IO errors, we want to wrap the IO error into one of our own errors.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;thiserror&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Error,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;BeatMakerError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(&lt;/span&gt;&lt;span class="s"&gt;"The music notes are not all valid. Please ensure they are between A &amp;amp; G"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;InvalidNotes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(&lt;/span&gt;&lt;span class="s"&gt;"The format of your .bm file is invalid. Check the guide to learn how to create .bm files"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;InvalidFormat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(&lt;/span&gt;&lt;span class="s"&gt;"The name of your instrument is invalid. Please check the instrument list for all valid instruments"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;InvalidInstrumentName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// This wraps all IO errors produced by the std lib into our defined IOError&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(transparent)]&lt;/span&gt;
    &lt;span class="nf"&gt;IOError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;#[from]&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use it in an application 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;fn&lt;/span&gt; &lt;span class="nf"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;BeatMakerError&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;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;BeatMakerError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidNotes&lt;/span&gt;&lt;span class="p"&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;BeatMakerError&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;match&lt;/span&gt; &lt;span class="nf"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;()&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All good!"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'd write better errors but I'm lazy. The error: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we've wrapped the standard library's IO errors, we can write a fallible function that returns an IO error and it will work seamlessly with &lt;code&gt;BeatMakerError&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;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;File&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;io_raise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;BeatMakerError&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;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ferris.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;BeatMakerError&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;match&lt;/span&gt; &lt;span class="nf"&gt;io_raise&lt;/span&gt;&lt;span class="p"&gt;()&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All good!"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'd write better errors but I'm lazy. The error: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On error, this gives us the error message&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'd write better errors but I'm lazy. The error: No such file or directory (os error 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The future of errors
&lt;/h2&gt;

&lt;p&gt;One aspect of Rust's community I really enjoy is its grandiose imagination. In particular, Rust's language designers have a seemingly unbounded imagination. They dream of designing a language that is overwhelmingly pleasant to use. In many ways, they are getting this right - adoption for the language is growing even in the face of complexity such as the borrow checker. Error handling is no different. In reading more about error handling, I came across &lt;a href="https://twitter.com/yaahc_" rel="noopener noreferrer"&gt;Jane Lusby&lt;/a&gt;'s RustConf 2020 talk, &lt;a href="https://www.youtube.com/watch?v=rAF8mLI0naQ" rel="noopener noreferrer"&gt;Error handling Isn't All About Errors&lt;/a&gt;. She wrote &lt;a href="https://docs.rs/eyre/0.6.5/eyre/" rel="noopener noreferrer"&gt;eyre&lt;/a&gt;, a fork of &lt;code&gt;anyhow&lt;/code&gt; that adds support for customised error reports. I encourage you to watch the video and check out the library. The core focus of &lt;code&gt;eyre&lt;/code&gt; is to further improve error messages/reports. It's imagining even more informative errors in Rust.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error:
   0: Unable to read config
   1: cmd exited with non-zero status code

Location:
   src/main.rs:50

Stderr:
   cat: fake_file: No such file or directory

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                                ⋮ 10 frames hidden ⋮
  11: &amp;lt;std::process::Command as solo::Output&amp;gt;::output2::h8837a51b9856a548
      at /Users/senyosimpson/Projects/test/solo/src/main.rs:50
  12: solo::read_file::h21ce0bfb8b0da736
      at /Users/senyosimpson/Projects/test/solo/src/main.rs:88
  13: solo::read_config::h048c15951f2a6b11
      at /Users/senyosimpson/Projects/test/solo/src/main.rs:93
  14: solo::main::hec1c621ee896fc4a
      at /Users/senyosimpson/Projects/test/solo/src/main.rs:65
  15: core::ops::function::FnOnce::call_once::h94986c4cb4784c0a
      at /Users/senyosimpson/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/..
                                ⋮ 9 frames hidden ⋮

Suggestion: try using a file that exists next time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above error report is an example of this. There are some nice novelties. The error contains both the error messages and the order in which they occurred in a nice format. There is also a suggestion which is something we do not see often in standard error reports. The other information we are used to seeing but it is nicely formatted. It really contains all the information you need in a nice and succinct format. There's even possibilities of extending this further. If we have a chain of errors, we can generate a report like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error:
   0: encountered multiple errors

Location:
   src/main.rs:47

Error:
   0: The task could not be completed
   1: The task you ran encountered an error

Error:
   0: The machine is unreachable
   1: The machine you're connecting to is actively on fire

Error:
   0: The file could not be parsed
   1: The file you're parsing is literally written in c++ instead of rust, what the hell

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                                ⋮ 10 frames hidden ⋮
  11: solo::join_errors::hd118537501e8ddf7
      at /Users/senyosimpson/Projects/test/solo/src/main.rs:47
  12: solo::main::hec1c621ee896fc4a
      at /Users/senyosimpson/Projects/test/solo/src/main.rs:35
  13: core::ops::function::FnOnce::call_once::h94986c4cb4784c0a
      at /Users/senyosimpson/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/..
                                ⋮ 9 frames hidden ⋮
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is so cool! We get all the information we need with the full chain of errors. The error messages are also stellar, nice touch Jane :)&lt;/p&gt;

&lt;p&gt;We have the capacity to imagine a future with the most enjoyable and ergonomic error handling and informative, easily readable error reports. It's great to see there is active work on this front. Hopefully, Rust will continue to make our lives all a bit better, one error message at a&lt;br&gt;
time.&lt;/p&gt;




&lt;p&gt;Shoutouts to &lt;a href="https://twitter.com/a_hoverbear" rel="noopener noreferrer"&gt;Ana&lt;/a&gt; for reviewing this post 🐻&lt;/p&gt;

</description>
      <category>rust</category>
      <category>errors</category>
      <category>programming</category>
    </item>
    <item>
      <title>The basics of gRPC</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Sat, 19 Sep 2020 17:04:18 +0000</pubDate>
      <link>https://dev.to/senyeezus/the-basics-of-grpc-4kok</link>
      <guid>https://dev.to/senyeezus/the-basics-of-grpc-4kok</guid>
      <description>&lt;p&gt;If you are similar to me, you've heard about gRPC countless times but have little idea of what it actually is, what its use cases are and why everyone keeps speaking about it. Initially, I thought it must be &lt;em&gt;another&lt;/em&gt; buzzword being thrown around. Fortunately, I was wrong 😆. I've spent a couple of days reading and learning more about it. This blog post is a summary of all I've learned. I hope you enjoy it! &lt;/p&gt;

&lt;h1&gt;
  
  
  What is Remote procedure call?
&lt;/h1&gt;

&lt;p&gt;Remote procedure call (RPC) is a communication protocol used between web services. The central idea around RPC is to allow a client application to execute a procedure (function) on a server application as if the procedure is running locally. The networking details are abstracted away from the developer making it simple to use.&lt;/p&gt;

&lt;p&gt;To concretize it, a bird's eye view of a typical RPC flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A client calls a function&lt;/li&gt;
&lt;li&gt;The function is actually a remote procedure call. A request is made to a server to execute the procedure&lt;/li&gt;
&lt;li&gt;The request contains the parameters to be passed into the procedure&lt;/li&gt;
&lt;li&gt;The procedure is executed on the server&lt;/li&gt;
&lt;li&gt;A response is returned to the client containing the result of the procedure execution&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From the client's perspective, the procedure seems as if it is running locally. This is a great abstraction, however there are pitfalls. Martin Kleppmann, in his book &lt;a href="https://dataintensive.net" rel="noopener noreferrer"&gt;Designing Data-Intensive Applications&lt;/a&gt;, highlights some of the differences between remote and local procedure calls.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A local function call is predictable and its success depends on factors under your control. In contrast, a networking request is unpredictable and fails for various reasons.&lt;/li&gt;
&lt;li&gt;A local function returns a result, throws an exception or never returns. A networking request, in addition, can return without a result due to a timeout. In this scenario, there is no way to know what occured.&lt;/li&gt;
&lt;li&gt;A network request may be received and execute but only the network &lt;em&gt;response&lt;/em&gt; fails. Network request failures are often handled by retries but unfortunately in this case, the function would be executed multiple times as you would not know only the responses are getting lost.&lt;/li&gt;
&lt;li&gt;A local function takes a similar amount of time to execute every time it is invoked. Network requests have variable latency due to networking specific issues - network is congested, server is at maximum capacity etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is gRPC?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://grpc.io" rel="noopener noreferrer"&gt;gRPC website&lt;/a&gt; describes it as a, "modern, open source remote procedure call (RPC) framework that can run anywhere. It enables client and server applications to communicate transparently, and makes it easier to build connected systems". It was created by Google and subsequently open-sourced in 2016. gRPC has driven the resurgence of communications using RPC. With the move towards service-oriented architectures, it has found a natural home in service-to-service communications.&lt;/p&gt;

&lt;p&gt;gRPC uses protocol buffers (protobufs) - a method for serializing/deserializing structured data. Protocol buffer messages are encoded in a binary format. This makes it fast to send information over the wire; at least in comparison to textual formats such as JSON. The use of protocol buffers alongside the great and easy to use tooling around gRPC has made it the preferred framework for implementing RPC.&lt;/p&gt;

&lt;p&gt;As with any technology, there are advantages and disadvantages. This &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/grpc/comparison?view=aspnetcore-3.1" rel="noopener noreferrer"&gt;article&lt;/a&gt; by Microsoft highlights some of the them. In summary&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;gRPC Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance - gRPC is fast in comparison to other protocols&lt;/li&gt;
&lt;li&gt;Code generation - server and client code is automatically generated from a single file&lt;/li&gt;
&lt;li&gt;Streaming - gRPC supports HTTP streaming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;gRPC Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited browser support - there is limited support for HTTP/2 in the browser&lt;/li&gt;
&lt;li&gt;Not human readable - gRPC uses a binary format and therefore is not human readable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Protocol Buffers
&lt;/h1&gt;

&lt;p&gt;As stated above, protocol buffers are a method for serializing/deserializing structured data. Protocol buffer messages are defined using a schema consisting of key-value pairs.&lt;/p&gt;

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

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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;You can think of Person as a struct. Each field is a key-value pair and is annotated with their respective data type. Each field has a number associated to it which is used as the key. In actual fact, the key contains the field number and information about the type of data being encoded in order to determine the length of the value. This is commonly referred to as the tag. As an example, if we have a protobuf message&lt;/p&gt;

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

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Test2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;with the value of &lt;code&gt;b&lt;/code&gt; set to &lt;code&gt;testing&lt;/code&gt;, the corresponding encoding will be&lt;/p&gt;

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

12 07 74 65 73 74 69 6e 67


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

&lt;/div&gt;

&lt;p&gt;The bytes &lt;code&gt;12&lt;/code&gt; and &lt;code&gt;07&lt;/code&gt; form the tag. The value &lt;code&gt;12&lt;/code&gt; is decoded to give the field number 2 and the data type string. The value &lt;code&gt;07&lt;/code&gt; is decoded to give the length of the value which is 7 in this case. As you can see, there are 7 bytes remaining which give the value of the string. If you are interested, you can find more information about the protocol buffer encoding from the &lt;a href="https://developers.google.com/protocol-buffers/docs/encoding" rel="noopener noreferrer"&gt;official guide&lt;/a&gt;. This example is actually from there albeit with much less detail.&lt;/p&gt;

&lt;h1&gt;
  
  
  What happened to REST?
&lt;/h1&gt;

&lt;p&gt;REST is the canonical standard for communications over the web. It has been battle-tested in production, extensive tooling exists for implementing RESTful services and most developers are comfortable with designing, building and maintaining RESTful services. Naturally the big question is what is so great about gRPC that we would forego creating a RESTful service? The answer is fairly straightforward: performance. While there are other benefits of using gRPC such as the use of HTTP/2 or bidirectonal streaming, for the standard use case, performance is the central reason for adopting it. JSON is much slower to serialize/deserialize than protobufs. At scale, this can lead to a noticeable degradation in performance of the overall system. As protobufs are a binary format, they are much faster to serialize/deserialize. some articles claiming there is an improvement of 5-6 times. &lt;/p&gt;

&lt;h1&gt;
  
  
  gRPC by example
&lt;/h1&gt;

&lt;p&gt;Nothing is ever complete without some code examples! I've tried to make this as easy to follow as possible. Let me know if any improvements can be made. All the code can be found &lt;a href="https://github.com/senyosimpson/tutorials/tree/master/grokkingrpc" rel="noopener noreferrer"&gt;here&lt;/a&gt;. We will implement the service in the &lt;a href="https://grpc.io/docs/languages/go/quickstart/" rel="noopener noreferrer"&gt;Quick Start&lt;/a&gt; section of the gRPC website. I'm using Golang for this tutorial.&lt;/p&gt;

&lt;p&gt;One snag that got me was the automatic code generation from the proto files. There is a move towards a new Golang plugin for the protobuf compiler (it performs the automatic code generation). The old (which I used) and new version output slightly different files and so I couldn't follow the code in the official grpc &lt;a href="https://github.com/grpc/grpc-go/tree/master/examples/helloworld" rel="noopener noreferrer"&gt;examples&lt;/a&gt; repository. To make things simple, this tutorial uses the old Golang plugin. Awesome, let's get into it 🥳&lt;/p&gt;




&lt;p&gt;The service is really simple, all it does is greet a person. The client can send a request containing a name to the server. The server produces a simple message, &lt;code&gt;"Hello &amp;lt;name&amp;gt;"&lt;/code&gt;. To recap, the server is responsible for executing the procedure and returning the result to the client. From the client's perspective, the procedure ran locally.&lt;/p&gt;

&lt;p&gt;First things first, the dependencies need to be installed. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Protobuf compiler - installation &lt;a href="https://grpc.io/docs/protoc-installation/" rel="noopener noreferrer"&gt;instructions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Golang plugin for the Protobuf compiler - installation &lt;a href="https://grpc.io/docs/languages/go/quickstart/" rel="noopener noreferrer"&gt;instructions&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The protobuf compiler and Golang plugin are used for code generation. They automatically implement the server and client code, only leaving the functions definitions up to the developer.&lt;/p&gt;

&lt;p&gt;We create our protobuf schema &lt;code&gt;helloworld.proto&lt;/code&gt;.&lt;/p&gt;

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

&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This denotes the protobuf version&lt;/span&gt;

&lt;span class="c1"&gt;// All protobufs have a package name. This is to avoid name clashes with other protocol&lt;/span&gt;
&lt;span class="c1"&gt;// message types. In Golang, the package name is used as the Go package name for the&lt;/span&gt;
&lt;span class="c1"&gt;// generated files. This is however overwritten if you specify the go_package option&lt;/span&gt;
&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;helloworld&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="c1"&gt;// This option is specifies the full import path of the Go package that contains&lt;/span&gt;
&lt;span class="c1"&gt;// the generated code.&lt;/span&gt;
&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;go_package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"github.com/senyosimpson/tutorials/grokkingrpc/helloworld"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This defines the service. In a service, you define rpc methods. These are&lt;/span&gt;
&lt;span class="c1"&gt;// method signatures that contain their request and response types.&lt;/span&gt;
&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;HelloWorld&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloReply&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;// Messages are defined by specifying their type and name of the variables it holds.&lt;/span&gt;
&lt;span class="c1"&gt;// These are enumerated from 1 to n.&lt;/span&gt;
&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloReply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now that we have our protobuf schema, we can generate the Go files. These files will have an extension &lt;code&gt;.pb.go&lt;/code&gt;. To do so, execute the command&lt;/p&gt;

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

protoc &lt;span class="nt"&gt;-I&lt;/span&gt; helloworld/ helloworld/helloworld.proto &lt;span class="nt"&gt;--go_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;grpc:helloworld &lt;span class="nt"&gt;--go_opt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;source_relative


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

&lt;/div&gt;

&lt;p&gt;Now that we have our generated files, we're ready to create our server. If you look in the generated file, &lt;code&gt;helloworld.pb.go&lt;/code&gt;, you should find an interface named &lt;code&gt;HelloWorldServer&lt;/code&gt;. &lt;/p&gt;

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

&lt;span class="c"&gt;// HelloWorldServer is the server API for HelloWorld service.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;HelloWorldServer&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&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="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We have to implement this interface to define our service. In the implementation, the server prints out that it received a given name. It returns a reply message that contains the greeting, &lt;code&gt;Hello &amp;lt;name&amp;gt;&lt;/code&gt;.&lt;/p&gt;

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

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;helloWorldService&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;HelloWorldServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&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="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;As an fyi, the function &lt;code&gt;GetName&lt;/code&gt; is automatically generated. This can be found in the &lt;code&gt;helloworld.pb.go&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The rest of the necessary code is implementing the server itself. The full code&lt;/p&gt;

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

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net"&lt;/span&gt;

    &lt;span class="n"&gt;pb&lt;/span&gt; &lt;span class="s"&gt;"github.com/senyosimpson/tutorials/grokkingrpc/helloworld"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;helloWorldServer&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;helloWorldServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&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="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":50051"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to listen: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterHelloWorldServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;helloWorldServer&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lis&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to serve: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;The client is straightforward, I just copied it from the examples repository. The main line of consequence is the request to the server.&lt;/p&gt;

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

&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Here we see the client calling the &lt;code&gt;Greet&lt;/code&gt; method. A request message is passed in with a specified name.&lt;/p&gt;

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

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
    &lt;span class="n"&gt;pb&lt;/span&gt; &lt;span class="s"&gt;"github.com/senyosimpson/tutorials/grokkingrpc/helloworld"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost:50051"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Set up a connection to the server.&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithInsecure&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithBlock&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"did not connect: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewHelloWorldClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Contact the server and print out its response.&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Bas"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"could not greet: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Greeting: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetMessage&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're now ready to test it! In one terminal, start the server. In the other, we can run the client code and make requests to the server. In the image below, the server is on the left and client on the right. We can see the client gets back the reply message and prints the message to the console.&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%2F7lnmtmdr1kxl1tq0jo5y.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%2F7lnmtmdr1kxl1tq0jo5y.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! I hope you've taken something valuable out of this walkthrough of the basics of gRPC. I've certainly enjoyed learning and writing about it.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  RPC
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.tutorialspoint.com/remote-procedure-call-rpc" rel="noopener noreferrer"&gt;Remote Procedure Call - Tutorialspoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/remote-procedure-call-rpc-in-operating-system/" rel="noopener noreferrer"&gt;Remote Procedure Call - Geeks for Geeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Remote_procedure_call" rel="noopener noreferrer"&gt;Remote Procedure Call - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  gRPC VS REST
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://wecode.wepay.com/posts/migrating-apis-from-rest-to-grpc-at-wepay" rel="noopener noreferrer"&gt;Migrating APIs from REST to gRPC&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  gRPC
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://grpc.io" rel="noopener noreferrer"&gt;gRPC Official Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/GRPC" rel="noopener noreferrer"&gt;gRPC - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Protocol Buffers
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Protocol_Buffers" rel="noopener noreferrer"&gt;Protocol buffers - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeclimate.com/blog/choose-protocol-buffers/" rel="noopener noreferrer"&gt;5 Reasons to use protocol buffers&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>grpc</category>
      <category>go</category>
      <category>networking</category>
      <category>api</category>
    </item>
    <item>
      <title>Concepts I learned from diving into Clojure</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Sat, 25 Jul 2020 16:49:59 +0000</pubDate>
      <link>https://dev.to/senyeezus/concepts-i-learned-from-diving-into-clojure-407f</link>
      <guid>https://dev.to/senyeezus/concepts-i-learned-from-diving-into-clojure-407f</guid>
      <description>&lt;p&gt;This year, one of my goals was to learn a functional programming language. I carried this over from last year because who actually achieves their goals, right? To be fair, I did make an attempt - I began learning Haskell. Let's just say, I'll try again one day! Around April this year, on recommendation from one of my mentors, I decided to look into Clojure. It turned out to be a great suggestion and I've been enjoying hacking away in Clojure ever since! With all that being said, I have been pleasantly surprised by the language, learning plenty along the way.&lt;/p&gt;

&lt;p&gt;Clojure is a functional programming language &lt;em&gt;and&lt;/em&gt; a dialect of &lt;a href="https://en.wikipedia.org/wiki/Lisp_(programming_language)" rel="noopener noreferrer"&gt;Lisp&lt;/a&gt;. Coming from an object-oriented and imperative coding background, both of these ideas were new to me. I'll dedicate the first portion of this post to the Lisp aspects of Clojure and the second portion to functional programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lisp
&lt;/h2&gt;

&lt;p&gt;List processing (Lisp) is a programming language created by John McCarthy in 1958. It is designed to make processing lists simple and efficient (hence the name). During its peak, its main use case was in artificial intelligence research. Clojure is a dialect of Lisp, giving it some useful properties common to all Lisp languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  S-Expressions
&lt;/h3&gt;

&lt;p&gt;A symbolic expression (s-expression) is the syntax used in the Lisp language and its variants. It provides a representation of a nested list of data. In Lisp, both code and data are represented as s-expressions which leads to the philosophy of &lt;em&gt;code as data&lt;/em&gt;. Examples of s-expressions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; (+ 2 6) =&amp;gt; 8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful property of s-expressions is that they provide a uniform structure. All syntax follows the structure &lt;code&gt;(operator arg1 arg2 ...)&lt;/code&gt;. This maps well to tree-structured data (as will be discussed further on) and makes writing compilers more trivial. In the above example, the first line adds numbers 2 and 3 to give 5. In the second line, we have a nested list. The inner operation is performed first and then the outer operation - first 3 and 3 are added to give 6 and then 2 and 6 are added to give the final result of 8.&lt;/p&gt;

&lt;p&gt;For most programmers, this syntax is strange - I certainly found it awkward to work with in the beginning. After some time with it, I really began to enjoy it. The simple structure of the language makes reading and writing code straightforward. It lends itself to concise and readable functional code which made the process of learning functional programming easier. Considering we often want to chain a set of functions to apply to some data, having this uniform syntax made the mental model of how to achieve your goal simple. For example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; (add 4 (multiply 3 4)) - (subtract 8 4) is computed to give 4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; (add 4 12) - (multiply 3 4) is computed to give 12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 16 ; the final output is 16 as we add 4 and 12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code as Data, Data as Code
&lt;/h3&gt;

&lt;p&gt;One of the central philosophies in Lisp is the idea of homoiconicity, commonly known as &lt;em&gt;code as data&lt;/em&gt;. A homoiconic language is one that treats code as regular data that can be manipulated by the language itself. The main advantage of a homoiconic language is that it is easy to extend the language through the use of macros - new features or additions to the language can be easily created by manipulating already known constructs in the language. There is no inherent need to wait for new versions of the language to be introduced to gain features you need urgently, you can just create them yourself. &lt;/p&gt;

&lt;p&gt;Concretely, Lisp code is stored as a valid data structure, an &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" rel="noopener noreferrer"&gt;abstract syntax tree&lt;/a&gt; (ast). One of the design goals of the language was to make the correspondence between the syntax and the resulting ast as direct as possible. Consider the Clojure code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates the ast&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%2Fi%2Fnb8cbwxj8vjadqm3bmua.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%2Fi%2Fnb8cbwxj8vjadqm3bmua.png" alt="Abstract Syntax Tree" width="103" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the internal representation and is evaluated when the code is executed. However, given that &lt;code&gt;+&lt;/code&gt; is just a function and the rest are literals, the expression can be stored as a list&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a list with the elements &lt;code&gt;+, 4, (+ 2 3)&lt;/code&gt;. One can imagine we can rearrange this, replace the first operator, replace the second function, etc. This will result in a list that can be converted into the adequate ast. Through this capability, we arrive at &lt;em&gt;code as data, data as code&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functional Programming
&lt;/h2&gt;

&lt;p&gt;Functional programming is a programming paradigm that is based on the composition and application of functions - the core construct in the paradigm. Programs are built from composing multiple pure functions together. Given this structure, functional programming does not maintain or mutate state. This is in stark contrast to object-oriented programming where code is built around objects that have state and that state can be mutated. The core tenets of functional programming are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure functions&lt;/li&gt;
&lt;li&gt;No side effects&lt;/li&gt;
&lt;li&gt;Immutability&lt;/li&gt;
&lt;li&gt;Function composition&lt;/li&gt;
&lt;li&gt;First-class functions&lt;/li&gt;
&lt;li&gt;Referential transparency&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pure Functions
&lt;/h3&gt;

&lt;p&gt;Pure functions are functions that return the same output for a given input. An example of a pure function is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="c1"&gt;; this function squares a number&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; in Clojure, the last evaluated expression is returned&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;square-num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;square-num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will &lt;em&gt;always&lt;/em&gt; give the same output if the same input is given no matter how many times it is invoked. The other important aspect of a pure function is that is has no side effects (i.e it does not mutate state).&lt;/p&gt;

&lt;h3&gt;
  
  
  No Side Effects
&lt;/h3&gt;

&lt;p&gt;Side effects occur when a function mutates state out of its context. Side effects make it harder to reason about code; it is not always easy to understand the flow of data. Example of side effects are reading or writing files, updating databases, creating database connections, printing to the console, so on and so forth. Naturally, functional programs cannot completely rid themselves of side effects, however, they are often separated from the data and are integrated in a principled manner. An example of a function with a side effect&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add-numbers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; binds the value (+ 4 3) to num&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; to return the number&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add-numbers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; hello&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example, while simple, adequately highlights a side effect. When adding the numbers, "hello" is printed to the console. In this case, it is a fairly harmless side effect. In other situations it may be detrimental. Imagine the function updated a database with the calculated number. The outcome of the function is different every time it is executed as it is adding data to a database. The reason that this can be difficult to reason about is that the function gives no indication such an effect would occur.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutability
&lt;/h3&gt;

&lt;p&gt;Functional programming relies heavily on immutability. This means once declared, structures cannot be modified. For example in a mutable language, you can do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not possible in functional programming. In functional programming we can create a &lt;em&gt;new&lt;/em&gt; variable but we can't update an already instantiated variable. This, again, brings the benefit of making it easier to reason about code and understand the flow of data through a program. Another advantage of immutable data structures is that it makes concurrency much easier to implement. Since objects cannot change once defined, they can be shared amongst threads without qualm.&lt;/p&gt;

&lt;p&gt;Naturally, a common question is how do you write any useful code without mutable data structures. This requires a mental shift in the way you write programs - instead of having objects that are mutated as a program executes, you have data that is transformed as the program executes. Every time the data is transformed, a new output is created, leaving the input as it was. Clojure provides backdoors to mutability when necessary but it is not idiomatic Clojure. To formalise this, lets look at the same code done in a mutable manner and an immutable manner&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;engine_on&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine_on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;engine_on&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine_on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine_on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="n"&gt;car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine_on&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; True
&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine_on&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; True
&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine_on&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we have an object and we mutated its state (i.e the &lt;code&gt;engine_on&lt;/code&gt; variable).&lt;/p&gt;

&lt;p&gt;Functional programming languages do not have classes. Instead, we store this data as a hash map/dictionary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="c1"&gt;; this defines a variable called car with a key engine-on set&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; as false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:engine-on&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;; a function that switches a car engine on. In this case,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; the assoc function returns a new map with the key&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; updated to true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;switch-engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;; a function that switches a car engine off. In this case,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; the assoc function returns a new map with the key&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; updated to false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;switch-engine-off&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;; the car is passed into the function switch-engine-on&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; which returns a new map with the key updated to true.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; the next operation fetches the value of engine-on.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; Finally true? checks whether the value is true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;true?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;switch-engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; true&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;; because that function returned a new car map, the&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; original car map still has the value engine-on set to false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;false?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; true&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;; we can chain commands to switch the car on and off&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; first the engine is switched on, then it is switched&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; off. Then we get the value of the key engine-on.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; finally we check if it is false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;false?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;switch-engine-off&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;switch-engine-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Function Composition
&lt;/h3&gt;

&lt;p&gt;Function composition is the act of combining multiple (simple) functions to build more complex functions. Due to functional programming emphasis on purity and mitigating side effects, it lends itself well to this pattern. We have already seen examples of function composition in previous Clojure code. Function composition is not unique to functional programming, however, the paradigm makes it feel natural. Alongside this, its support for first-class function makes function composition all the more powerful.&lt;/p&gt;

&lt;h3&gt;
  
  
  First-class Functions
&lt;/h3&gt;

&lt;p&gt;In simple terms, first-class functions are functions that are treated as variables. This means they can be passed into other functions as arguments, be returned from functions and be saved in variables. First-class functions allow developers to create higher-level with abstractions with functions alone and enables function composition. Other programming languages such as Python also support first-class functions. An interesting use case for first-class functions is the &lt;code&gt;partial&lt;/code&gt; function. This function takes in a function, binds a set of arguments to the specified values and returns the updated function. Since Python has this function, lets look at it in both Python and Clojure.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&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="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="c1"&gt;# bind the argument a to the value 2. Adder is now a new function
&lt;/span&gt;&lt;span class="n"&gt;adder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# we can use adder now and only specify one argument (i.e a)
&lt;/span&gt;&lt;span class="nf"&gt;adder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 6
&lt;/span&gt;&lt;span class="nf"&gt;adder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 3
&lt;/span&gt;&lt;span class="nf"&gt;adder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 0
&lt;/span&gt;
&lt;span class="c1"&gt;# In essence the partial function has done this
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;adder&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;add&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly in Clojure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;partial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;partial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;partial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; 0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Referential Transparency
&lt;/h3&gt;

&lt;p&gt;Referential transparency is when a function can be replaced with the value it returns without changing the program's behaviour. This is dependent on the fact that functions are &lt;em&gt;pure&lt;/em&gt;. Breaking function purity breaks referential transparency. The main advantages it brings are that it makes code easier to reason about, test, refactor and optimize. A simple example of a referentially transparent function is an addition function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can replace that function with its return value and the calling program will still function the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; in this case, adds a to itself and then compares if it is equal to 8&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Sum function works"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; executes if true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Error in sum function"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; executes if false&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;; =&amp;gt; Sum functions works&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is clear that if we replace &lt;code&gt;a&lt;/code&gt; with &lt;code&gt;4&lt;/code&gt;, the program would work the same, printing &lt;code&gt;sum function works&lt;/code&gt;. Now imagine we defined the &lt;code&gt;add&lt;/code&gt; functions as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Adding"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"and"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the program would first print &lt;code&gt;Adding 2 and 2&lt;/code&gt;, then &lt;code&gt;Adding 4 and 4&lt;/code&gt; and finally &lt;code&gt;sum function works&lt;/code&gt;. If we replaced &lt;code&gt;a&lt;/code&gt; with &lt;code&gt;4&lt;/code&gt;, we would not get the first print message. This has altered the program and therefore it is not referentially transparent.&lt;/p&gt;

&lt;h2&gt;
  
  
  To more Clojure
&lt;/h2&gt;

&lt;p&gt;Learning Clojure has been an enlightening experience. I hope you found some of the concepts equally as awe-inspiring. It's an awesome language to learn to expand your horizons as a developer and at the same time, is a powerful language in its own right. I've found it to be one of the most productive languages I've used. To more Clojure!&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>functional</category>
      <category>lisp</category>
    </item>
    <item>
      <title>Machine Learning in the Wild</title>
      <dc:creator>senyo</dc:creator>
      <pubDate>Tue, 09 Jun 2020 08:09:14 +0000</pubDate>
      <link>https://dev.to/senyeezus/machine-learning-in-the-wild-3lc2</link>
      <guid>https://dev.to/senyeezus/machine-learning-in-the-wild-3lc2</guid>
      <description>&lt;p&gt;Machine learning promises to be transformational, providing much needed innovation across industries ranging from financial services to healthcare to agriculture. The resurgence of machine learning owing to the astonishing performance of deep learning in computer vision and natural language processing has prompted industry to jump on the bandwagon and utilise machine learning in their businesses. In fact, entire startups are being built around machine learning alone, promising that their new found algorithms will vastly improve and outperform existing products and services.&lt;/p&gt;

&lt;p&gt;Whilst new state of the art algorithms are being published week-on-week, using them in a production setting is non-trivial. The additional complexity of using machine learning to power products cannot be understated. It may come as a surprise to new practitioners that most of this complexity has very little to do with the model itself but rather with the infrastructure supporting it. In fact, a common trope is that the development of machine learning models comprises only a small part of the puzzle. So what makes machine learning complex? Data cleaning and warehousing, data versioning, model versioning, distributed training (in the event you are training large models), reproducibility, concept drift, inference speed and optimizing the right thing, to name a &lt;em&gt;few&lt;/em&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%2Fi%2Ftz7kbtnrysax7g1uwakz.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%2Fi%2Ftz7kbtnrysax7g1uwakz.png" alt="Alt Text" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fortunately, this makes for an extremely rewarding engineering experience. As engineers, we are drawn to technically challenging problems - at least, I'd like to think so! Machine learning in the wild does not fall short in any regard. It is truly stimulating, though it might cause you to lose a few hairs, destroy your laptop and move to Motuo - consider yourself warned. In this post, I illuminate some of the core challenges faced in walking the distance with machine learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Quality
&lt;/h2&gt;

&lt;p&gt;What is machine learning without data? The answer is nothing. Absolutely nothing. As the common saying goes, "garbage in, garbage out". Perhaps the most important aspect of machine learning is the data used to train models. Without quality data, no amount of sophistication and creativity will help your machine learning model perform accurately. Whether you agree with the below tweet or not, it does provide an interesting angle on what a model is - a view of the data it was trained on. &lt;iframe class="tweet-embed" id="tweet-1260658763687538688-656" src="https://platform.twitter.com/embed/Tweet.html?id=1260658763687538688"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1260658763687538688-656');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1260658763687538688&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;Data is the source of truth for your model. Every phenomenon it learns is encompassed by that data. Given this stance, you'd be crazy to not ensure that your model is trained on the highest quality data you can create or get your hands on. Unfortunately, ensuring data quality is difficult, expensive and laborious. Rather than trying to circumvent this, it should be incorporated into the company/team strategy. Making the necessary capacity and budget provisions will  make this manageable. Ideally, ensuring data quality should be reduced to a mere nuisance as opposed to a blocking point to deploying machine learning models.&lt;/p&gt;
&lt;h2&gt;
  
  
  Concept Drift
&lt;/h2&gt;

&lt;p&gt;Real-life data is akin to a living organism. It is dynamic and changes over time, drifting further and further away from the data that came before it. This is called concept drift and is a common challenge in machine learning. In its simplest form it is not difficult to deal with as it only requires training on the new batch of data. The complexity arises on an infrastructural level. To handle this effectively, it requires models to be continuously retrained as their performance starts deteriorating in production. Setting up the correct infrastructure to facilitate easy training to deployment and monitoring in production can be difficult depending on the velocity at which this needs to happen. In &lt;a href="https://netflixtechblog.com/system-architectures-for-personalization-and-recommendation-e081aa94b5d8" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; by Netflix, they discuss their system architecture for recommendations. Interesting to note is their separation of offline, online and nearline computation. Offline is the most common paradigm in machine learning today where data is stored and models are trained on the new data. However, they reached limitations with this approach as it often took time between updates to the models, impacting their recency. They solve this problem using online computation which reacts to the latest changes in the data in real-time. Nearline computation is a hybrid of these two approaches. Considering Netflix's scale, most of us would not need such comprehensive architectures to run machine learning in production but it certainly highlights the complexity that can arise.&lt;/p&gt;

&lt;p&gt;To drive concept drift home, I'll  walk through an example. Keeping with the  theme of Netflix, imagine you worked there and trained a recommendation model in January. At this time, life was good and relaxed. The majority of customers were watching comedy shows. The model was able to learn this and its performance was admirable and subsequently deployed into production. It is now June and you realise the model is underperforming. The world is going through a pandemic and in response, people have shifted away from  comedy shows toward thrillers and horrors. Evidently, this behavioural change implies that the dataset that was used to train the model in January is outdated. To bring the model up to date, you train it on the latest data and as expected, your magic algorithm is performing well once again. Hooray!&lt;/p&gt;
&lt;h2&gt;
  
  
  Versioning
&lt;/h2&gt;

&lt;p&gt;Versioning is an essential part of software engineering. Git has largely solved this problem for traditional software development. In machine learning, we not only have to version our code but also the parameters of our model and the data that was used to train the model.&lt;/p&gt;

&lt;p&gt;Data versioning is a new challenge that machine learning brings to the table. As discussed earlier, data is the source of truth for a model. When models are trained on different data, we naturally expect differences in their performance. Without keeping track of which data a model was trained on, we cannot make any significant claims on its performance relative to another model. Alongside that, without knowing which dataset a model was evaluated on, we cannot fairly compare competing models. Finally, we cannot reproduce experiments if we do not version our data. Reproducibility is a growing concern in the machine learning community and rightfully so - ensuring we create the best environment for it is important. From this, it is clear that data provenance is of  utmost importance in machine learning efforts. At this current time, there is no industry standard for data versioning. There are many options available in the market. A few of them include &lt;a href="https://dvc.org/" rel="noopener noreferrer"&gt;dvc&lt;/a&gt;, &lt;a href="https://www.liquidata.co/" rel="noopener noreferrer"&gt;dolt&lt;/a&gt; and &lt;a href="https://www.pachyderm.com/data-lineage/" rel="noopener noreferrer"&gt;pachyderm&lt;/a&gt;. They do not all fall within the same use cases but there is extensive overlap between them.&lt;/p&gt;

&lt;p&gt;One example of a scenario in which poor data versioning can play against you is during the experimentation phase. Let's suppose you  decide to create an object detection system. You train a model with dataset A. You decide to change the data slightly and train a model on this data; dataset B. You repeat this data alteration process twice more, creating dataset C and D. After these experiments, you find that the models trained on dataset A and C perform the best. Unfortunately, you did not record the differences  between these datasets and only possess the data with the most recent  changes (i.e. dataset D). It is now impossible for you to reproduce  the best performing model. Alongside this, you  cannot understand why datasets A and C result in the best models, reducing your  understanding and confidence in the model's performance. This highlights the importance of data versioning and why it is critical to the machine learning process.&lt;/p&gt;
&lt;h2&gt;
  
  
  Experimentation Platforms
&lt;/h2&gt;

&lt;p&gt;Experimentation platforms refer to the necessary platforms needed to use machine learning as effectively as possible. It is not necessary in the beginning of the machine learning journey but as a company begins to scale up their machine learning efforts, it becomes critical. Thousands of experiments need to be run and evaluated. Having the correct infrastructure and tools makes the iteration speed fast and allows models to make it into production.&lt;/p&gt;

&lt;p&gt;Let's walk through an example to highlight its importance. You've decided that you need to create and train a new model for fraud detection. You whip out your trusty jupyter notebook and set off on the adventure of a lifetime. On completion of your model and dataset, you proceed to train the model on a virtual server provided by the company on their prefered cloud provider. The virtual server is not configured, has no fault tolerance and requires many manual steps (ssh into it, install all dependencies, monitor it, etc). Naturally, these steps present many points of potential failure as well as general headaches, slowing down development. The company realises that this is inefficient and invests into tooling to ease the machine learning development process. There are a whole host of tools such as &lt;a href="https://www.kubeflow.org/" rel="noopener noreferrer"&gt;Kubeflow&lt;/a&gt;, &lt;a href="https://www.comet.ml" rel="noopener noreferrer"&gt;Comet&lt;/a&gt;, &lt;a href="https://www.wandb.com" rel="noopener noreferrer"&gt;Weights &amp;amp; Biases&lt;/a&gt;, &lt;a href="https://mlflow.org" rel="noopener noreferrer"&gt;MLflow&lt;/a&gt; to name a few. These are utilised to create a machine learning platform that makes the machine learning lifecycle easier to manage. Now you have the instant ability to monitor progress, visualise training and validation loss and view the results on a user-friendly dashboard. Clearly, this has improved the iteration speed, removed the need to understand infrastructure and provided the necessary amount of visibility. By using the correct platform, the time taken between iterations has decreased substantially.&lt;/p&gt;

&lt;p&gt;Eventually, there is an upfront cost that must be paid in scaling out machine learning efforts by providing the necessary platforms. Data scientists and machine learning engineers need to be empowered to do their work effectively and this is one step in that direction. Alongside this, it allows them to add more value by being able to improve their models in a shorter period of time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Optimizing the Right Thing
&lt;/h2&gt;

&lt;p&gt;In many product offerings, the core goal of machine learning is to improve the &lt;em&gt;customer&lt;/em&gt; experience. In a music company such as Spotify, examples of improving the customer experience include song recommendations and personalisation based on music taste. In a medical imaging company, it could help doctors make more accurate diagnoses or provide diagnoses themselves. Metrics provide an objective way of ranking the performance of models and ensuring you have the latest and greatest model in production. Unfortunately, a common pitfall is optimizing the wrong metric meaning that the metric does not translate to an improvement in the &lt;em&gt;customer&lt;/em&gt; experience. A simple question to ask is: what does a 10% improvement of this metric mean for the customer? It is often quite simple to analyse your model against standard metrics in that line of work, however, it does not always translate to a tangible improvement  for the purpose they were designed to serve. &lt;/p&gt;

&lt;p&gt;A simple case to illuminate this is in medical diagnosis. Imagine you are the patient and this revolutionary AI is used to provide you with a  diagnosis. If the model predicts that you have a disease and you do not, the overall harm inflicted by the incorrect diagnosis is minimal. Despite being incorrect, you  will survive and hopefully live for many years. Now imagine the model predicts that you do not have a disease that you do in fact have. In response to this prediction,  the doctor lets you off into the world to fend for yourself without medication or treatment. Evidently, this is a harmful situation which will likely have  severe consequences. How does this relate to optimizing the right thing? Imagine being responsible for creating the model that performs this task and your chosen metric is accuracy. Accuracy measures the total number of correct predictions out of total predictions. Your new model is 5% better than your old model and so you release it into production - happy days! Unfortunately, that metric does not communicate the most important value to you: how often your model predicts an individual does not have a disease when they actually do! The appropriate metric here is recall. Contextually, perfect recall means that the model successfully predicts every case where an  individual has a disease, however it makes some mistakes where it incorrectly predicts that individuals have a disease that they do not have.&lt;/p&gt;

&lt;p&gt;If only it was as easy as the example makes it seem! In most cases, metrics will have to be designed with the aim of improving the extent to which they translate to an improvement in the customer experience. This talk by &lt;a href="https://medium.com/@alienelf" rel="noopener noreferrer"&gt;Jade Abbott&lt;/a&gt; walks through an example of this - start at the 15 minute mark. &lt;iframe width="710" height="399" src="https://www.youtube.com/embed/keai5wCGAgs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The main takeaway is that metrics should be carefully designed and give an indication of the model's impact on the customer. Additionally, it allows the rest of the business to understand the value of the work you are doing. Then they will also celebrate when your model improves by 0.01%!&lt;/p&gt;

&lt;h2&gt;
  
  
  Greener Pastures
&lt;/h2&gt;

&lt;p&gt;Machine learning in the wild is difficult! This should not discourage us by any means. While difficult, it is extremely rewarding and if you're the kind of engineer I hope you are, it is exciting! With all difficult things comes the joy of working on technically challenging problems.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
    </item>
  </channel>
</rss>
