<?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: Vincenzo Chianese</title>
    <description>The latest articles on DEV Community by Vincenzo Chianese (@vncz).</description>
    <link>https://dev.to/vncz</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%2F134397%2Ffbf8ab03-7d28-4cdc-9fde-b2fab65d568d.jpg</url>
      <title>DEV Community: Vincenzo Chianese</title>
      <link>https://dev.to/vncz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vncz"/>
    <language>en</language>
    <item>
      <title>Things I discovered while writing Clojure</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Mon, 30 Nov 2020 18:34:46 +0000</pubDate>
      <link>https://dev.to/vncz/things-i-discovered-while-writing-clojure-57hl</link>
      <guid>https://dev.to/vncz/things-i-discovered-while-writing-clojure-57hl</guid>
      <description>&lt;p&gt;For some motivations I am not going to go into, I found myself writing a piece of software that would transform a data structure representing a query and transform them in SQL statements, something like &lt;a href="https://en.wikipedia.org/wiki/Datalog"&gt;Datalog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There have been some items that made me spent more time than I was expecting; I guess these are mostly because I still am not that proficient in Clojure and in the spirit of openness (or more like, I wanted to write something no matter what) here is what I've noticed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I am still not used to the idea of running the REPL and keep it running forever. I’d run it to test some commands and then close it only to realise I needed it again. Doing this more than 30 times — well it’s probably a 3-4 minutes lost in waiting the REPL to spin up&lt;/li&gt;
&lt;li&gt;I’ve paused multiple times on functions that have logical conditions and pondered whether it would’t be better to write a multi-method. Then I would do so and thought that it was not really a great idea, and revert the code back.&lt;/li&gt;
&lt;li&gt;I’ve noticed an hard to hold desire, when writing a piece of code, to rewrite it more succinctly because you just remembered that there’s a function in the core library that does exactly what you’re trying to do. I’ve rewrote functions multiple times from using &lt;code&gt;if&lt;/code&gt; to use &lt;code&gt;cond&lt;/code&gt; and then &lt;code&gt;cond-&amp;gt;&amp;gt;&lt;/code&gt; and then go back to &lt;code&gt;cond&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sequence functions on strings do not work in the way I was expecting. They all return a char array, so (concat “hello” “ world”) won’t give me the result I was expecting. Then I figured there’s `clojure.string&lt;/li&gt;
&lt;li&gt;Since I am still missing the “muscular” memory for the core functions, I had the clojuredocs website opened all the time, looking up functions, usages and doing small tests before writing the actual code&lt;/li&gt;
&lt;li&gt;Apparently there are some situations where you have to please the compiler. The multi method dispatcher appears before — so that the subsequent function can use it; then the singular methods can be defined later. This specific case is a circular dependency so order matters. I wish the compiler would figure that out on its own but I understand that in Clojure the reader is single pass. I just wish I’d have know that earlier :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the two big ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Setting up the cognitec test runner took a while. I was not familiar with it, and although it has a decent documentation it took some time to make it run correctly. In particular I had to figure out the class path convention with filenames, the extra-paths to add in deps.edn, the namespace that has to end with “-test". While I haven’t really been counting the time, I feel I’ve spent somewhat between 25 - 35 minutes on this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This was the worst. When I finally got used to the idea of keeping the REPL opened forever, it just hit back to me very hard. It appears that the REPL does not reload the dispatching multi method function (it’s cached?), so no matter the changes I was doing, the REPL just would not pick them up. I haven’t been able to understand why for very long time and I ended up disassembling the entire program chasing an &lt;code&gt;ArityException&lt;/code&gt; that I simply was not there. I figured exclusively because I closed the REPL one more time by mistake and when reloading, it worked again. Suspicious, I googled the issue and got some confirmations. I do not know how much time I spent on this, but it was significant for sure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Believe me, when I figured this one out I was undecided whether throwing the computer or myself from the window :)&lt;/p&gt;

</description>
      <category>clojure</category>
    </item>
    <item>
      <title>Succinct JavaScript?</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Mon, 28 Sep 2020 16:18:10 +0000</pubDate>
      <link>https://dev.to/vncz/succinct-javascript-4ob7</link>
      <guid>https://dev.to/vncz/succinct-javascript-4ob7</guid>
      <description>&lt;p&gt;It goes with no saying, I am really liking &lt;a href="https://clojure.org"&gt;Clojure&lt;/a&gt; lately.&lt;/p&gt;

&lt;p&gt;Although I do not use in my day to day job (yet?), just in the same way I did with Haskell with regards of &lt;a href="https://dev.to/vncz/forewords-and-domain-model-1p13"&gt;Prism&lt;/a&gt;, I like to see how other languages approach problems and try to apply their ideas back to TypeScript.&lt;/p&gt;

&lt;p&gt;Last week I've been playing with the &lt;a href="https://en.wikipedia.org/wiki/Goofspiel"&gt;Game of pure strategy problem&lt;/a&gt;, and try to implement a possible solution in Clojure.&lt;/p&gt;

&lt;p&gt;After some back and forth and some good feedback from the Clojurians Slack channel, I ended up with a next state function that looks like this:&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;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;initial-state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Initial game state"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:first-player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&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="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;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&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;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:score&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:second-player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&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="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;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&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;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:score&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:bounty-deck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&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="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;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&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;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&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;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;random-card-strategy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;deck&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;rand-nth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deck&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;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;highest-card-strategy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;deck&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;apply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deck&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;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;draw-card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;random-card-strategy&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;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;game-step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;current-state&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="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bounty-deck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first-player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;second-player&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current-state&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;drawn-card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;draw-card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bounty-deck&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;first-player-card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random-card-strategy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:deck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first-player&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;second-player-card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;highest-card-strategy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:deck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;second-player&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;match-winner&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;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first-player-card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;second-player-card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:first-player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:second-player&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;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current-state&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;update-in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;match-winner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:score&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;inc&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;update-in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:bounty-deck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;disj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;drawn-card&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;update-in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:first-player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:deck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;disj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first-player-card&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;update-in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:second-player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:deck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;disj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;second-player-card&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;It's kind of known that LISP is generally a very dense language; if we also take in consideration the rich set of Clojure's seq functions and macros, turns out that small chunks of code can do a lot of things in Clojure.&lt;/p&gt;

&lt;p&gt;I am (still) primarily a JavaScript/TypeScript developer, and I have been asking "What is the most succinct code that I can write to achieve the same end result?&lt;/p&gt;

&lt;p&gt;I cobbled something some code as fast as possible and this is the base line I started from:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bountyDeck&lt;/span&gt;&lt;span class="p"&gt;:&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;:&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;secondPlayer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;:&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomCardStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;highestCardStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;drawCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;randomCardStrategy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gameStep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;drawnCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;drawCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bountyDeck&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstPlayerCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;randomCardStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secondPlayerCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;highestCardStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matchWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firstPlayerCard&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;secondPlayerCard&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstPlayer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secondPlayer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bountyDeck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bountyDeck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bountyDeck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;drawnCard&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="na"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;==&lt;/span&gt; &lt;span class="nx"&gt;firstPlayerCard&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;matchWinner&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstPlayer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;secondPlayer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;==&lt;/span&gt; &lt;span class="nx"&gt;firstPlayerCard&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;matchWinner&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secondPlayer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&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;Note that I have omitted the type definitions in this snippet, since they're not part of the actual code.&lt;/p&gt;

&lt;p&gt;It's clear enough that the problem here is that JavaScript does not have a great story to mutate stuff in place, but we can probably do something better by using a Lens library: &lt;a href="https://github.com/gcanti/monocle-ts"&gt;monocle-ts&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Without the boilerplate, the final code that we should take in account is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gameStep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;drawnCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;drawCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bountyDeck&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstPlayerCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;randomCardStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secondPlayerCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;highestCardStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matchWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firstPlayerCard&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;secondPlayerCard&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstPlayer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;secondPlayer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;matchWinner&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstPlayer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;incrementFirstPlayerScore&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;incrementSecondPlayerScore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;removeBountyDeckCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;drawnCard&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;removeFirstPlayerDrawnCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstPlayerCard&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;removeSecondPlayerDrawnCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secondPlayerCard&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;…which is not exactly that far from the Clojure counterpart.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JavaScript is missing a good story for data manipulation out of the box. You need lenses and/or collection libraries to effectively manipulate stuff. Still, it's not an excuse to write bad code.&lt;/li&gt;
&lt;li&gt;Without the dot notation (&lt;code&gt;a.b.c&lt;/code&gt;), destructuring and threading macro become very important in Clojure. Without them this:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;(-&amp;gt; structure :first-player :deck :card :somethingelse)&lt;/code&gt;&lt;br&gt;
would be:&lt;br&gt;
&lt;code&gt;(:somethingelse (:card (:deck (:first-player structure))))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;which I guess ain't that cool.&lt;/p&gt;

&lt;p&gt;P.S: I am aware of &lt;a href="https://github.com/immutable-js/immutable-js"&gt;ImmutableJS&lt;/a&gt;. However their story around typings is not that polished as the one that monocle-ts is offering, so I removed it early from the selection.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Break functions apart</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Mon, 21 Sep 2020 19:34:47 +0000</pubDate>
      <link>https://dev.to/vncz/break-functions-apart-162l</link>
      <guid>https://dev.to/vncz/break-functions-apart-162l</guid>
      <description>&lt;p&gt;For a while now I have been exploring the &lt;a href="https://clojure.org"&gt;Clojure&lt;/a&gt; programming language. I ended up doing this almost exclusively driven by &lt;a href="https://twitter.com/richhickey"&gt;Rich Hickey&lt;/a&gt;'s presentations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=MCZ3YgeEUPg"&gt;Design, composition and performance&lt;/a&gt; is among my favorite ones, and there are two specific things that burned in my mind since I saw them:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Design means break things apart in such a way that they can be put back together.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;…and&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Whenever there is a problem, it's likely because we haven't broken things apart enough.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since I saw that video, I've kept these in mind every time I would be looking at some piece of code — and it turns out n.2 applies so many times — way more than I was expecting.&lt;/p&gt;

&lt;p&gt;This is a small walkthrough of a refactoring opportunity I came across recently while working on a fairly large codebase.&lt;/p&gt;

&lt;p&gt;Suppose we have a &lt;code&gt;node&lt;/code&gt; type and some functions that grabs a token from somewhere and — in case a specific path is defined, it will need to grab the parent node before continuing the processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&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 function will probably do its job, but frankly speaking, this is a mess in my eyes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The function name claims to return the node data; on the other hand is also retrieving an authentication token from the system in case is necessary and will happily fallback to the parent node if required.&lt;/li&gt;
&lt;li&gt;The function requires two additional function that are used to get the data in case the computation fails for some reason. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When asking/arguing why about the n.2 — the response I'd usually get is that such "pattern" will improve the testability, because I can pass mocks function when testing the code, something along these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;returns parent data when path starts with /&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenMock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentNodeMock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/s/10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;tokenMock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;parentNodeMock&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;resolves&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// assertions&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I find this not a valid argument; to me this is more a tape-patchy way to fix something that has been put together incorrectly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Whenever there is a problem, it's likely because we haven't broken things apart enough.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First — let's move the token logic away from this function, and pass it as a regular argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&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;By changing the function signature to ask for the token directly instead of taking it on our own, we have effectively moved a non pure operation out of this function. That is a good thing.&lt;/p&gt;

&lt;p&gt;At this stage, we might noticed that the &lt;code&gt;token&lt;/code&gt; argument is used exclusively to feed the &lt;code&gt;getParentNode&lt;/code&gt; function — that we're passing as an argument. &lt;/p&gt;

&lt;p&gt;We can do something about it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- getParentNode: (data: node, token: string) =&amp;gt; Promise&amp;lt;node&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ getParentNode: (token: string) =&amp;gt; (data: AppNode) =&amp;gt; Promise&amp;lt;AppNode&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can externally bind the token, and get rid of such dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and then call the token-free function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenizedGetParentNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tokenValue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/p/10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;tokenizedGetParentNode&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is now inarguably better; still, we're passing the &lt;code&gt;getParentNode&lt;/code&gt; — which is not good.&lt;/p&gt;

&lt;p&gt;We could reiterate with the same solution we applied above to the &lt;code&gt;getParentNode&lt;/code&gt; function, so that we'd be passing the parent node ahead of the time; but it might be a waste of resources: the parent node is only required on certain conditions.&lt;/p&gt;

&lt;p&gt;Sometimes sacrificing performances/efficiency for readability is a good call. However for this use case we're going to assume that fetching a parent node is a very expansive operation that we really want to avoid.&lt;/p&gt;

&lt;p&gt;Let's break this function apart and reduce its scope to only work with the current node. If the parent node is required, we're going to make this fail and the caller will have to sort this out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then the caller can do its job to understand if the parent node call is required or not.&lt;/p&gt;

&lt;p&gt;We have now successfully broken the things apart, with all the pieces doing ONE thing. It's now time to put them back together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;RTE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReaderTaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parent node required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getParentNodeData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getParentNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startNode&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;RTE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractDataFromNode&lt;/span&gt;&lt;span class="p"&gt;))(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromEither&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="nx"&gt;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orElse&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getParentNodeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&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 go, and break your functions apart. &lt;/p&gt;

&lt;p&gt;Then break your systems apart.&lt;/p&gt;

&lt;p&gt;Then put them back together.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>From 0 to Reader</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Fri, 18 Sep 2020 14:27:38 +0000</pubDate>
      <link>https://dev.to/vncz/from-0-to-reader-1g2d</link>
      <guid>https://dev.to/vncz/from-0-to-reader-1g2d</guid>
      <description>&lt;p&gt;The following notes come from an internal discussion I had with some coworkers with no pretension to be an accurate explanation of the Reader monad. Still, my teammates claimed they were helpful to understand the concept; so better put them online.&lt;/p&gt;




&lt;p&gt;We'll start with a function whose job is to insert an user in a database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Let's write some code to implement the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isPresent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inserted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accountCreated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to create user account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to insert user in Db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's say that somebody comes says we need to add logging with this object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;Additionally, let's put the constraint in place that the logger is not a singleton instance — thus it's an instance that needs to be carried around.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User inserted, running trigger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isPresent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inserted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accountCreated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to create user account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to insert user in Db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="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;Two things aren't really cool with such approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I have to pass the logger in every single function that needs this — every function must be aware of the new dependency&lt;/li&gt;
&lt;li&gt;The logger is a &lt;em&gt;dependency&lt;/em&gt;, not really a function argument.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To start fixing this, let's try to put the dependency elsewhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- declare function userExists(user: string, l: Logger): Promise&amp;lt;boolean&amp;gt;;
&lt;/span&gt;&lt;span class="gi"&gt;+ declare function userExists(user: string): (l: Logger) =&amp;gt; Promise&amp;lt;boolean&amp;gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that we change the way we use the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- const promise = userExists(user, logger);
&lt;/span&gt;&lt;span class="gi"&gt;+ const promise = userExists(user)(logger);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isPresent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inserted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accountCreated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to create user account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to insert user in Db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="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;Let's now introduce a type to help us out to model this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;type Reader&amp;lt;R, A&amp;gt; = (r: R) =&amp;gt; A;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And so we can now rewrite &lt;code&gt;userExists&lt;/code&gt; as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- declare function userExists(user: string): (l: Logger) =&amp;gt; Promise&amp;lt;boolean&amp;gt;;
&lt;/span&gt;&lt;span class="gi"&gt;+ declare function userExists(user: string): Reader&amp;lt;Logger, Promise&amp;lt;boolean&amp;gt;&amp;gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since TypeScript does not support HKT (but I still pray everyday that eventually it will), I am going to define a more specific type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ReaderPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I can make the following replacement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- declare function userExists(user: string): Reader&amp;lt;Logger, Promise&amp;lt;boolean&amp;gt;&amp;gt;;
&lt;/span&gt;&lt;span class="gi"&gt;+ declare function userExists(user: string): ReaderPromise&amp;lt;Logger, boolean&amp;gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and if I define an helper function called chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReaderPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ReaderPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ReaderPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;ma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can now rewrite the entire flow in such way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ReaderPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&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="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to insert user in Db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to create user account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="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;but that ain't that cool, since we're nesting nesting and nesting. We need to move to the next level.&lt;/p&gt;

&lt;p&gt;Let's rewrite chain to be curried…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- const chain = &amp;lt;R, A, B&amp;gt;(ma: ReaderPromise&amp;lt;R, A&amp;gt;, f: (a: A) =&amp;gt; ReaderPromise&amp;lt;R, B&amp;gt;): ReaderPromise&amp;lt;R, B&amp;gt; =&amp;gt; (r) =&amp;gt;
&lt;/span&gt;  ma(r).then((a) =&amp;gt; f(a)(r))
&lt;span class="gi"&gt;+ const chain = &amp;lt;R, A, B&amp;gt;(f: (a: A) =&amp;gt; ReaderPromise&amp;lt;R, B&amp;gt;) =&amp;gt; (ma: ReaderPromise&amp;lt;R, A&amp;gt;):  ReaderPromise&amp;lt;R, B&amp;gt; =&amp;gt; (r) =&amp;gt;
&lt;/span&gt;  ma(r).then((a) =&amp;gt; f(a)(r))

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

&lt;/div&gt;



&lt;p&gt;Well what happens now is that I can use ANY implementation of the pipe operator (the one in lodash will do), and write the flow in this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUser2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ReaderPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&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="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to create user account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;DoSomething&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to create user account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="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 can introduce another abstraction called &lt;code&gt;Task&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;type Task&amp;lt;T&amp;gt; = () =&amp;gt; Promise&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and then, just for commodity&lt;/p&gt;

&lt;p&gt;&lt;code&gt;type ReaderTask&amp;lt;R, A&amp;gt; = Reader&amp;lt;R, Task&amp;lt;A&amp;gt;&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then I can refactor this part a little bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- declare function userExists(user: string): Reader&amp;lt;Logger, Promise&amp;lt;boolean&amp;gt;&amp;gt;;
&lt;/span&gt;&lt;span class="gi"&gt;+ declare function userExists(user: string): ReaderTask&amp;lt;Logger, boolean&amp;gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out &lt;a href="https://github.com/gcanti/fp-ts"&gt;fp-ts&lt;/a&gt; already has a bunch of these defined, so I'm not going to bother using mines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fp-ts/Reader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;RT&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fp-ts/ReaderTask&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fp-ts/pipeable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReaderTask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReaderTask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReaderTask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReaderTask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;runAutomaticTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReaderTask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;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="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPresent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;insertInDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inserted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;createUserAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to create user account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;RT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unable to insert user in Db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="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;What are the differences with the original, naive, solution?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Functions are not aware of the dependency at all. You just chain them and inject the dependency once: &lt;code&gt;const user = await createUser(details)(logger)()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The logger is now a separate set of arguments, making really clear what is a dependency and what is a function argument&lt;/li&gt;
&lt;li&gt;You can reason about the result of the computation even though you haven't executed anything yet.&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Relocating during the COVID-19</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Thu, 11 Jun 2020 13:58:50 +0000</pubDate>
      <link>https://dev.to/vncz/relocating-during-the-covid-19-2ok4</link>
      <guid>https://dev.to/vncz/relocating-during-the-covid-19-2ok4</guid>
      <description>&lt;p&gt;&lt;em&gt;TL; DR:&lt;/em&gt; I had the pleasure of relocating exactly a week or so before the COVID-19 spread to a level where the United States decided to declare the shelter in place and lock down the country.&lt;/p&gt;

&lt;p&gt;This is a quick and hopefully humorous tale about what happened to me.&lt;/p&gt;




&lt;p&gt;For those of you that do not really know me — I have relocated 3 times over the last 6 years; and by relocation I do not mean moving to a house behind the corner or to a nearby city. I mean changing 3 states and a continent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prague, December 2014
&lt;/h2&gt;

&lt;p&gt;I had already decided that it was time for me to leave my original country (Naples, Italy) with the clear idea of not coming back for a very good chunk of time.&lt;/p&gt;

&lt;p&gt;At that time, I was so desperate to leave that my desidered standard levels were basically 0. Anything would have done the job. I indeed ended up in Prague, Czech Republic — landing on 12/14/2014.&lt;/p&gt;

&lt;p&gt;That ultimately was a very good experience, from both a working perspective (I had a great gig for a local startup) and from personal life as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Madrid, September 2017
&lt;/h2&gt;

&lt;p&gt;Once the company I was working for was sold to Oracle in January 2017, I started to talk with my managers about opportunities of leaving the country and work from somewhere else along with other requests that have been on hold for a long time.&lt;/p&gt;

&lt;p&gt;I wasn't satisfied with the answers I received — and Oracle was not worth my time in Prague, and decided that leaving would be the n. 1 priority.&lt;/p&gt;

&lt;p&gt;I quickly found a gig in Madrid, Spain. It was a place that I always wanted to go and the offer was good, so I agreed.&lt;/p&gt;

&lt;p&gt;After one month offline (August), on September 4 I moved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Austin, March 2020
&lt;/h2&gt;

&lt;p&gt;Time passes, in 2018 I was hired by &lt;a href="https://stoplight.io"&gt;Stoplight&lt;/a&gt; and after they realised I was a good fit, we agreed that moving to the United States would be a good idea.&lt;/p&gt;

&lt;p&gt;Unexpectedly, I was selected in the H1B lottery AND was approved by the USCIS at the first shot without questioning or asking additional documentation.&lt;/p&gt;

&lt;p&gt;I went from the mood I had at the beginning of the application  "we'll try, but most likely we won't make it" to "this was clearly destiny, the United States is calling me".&lt;/p&gt;

&lt;p&gt;I got my VISA stamped in December and I decided that January 2020 would be my moving date.&lt;/p&gt;

&lt;p&gt;For personal reasons, I couldn't finish all the things I had in mind in January and I shifted the relocation, aiming the beginning of February. &lt;/p&gt;

&lt;p&gt;Since I had a speaking engagement at the end of February in Atlanta, I decided that it'd have been a better idea to do a single trip (Madrid - Atlanta) and then move to Austin to settle down.&lt;/p&gt;

&lt;p&gt;My time in Europe was about to end and I wanted to use it all. I traveled every weekend of January and February. Me and my flatmate wanted to enjoy our time together till the very last drop and so we went to Granada, Berlin and then Tenerife.&lt;/p&gt;

&lt;p&gt;Tenerife was already on the spot because &lt;a href="https://www.theguardian.com/world/2020/feb/25/tenerife-coronavirus-guests-hotel-quarantined"&gt;COVID cases were signaled at the time&lt;/a&gt; but we all felt safe anyway, since we had very little knowledge about this virus. We were still in the phase of "it’s only in Wuhan")&lt;/p&gt;

&lt;p&gt;In any case, I took my plane, I landed in Miami first (where somebody was waiting for me just outside of the plane to bring the for the first inspection — had no problem with that; did my work in Atlanta and then I ultimately landed in Austin.&lt;/p&gt;

&lt;p&gt;Then, the COVID and the restriction started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flight schedule: gone
&lt;/h3&gt;

&lt;p&gt;I had different flights all booked ahead of the time that I had to cancel. Namely:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;From&lt;/th&gt;
&lt;th&gt;To&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mar  19&lt;/td&gt;
&lt;td&gt;Austin&lt;/td&gt;
&lt;td&gt;Osaka&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 29&lt;/td&gt;
&lt;td&gt;Osaka&lt;/td&gt;
&lt;td&gt;Singapore&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 4&lt;/td&gt;
&lt;td&gt;Singapore&lt;/td&gt;
&lt;td&gt;Bali&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 7&lt;/td&gt;
&lt;td&gt;Bali&lt;/td&gt;
&lt;td&gt;Singapore&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 7&lt;/td&gt;
&lt;td&gt;Singapore&lt;/td&gt;
&lt;td&gt;Madrid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 20&lt;/td&gt;
&lt;td&gt;Madrid&lt;/td&gt;
&lt;td&gt;Amsterdam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 23&lt;/td&gt;
&lt;td&gt;Amsterdam&lt;/td&gt;
&lt;td&gt;Madrid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 27&lt;/td&gt;
&lt;td&gt;Madrid&lt;/td&gt;
&lt;td&gt;Austin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 31&lt;/td&gt;
&lt;td&gt;Austin&lt;/td&gt;
&lt;td&gt;London&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jun 16&lt;/td&gt;
&lt;td&gt;Madrid&lt;/td&gt;
&lt;td&gt;Austin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jul 31&lt;/td&gt;
&lt;td&gt;Austin&lt;/td&gt;
&lt;td&gt;Madrid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dec 8&lt;/td&gt;
&lt;td&gt;Austin&lt;/td&gt;
&lt;td&gt;Madrid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When the whole thing started, the trip in Asia was the first one to be gone. I purchased another flight to reach Madrid anyway in April through a connection in Miami. Such flights ended up being cancelled anyway.&lt;/p&gt;

&lt;p&gt;I could have taken the one for June (they can't prevent me because of my passport), but I when I phoned the CBP officer in Dallas to understand what would be the rules to enter the country again they were very clear that if I go out, I would not be able to come back. &lt;/p&gt;

&lt;p&gt;Further, once landed in London there would be no flight out for different days; therefore I would be blocked there and it was just not an option.&lt;/p&gt;

&lt;p&gt;Current situation: I have spent a significant amount of time on phone calls with different airlines (American Airlines, Scoot, Qatar, Iberia, British Airways). Some of them have refunded me, some of them have offered credit that I decided to keep since I fly with them pretty often.&lt;/p&gt;

&lt;p&gt;I still have a significant amount of money out because of this (mostly with American Airlines).&lt;/p&gt;

&lt;h2&gt;
  
  
  The loop
&lt;/h2&gt;

&lt;p&gt;Once you land in the United States, the first thing you want to do is likely get a Social Security Number, as it's really the door for a lot of other things you probably are going to need such as a bank account, a driving license/ID, set up your health insurance and so on.&lt;/p&gt;

&lt;p&gt;When I landed, the offices were already starting to wind down because of the COVID spread, so I ran to the only one still open in Austin and went there 1h ahead of the opening time with no appointment. It goes with no saying that the queue was immense — and with some very weird people there as well.&lt;/p&gt;

&lt;p&gt;Once I got that figured out — the employee told me it would take a couple of weeks before I'd get the SSN mailed to my address. That wouldn't normally be a problem, but when also that office closed, I was uncertain if my file had been processed already or not. Without a SSN I was in a situation where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I couldn't open a bank account&lt;/li&gt;
&lt;li&gt;Without a bank account, getting paid would have been way more difficult&lt;/li&gt;
&lt;li&gt;I could not enable my health benefits&lt;/li&gt;
&lt;li&gt;I could not get a Texas ID&lt;/li&gt;
&lt;li&gt;I could not rent a place — at least not through a regular leasing agreement. The only way would have been a sublet, which I wanted to avoid if possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had the luck of being hosted by a very good friend of mine and, although he didn't have any problem hosting me for all the necessary time I wanted to get out of his way as soon as possible. I'm not the kind of person that takes advantage of situations.&lt;/p&gt;

&lt;p&gt;The SSN fortunately arrived 8 days later (that was fast, according to what people told me around) and I was able to register for my health benefits. On the other hand, it wasn't really that easy with the rent and the bank account.&lt;/p&gt;

&lt;p&gt;The leasing agency tried to verify my credit score, although I told them ahead of the time I had literally landed 10 days ago, resulting in my file being empty. After being refused and some begging, they agreed to rent me the place anyway with a big deposit (3 months) paid in advance. I liked the place very much for a number of reasons, so I agreed.&lt;/p&gt;

&lt;p&gt;Regarding the bank account, the experience was even worse. Since all the physical offices were locked down, I went ahead and tried multiple online services. Chime, N26, Varo, Simple, Capital One you name it. &lt;/p&gt;

&lt;p&gt;They would all refuse me with no explanation and calling them on the phone wouldn't help. They wouldn't disclose why I was not eligible for a bank account, and my only clue would be insufficient credit history.&lt;/p&gt;

&lt;p&gt;While walking on the street I realised the strong presence of the Spanish bank group BBVA. Although I was not their customer when I was living in Madrid —  I tried to call them and see if they could help me somehow. Here's a summary of the phone conversation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sure no problem, just come here in person and we'll set up a bank account in less than an hour.&lt;/p&gt;

&lt;p&gt;Fantastic. When's a good time to come?&lt;/p&gt;

&lt;p&gt;Now? Oh now impossible, we're not letting anybody in with the pandemic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;End result: no bank account in any case. I ended up resolving by opening an account with Revolut which had recently opened their operations in the United States; they wouldn't usually do that but since I am a customer in the EU as well, they have "converted" my account to an US one without having to go through the whole procedure of opening a new one.&lt;/p&gt;

&lt;p&gt;Revolut has some limitations: it does not support ACH transfers / Direct Debits and does not provide regular checks — which apparently are still important here, but at least I could get paid and (with a 2.3% surplus) I would be able to pay my rent as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a credit score
&lt;/h2&gt;

&lt;p&gt;I was aware that credit score here is a thing. What I didn't know was how big of a deal it is.&lt;/p&gt;

&lt;p&gt;I never had a credit card while in Europe — and I was not planning to have one in the US either; I then realised at my own expenses that credit score is a little bit more than a simple score for merely credit purposes. It tells a lot about you and essentially for anything that is a monthly subscription — people might ask and check your credit score.&lt;/p&gt;

&lt;p&gt;My credit score has been checked so many times that I felt that even buying a coffee would require your credit score to be above 650.&lt;/p&gt;

&lt;p&gt;From what I've seen so far, there are 3 ways to build your credit score:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask for a secured loan. Essentially a company is going to theoretically lend you some money; in reality they won't give you anything but you're still paying the monthly instalment. In exchange for that, the company will report your payments to the credit score agencies. At the end of the repayment, you'll get all your money back minus interests and fees. Fundamentally, it's like asking for a loan and get only its negative parts&lt;/li&gt;
&lt;li&gt;Ask your landlord to report your payments&lt;/li&gt;
&lt;li&gt;Get a credit card (secured or not) and pay its balance on time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first one felt so ridiculous that I imperatively refused to do that, so I went for the option n. 2.&lt;/p&gt;

&lt;p&gt;Good thing, the community manager of the property I'm living has already an agreement with an automatic platform to report the rent payments. I would just need to register, pay the 6.95$/month fees and I would be good to go.&lt;/p&gt;

&lt;p&gt;I did that, and 20 days later I got an email that my application was canceled. I called the support to understand why and the conversation went like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My application has been rejected, I would like to understand why.&lt;/p&gt;

&lt;p&gt;Sure, let me check that out…oh yeah, we can't accept your application because you do not have any credit score&lt;/p&gt;

&lt;p&gt;Ehm, but the purpose of all this is to build a credit score.&lt;/p&gt;

&lt;p&gt;Oh I'm so sorry, I understand, but I can't help you. Is there anything else I can help with?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Option 2, gone. I had no choice but to try with a credit card. I tried to apply to the Apple one, and I got rejected. Insufficient credit score.&lt;/p&gt;

&lt;p&gt;Ok fair. Then I tried with Discover. Rejected. All right, I'll go with a secured credit card and go from there.&lt;/p&gt;

&lt;p&gt;Discover has a good offer, so I decided to go with them. I filled out the form, got the application approved. Unfortunately when it's time to pay for the deposit I realise they only support payments through direct debits, which my bank does not support. As long as I liked Discover, I couldn’t work with them for the time being.&lt;/p&gt;

&lt;p&gt;All right, time to find another alternative. I check out on the internet relentlessly and I land on OpenSky CC webpage. They claim to accept the deposit via Debit Card, and it effectively worked.&lt;/p&gt;

&lt;p&gt;I filled up the application and I got approved for the pharaonic amount of 100$ per month (Las Vegas, here I come) but you know everybody has to start from something, so I'll go with that.&lt;/p&gt;

&lt;p&gt;Once the card finally arrives and I swipe it a couple of times, I realise that they accept a debit card to pay for the deposit, but the only option to pay the monthly due amount is via direct deposit or mail a check. Guess what? My bank does not support any of these.&lt;/p&gt;

&lt;p&gt;I needed to find a way to pay back my due amount as soon as possible, otherwise I would start very bad in terms of credit score.&lt;/p&gt;

&lt;p&gt;I started to google any single combination of keywords about credit, bank account, checks, credit cards until I found &lt;a href="https://www.plastiq.com"&gt;https://www.plastiq.com&lt;/a&gt;. The basic idea is simple: you swipe your card, Plastiq will mail a check to the designated recipient.&lt;/p&gt;

&lt;p&gt;Although complicated, I thought I finally found a way to close the loop with my secured credit card and slowly build the credit score. I sign up for the service and I issue an order to mail a check to pay my due balance. I went to sleep convinced that I’d have fixed it.&lt;/p&gt;

&lt;p&gt;Unfortunately for me, my tale with this wasn’t over yet. I received an email 4-5 days later with a “good” news from Plastiq:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V8v-Lr2_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hx4mq4knz8nxxrb2ldnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V8v-Lr2_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hx4mq4knz8nxxrb2ldnv.png" alt="Plastic Announcement" width="818" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m back to the beginning. I can’t pay for my secured credit card balance — and the due date is almost coming. I needed to find a bank account with direct debit support. There was no other option.&lt;/p&gt;

&lt;p&gt;I started very early the following morning with a sole purpose: finding somebody willing to open me a bank account online (or even in person, didn’t really matter) with direct debit support.&lt;/p&gt;

&lt;p&gt;I’ll skip the whole tale and the 3000 phone calls I had to do. The ultimate choice was between Betterment and Radius and, after a long chat with the support person on the phone, Radius approved to open a bank account right away with full support for paper checks and direct debit. I was finally done. I transferred some money on it as soon as it was opened and paid the secured credit card balance in time.&lt;/p&gt;

&lt;p&gt;Totally out of curiosity/boredom I applied again for a Discover Credit Card — not even secured — and it got approved right away for a line of 1000$. I was very very surprised. I guess that the first payment was reported and the fact of having an US Bank Account probably helped during the qualification process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The skin rashes
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I am not allergic to anything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve been saying this sentence since forever; not because I wanted to brag myself; but rather because it was my belief since my childhood.&lt;/p&gt;

&lt;p&gt;How wrong I was — and if you’re thinking about the same, it’s highly probable that you’re wrong too.&lt;/p&gt;

&lt;p&gt;Austin is one of the worst places in terms of allergies — and I knew that when I was relocating. I really never worried about that though since by the time I was about to relocate I had visited the city multiple times (October 2018, May 2019, August 2019, November 2019) for a relatively long time (2 to 6 weeks) and I never had any problem.&lt;/p&gt;

&lt;p&gt;So after a couple of weeks I’d have moved, welts would start appearing on my body, but since they were few (4-5), localised and weren’t bothering me at all, I didn’t care at all.&lt;/p&gt;

&lt;p&gt;The situation degenerated quickly — when I started to have them almost everywhere in my body; I would start to feel itchy; wake up during the night because I would be itchy, and some occasions even painful.&lt;/p&gt;

&lt;p&gt;Initially (since I was still convinced that I wasn’t allergic) I thought about bed bugs. I inspected all my furniture (for the record, it was all brand new) and I effectively did not find anything; still, I was still paranoid about it and called the leasing office for an inspection/sanitisation and left the place just to be sure, being hosted by a friend of mine here in Austin for an entire week.&lt;/p&gt;

&lt;p&gt;In the meantime, I started to look for a doctor to get a diagnosis and eventually a treatment, if necessary. I looked for a primary physician and a dermatologist.&lt;/p&gt;

&lt;p&gt;Because of the pandemic, unfortunately, nobody was willing to see me in person and all they would be able to offer would be video calls, which I refused for some time until I started to see the symptoms worsening (I was literally unable to sleep and felt zoned out the whole day).&lt;/p&gt;

&lt;p&gt;The situation did not improve and I was on my way to the emergency room (I had no other choice); fortunately by speaking with my coworkers found a dermatologist willing to see me in person.&lt;/p&gt;

&lt;p&gt;That was NOT the end of it. I am not going to go too much into detail, but here’s the history of the visits I had (so far):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Physician&lt;/th&gt;
&lt;th&gt;Diagnosis&lt;/th&gt;
&lt;th&gt;Prescription&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Apr 1&lt;/td&gt;
&lt;td&gt;TelaDoc&lt;/td&gt;
&lt;td&gt;Bed Bugs&lt;/td&gt;
&lt;td&gt;Triamcinolone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 13&lt;/td&gt;
&lt;td&gt;Walk In Clinic&lt;/td&gt;
&lt;td&gt;Seasonal Allergy&lt;/td&gt;
&lt;td&gt;Claritin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 16&lt;/td&gt;
&lt;td&gt;TelaDoc&lt;/td&gt;
&lt;td&gt;Hives/Urticaria&lt;/td&gt;
&lt;td&gt;Prednisone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 20&lt;/td&gt;
&lt;td&gt;TelaDoc&lt;/td&gt;
&lt;td&gt;Hives/Urticaria&lt;/td&gt;
&lt;td&gt;Hydroxyzine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 23&lt;/td&gt;
&lt;td&gt;Dermatologist&lt;/td&gt;
&lt;td&gt;Folliculitis/Atopic Dermatitis&lt;/td&gt;
&lt;td&gt;Keflex/Clobetasol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 30&lt;/td&gt;
&lt;td&gt;Dermatologist&lt;/td&gt;
&lt;td&gt;Folliculitis/Atopic Dermatitis&lt;/td&gt;
&lt;td&gt;Keflex/Clobetasol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 15&lt;/td&gt;
&lt;td&gt;Dermatologist&lt;/td&gt;
&lt;td&gt;Skin infection&lt;/td&gt;
&lt;td&gt;Not disclosed until I know more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jun 3&lt;/td&gt;
&lt;td&gt;Dermatologist&lt;/td&gt;
&lt;td&gt;Skin infection&lt;/td&gt;
&lt;td&gt;Not disclosed until I know more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jun 12&lt;/td&gt;
&lt;td&gt;Dermatologist&lt;/td&gt;
&lt;td&gt;Skin infection&lt;/td&gt;
&lt;td&gt;Not disclosed until I know more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sep 11&lt;/td&gt;
&lt;td&gt;Dermatologist&lt;/td&gt;
&lt;td&gt;Skin infection&lt;/td&gt;
&lt;td&gt;Not disclosed until I know more&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can see that almost every doctor had a different idea of what my problem is. It seems like the last one finally got it right. I’m still keeping my fingers crossed.&lt;/p&gt;

&lt;p&gt;During this weird situation I discovered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I am effectively allergic to Cephalexin&lt;/li&gt;
&lt;li&gt;My family has an history of Psoriasis&lt;/li&gt;
&lt;li&gt;My sister has been suffering of atopic dermatitis for a while&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What about now?
&lt;/h2&gt;

&lt;p&gt;My skin issue is not solved yet, although it seems that it has been dramatically improving.&lt;/p&gt;

&lt;p&gt;In any case, I am now trying to leave the country on July to rest a bit in Europe, and try to start over in September. Again.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Frequently Asked Questions</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Fri, 29 May 2020 11:15:57 +0000</pubDate>
      <link>https://dev.to/vncz/frequently-asked-questions-1108</link>
      <guid>https://dev.to/vncz/frequently-asked-questions-1108</guid>
      <description>&lt;p&gt;This series is about sharing some of the challenges and lessons I learned during the development of Prism and how some functional concepts taken from Haskell lead to a better product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As of January 2021, I no longer work at Stoplight and I have no control over the current status of the code. There is a &lt;a href="https://github.com/XVincentX/prism" rel="noopener noreferrer"&gt;fork&lt;/a&gt; on my GitHub account that represents the state of the project when I left the company.&lt;/p&gt;




&lt;p&gt;While explaining the journey of refactoring Prism around and writing this article, I've received a set of FAQ. I've grouped them here.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the state of the functional rewrite?
&lt;/h2&gt;

&lt;p&gt;I am generally satisfied with the shape of Prism; but this journey is not over yet.&lt;/p&gt;

&lt;p&gt;At first, not all the parts have been converted/refactored to use fp-ts. Although this series is only talking about that, I want to emphasize it has never been our primary focus. We never halted the regular development of Prism to rewrite its parts; on the contrary we have continued to fix bugs and ship new features. We never broke the user space.&lt;/p&gt;

&lt;p&gt;There are still good opportunities to refactor and make the codebase even better. To give you a brief idea of what we’re working on at the moment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We recently introduced the &lt;code&gt;Do&lt;/code&gt; notation (lend from Haskell) to make the code even more readable, with everybody's quick approval on that: &lt;a href="https://github.com/stoplightio/prism/pull/1143" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/1143&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;We will hopefully start to work on the third validation refactor, where I hope to introduce a new data structure (&lt;code&gt;These&lt;/code&gt;) that will allow us to have an accumulating (and not halting) validation in case of warnings&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On the other hand, there are some parts that will probably never be refactored to be functional, because the value that it would bring is less than the cost of making the transformation. About this, one good example is logging: as I mentioned in part 3, logging is deterministic but it has side effects; therefore, it should be wrapped in a &lt;code&gt;IO&lt;/code&gt; monad.&lt;/p&gt;

&lt;p&gt;I do not see this happening. This is one of the tradeoffs and I think it is important to stay pragmatic; I am not one of these programmers that are feticist about functional concepts.&lt;/p&gt;

&lt;p&gt;Sometimes I had to intervene to stop the FP discussion from going too far: &lt;a href="https://github.com/stoplightio/prism/pull/649#discussion_r329107225" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/649#discussion_r329107225&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What do your coworkers think about it
&lt;/h2&gt;

&lt;p&gt;Believe it or not, so far all the people that have been working on Prism — after some time — ended up loving it. What I have observing with all the people that had to work on Prism (and some other software, since I’ve been in meantime expanding the usage of this into the internal Stoplight’s codebase — is that there are essentially 4 phases the people go into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the heck is this&lt;/li&gt;
&lt;li&gt;I understand it, but I do not like it at all&lt;/li&gt;
&lt;li&gt;Oh now I get why this is useful&lt;/li&gt;
&lt;li&gt;I think I am in love and I want to write all the software with it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I went into the same exact steps listed here but more importantly I do remember going through the same phases also when I had to use React the first time — and recently when I started to use TypeScript professionally.&lt;/p&gt;

&lt;p&gt;Hopefully this is a good evidence that functional programming and its related tooling has no difference with any new methodology/piece of technology: people are just scared about new stuff and with the good amount of education they will go over it.&lt;br&gt;
At the time of writing, I have people in phase 4 as well as in phase 1 and 2.&lt;/p&gt;

&lt;p&gt;There is a difference with adopting React or TypeScript though. The first two have a very wide audience and online you can consult. It is easy to find people familiar with the technologies.&lt;/p&gt;

&lt;p&gt;Although functional programming has been around for way more years than React or TypeScript, we have to face the fact that’s not &lt;strong&gt;that&lt;/strong&gt; spread around as some of us want.&lt;/p&gt;

&lt;p&gt;If we pair this with JavaScript, then the niche is already significantly narrowing and if we add TypeScript on top of it, we start to run out of options. For this reason, &lt;strong&gt;I&lt;/strong&gt; was essentially the education for my comrades. Here are some examples of conversations we had:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/stoplightio/prism/pull/648#discussion_r328157183" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/648#discussion_r328157183&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/stoplightio/prism/pull/648#discussion_r328160675" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/648#discussion_r328160675&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/stoplightio/prism/pull/648#discussion_r328162406" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/648#discussion_r328162406&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/stoplightio/prism/pull/648#discussion_r328165087" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/648#discussion_r328165087&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that these comments, more than code reviews, were more like live tutorials on the code. From my point of view, they have helped my fellow coworker speed up the onboarding significantly. It also made him &lt;a href="https://github.com/stoplightio/prism/pull/648#discussion_r328485598" rel="noopener noreferrer"&gt;excited about it&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How much time did it take to get this far? Was it worth it at all?
&lt;/h2&gt;

&lt;p&gt;Giving a precise timeline is hard, since we never stopped completely working on Prism to refactor the codebase. This has always been a parallel and opportunistic work. Just looking at the dates though, we started in June last year and we still haven’t finished it yet.&lt;/p&gt;

&lt;p&gt;On the worthiness of the whole operation your mileage will of course vary. I still have people in the company that did not even dare read the codebase and just claimed it’s bad, but I firmly believe the quality maintainability of the code outweighs pushing contributors away and I’ve stayed away from these kinds of conversations. There are some points that we gained with the switch that alone, were worth the efforts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I have never seen Prism crashing on my computer. I’ve never seen Prism crashing on our servers in the hosted version. I’ve never seen a bug report about a crash. Sure, it will respond incorrectly from time to time — but that is a completely separate issue. Since all our errors are modeled as &lt;code&gt;Either&lt;/code&gt;, there is no way you can forget to handle an error making the software crash&lt;/li&gt;
&lt;li&gt;We as a team are always automatically on the same page. There’s no more debate about throwing an exception vs return &lt;code&gt;null&lt;/code&gt; vs return &lt;code&gt;undefined&lt;/code&gt; and then try to handle all the use cases somehow. There are a lot of areas where the appliance of functional concepts just makes everybody agree. We have only one rule: if it composes, then 99% it’s good. If it does not, then something is wrong.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During this journey and while telling the people about it, I received some questions multiple times. I’m going to try to answer all of them here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not using Haskell/F#/Clojure/WhatEverFancyLanguage?
&lt;/h2&gt;

&lt;p&gt;This is a non-question for me. I am familiar with Haskell and for sure, I would love to have Prism in Haskell. It would probably be an even better product.&lt;/p&gt;

&lt;p&gt;On the other hand we have to stay pragmatic and Stoplight made the initial investment in TypeScript — and such language is here to stay. This does &lt;strong&gt;NOT&lt;/strong&gt; mean that I can’t write good software though.&lt;/p&gt;

&lt;p&gt;In particular, I got the feeling that TypeScript is mature enough to give a non optimal, but still a pretty decent experience when writing functional code. With Prism, I finally have a tangible example when people are pointing out that this is not possible and we’re condemned to write shitty code forever and ever:&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%2Fwmjiz1uw0idhv3563slr.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%2Fwmjiz1uw0idhv3563slr.png" alt="GitHub discussiont"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you think FP makes always sense?
&lt;/h2&gt;

&lt;p&gt;That’s also kind of a non-question too. I have seen what I call feticist that are like “everything is functional or you’re out of the game” — or something along these lines. I do think it is possible to stay pragmatic and grab the abstractions you need for your application.&lt;/p&gt;

&lt;p&gt;For instance, in Prism the functions emitting logs are considered pure, even though they clearly are not (if you remember from the previous article, &lt;code&gt;console.log&lt;/code&gt; is deterministic but it has the side effect to write on the screen). This is theoretically wrong, but for the sake of my application, I really do not care.&lt;/p&gt;

&lt;p&gt;I will say though that it is always going to make sense to model a significant class of errors not as an exception, but as a real entity of your domain model. Making your application error-aware is only going to give you benefits.&lt;/p&gt;

&lt;p&gt;For instance, when looking for an user via email in a database — the fact that such a user does not exist is very possible. There is no reason to throw an exception for that instead of returning an Error object that people will have to handle accordingly. The choice of the errors to treat in such a way is ultimately up to you.&lt;/p&gt;

&lt;p&gt;In the case of Prism, we are kind of lucky since it has almost no interactions with the outside impure world (file system, network) and when they happen, most of them are confined in the CLI. The core of Prism is pretty much pure and functional and so almost all errors are properly modelled. Functional core, imperative shell. In a line of business applications though, things might be different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Are you seriously betting all this on an unknown library called &lt;code&gt;fp-ts&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;The short answer is yes. In general I have never been hype or GitHub star driven, and for this case I do not care about the library itself at all.&lt;/p&gt;

&lt;p&gt;The reason is simple: fp-ts and any other alternative that you can find on the web (another notable one is &lt;a href="https://github.com/funfix/funfix" rel="noopener noreferrer"&gt;funfix&lt;/a&gt;) are simply formalising a mathematical structure. It’s a set of proven laws that, unless some mathematician wakes up one day and claims “We did it all wrong for the last 200 years” — ain’t going to change. &lt;/p&gt;

&lt;h2&gt;
  
  
  What about the performances?
&lt;/h2&gt;

&lt;p&gt;There’s always going to be somebody in the audience asking this question, and my feeling is that somebody asking this is probably missing the point of the whole presentation.&lt;/p&gt;

&lt;p&gt;In any case, since I was getting this so much I decided to collect some random data and see what the results would look like.&lt;/p&gt;

&lt;p&gt;I am not going to go too much into details, but essentially by looking at the flamegraph of Prism responding to 10k, it turns out the bottleneck is mostly in the validation and the example generation. I was barely able to find any overhead driven by the monads used in Prism. I have never ran any memory benchmarking, and I am not planning to run one at the moment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks!
&lt;/h2&gt;

&lt;p&gt;If you've arrived here, it means that you've probably enjoyed the whole series and I hope it brought you some value.&lt;/p&gt;

&lt;p&gt;I wanted also to thank everybody that's been proofreading all the parts and did some constructive observations and comments. I would have to put so many names that it's probably better to just say thanks to all.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>functional</category>
    </item>
    <item>
      <title>The road to the return of the investment</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Wed, 27 May 2020 10:29:29 +0000</pubDate>
      <link>https://dev.to/vncz/the-road-to-the-return-of-the-investment-lbd</link>
      <guid>https://dev.to/vncz/the-road-to-the-return-of-the-investment-lbd</guid>
      <description>&lt;p&gt;This series is about sharing some of the challenges and lessons I learned during the development of Prism and how some functional concepts taken from Haskell lead to a better product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As of January 2021, I no longer work at Stoplight and I have no control over the current status of the code. There is a &lt;a href="https://github.com/XVincentX/prism" rel="noopener noreferrer"&gt;fork&lt;/a&gt; on my GitHub account that represents the state of the project when I left the company.&lt;/p&gt;




&lt;p&gt;In the previous post I introduced &lt;a href="https://github.com/gcanti/fp-ts" rel="noopener noreferrer"&gt;fp-ts&lt;/a&gt; in Prism with the logging as the primary use case. In this post we'll take a look at how the usage of fp-ts slowly spread in the whole codebase, how we misunderstood some concepts, how some of the coworkers took the adoption of &lt;code&gt;fp-ts&lt;/code&gt; and how it helped us refactor problematic parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Expansion: Router
&lt;/h2&gt;

&lt;p&gt;Time passed after the merging of the PR introducing &lt;code&gt;fp-ts&lt;/code&gt; in Prism; in the meantime teams in Stoplight were reshuffled a little bit. As a result, I got a new teammate on the project. Curiously, he was previously working on the initial new Prism design; then he was reallocated somewhere else when I took Prism and now he was coming back.&lt;/p&gt;

&lt;p&gt;Essentially, I had a fresh member to onboard on the new direction I wanted to give to the code base. I quickly realized this was an incredible occasion to show the company that picking up functional concepts is not an impossible mission and I wanted to play my cards in the most efficient way.&lt;/p&gt;

&lt;p&gt;As the first step for the onboarding, I decided to let my new comrade review a PR I would write that would migrate a component to a functional approach.&lt;/p&gt;

&lt;p&gt;From there, I would then observe his reactions and of course answer his questions.&lt;/p&gt;

&lt;p&gt;This time identifying the next possible candidate component to refactor was easy. As I explored in the &lt;a href="https://dev.to/vncz/forewords-and-domain-model-1p13"&gt;part 1&lt;/a&gt;, Prism has the following components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Router&lt;/li&gt;
&lt;li&gt;Input Validator&lt;/li&gt;
&lt;li&gt;Negotiator&lt;/li&gt;
&lt;li&gt;Output Assembler&lt;/li&gt;
&lt;li&gt;Output Validator&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The negotiator was partially done already in the first PR introducing fp-ts in Prism, and I was well aware that the validation (both input and output) would require a major refactor since they were all state-class based and objectively complicated more on this later.&lt;/p&gt;

&lt;p&gt;I decided to go with the router. Being the first part in the whole flow it would have almost no dependencies from the previous steps, meaning that there would not be plumbing code and/or weird wrappers to match inputs and outputs. Further, its logic was not complicated and the refactor was exclusively to bring it into the functional world, with no changes on its behaviours; this way my comrade would only review effective &lt;code&gt;fp-ts&lt;/code&gt; related changes.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/stoplightio/prism/pull/402" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Expand fs-ts in Prism's router 
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#402&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/XVincentX" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F1416224%3Fv%3D4" alt="XVincentX avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/XVincentX" rel="noopener noreferrer"&gt;XVincentX&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/stoplightio/prism/pull/402" rel="noopener noreferrer"&gt;&lt;time&gt;Jul 06, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;The following PR extends the usage of fp-ts to the routing package as well by basically making sure it does not throw exceptions anymore, but rather use the &lt;code&gt;Either&lt;/code&gt; object to express an error object.&lt;/p&gt;
&lt;p&gt;With this — the router and the mocker finally compose because the type match (they both return an &lt;code&gt;Either&amp;lt;Error, T&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Extend the &lt;code&gt;Either&lt;/code&gt; usage to the router was indeed the easy part: &lt;a href="https://github.com/stoplightio/prism/pull/402/files#diff-f9a10b37616fb5669ecd5218fc8535c9L16" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/402/files#diff-f9a10b37616fb5669ecd5218fc8535c9L16&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The problem started when I started to integrate and try to compose the new function in the mega-file-to-split:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The whole flow is sync apart from the edge case when we need to employ the forwarder, and this requires an additional abstraction layer
&lt;a href="https://github.com/stoplightio/prism/pull/402/files#diff-47c5dc2d65fd624c869f5f08d0cfb56aR45" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/402/files#diff-47c5dc2d65fd624c869f5f08d0cfb56aR45&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What's really preventing from having a clean and functional flow is the validation process that's basically creating an empty array, giving it to the mocker and expecting to receive a filled array. This forces me to keep some stuff here and some stuff there; if the mocker could just return the validations, that'd improve the code a lot.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In order to keep the API compatible with what we have, I have to do some wrapping I'd like to avoid
&lt;a href="https://github.com/stoplightio/prism/pull/402/files#diff-47c5dc2d65fd624c869f5f08d0cfb56aR98" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/402/files#diff-47c5dc2d65fd624c869f5f08d0cfb56aR98&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That said, the funny thing is that, although this Pull Request is meant to be an improvement, you can argue that the code is effectively uglier than it is. (Well I do not think it is, but you mileage may vary)&lt;/p&gt;
&lt;p&gt;The good news though is that — I'm not sure if you remember, we were discussing on how to refactor this part and nobody (me included) really came up with good ideas.&lt;/p&gt;
&lt;p&gt;By trying to extend the functional parts to the router — I now know exactly what needs to be done and how to move forward. This is freaking awesome, to be honest.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/stoplightio/prism/pull/402" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The conversation was not that long and chatty as the first one. I also remember there was almost no conversation at all in our internal Slack channel. &lt;/p&gt;

&lt;p&gt;It is hard to tell why exactly. It could either be because the team assimilated the concepts or maybe they "resigned" on the fact that this was happening and so arguing would not have changed a lot.&lt;/p&gt;

&lt;p&gt;I find the first one very improbable and I would say the truth is in between but clearly leaning on the latter hypothesis. The regret I have today is not asking this explicitly instead of taking advantage of the situation to merge the PR in right away.&lt;/p&gt;

&lt;p&gt;My teammate observed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the code looks complicated because it is long and deeply nested&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is interesting because the code has been long and deeply nested since forever. &lt;code&gt;fp-ts&lt;/code&gt; made that thing visible to a point it could not be ignored anymore. We’ll see an example of a successful refactor later.&lt;/p&gt;

&lt;p&gt;The feedback I was receiving in our internal channels was that generally the code would look dirtier than it was previously. This was mostly happening at the "edges" between the regular code and the functional one because of required bridging to maintain compatibility with the current Prism functionality.&lt;/p&gt;

&lt;p&gt;For instance, there was a function of Prism that could have thrown an exception in case something went wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a lot of code&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is not ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// a lot of code again&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;anotherCondition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is not ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When such a part got refactored to use &lt;code&gt;Either&amp;lt;Error, T&amp;gt;&lt;/code&gt; exceptions wouldn't be thrown at all. On the other hand, whoever would have called this function might have relied on the thrown exception. As long as all the callers wouldn't have been refactored, &lt;code&gt;foo&lt;/code&gt; would always have to ultimately throw. This is what I called "bridging".&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;foo&lt;/code&gt; function, the bridging would probably look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;import * as E from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/pipeable';
Import { identity } from ‘lodash’;
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;function foo() {
&lt;/span&gt;  pipe(
    operation1(arg1, arg2),
    E.chain(result =&amp;gt; operation2(result.outstandingBalance)),
    E.chain(operation3),
&lt;span class="gi"&gt;+   E.fold(error =&amp;gt; { throw error }, identity)
&lt;/span&gt;  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There were cases with some monads where the bridging code would look even uglier. On the positive side, this would clearly communicate to the developer that this function was still impure exclusively because of something relying on the impure behaviour. This facilitated the search for refactoring opportunities significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Return Of Investment: Validation
&lt;/h2&gt;

&lt;p&gt;Finally after some time we got the downpayment of a series of returns of investment given by the employment of &lt;code&gt;fp-ts&lt;/code&gt; in Prism.&lt;/p&gt;

&lt;p&gt;I have already stated that validation in Prism is hard, and the way it was initially implemented in Prism made it even harder. We complained and tried to do something about it (with no results) multiple times:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/stoplightio/prism/pull/351#discussion_r293254707" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/351#discussion_r293254707&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that ultimately the whole team would agree that passing on the opportunity would be the best idea for the time being, since it would be too much time consuming.&lt;/p&gt;

&lt;p&gt;The real deal was that nobody knew where to start. That piece of code was terrible, but &lt;code&gt;fp-ts&lt;/code&gt; gave me the key to move on and finally refactor that part of the validation. &lt;/p&gt;

&lt;p&gt;One of the good things when using category theory constructs is that things tend to naturally compose. It's like having two pieces of code with a magnet at the extremities: they naturally want to bond. Such property suggests to you that, when things do not compose, something is probably not going well.&lt;/p&gt;

&lt;p&gt;Let’s take yet another look to some of the Prism components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Router (fp-ts-ized)&lt;/li&gt;
&lt;li&gt;Input Validator&lt;/li&gt;
&lt;li&gt;Negotiator (fp-ts-ized)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We were fundamentally in the situation where two pieces that wanted to compose (the router and the negotiator) couldn't because the Validator had not the right interface. The lack of composability became the driving factor that I used to refactor the input validation.&lt;/p&gt;

&lt;p&gt;What happened was fascinating: I was about to ask for suggestions in the Slack channel where I used (and still use) to hangout and talk about functional stuff. While writing the message, I wrote the solution without getting any input from outside:&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%2Fqj7gmb5pw53iep7x4kxt.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%2Fqj7gmb5pw53iep7x4kxt.png" alt="Plan of attack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last sentence I wrote is kind of memorable&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I think fp-ts made me understand why the code is so horrible and how I should move forward.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This, indeed, ultimately happened some time ago:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/stoplightio/prism/pull/862" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/862&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When It Went Wrong: Security Checks
&lt;/h2&gt;

&lt;p&gt;This is not a story where we did everything right. It would mean that's either invented or it omits details. Although I am inclined to say we did &lt;em&gt;most&lt;/em&gt; of the things right, we clearly made some mistakes along the journey.&lt;/p&gt;

&lt;p&gt;One of these was the porting of the security checks. It's essentially the part that checks if the call can go through the negotiator for mocking or being rejected with a &lt;code&gt;401&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This part didn't go very well. Although after the conversion the feature was still working correctly from a functionality standpoint, the resulting code was really hard to reason about, resulting in two additional refactors to bring it back to a reasonable state.&lt;/p&gt;

&lt;p&gt;Looking at this now I think there were some factors that brought the things out of control:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Although familiar with functional concepts, the developer working on the security checks didn't grasp enough of it to be able to complete the feature alone. This resulted in frustration on his side and ultimately brought him to switch in the “get it done, no matter what” mode.&lt;/li&gt;
&lt;li&gt;I also had some blanks. For instance, I thought that passing a &lt;code&gt;Left&amp;lt;T&amp;gt;&lt;/code&gt; as a function argument would be totally legit — it turns out that 99% it is not.&lt;/li&gt;
&lt;li&gt;In order to get the feature done and give some relief to the comrade, I lowered my code review standards and merged it in anyway.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This episode costed me a lot of time to clean it up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/stoplightio/prism/pull/804" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/804&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/stoplightio/prism/pull/830" rel="noopener noreferrer"&gt;https://github.com/stoplightio/prism/pull/830&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second PR, although the changes are minimal, took me &lt;em&gt;ages&lt;/em&gt; to put together. I still have a vivid remembering of me working on it. The logic behind that was so complicated that I would lose the context quickly and had to restart from scratch. Multiple times.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the lessons learned?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;It is inevitable that things will go wrong during any journey. Keep that in consideration and allocate some time to clean up stuff.&lt;/li&gt;
&lt;li&gt;Short term solutions will bring long term conflicts. Short term conflicts will bring long term solutions. I decided to give my coworker a relief by merging something that wasn’t really ok. I had to pay that back with a very high interest rate.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;In the next article, we'll respond to some of the FAQ that I have received while talking about this and showing Prism around.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>functional</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Introducing in the company</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Fri, 22 May 2020 12:48:25 +0000</pubDate>
      <link>https://dev.to/vncz/introducing-in-the-company-4hg4</link>
      <guid>https://dev.to/vncz/introducing-in-the-company-4hg4</guid>
      <description>&lt;p&gt;This series is about sharing some of the challenges and lessons I learned during the development of Prism and how some functional concepts taken from Haskell lead to a better product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As of January 2021, I no longer work at Stoplight and I have no control over the current status of the code. There is a &lt;a href="https://github.com/XVincentX/prism" rel="noopener noreferrer"&gt;fork&lt;/a&gt; on my GitHub account that represents the state of the project when I left the company.&lt;/p&gt;




&lt;p&gt;In the previous post we saw how I discovered a set of abstractions that apparently were a perfect fit for Prism's use cases. In this post we'll instead cover how we got the concepts applied for the first time in Prism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding an introduction point
&lt;/h2&gt;

&lt;p&gt;At this point, I was convinced that adopting fp-ts in Prism would make a lot of sense; the problem was to find a way to introduce it in a reasonable way.&lt;/p&gt;

&lt;p&gt;Prism was already at a late development stage. Although we didn't have a fixed timeline we were already releasing beta versions a couple of times per week and we also had a decent amount of users trying it out.&lt;/p&gt;

&lt;p&gt;For these reasons, I decided there were a couple of points that I was not willing to compromise while trying out fp-ts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Although we did not have a precise deadline, I knew that Prism's stable release was close. For this reason, no matter what was the state of fp-ts in Prism, I set myself the goal that the &lt;code&gt;master&lt;/code&gt; branch should &lt;em&gt;always&lt;/em&gt; be ready to be released as the new major version.&lt;/li&gt;
&lt;li&gt;Because we already had a good number of users, I set the hard rule that &lt;strong&gt;we would never break the user space&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Because I knew that this was new stuff even for me and nobody in the team was really into functional programming, I set the aim of introducing this into a relatively low-risk part of the software so that:

&lt;ul&gt;
&lt;li&gt;It would be relatively easy to revert the changes in case we'd realise that fp-ts wouldn't really fit the use case or in any case not play well together with the rest of the code base&lt;/li&gt;
&lt;li&gt;In case we would have misunderstood some parts of the library or screwed up something, it should not alter the software in any way. Preferably, the main features of Prism should still be functioning correctly&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These are very strong constraints, narrowing down the possible choices a lot. I guess that's the fun of the software modelling.&lt;/p&gt;

&lt;p&gt;Eventually the occasion I was waiting for came up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging in Prism
&lt;/h2&gt;

&lt;p&gt;Logging is probably one of the most appreciated features of Prism because it provides a clear introspection on the decision process and tells you exactly why Prism has decided to respond to you in such a way.&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%2F83mlg650g5sj5x2znicp.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%2F83mlg650g5sj5x2znicp.png" alt="Prism logging in action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, the logger brought a lot of value to us as well. If for some reason Prism would respond incorrectly, because of the logger being so verbose we've always been able to quickly identify what component was misbehaving (&lt;a href="https://dev.to/vncz/forewords-and-domain-model-1p13#custom-negotiator"&gt;negotiator, validator, the http server&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Thinking about the logging in Prism I realised that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There would be no way the logging would break the user space, since there was no impact nor in the CLI, nor the Prism HTTP Client API nor the Http Server&lt;/li&gt;
&lt;li&gt;The worst that would happen in case the logging would be wrong (because of a misusage/misunderstanding of fp-ts) would have been wrong log lines; the mocking functionality wouldn't have been affected per-se&lt;/li&gt;
&lt;li&gt;At the time of the introduction logging was planned only for the Negotiator, making possible an ideal "revert PR" and return back to where we were.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For these reasons I thought the logging was a good introduction point and I took the risk of trying it out fp-ts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the PR merged
&lt;/h2&gt;

&lt;p&gt;I decided to go with &lt;a href="https://getpino.io" rel="noopener noreferrer"&gt;pino&lt;/a&gt; as a logging solution. The decision was &lt;strong&gt;NOT&lt;/strong&gt; based on the low overhead/high performance claims that are on the website/project documentation, but more because Pino does not include any way to process/alert/react to logs; it simply outputs the log statements as JSON on the stdout (or any stream you provide to it). It means that, by design, there's no way somebody can make messes with logs and do any action that's logging dependent. You can't break what's not even included.&lt;/p&gt;

&lt;p&gt;Now the compromises start to come. In the complete pureness of the functional world, writing messages on the standard output through &lt;code&gt;console.log&lt;/code&gt; is deterministic (since it always returns &lt;code&gt;undefined&lt;/code&gt;) but it has a side effect (printing on the screen). &lt;/p&gt;

&lt;p&gt;Haskell indeed considers it as an action that can only be ran in the &lt;code&gt;main&lt;/code&gt; program&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;putStrLn&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Similarly, fp-ts provides the same mechanism:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&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;Moreover, printing on the screen is not considered something that it might fail – so the &lt;code&gt;Either&lt;/code&gt; abstraction (which is the one I really valued in Prism and wanted to adopt) would not be useful in this specific case.&lt;/p&gt;

&lt;p&gt;We'll talk more about the compromises in a next article; however I decided, at least to start that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I would &lt;strong&gt;not&lt;/strong&gt; consider the &lt;code&gt;console.log&lt;/code&gt; as a side effect; therefore the actions would have been considered pure at the time. I was perfectly aware that it's wrong, but to respect the rules that I gave myself (and listed above) I had to go with a minimal codebase invasion&lt;/li&gt;
&lt;li&gt;Since logging is not considered to be a failing action and I would not consider it to have a side effect, I decided instead to get started with the &lt;a href="https://dev.to/napicella/dependency-injection-and-reader-monad-5ap4"&gt;Reader&lt;/a&gt; monad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea was to use the Reader monad to inject the logger to the &lt;a href="https://github.com/stoplightio/prism/tree/master/packages/http" rel="noopener noreferrer"&gt;Prism Http Package&lt;/a&gt; without having to pass it explicitly as a parameter everywhere.&lt;/p&gt;

&lt;p&gt;This made a lot of sense, since we wanted to have different loggers according to the context (CLI, Hosted Prism).&lt;/p&gt;

&lt;p&gt;I had a very brief conversation about my intentions with one of my coworkers (who essentially nodded) and I made it happen:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/stoplightio/prism/pull/323" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Logging Prism's decisions.
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#323&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/XVincentX" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F1416224%3Fv%3D4" alt="XVincentX avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/XVincentX" rel="noopener noreferrer"&gt;XVincentX&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/stoplightio/prism/pull/323" rel="noopener noreferrer"&gt;&lt;time&gt;May 27, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;All right, be prepared.&lt;/p&gt;
&lt;h4&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;TL; DR&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Prism can now log stuff from the negotiation.&lt;/li&gt;
&lt;li&gt;The negotiation and logging process can't make Prism crash anymore for any reason.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Long version&lt;/h4&gt;
&lt;p&gt;The following PR, in theory, implements logging for the negotiator. Practically, though, this PR is laying down the foundation for the logging for the future hosted version as well and hopefully start moving Prism's code in a different direction.&lt;/p&gt;
&lt;p&gt;There were some main principles I've been keeping in mind while writing the code for this stuff:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Prism should not process/format/react to the logs. Somebody else should do it; doing stuff on logs is usually slow and Prism should instead answer all the requests as fast as possible.&lt;/li&gt;
&lt;li&gt;The negotiation process in Prism is currently composed by numerous and nested function calls and last thing I wanted to do is to carry over this &lt;code&gt;logger&lt;/code&gt; parameter in all the function and having to deal with it everywhere&lt;/li&gt;
&lt;li&gt;The logging cannot be a singleton defined somewhere — because the logging instance will be provided externally (Prism Http Server, in this case)&lt;/li&gt;
&lt;li&gt;The logging process and the negotiation process should never make Prism crash. In any circumstance. I repeat, in &lt;em&gt;ANY&lt;/em&gt; circumstances.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let's now see how I've tamed them down.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;a href="https://getpino.io" rel="nofollow noopener noreferrer"&gt;Pino&lt;/a&gt;. If you go on their website the write that "it's the fastest logger on the world" but you can ignore that, that was not the reason why I went with it. The main points were:
&lt;ul&gt;
&lt;li&gt;It's included with &lt;a href="https://fastify.io" rel="nofollow noopener noreferrer"&gt;fastify&lt;/a&gt; — and so we're not introducing a new dependency. We've been shipping it since forever.&lt;/li&gt;
&lt;li&gt;Pino does not include any way to process/alert/react to logs; it simply outputs the log statements as JSON on the stdout (or any stream you provide to it). It means that all the processing must be off process and I think this is great. It means that, by design, there's no way somebody can make messes with logs and do any action that's logging dependant. You can't break what's not even included.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So where's the log processing happening in our case? In the CLI. You can see from the code that, whenever the production environment is detected (or the &lt;code&gt;-m&lt;/code&gt; flag is passed) the &lt;a href="https://github.com/stoplightio/prism/pull/323/files#diff-354729d6ad7943965bb0088ba7d8f7d8R36" rel="noopener noreferrer"&gt;CLI will effectively use the cluster module to fork the process&lt;/a&gt;, run Prism Server and funnel its stdout logs back to the CLI, where Signale will pretty print them. When Prism will be hosted somewhere, we'll likely do the same.&lt;/p&gt;
&lt;p&gt;In case you're running the things locally to write code and test the stuff, you'll see that the fork is avoided and all is done in process. This is done fundamentally because it's going to be way easier to debug stuff in a single process. This is exactly the same that Jest does with the &lt;code&gt;--runInBand&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/1416224/59599108-09156200-90fe-11e9-9e04-e20d96d10bd4.png" rel="nofollow noopener noreferrer"&gt;&lt;img width="2000" alt="image" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F1416224%2F59599108-09156200-90fe-11e9-9e04-e20d96d10bd4.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see from the image what when the &lt;code&gt;-m&lt;/code&gt; flag is specified, you'll find an additional process with node running — this is exactly the forking happening.&lt;/p&gt;
&lt;p&gt;Note: if &lt;code&gt;NODE_ENV===production&lt;/code&gt; the forking is enabled by default, so that if you use the CLI in a Docker Environment you get what the production behaviour.&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;
&lt;p&gt;Inject the logger through currying. Thanks to the partial application I can basically write a function that takes the &lt;em&gt;regular&lt;/em&gt; arguments which returns a function needing an additional dependency to run.
&lt;code&gt;const negotiate = (arg1, arg2, arg3) =&amp;gt; logger =&amp;gt; { // real body }&lt;/code&gt;. For this, I've employed &lt;code&gt;fp-ts&lt;/code&gt;'s reader implementation, that allows me to do exactly that: write code that has regular arguments and returns something that will need a logger to be executed. By leveraging &lt;code&gt;chain&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt; method, intermediate functions can easily introspect and modify the result in the middle without having to worry about the logging presence. It'll be put as last step. Moreover, if one day we will want to make the Router start outputting logs as well — it's really easy. All we need to do is make the router spit up a Reader and chain it with the following one in the mocker. All good, profit.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;See point 2. With Currying I can pretend the inner functions will eventually have a logger, it's resolution is happening in a &lt;em&gt;completely different npm package&lt;/em&gt;; this is important to understand why I could not simply have a shared instance to require from somewhere.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This happened as an effect of the reader. Since the logger in injected at the end, the traditional try catch in the middle of the code to decorate the errors does not work anymore. I could have workaround this but I decided instead to change the approach and make sure the negotiation and the logging process never throws exceptions. Therefore the code has been modified to use the &lt;code&gt;Either&lt;/code&gt; implementation that's included in &lt;code&gt;fp-ts&lt;/code&gt;, which is not that hard to understand. If you check out the &lt;code&gt;NegotiatorHelper.ts&lt;/code&gt; you can see there are not that many changes and more importantly nested exceptions are now been flattened — which is good. Clearly there are 1-2 things that aren't &lt;em&gt;that&lt;/em&gt; cool but I'm on all of them. In particular:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jest should support wrapped helpers so I can remove my home made helpers &lt;a href="https://github.com/facebook/jest/issues/8540" rel="noopener noreferrer"&gt;https://github.com/facebook/jest/issues/8540&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A built-in &lt;code&gt;ReaderEither&lt;/code&gt; could let me remove some &lt;a href="https://github.com/stoplightio/prism/pull/323/files#diff-e18554f8d62727c21aaa7a2ea6de4a72R65" rel="noopener noreferrer"&gt;nested maps&lt;/a&gt;. I'm quite sure &lt;a class="mentioned-user" href="https://dev.to/gcanti"&gt;@gcanti&lt;/a&gt; will make it happen soon &lt;img class="emoji" title=":trollface:" alt=":trollface:" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Fimages%2Ficons%2Femoji%2Ftrollface.png" height="20" width="20"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Outstanding points&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[x] Refactor &lt;code&gt;mock.ts&lt;/code&gt; to look a little bit more human&lt;/li&gt;
&lt;li&gt;[x] Resolve the null-ness of &lt;code&gt;logger&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;[x] Understand whether we're logging enough or too much&lt;/li&gt;
&lt;li&gt;[x] CLI Readme Update&lt;/li&gt;
&lt;li&gt;[x] Deduplicate the testing helpers&lt;/li&gt;
&lt;li&gt;[x] General review and cleanup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SO-231&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/stoplightio/prism/pull/323" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;The PR is kind of big and although I would encourage you to check it out, I am pretty sure nobody will. Therefore, here's the TL;DR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I decided to put my &lt;code&gt;--verbose&lt;/code&gt; flag to 9000 and over-explain my intentions, how I executed them, what were the consequences, limitations and how we would move forward with that.&lt;/li&gt;
&lt;li&gt;Some coworkers were confused by the terminology; people unfamiliar with the functor in general will think that &lt;code&gt;map&lt;/code&gt; is only a thing for arrays and make up their noses when they see it applied somewhere else&lt;/li&gt;
&lt;li&gt;A coworker was excited about the work and since he effectively was a little bit more familiar with this stuff, he helped the review and corroborated the benefits that I was trying to bring&lt;/li&gt;
&lt;li&gt;Different libraries and languages have different names for the same "operation". In the specific case, we had people confused by the &lt;code&gt;chain&lt;/code&gt; function because somewhere else is usually called &lt;code&gt;flatMap&lt;/code&gt; or &lt;code&gt;bind&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We had some people concerned about the general readability of the code (that's a funny thing to me but I was aware that people's brain needed to be rewired) and growing the contribution barrier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I took all the necessary time to address the comments; most of them were actually more questions and clarification rather than requests for changes.  Most of them were easily resolvable once I would briefly explain the concept behind that (such as &lt;code&gt;chain&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;fold&lt;/code&gt;). I took that as a good sign.&lt;/p&gt;

&lt;p&gt;Then the conversation kind of stalled for some days until I decided to take control of the situation and risk it by merging the PR although not everybody approved it. I felt that in some cases it is better to do something and ultimately be wrong rather than not doing anything and then be wrong anyway. Nobody complained about it so it was official, we were starting to get the core of Prism functional.&lt;/p&gt;

&lt;p&gt;Somebody was a little bit angry about it, but I also received a great feedback during one of our retrospectives:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The introduction of fp-ts in Prism makes me think we'll finally do something differently here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next article we’ll see how, by continuing to expand fp-ts’s usage in Prism we started to get the first wins and return of the investment we did.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>functional</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Finding the right abstraction</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Fri, 15 May 2020 12:59:22 +0000</pubDate>
      <link>https://dev.to/vncz/finding-the-right-abstraction-57bb</link>
      <guid>https://dev.to/vncz/finding-the-right-abstraction-57bb</guid>
      <description>&lt;p&gt;This series is about sharing some of the  challenges and lessons I learned during the development of &lt;a href="https://github.com/stoplightio/prism" rel="noopener noreferrer"&gt;Prism&lt;/a&gt; and how some functional concepts lead to a better product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As of January 2021, I no longer work at Stoplight and I have no control over the current status of the code. There is a &lt;a href="https://github.com/XVincentX/prism" rel="noopener noreferrer"&gt;fork&lt;/a&gt; on my GitHub account that represents the state of the project when I left the company.&lt;/p&gt;




&lt;p&gt;In the previous post we had a 30k feet view of Prism and some of its technical features and challenges.&lt;/p&gt;

&lt;p&gt;In this specific post, I will explain the series of events that ended up me deciding to give a try to a functional library that apparently would fit the Prism's use case perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  A validator in TypeScript
&lt;/h2&gt;

&lt;p&gt;Prism was not the first project that I was working on when I joined &lt;a href="https://stoplight.io" rel="noopener noreferrer"&gt;Stoplight&lt;/a&gt;; before landing there I have been bounced around different projects while trying to understand where I could best contribute.&lt;/p&gt;

&lt;p&gt;During that time, the development of the new version of Prism was just &lt;a href="https://github.com/stoplightio/prism/pull/154/files" rel="noopener noreferrer"&gt;getting started&lt;/a&gt; by a different team, and I was totally unaware of the project's status, direction and technical choices that were made.&lt;/p&gt;

&lt;p&gt;However, we can say that Prism was developed as a typical TypeScript web application; throwing exception where things were going unexpectedly wrong (somewhere returning &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;), using classes holding state for the validators, a strong classical inheritance model to let the software expand in the future and so on.&lt;/p&gt;

&lt;p&gt;Months pass. I am working on &lt;a href="https://stoplight.io/studio" rel="noopener noreferrer"&gt;Stoplight Studio&lt;/a&gt; and I was actively looking for a validation library that would be TypeScript friendly and would be able to type the returned value in case the validation would pass.&lt;/p&gt;

&lt;p&gt;I googled the relative keyword around ending up in &lt;a href="https://github.com/typestack/class-validator" rel="noopener noreferrer"&gt;solutions using decorators&lt;/a&gt; that were not what I was looking for. &lt;/p&gt;

&lt;p&gt;I do not like decorators. They're not even standards. I do not like classes neither.&lt;/p&gt;

&lt;p&gt;During the search though, I stumbled on this Tweet that gave me some hope:&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;I headed to the &lt;a href="https://github.com/gcanti/io-ts" rel="noopener noreferrer"&gt;mentioned project&lt;/a&gt; and after a quick read to the README (which, I would agree with you, is not that…&lt;em&gt;eloquent&lt;/em&gt;) I felt it looked promising and so I tried create a sample project to try it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  First impressions
&lt;/h2&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%2Fg9xsm01v7fxmn0n41b1z.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%2Fg9xsm01v7fxmn0n41b1z.png" alt="io ts first impression"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: this image is relative to io-ts 1.x. The current version is 2.x. Your experience is likely going to be different.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are two things that are very evident:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There's a bunch of methods whose name aren't familiar at all:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;inspect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isLeft&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isRight&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;map&lt;/code&gt; (well actually this was not unknown)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mapLeft&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orElse&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;…the list goes on and on&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I can't find my data. Once I've defined a type and decoded an &lt;code&gt;unknown&lt;/code&gt; payload, where is my data stored? I could only see functions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I was already on the point of ditching the whole thing and look for the next alternative, but I then noticed I actually knew the author (we've been hanging out in the same Slack channel for a while, but mostly ignoring each other), so I decided to ask what was the deal with io-ts.&lt;/p&gt;

&lt;p&gt;After some chit chats, it turned out that io-ts is using &lt;a href="https://github.com/gcanti/fp-ts" rel="noopener noreferrer"&gt;fp-ts&lt;/a&gt;, providing the functional primitives that the library is using and exposing, and that was the primary reason for the "weird" set of functions returned from the decode process.&lt;/p&gt;

&lt;p&gt;Ultimately we ended up philosophically discussing what kind of software  I have been writing all these years by ignoring the functional concepts.&lt;/p&gt;

&lt;p&gt;At the end of the day, I learned that the &lt;code&gt;decode&lt;/code&gt; function of &lt;code&gt;io-ts&lt;/code&gt; would return an &lt;code&gt;Either&lt;/code&gt; — a monad representing the effect that a computation might fail. So, in order to continue my journey, I had to master that.&lt;/p&gt;

&lt;p&gt;It's not my intention here to explain to you functional programming. I am not qualified for that and if you're interested I really suggest you to read the amazing series of articles written by Giulio Canti directly:&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__126680"&gt;
    &lt;a href="/gcanti" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&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%2Fuser%2Fprofile_image%2F126680%2Fc9e86d35-d464-440e-9981-849b4eb65804.jpeg" alt="gcanti image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gcanti"&gt;Giulio Canti&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gcanti"&gt;/gcanti&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;However, I just wanted to give a basic explanation of the &lt;code&gt;Either&lt;/code&gt; monad and how I felt it would be just what I'd need for Prism&lt;/p&gt;

&lt;h2&gt;
  
  
  Either 101
&lt;/h2&gt;

&lt;p&gt;An Either is a &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions" rel="noopener noreferrer"&gt;tagged union&lt;/a&gt; that holds a value whose type depends on the &lt;code&gt;tag&lt;/code&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Right&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;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 typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Right&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;A&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;readonly&lt;/span&gt; &lt;span class="na"&gt;_tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Right&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you want to store in such a structure it's ultimately up to you, but what's mostly used for in all the code I saw so far in the wild is essentially to hold errors (usually put on the Left) and the value (usually on the Right) in as an alternative way to throw an exception when something is going wrong.&lt;/p&gt;

&lt;p&gt;For instance, consider this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createParamUriTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpParamStyles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;starOrVoid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;explode&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;HttpParamStyles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Simple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`{&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;starOrVoid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;HttpParamStyles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`{.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;starOrVoid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;HttpParamStyles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`{;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;starOrVoid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unsupported parameter style: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and now let's rewrite it to use the Either tagged union:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;import { left, right } from ‘fp-ts/lib/Either’;
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;function createParamUriTemplate(name: string, style: HttpParamStyles, explode: boolean) {
&lt;/span&gt;   switch (style) {
     case HttpParamStyles.Simple:
&lt;span class="gi"&gt;+      return right(`{${name}${starOrVoid}}`);
&lt;/span&gt;&lt;span class="gd"&gt;-      return `{${name}${starOrVoid}}`;
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;     case HttpParamStyles.Label:
&lt;span class="gi"&gt;+      return right(`{.${name}${starOrVoid}}`);
&lt;/span&gt;&lt;span class="gd"&gt;-      return `{.${name}${starOrVoid}}`;
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;     case HttpParamStyles.Matrix:
&lt;span class="gi"&gt;+      return right(`{;${name}${starOrVoid}}`);
&lt;/span&gt;&lt;span class="gd"&gt;-      return `{;${name}${starOrVoid}}`;
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;     default:
&lt;span class="gi"&gt;+      return left(new Error(`Unsupported parameter style: ${style}`));
&lt;/span&gt;&lt;span class="gd"&gt;-      throw new Error(`Unsupported parameter style: ${style}`);
&lt;/span&gt;   }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Such changes inevitably will mandate a change in the function signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;import * as E from 'fp-ts/lib/Either';
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt; declare function createParamUriTemplate(
   name: string,
   style: HttpParamStyles,
   explode: boolean
&lt;span class="gd"&gt;- ): string;
&lt;/span&gt;&lt;span class="gi"&gt;+ ): E.Either&amp;lt;Error, string&amp;gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it also made me observe something:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;While the first signature does not communicate in any way that the function could error and throw an exception (the only way to get that is to inspect the source code), the second version is very clear about the possibility of a failure.&lt;/li&gt;
&lt;li&gt;While in the first case I can &lt;em&gt;pretend&lt;/em&gt; (and pray) that no error will happen and carry on the happy path only, the second function will not let you access the data if you don't perform explicit checks&lt;/li&gt;
&lt;li&gt;It makes the Error an explicit part of your domain model instead of an exceptional thing that should never happen (that WILL happen one day, believe it or not)&lt;/li&gt;
&lt;li&gt;Since Either admits instances for Monad, Applicative and a Functor, it can leverage some good tooling to restore composability even if processes that might error (more about that later)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Obviously, these points didn't come in my mind all at once; it required some effort and education to get past the "meh, does not look so good" phase and understand the concepts and the benefits it would bring (and make the coworkers excited about it, but we'll discuss this later).&lt;/p&gt;

&lt;p&gt;I was still super skeptical about it, but the bell was ringing. At that time, I had the two considerations in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If Prism's job is to &lt;strong&gt;return errors&lt;/strong&gt; then treating them as a domain entities instead of a undesired effect that should never happen (aka: exceptions) would make a lot of sense&lt;/li&gt;
&lt;li&gt;By having to handle all the errors no matter what, I could make sure that I would always return the correct status code and not leave anything unhandled (and returning an incorrect 500).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was worth giving it a try; but how do you introduce such stuff in a codebase that's already in progress, with other people working on it and that's close to a major release?&lt;/p&gt;

&lt;p&gt;We'll explore that in the next article.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>architecture</category>
      <category>functional</category>
    </item>
    <item>
      <title>Forewords and domain model</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Fri, 08 May 2020 11:16:27 +0000</pubDate>
      <link>https://dev.to/vncz/forewords-and-domain-model-1p13</link>
      <guid>https://dev.to/vncz/forewords-and-domain-model-1p13</guid>
      <description>&lt;p&gt;This series is about sharing some of the  challenges and lessons I learned during the development of &lt;a href="https://github.com/stoplightio/prism" rel="noopener noreferrer"&gt;Prism&lt;/a&gt; and how some functional concepts lead to a better product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As of January 2021, I no longer work at Stoplight and I have no control over the current status of the code. There is a &lt;a href="https://github.com/XVincentX/prism" rel="noopener noreferrer"&gt;fork&lt;/a&gt; on my GitHub account that represents the state of the project when I left the company.&lt;/p&gt;




&lt;p&gt;In this specific post, I will start explaining what Prism is, detail some of its key features and discuss a little bit about its domain and its intended audience.&lt;/p&gt;

&lt;p&gt;This will hopefully help you understand the technical choices I made that I will cover in the next articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Prism
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/stoplightio" rel="noopener noreferrer"&gt;
        stoplightio
      &lt;/a&gt; / &lt;a href="https://github.com/stoplightio/prism" rel="noopener noreferrer"&gt;
        prism
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Turn any OpenAPI2/3 and Postman Collection file into an API server with mocking, transformations and validations.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Prism is a mock server for &lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md" rel="noopener noreferrer"&gt;OpenAPI 2&lt;/a&gt; (from now on OAS2), &lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md" rel="noopener noreferrer"&gt;OpenAPI 3&lt;/a&gt; (from now on OAS3) and &lt;a href="https://www.postman.com/collection" rel="noopener noreferrer"&gt;Postman Collections&lt;/a&gt; (from now on PC). &lt;/p&gt;

&lt;p&gt;For those of you that aren't familiar with such, OAS2/3 and PC are essentially specifications defining a standard and language-agnostic interface to (possibly RESTful) APIs.&lt;/p&gt;

&lt;p&gt;To be a little bit more pragmatic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.0.0&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/list&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Returns&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;list&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;stuff"&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successful&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;response"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This YAML file is an OpenAPI 3.0 document claiming that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There's an API&lt;/li&gt;
&lt;li&gt;It has a &lt;code&gt;/list&lt;/code&gt; path&lt;/li&gt;
&lt;li&gt;It has a &lt;code&gt;GET&lt;/code&gt; method&lt;/li&gt;
&lt;li&gt;When a &lt;code&gt;GET&lt;/code&gt; request to the &lt;code&gt;/list&lt;/code&gt; endpoint is made, &lt;code&gt;200&lt;/code&gt; is one of the possible responses you &lt;em&gt;might&lt;/em&gt; get, whose details (such as payload shape, returned headers) haven't been specified.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We aren't going to go too much into detail about these formats; if you’re interested, you can go and read the official specifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md" rel="noopener noreferrer"&gt;OpenAPI 2.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md" rel="noopener noreferrer"&gt;OpenAPI 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.getpostman.com/json/collection/v2.0.0/docs/index.html" rel="noopener noreferrer"&gt;Postman Collections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite this simple example, we can say that all the specifications allow (with some nuances) to specify pretty complicated scenarios, ranging from authentication, request and response validation, to web hooks, callbacks and example generation.&lt;/p&gt;




&lt;p&gt;A mock server is nothing more than a little program that reads the description document and spins up a server that will behave in the way that the document mandates.&lt;/p&gt;

&lt;p&gt;Here's an example of Prism starting up with a standard OAS3 document:&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%2Frawcdn.githack.com%2Fstoplightio%2Fprism%2Fed3aeb4ae00481a3720d2674caee7acabe71fa5b%2Fexamples%2Fprism-cli.svg" 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%2Frawcdn.githack.com%2Fstoplightio%2Fprism%2Fed3aeb4ae00481a3720d2674caee7acabe71fa5b%2Fexamples%2Fprism-cli.svg" alt="Prism starting up with a standard OAS3 document"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prism Peculiarities
&lt;/h2&gt;

&lt;p&gt;Technical decisions and trade-offs were driven by features. Here are the most relevant ones regarding this series:&lt;/p&gt;

&lt;h3&gt;
  
  
  100% TypeScript
&lt;/h3&gt;

&lt;p&gt;Prism is written entirely in &lt;a href="https://typescriptlang.org" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;. Primarily because &lt;a href="https://stoplight.io" rel="noopener noreferrer"&gt;Stoplight&lt;/a&gt;'s stack is largely based on NodeJS and TypeScript.&lt;/p&gt;

&lt;p&gt;We are using the maximum level of strictness that TypeScript allows.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Lot Of Custom Software
&lt;/h3&gt;

&lt;p&gt;Prism is not using any of the web frameworks you usually find on the market and employed for web applications, so you won't find Express, you won't find Hapi, nothing.&lt;/p&gt;

&lt;p&gt;It was initially written using &lt;a href="https://fastify.io" rel="noopener noreferrer"&gt;Fastify&lt;/a&gt;; and at that time I was not working on the project. I ultimately &lt;a href="https://github.com/stoplightio/prism/pull/927" rel="noopener noreferrer"&gt;decided to remove it&lt;/a&gt; in favour of a &lt;a href="https://github.com/turist-cloud/micri" rel="noopener noreferrer"&gt;tiny wrapper&lt;/a&gt; on top of the regular &lt;code&gt;http&lt;/code&gt; server that NodeJS offers.&lt;/p&gt;

&lt;p&gt;In case you are asking, the main reason for this is because most of the frameworks focus on the 80% of the use cases, which is totally legit.&lt;/p&gt;

&lt;p&gt;On the other hand, Prism aims for 100% compatibility with the document types it supports, and, for instance, some of them have some &lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#encoding-object" rel="noopener noreferrer"&gt;very…creative parameters support&lt;/a&gt; that no parser on the market supports.&lt;/p&gt;

&lt;p&gt;Another example? OpenAPI 2 and 3 are using path templating, but not the same as URI Templating specified in the &lt;a href="https://tools.ietf.org/html/rfc6570" rel="noopener noreferrer"&gt;RFC6570&lt;/a&gt;. For this reason, a custom parser and extractor had to be defined.&lt;/p&gt;

&lt;p&gt;This specific case, together with other ones that required special code to be wrote, led us to gradually dismantle and neglect different Fastify features until I realised that we were not using it at all if not for listening on the TCP port; on the contrary, we were just fighting it because it was too opinionated on certain matters, such as errors.&lt;/p&gt;

&lt;p&gt;You can find more about the motivations in the relative &lt;a href="https://github.com/stoplightio/prism/issues/790" rel="noopener noreferrer"&gt;GitHub issue&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Negotiator
&lt;/h3&gt;

&lt;p&gt;Prism contains a custom made negotiator — which is that part of the software that taken an incoming HTTP Request, its validation results (headers, body, security) and the target API Specification document will return the most appropriate response definition that can then be used by the generator to return a response instance to the client.&lt;/p&gt;

&lt;p&gt;The negotiator itself is kind of complicated, but I think we've done a good job in both documenting its decision process:&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%2Frawcdn.githack.com%2Fstoplightio%2Fprism%2F9241546839be9be54e280a4db00268bf7643b92f%2Fpackages%2Fhttp%2Fdocs%2Fimages%2Fmock-server-dfd.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%2Frawcdn.githack.com%2Fstoplightio%2Fprism%2F9241546839be9be54e280a4db00268bf7643b92f%2Fpackages%2Fhttp%2Fdocs%2Fimages%2Fmock-server-dfd.png" alt="Prism negotiation process"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram is also pretty much reflected in the code as functions division.&lt;/p&gt;

&lt;h3&gt;
  
  
  Input, output and security validation
&lt;/h3&gt;

&lt;p&gt;One of Prism's key features is the extensive validation.&lt;/p&gt;

&lt;p&gt;Based on the provided API Description document, Prism will validate different parts of the incoming HTTP request, ranging from deserialising the body according to the &lt;code&gt;content-type&lt;/code&gt; header and then checking the resulting object with the provided JSON Schema (if any).&lt;/p&gt;

&lt;p&gt;The same goes for the query parameters (because yes, OpenAPI defines encoding for query parameters as well), the headers and ultimately the security requirements.&lt;/p&gt;

&lt;p&gt;The input validation result will influence the behaviour of the negotiator as well as the proxy's one.&lt;/p&gt;

&lt;p&gt;It turns out that validation is a very complicated part of Prism and, although &lt;a href="https://github.com/stoplightio/prism/pull/664" rel="noopener noreferrer"&gt;we&lt;/a&gt; have &lt;a href="https://github.com/stoplightio/prism/pull/731" rel="noopener noreferrer"&gt;reworked&lt;/a&gt; it &lt;a href="https://github.com/stoplightio/prism/pull/862" rel="noopener noreferrer"&gt;several times&lt;/a&gt; we still &lt;a href="https://github.com/stoplightio/prism/issues/1135" rel="noopener noreferrer"&gt;haven't got that right&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prism Request Flow
&lt;/h2&gt;

&lt;p&gt;The journey of an HTTP Request from hitting your application server to return a response to the client is articulated.&lt;/p&gt;

&lt;p&gt;We often do not think about it because the web frameworks do usually a very good job in abstracting away all the complexity.&lt;/p&gt;

&lt;p&gt;Since Prism is not using any frameworks, I fundamentally had the opportunity of reimplementing almost the whole pipeline — and I started to have observations.&lt;/p&gt;

&lt;p&gt;Here's what Prism is doing when a request is coming in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routing

&lt;ul&gt;
&lt;li&gt;Path Match with templating support, where we also extract the variables from the path, returning &lt;code&gt;404&lt;/code&gt; in case it fails&lt;/li&gt;
&lt;li&gt;Method Match, returning &lt;code&gt;405&lt;/code&gt; in case it fails&lt;/li&gt;
&lt;li&gt;Server Validation, which is checking the &lt;code&gt;HOST&lt;/code&gt; header of the request against the servers listed in the specification document, returning &lt;code&gt;404&lt;/code&gt; in case it fails&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Input deserialisation/validation

&lt;ul&gt;
&lt;li&gt;The path parameters get validated according to what is stated in the specification files (whether it's required, whether it's a number or a string) &lt;code&gt;422/400/default&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The query string is deserialised following the rules stated in the specification file, returning &lt;code&gt;422/400/default&lt;/code&gt; in case there is a deserialisation failure&lt;/li&gt;
&lt;li&gt;Headers get validated against the JSON-esque format that OAS2/3 defines; we convert them to a draft7 specification and run &lt;a href="https://github.com/ajv-validator/ajv" rel="noopener noreferrer"&gt;ajv&lt;/a&gt; on it, returning &lt;code&gt;422/400/default&lt;/code&gt; in case there is a validation failure.&lt;/li&gt;
&lt;li&gt;Body gets validated against the JSON-esque format that OAS2/3 defines; we convert it to a draft7 specification and run &lt;code&gt;ajv&lt;/code&gt; on it, returning &lt;code&gt;422/400/default&lt;/code&gt; in case there is a validation failure.&lt;/li&gt;
&lt;li&gt;Depending on the security requirements specified in the routed operation, Prism will check the presence of certain headers and when possible it will also try to validate that their content respects the general format required for such security requirements. Returns &lt;code&gt;401/400/default&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Negotiator/Proxy

&lt;ul&gt;
&lt;li&gt;The negotiator kicks in and looks for an appropriate response definition based on the validation result, the requested content type, the accepted media types and so on. It returns &lt;code&gt;2XX/406/500/User Defined Status code&lt;/code&gt; depending on the found response definition.&lt;/li&gt;
&lt;li&gt;If the Proxy is on, Prism will skip the negotiator and send the result to the upstream server and take note of the returned response.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Output violation and serialisation

&lt;ul&gt;
&lt;li&gt;Response Headers, whether they're generated from a response definition, extracted from an &lt;code&gt;example&lt;/code&gt; or returned from a Proxy request get validated agains the response definition, returning &lt;code&gt;500&lt;/code&gt; (erroring the request or a violation header) in case they do not match&lt;/li&gt;
&lt;li&gt;Response Body, whether it's generated from a response definition, extracted from an &lt;code&gt;example&lt;/code&gt; or returned from a Proxy request, gets validated agains the response definition, returning &lt;code&gt;500&lt;/code&gt; (erroring the request or a violation header) in case they do not match.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;p&gt;Here comes the first key observation: almost &lt;em&gt;every&lt;/em&gt; step that Prism executes might fail, and each failure has a specific semantic meaning and precise status code is associated.&lt;/p&gt;

&lt;p&gt;Last time that I checked, on over 32 "exit paths", 30 of these were errors and only two of them were a "successfully returned response". Doing some math:&lt;/p&gt;

&lt;p&gt;

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;2/32=1/16=0,06
2/32 = 1/16 = 0,06
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2/32&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1/16&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;06&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;This fundamentally says that, in case of evenly distributed exit paths occurrences, only 6% of the request will be successful.&lt;/p&gt;

&lt;p&gt;Are the exit path occurrences evenly distributed? Although I do not have a specific answer to that (but hopefully we will, since we're gathering statistics in the hosted version of Prism) — we have some empirical evidence I’ll talk about in the next paragraph that we can keep in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prism User
&lt;/h2&gt;

&lt;p&gt;Prism is a developer tool and, although it can be used as a runtime component, it is primarily used by API designers and client developers during the development phase of the API.&lt;/p&gt;

&lt;p&gt;This is a very important detail since the typical developer that is using Prism has totally different aims from a regular API developer. The following table summarised some the differences that I've identified with an Application Developer&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Client Application Developer&lt;/th&gt;
&lt;th&gt;API Developer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clear mission in mind&lt;/td&gt;
&lt;td&gt;No idea of what they're doing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Probably read API documentation&lt;/td&gt;
&lt;td&gt;Experimental phase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Likely sending valid data&lt;/td&gt;
&lt;td&gt;Likely sending garbage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aims for success&lt;/td&gt;
&lt;td&gt;Changes code and spec every second&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When you're developing an application, you're likely striving for success — and so you're going to create all the requests you need with likely valid data, likely following the flow indicated in the documentation.&lt;/p&gt;

&lt;p&gt;On the other hand, when mocking an API with Prism, you're deep in the design phase. You'll probably tweak the document multiple times per minute (and Prism will hot-reload the document). You'll likely send invalid data all the time because you just forgot what you wrote in the document. You'll try weird combinations of stuff that is never supposed to happen.&lt;/p&gt;

&lt;p&gt;We stated some paragraphs before that in case of evenly distributed exit path occurrences, only 6% of the request will be successful.&lt;/p&gt;

&lt;p&gt;Now that we have clarified a little bit the typical user of Prism, it's fair to say that the exit paths occurrences are clearly not evenly distributed and, although we can't give a precise number, we can claim that's heavily leaning towards the errors side.&lt;/p&gt;

&lt;p&gt;Essentially, when you send a request to Prism, most likely you'll get an error as a response.&lt;/p&gt;

&lt;p&gt;After thinking a lot about this, I wrote this sentence that was the key factor to radically change Prism's architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prism's job is to return errors.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the next article we'll talk about the abstraction used to model such use cases correctly and how I found it &lt;em&gt;accidentally&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>functional</category>
    </item>
    <item>
      <title>A reviewer's perspective on getting your conference proposal accepted</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Mon, 23 Sep 2019 07:01:45 +0000</pubDate>
      <link>https://dev.to/vncz/a-reviewer-s-perspective-on-getting-your-conference-proposal-accepted-1e6p</link>
      <guid>https://dev.to/vncz/a-reviewer-s-perspective-on-getting-your-conference-proposal-accepted-1e6p</guid>
      <description>&lt;p&gt;This year I've been organising the &lt;a href="https://youtu.be/6NLXKhpv8I8?t=355"&gt;Barcelona instalment of APIdays&lt;/a&gt;, where I’ve touched every aspect; from CFP evaluation, venue selection, catering as well as speakers' travel and accommodations.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/6NLXKhpv8I8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I’ve spoken at 40 events over the last three years. I was rejected  - a lot - a whole lot, and in some cases I really did not understand why. Now that I have been on the other side of the event, I have a better understanding of how things work behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Events get a lot of proposals
&lt;/h2&gt;

&lt;p&gt;APIdays Barcelona had &lt;strong&gt;41&lt;/strong&gt; speakers from multiple countries and backgrounds. We received &lt;strong&gt;184&lt;/strong&gt; CFPs.&lt;/p&gt;

&lt;p&gt;If we remove 20% from the total number because of duplicates and people filling the form with invalid data - that still leaves &lt;strong&gt;148&lt;/strong&gt; CFPs to consider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem: it’s too time consuming to evaluate every proposal in detail
&lt;/h2&gt;

&lt;p&gt;Being involved in almost everything, it turns out that my original intention of going through &lt;strong&gt;all&lt;/strong&gt; of the submissions one by one was not a viable option; it was very time consuming and I still have a full time job; therefore I had to develop a "fast framework" to decide whether a presentation was worth a serious evaluation.&lt;/p&gt;

&lt;p&gt;I ended up checking the following in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Presentation Title&lt;/li&gt;
&lt;li&gt;Presentation Abstract&lt;/li&gt;
&lt;li&gt;A previous video of a speaking engagement&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In case a video was not provided, I would then check&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Company submitter working for&lt;/li&gt;
&lt;li&gt;LinkedIn profile&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Failing any of these steps would mean not being evaluated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson learned: Title and Abstract are the most important filters
&lt;/h3&gt;

&lt;p&gt;No matter what great company you work for or what great previous speaking engagements/videos, GitHub profile or Open Source projects you have on the internet, these were secondary &lt;strong&gt;verifications&lt;/strong&gt; of your persona and get some more context; if the title and or the abstract did not engage the reviewer somehow, the proposal would not make it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I sometimes took the job position in consideration for  one of the  criteria; we'll talk about it more in the &lt;code&gt;Work with speakers&lt;/code&gt; section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem: titles and abstract might be misleading
&lt;/h2&gt;

&lt;p&gt;Selecting a presentation is hard because the only information you really have is the Title and the Abstract; sometimes you might get a recording because the presentation has been given somewhere else and in that case, BINGO! You have almost everything needed to make a good selection.&lt;/p&gt;

&lt;p&gt;Otherwise, you're left with your own judgement.&lt;/p&gt;

&lt;p&gt;My original intention was to get in touch with all the candidates to get a better sense of their proposal, but again, this wasn't a viable option.&lt;/p&gt;

&lt;p&gt;While it should not have been a surprise, I did make some poor choices where I was mislead by the title and the abstract where it sounded like there was going to be good content, only to realise later that I was accepting a sales pitch (or something not relevant).&lt;/p&gt;

&lt;p&gt;On the other hand, I also feel that I missed selecting some very interesting papers because of mediocre descriptions and titles.&lt;/p&gt;

&lt;p&gt;Fortunately several presentations that I had accepted, despite looking like they may not be very good, turned out to be great.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson learned (for the reviewers)
&lt;/h3&gt;

&lt;p&gt;You can't always make the right call. You're going to have failures in your selections, as well as great surprises.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson learned (for the speakers)
&lt;/h3&gt;

&lt;p&gt;You might get away with with a "fake" title and a sales pitch (or also something completely different); but rest assured the reviewers &lt;strong&gt;will remember you&lt;/strong&gt; and you won't likely be able to get away with it a second time.&lt;/p&gt;

&lt;p&gt;Yes, I've got my own list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work with the speakers
&lt;/h2&gt;

&lt;p&gt;There were some presentations where I was like &lt;code&gt;Yes, but…&lt;/code&gt; or also &lt;code&gt;No, but maybe…&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In these cases, I usually felt it was a good idea to get in touch with the speaker to kick off a "secondary" screening.&lt;/p&gt;

&lt;p&gt;The basic idea in this situation was to review who the speaker was working for as well as to check the speakers peers in LinkedIn.&lt;/p&gt;

&lt;p&gt;In case the speaker was working for a known company, like Microsoft, Google, GitHub, or any  that are "known" in the space, it's possible that the speaker could either point you to the right person in their organisation who had a better expertise/experience in the topic you're looking at or &lt;br&gt;
work with you on the proposal to be more in line with the topic.&lt;/p&gt;

&lt;p&gt;The point is that for some companies there's always going to be a good story to tell, if you really look for them.&lt;/p&gt;

&lt;p&gt;For this event I've been able to get very good presentations from some big companies that initially were off of the track; I proactively reached out to them, but more importantly, their willingness to work with me to find a good topic was the key to get them accepted.&lt;/p&gt;

&lt;p&gt;I had the opposite experience as well; some big companies didn't respond at all (even though they sent in a proposal); some wanted to stick with their original presentation no matter what; others indicated they didn't come up with anything interesting.&lt;/p&gt;

&lt;p&gt;Ultimately, we had to reject many of these proposals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson learned
&lt;/h3&gt;

&lt;p&gt;In the unlikely chance that a reviewer reaches out to you, it is usually a good sign that they want to work with you, and as the organizer, after you work on the content a bit can let them in. If you were not serious about your presentation, you might want to start to be from now on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not selected anyway
&lt;/h2&gt;

&lt;p&gt;One thing that surprised me was the amount of proposals that were totally not in line with the conference's main topic, which was (I think/hope) well specified in the CFP form as well as on the website.&lt;/p&gt;

&lt;p&gt;I am aware there are speakers that are submitting presentations in bulk no matter what the general topic is; I also found people submitting presentations with &lt;strong&gt;APIs&lt;/strong&gt; and other buzzwords in the CFPs (see point n.1), but the meat was still not in line with the topic. They tried, I guess.&lt;/p&gt;

&lt;p&gt;Some of these presentations, though, were &lt;strong&gt;really&lt;/strong&gt; good. They were just not a good fit for this specific event and topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Please take time to read what the conference/event is about.
&lt;/h3&gt;

&lt;p&gt;No matter how good your presentation is — if it is not in line with the conference topic you can put whatever buzzword you want, but you won't make it. And if you do for some reason, you're going to be marked as a &lt;code&gt;False Positive&lt;/code&gt; (see the relative section above)&lt;/p&gt;

&lt;h2&gt;
  
  
  Sponsors
&lt;/h2&gt;

&lt;p&gt;This is kind of a delicate topic. Sponsors are an important for every event. They make the conference possible and help keep the tickets prices reasonable; but they will likely expect something back from you, and usually a speaking slot is one of these perks.&lt;/p&gt;

&lt;p&gt;Some of the proposed talks might be good; in that case — &lt;strong&gt;BINGO!&lt;/strong&gt;, go get a beer.&lt;/p&gt;

&lt;p&gt;I also had  sponsors saying to me that being a sponsor didn't really change anything for them and they wanted to go through the "regular" process. I've really appreciated that.&lt;/p&gt;

&lt;p&gt;Unfortunately, chances are that the proposed presentation is something not in line with the conference. In the worst case, you might get a sales pitch.&lt;/p&gt;

&lt;p&gt;In certain cases you might be able to work with the sponsors' speaker and get them back on track and deliver something valuable for the audience. Sometimes they won't change their idea and either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reword the title and the abstract, but still plan to deliver the same content not in line with the conference topic&lt;/li&gt;
&lt;li&gt;Get a "NO" response from the sponsor - as in "This is what I have, and this is what I will deliver"&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Lesson learned (for the reviewers)
&lt;/h3&gt;

&lt;p&gt;There's nothing really you can do about this. You're going to get criticised anyway. The audience will usually not understand the situation and will send you emails letting you know when a presentation is not in alignment with their expectations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson learned (for the sponsors)
&lt;/h3&gt;

&lt;p&gt;You might be in a position to force your content onto the organizer; be aware that both the audience and likely the reviewers/organizers will not really like this approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timing is important
&lt;/h2&gt;

&lt;p&gt;Since the inception of the conference (10 months ago), I had a clear idea of what the event should all be about. I had 4 main tracks in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stories from the transportation industry&lt;/li&gt;
&lt;li&gt;APIs for B2B Applications&lt;/li&gt;
&lt;li&gt;APIs for B2C Applications&lt;/li&gt;
&lt;li&gt;APIs in Public Sector&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As time passes and the CFPs are coming and coming, you will periodically review them and start sending notifications to your speakers, slowly filling the slots.&lt;/p&gt;

&lt;p&gt;At a certain point, I realised that while I had some of the tracks pretty well covered, others were almost empty. For this reason, I had to change the strategy and give priority to empty tracks during the selection process.&lt;/p&gt;

&lt;p&gt;Although the review process was almost the same, presentations in topic but not in the track that I wanted to fill were put on hold. Some of them were ultimately not selected even though their content was very good.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson learned
&lt;/h3&gt;

&lt;p&gt;Submit your proposal as soon as possible. The more empty spaces there are, the greater the chance you will be selected.&lt;/p&gt;

</description>
      <category>techtalks</category>
      <category>conference</category>
      <category>organising</category>
    </item>
    <item>
      <title>Security in your OpenAPI Specification</title>
      <dc:creator>Vincenzo Chianese</dc:creator>
      <pubDate>Thu, 14 Feb 2019 12:34:25 +0000</pubDate>
      <link>https://dev.to/vncz/security-in-your-openapi-specification-422g</link>
      <guid>https://dev.to/vncz/security-in-your-openapi-specification-422g</guid>
      <description>&lt;h2&gt;
  
  
  Importance of Security during the API Design Phase
&lt;/h2&gt;

&lt;p&gt;It is no longer a mystery, APIs are eating the world. There are a lot of companies today that are offering their APIs as the primary medium to interact with a system, with the User Interface merely as a byproduct, or, in any case, not the primary product being sold. Companies such as Stripe and Twilio led the vanguard of this movement in 2012.&lt;/p&gt;

&lt;p&gt;Given this shift (which, by the way, is still happening), APIs have started to get more and more complicated, and so the API development process needed to evolve as well. APIs have become a product, therefore all the typical team members and methodologies have been employed to make that product successful.&lt;/p&gt;

&lt;p&gt;The increase in relevance of API based products requires new tooling to support the people and methodologies used to implement the product. How would you design an API so that you can review and iterate on the design before building it for real? When designing a mobile application, you have tools to easily create a mockup to make sure everybody in your organization is on the same page before committing your resources on creating the real app.&lt;/p&gt;

&lt;p&gt;For years, this wasn’t a thing for APIs. Until the OpenAPI Specification (and a bunch of other standards) came out.&lt;/p&gt;

&lt;p&gt;In this article, we’ll review what OpenAPI can offer from a security standpoint, how you can embrace these features today, and showcase some companies that are doing really cool stuff in this space!&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAPI History: What, Why, When
&lt;/h2&gt;

&lt;p&gt;OpenAPI — formerly known as Swagger — started out as a simple, open source specification for designing RESTful APIs in 2010 and, despite other API Specifications formats that came out during the following years (such as RAML and APIBlueprint), the Swagger project became the most popular one.&lt;/p&gt;

&lt;p&gt;In 2015, the Swagger project was donated to the Linux Foundation and renamed to OpenAPI Specification, with Microsoft and IBM joining the foundation to help move the format forward. Their first release was OpenAPI 2.0 ,which is nothing more than the original Swagger format rebranded; and then a couple of years later, OpenAPI 3.0 was released with some important updates.&lt;/p&gt;

&lt;p&gt;Today the OpenAPI initiative includes more than 10 companies that recognize the high value and importance of joining efforts to produce a standardized document to describe an API.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAPI 2.0
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Format overview
&lt;/h3&gt;

&lt;p&gt;OpenAPI 2.0 is nothing more than the good old Swagger format, rebranded after the donation to the Linux Foundation.&lt;/p&gt;

&lt;p&gt;OpenAPI 2.0 documents can be written both as a JSON or a YAML file, and they allow you to define how your exposed API looks like in terms of endpoints, accepted and returned payloads, media types, returned status codes, and servers where the API can be reached.&lt;/p&gt;

&lt;p&gt;We aren’t going to look at all these parts here. Instead, we will focus on the security features that the specification offers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Features of OpenAPI 2.0
&lt;/h3&gt;

&lt;p&gt;OpenAPI 2.0 offers a dedicated section to declare the security features and requirements of your API and then use these where appropriate in your paths and operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apiKey&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api_key&lt;/span&gt;
  &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;header&lt;/span&gt;
&lt;span class="na"&gt;petstore_auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oauth2&lt;/span&gt;
  &lt;span class="na"&gt;authorizationUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://swagger.io/api/oauth/dialog&lt;/span&gt;
  &lt;span class="na"&gt;flow&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;implicit&lt;/span&gt;
  &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;write:pets: modify pets in your account&lt;/span&gt;
    &lt;span class="s"&gt;read:pets: read your pets&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example we’ve declared 2 security definitions: the first one will be looking for an API Key in the specified header (api_key in this case), while the second one is declaring an implicit oAuth2 flow, requiring some particular scopes.&lt;/p&gt;

&lt;p&gt;OpenAPI 2.0 supports another security definition type called basic , which is fundamentally the old plain HTTP Authentication format.&lt;/p&gt;

&lt;p&gt;OpenAPI 2.0 does not have other built-in security definitions and it’s not possible to define custom ones without using vendor-provided extensions. While these three options cover a good chunk of real-world use cases, they might not be enough for special cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAPI 3.0
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Format overview and improvements over OpenAPI 2.0
&lt;/h3&gt;

&lt;p&gt;OpenAPI 3.0 was released in 2017 with the intention of addressing some of the drawbacks and limitations version 2.0 was suffering from.&lt;/p&gt;

&lt;p&gt;We are not going to focus on the OpenAPI 3.0 Specification and highlight all the differences between the two formats: there are plenty of links out on the internet detailing the changes. Instead, we are going to focus on the security changes that have been introduced in this new version of the specification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Features of OpenAPI 3.0
&lt;/h3&gt;

&lt;p&gt;In the same way OpenAPI 2.0 has a dedicated part of the document to declare security definitions, OpenAPI 3.0 has one too. The difference is that OpenAPI 3.0 has changed the terminology to "security schemes." The spec also standardized the way to declare all the parts of the spec that can be reused across multiple paths. While previously the shared components was something left to the common sense of the developers, now they are all grouped under the components key.&lt;/p&gt;

&lt;p&gt;Moreover, OpenID Connect support has been added as well as the ability for a security definition to include multiple oAuth2 flows (which is a common functionality used around, today).&lt;/p&gt;

&lt;p&gt;To give an idea of how the Security declaration have changed from OAS2.0 to OAS 3.0, this is the same example we mentioned before, wrote for OAS3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;securitySchemes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apiKey&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api_key&lt;/span&gt;
    &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;header&lt;/span&gt;
  &lt;span class="na"&gt;petstore_auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oauth2&lt;/span&gt;
    &lt;span class="na"&gt;flows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;implicit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;authorizationUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://swagger.io/api/oauth/dialog&lt;/span&gt;
        &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="s"&gt;write:pets: modify pets in your account&lt;/span&gt;
          &lt;span class="s"&gt;read:pets: read your pets&lt;/span&gt;
      &lt;span class="na"&gt;authorizationCode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;authorizationUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://swagger.io/api/oauth/dialog&lt;/span&gt;
        &lt;span class="na"&gt;tokenUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://swagger.io/api/oauth/token&lt;/span&gt;
        &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="s"&gt;read:pets: Grants read access&lt;/span&gt;
          &lt;span class="s"&gt;write:pets: Grants write access&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that now the oAuth2 definition supports multiple flows, defined by a new key in the security section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On: Designing a Secure API
&lt;/h2&gt;

&lt;p&gt;Let’s now go hands-on and try to create a document representing an API that’ll be exposed on the public internet. We will go through the design phase — as well as the implementation code and contract testing for it.&lt;/p&gt;

&lt;p&gt;As most of the tooling around OpenAPI is still sticking with the 2.0 version, that is the version we are going to use. However, all the concepts we will be showing here today are still valid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an OpenAPI Specification
&lt;/h3&gt;

&lt;p&gt;OpenAPI specification documents are nothing more than YAML or JSON files. Although this is effectively lowering the barrier for new folks willing to write docs (everybody can write a JSON or a YAML document) this hides the complexity of the specification itself. This is where a visual designer or other tools can really be handy.&lt;/p&gt;

&lt;p&gt;There are plenty of these on the market; namely &lt;a href="https://stoplight.io"&gt;Stoplight&lt;/a&gt;, &lt;a href="https://apiary.io"&gt;Apiary&lt;/a&gt;, &lt;a href="https://swagger.io/tools/swaggerhub/"&gt;SwaggerHub&lt;/a&gt;. The decision of which one to choose is really up to you and your needs. In any case, all of them offer a free plan so you do not have to pay to get started.&lt;/p&gt;

&lt;p&gt;We are going to write nothing more than a simple API that is a trimmed version of the well known example of the PetStore. This API is part of the official examples in both &lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/petstore.yaml"&gt;OAS2&lt;/a&gt;.0 and &lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore.yaml"&gt;3.0&lt;/a&gt;. I’ve chosen this one because of the simplicity of the content itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write the code
&lt;/h3&gt;

&lt;p&gt;Writing the code, in the world of APIs, is really the most trivial part. Building an API is more a conceptual work and a collaboration effort rather than committing stuff on your repository.&lt;/p&gt;

&lt;p&gt;For this reason, we will stick to a very basic example, whose code is hosted on &lt;a href="https://glitch.com/edit/#!/petstore-backend"&gt;Glitch&lt;/a&gt;. For those who do not know it, Glitch is a free hosted service for NodeJS applications. It’s perfect for prototyping and shipping small applications in a very fast way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing your API
&lt;/h3&gt;

&lt;p&gt;Now what we really want to do is keep checking, as you’re developing the server, that the implementation we just wrote is in sync with the specification document we have in our repository. This is where the contract testing tools come into the play; they spin up an instance of your server and, by going through the OpenAPI document, they send HTTP requests to your servers which check the status codes as well as returned payload. If any of these do not match, it will make the CI/CD step fail, and the API will not be deployed. You can also see this as TDD development, where you initially have just an OpenAPI document with all tests failing because you do not have any code.&lt;/p&gt;

&lt;p&gt;As you’re developing the API and adding more and more endpoint, you will start seeing more parts of the tests pass until you’re on green (which means you covered the entire API surface declared in the OpenAPI Document).&lt;/p&gt;

&lt;p&gt;In the example we just did, I decided to go with &lt;a href="https://github.com/stoplightio/prism"&gt;Prism&lt;/a&gt; but &lt;a href="https://dredd.com/en/latest"&gt;Dredd&lt;/a&gt; is another one you can use. They both support OpenAPI 2.0, but unfortunately none of these support OpenAPI 3.0 (yet).&lt;/p&gt;

&lt;p&gt;The setup for these tools is usually straightforward and does not require any particular effort.&lt;/p&gt;

&lt;p&gt;The first thing we’re going to do is to download the Prism server on the machine:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -L https://github.com/stoplightio/prism/releases/download/v2.0.16/prism_linux_amd64 -o prism &amp;amp;&amp;amp; chmod +x ./prism&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once done, we need to start our application server locally and then run Prism providing the listening URL to send the requests to and the OpenAPI document to use as a source of truth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
npm start
prism conduct ./sl/tests.scenarios.yml &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:&lt;span class="nv"&gt;$PORT&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Prism will now read the OpenAPI specification files, go through all the paths and start crafting HTTP Requests following the provided examples or creating payloads using the JSON Schema as a reference and send them to your application server. Once the response comes, Prism will verify the status code as well as that the response’s shape matches the declared one. If any of these do not match, the server will report and error and mark the test as a failure.&lt;/p&gt;

&lt;p&gt;Note: these commands should be suitable in a CI/CD environment as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrate your OpenAPI Security Specification in Auth0
&lt;/h3&gt;

&lt;p&gt;Now that we have an API whose design specification matches the implementation, it’s time to deploy it. Most likely we want to protect the API, and Auth0 is clearly one of the choices.&lt;/p&gt;

&lt;p&gt;Not all the flows are currently supported by Auth0. Here’s a breakdown of the situation currently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;oAuth2&lt;/strong&gt;: all the flows are supported and is the recommended way to deal with authentication/authorization in general. It is also possible to emit JSON based tokens instead of opaque ones, enabling other scenarios (such as passing the token around web apps)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;openIdConnect&lt;/strong&gt;: supported by Auth0 with all the standard claims&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;basic/http&lt;/strong&gt;: supported as a particular type of oAuth 2.0 flow. Any client that has a client password might send this using the HTTP Basic Authentication Scheme. To be fair, this is rather a way to send the client password rather than full support for the scheme; as you won’t get any prompt on your browser while trying to hit the target path&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;apiKey&lt;/strong&gt;: Not supported. This is not formalized in any standard per se — but it is a common way to send a preshared credential on the wire. The nearest authentication method that resembles the presence of an API Key is to use a Client Credential Grant Request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see that, as long you’re using oAuth2.0 or openIdConnect, there’s nothing to worry about. You might get in trouble in case you want to stick with some "older" methods, which can be emulated to a certain degree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime integration
&lt;/h2&gt;

&lt;p&gt;At this stage, &lt;a href="https://glitch.com/edit/#!/petstore-backend"&gt;we have a backend server implementing our API and an Identity Provider&lt;/a&gt; (in this case Auth0) that is storing all our users and providing the necessary infrastructure to authenticate and authorize them in our platform. We are missing the glue between the two pieces: how can an user willing to authenticate in my application get redirected to Auth0’s services?&lt;/p&gt;

&lt;p&gt;You can do that in your application code, but in that case it’s no more declarative and a change in  your OpenAPI document regarding the security requirements will require a change in your code too.&lt;/p&gt;

&lt;p&gt;There’s a possibility to automate this stage with the help of an API Gateway. Given this piece of software is usually configured in an declarative manner and the fact that most of the time your OpenAPI document matches the exposed API, there’s almost a perfect match between the spec and the API Gateway configuration. Unfortunately, as of today, none of the Gateways on the market have reached such level of integration.&lt;/p&gt;

&lt;p&gt;For people that are interested in this topic, I gave a presentation last December whose &lt;a href="http://youtube.com/watch?v=_bt1r_SHfaU"&gt;video is published online&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We have gone through the security features that are part of OpenAPI 2.0 and 3.0 specifications, and they can help the API users and developers clearly set expectations when consuming and building an API. Then we went a little bit into the API lifecycle and, as you probably noticed, it’s more about communication, being on the same page, and about what you want to expose rather than simply writing the code. That’s just a single step in the whole process. In the end, we explored the opportunities of a runtime integration with an Identity Provider, which is not there yet.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
