<?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: Federico Sordillo</title>
    <description>The latest articles on DEV Community by Federico Sordillo (@fes300).</description>
    <link>https://dev.to/fes300</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%2F72899%2F0f1ae76c-89f4-4b08-b9a4-35519d979c70.jpeg</url>
      <title>DEV Community: Federico Sordillo</title>
      <link>https://dev.to/fes300</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fes300"/>
    <language>en</language>
    <item>
      <title>Effective communication between services (and people)</title>
      <dc:creator>Federico Sordillo</dc:creator>
      <pubDate>Tue, 24 Aug 2021 08:54:39 +0000</pubDate>
      <link>https://dev.to/fes300/effective-communication-between-services-and-people-2bal</link>
      <guid>https://dev.to/fes300/effective-communication-between-services-and-people-2bal</guid>
      <description>&lt;p&gt;As programmers we known full well that code without side-effects is both perfect and perfectly useless, which should be enough to convince you of how important communication and boundaries (or I/O, using software jargon) are.&lt;/p&gt;

&lt;p&gt;But they are not just important, they are ubiquitous: there is a boundary between databases and servers, a boundary between servers and clients, a boundary between clients and the final user, but also boundaries between servers and servers, between clients and third-party softwares, and the list goes on..&lt;/p&gt;

&lt;p&gt;At the end of the road, any software we can think of is just implementation detail over the mapping it creates between its domain and codomain.&lt;/p&gt;

&lt;p&gt;If that wasn't enough, with the rising of micro-services the problem of communication has become even more apparent as there is an ever increasing number of actors and communications to juggle.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Communication is facing the same scaling problems that it was trying to solve in the first place.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But what is a communication? How can we achieve success when communicating? &lt;/p&gt;

&lt;p&gt;I argue that you need two things (plus an additional one that I will mention at the end):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;a shared format&lt;/strong&gt;: in software engineering this is usually represented by a protocol like &lt;code&gt;HTTP&lt;/code&gt; or &lt;code&gt;SOAP&lt;/code&gt;, in verbal communication it is sound.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;a shared meaning&lt;/strong&gt;: in verbal communication it is created by validating decoded input against a more or less shared "common sense" while in software engineering it usually corresponds to input parsing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Shared format
&lt;/h2&gt;

&lt;p&gt;As applications are loosely coupled, there is no guarantee that the same context will apply to both ends of the communication, which is why you usually have to translate your communication using a &lt;em&gt;"shared format"&lt;/em&gt; to make sure that what is being sent can be identified as communication by the receiving party.&lt;/p&gt;

&lt;p&gt;When a communication takes place four things happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The sender "serializes" a communication intent into the shared format.&lt;/li&gt;
&lt;li&gt;the sender then sends the communication.&lt;/li&gt;
&lt;li&gt;The receiver receives the communication.&lt;/li&gt;
&lt;li&gt;The receiver "deserialize" the communication using the same shared format used by the sender, then process it accordingly. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Summarizing, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 actors talking in their own dialects&lt;/li&gt;
&lt;li&gt;1 shared communication protocol&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that is all apparently. Except it is not.&lt;/p&gt;

&lt;p&gt;Agreeing on a protocol and knowing how to translate to/from such shared protocol is in fact not enough to guarantee a communication is taking place: it only guarantees the syntactical correctness of the content but there are still zero guarantees about its contextual coherence and its "purpose".&lt;/p&gt;

&lt;p&gt;As an example, is this a conversation?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Person_A&lt;/strong&gt;: "hi person_B! How are you? Everything fine?"&lt;br&gt;
&lt;strong&gt;Person_B&lt;/strong&gt;: "I own five dogs"&lt;/p&gt;

&lt;p&gt;Sure both persons were able to "decode" each other's sentences, but I have difficulties marking it as a "successful conversation"... Person_A was probably able to "deserialize" the message sent by Person_B but it doesn't make any sense.. It could mean that life is a blessing because he/she is enjoying the company of five (five!) dogs or it could mean that he/she is on the verge of death because Person_B is very allergic to dogs fur.&lt;/p&gt;

&lt;p&gt;There is likely a context missing or a a problem with how Person_B communicate "meaning".&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared meaning
&lt;/h2&gt;

&lt;p&gt;There is indeed another level of abstraction that we have to secure to deem our conversation successful: &lt;strong&gt;we have to agree on a set of intelligible communication intents&lt;/strong&gt;. In other words, we have to make sure that the receiver can interpret the messages forwarded by the sender in a meaningful way and viceversa.&lt;/p&gt;

&lt;p&gt;How do we do it? Well, in human interactions we (usually) have a second "shared asset" other than the communication protocol which is &lt;strong&gt;common sense&lt;/strong&gt;: both the sender and the receiver just assume that they both have the "common-sense" resource available and validate communications against it.&lt;br&gt;
Nonetheless, this is not a perfect guarantee that the conversation will be successful: if the versions of "common-sense" held by the two actors differ in substantial ways the conversation intent will be lost in translation. &lt;/p&gt;

&lt;p&gt;Software development is a whole other story. We have to deal with extremely limited resources compared to our brains and even if someone ever succeded in encoding a digital "common sense" (something very far from happening, if ever so) we would still not have a guarantee that our softwares are able to communicate effectively.&lt;/p&gt;

&lt;p&gt;The poor man solution to this dilemma is to always encode all valid communication intents and validate every deserialized content against it. If we can decipher the communication intent it is all good, otherwise the best thing we can do is to &lt;strong&gt;fail fast&lt;/strong&gt;, break everything (maybe with a gracious error message) and wait for someone to fix it.  &lt;/p&gt;

&lt;p&gt;In real life the set of valid communication intents is huge, but in software development it is usually much smaller, often just a singleton set, so this encoding effort, albeit sometimes expensive, is at least doable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ergonomicity
&lt;/h2&gt;

&lt;p&gt;That would be all if it wasn't for one last thing that we always do (usually going unnoticed in human communication), which is the &lt;strong&gt;translation from the sender dialect to the receiver dialect&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When we talk with someone we always unconsciously map the content of its communication intent to the set of our own internal meanings before analyzing it and creating our response. This is particularly evident when we talk with someone in a different language: we receive a communication that we are able to &lt;em&gt;deserialize&lt;/em&gt; through our shared format (sound), &lt;strong&gt;validate&lt;/strong&gt; through our shared meaning (common sense) then, before processing it and continue the conversation with a response that we deem reasonable, we &lt;strong&gt;parse&lt;/strong&gt; it to translate to our own language.&lt;/p&gt;

&lt;p&gt;This parsing phase is merely for the sake of ergonomics: we already known that the message is well-formatted and make sense but we transform it into something that our brain can handle faster and better in order to "smoothen the gears".&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Each of the three steps depicted are of fundamental importance for a conversation to be successful, yet, especially in software using dynamic languages like JavaScript or PHP, one or more of these steps is  often overlooked or even skipped altogether.&lt;/p&gt;

&lt;p&gt;My passionate suggestion is to never try to skip the un-skippable, there are tons of great libraries that helps you not only validating but parsing your payloads like &lt;a href="https://github.com/gcanti/io-ts"&gt;io-ts&lt;/a&gt; or &lt;a href="https://github.com/jquense/yup"&gt;yup&lt;/a&gt; (if you are not willing to give functional programming a try :)) &lt;/p&gt;

</description>
      <category>typescript</category>
      <category>iots</category>
      <category>software</category>
    </item>
    <item>
      <title>Refactoring absolute paths to relative ones</title>
      <dc:creator>Federico Sordillo</dc:creator>
      <pubDate>Mon, 29 Jun 2020 10:03:36 +0000</pubDate>
      <link>https://dev.to/fes300/refactoring-absolute-paths-to-relative-ones-in-vscode-3iaj</link>
      <guid>https://dev.to/fes300/refactoring-absolute-paths-to-relative-ones-in-vscode-3iaj</guid>
      <description>&lt;p&gt;This is hardly a post, more like simple advice to anyone willing to move his/her codebase to relative paths.&lt;/p&gt;

&lt;p&gt;I came to despise magic paths as I believe they solve no problem and usually introduce several non-trivial compilation bugs as soon as you move things around a little.&lt;/p&gt;

&lt;p&gt;I did this kind of refactoring several times in the past and noticed that often people just go brute force at the problem, rewriting all the absolute paths one by one and wasting hours of their time.&lt;/p&gt;

&lt;p&gt;A simple way to critically reduce the time spent on the task is to use VSCode regexp pattern matching to only target files located at a specific depth level. Assuming you have a magic path pointing to your &lt;code&gt;components&lt;/code&gt; folder and a project structure like this:&lt;/p&gt;

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

...
├── package.json
└── src
    └── components


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

&lt;/div&gt;

&lt;p&gt;You can refactor it by a simple find and replace:&lt;br&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%2Foakcsc2dmgwkm0ad8ak4.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%2Foakcsc2dmgwkm0ad8ak4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then you just go recursively:&lt;br&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%2F7vjd6l3v23fqnaapi68q.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%2F7vjd6l3v23fqnaapi68q.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope this will save someone some minutes :)&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>refactoring</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What should and shouldn't be handled with Reader</title>
      <dc:creator>Federico Sordillo</dc:creator>
      <pubDate>Mon, 24 Feb 2020 10:45:54 +0000</pubDate>
      <link>https://dev.to/fes300/what-should-and-what-shouldn-t-be-handled-with-reader-iib</link>
      <guid>https://dev.to/fes300/what-should-and-what-shouldn-t-be-handled-with-reader-iib</guid>
      <description>&lt;p&gt;Recently I had the chance to discuss with a colleague (friend?) of mine about the Reader monad and why all the examples found in literature seem to always be about implicitly threading a &lt;code&gt;Config&lt;/code&gt; object through your application.&lt;/p&gt;

&lt;p&gt;I was frustrated to see every article resort to the same old example and felt there would surely be dozens of other use cases where you could fruitfully put &lt;code&gt;Reader&lt;/code&gt; to use. This frustration led me to a few thoughts that I want to share with everyone in the hope that it may be helpful to other people naively approaching the subject (as I was).&lt;/p&gt;

&lt;p&gt;First of all a little intro: the Reader monad in &lt;code&gt;fp-ts: 2.0&lt;/code&gt; is nothing else than an alias of  the function profunctor,  its signature is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Reader&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="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;In fact, this very simple (and powerful) structure allows us to define not only profunctor instances for it but also monadic ones! So feel free to chain on it like there's no tomorrow.&lt;/p&gt;

&lt;p&gt;The way this abstraction is usually put into use in codebases is by creating a context that can be accessed at any level of your application without the need to thread it to all the places where it needs to be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/index.ts&lt;/span&gt;
&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="na"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;threads&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="na"&gt;dbHost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&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;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="c1"&gt;// src/repository/entities/arbitraryNesting/../index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ask&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fp-ts/lib/Reader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dbHost&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&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;C&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;so what I was thinking is: why just configuration? Why don't we use &lt;code&gt;Reader&lt;/code&gt; every time there is unnecessary chaining of parameters?&lt;/p&gt;

&lt;p&gt;In this example (from which I stripped everything not strictly related to the point I am trying to make) I only pass &lt;code&gt;roles&lt;/code&gt; to the function &lt;code&gt;getDocsByRoles&lt;/code&gt; and &lt;code&gt;filter&lt;/code&gt; is retrieved autonomously by &lt;code&gt;getDocsByRole&lt;/code&gt; from the Reader context, thus avoiding defining it explicitly on &lt;code&gt;getDocsByRoles&lt;/code&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Reader&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/lib/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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;array&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/lib/Array&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;getDocsByRole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;any&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getDocsByRoles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;any&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="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&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;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getDocsByRole&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;reader&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;docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fancyTransformation&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;getUserDocs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DocsRequest&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;roles&lt;/span&gt; &lt;span class="o"&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;filter&lt;/span&gt; &lt;span class="o"&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;getDocsByRoles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roles&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What I did in this example may look right but there is fundamental (and subtle IMHO) flaw: while we gained a little in conciseness by avoiding to chain down the &lt;code&gt;filter&lt;/code&gt; parameter, we lost a lot in terms of readability of the API. In fact, there would be no working implementation of &lt;code&gt;getDocsByRoles&lt;/code&gt; without a &lt;code&gt;filter&lt;/code&gt; and its return value strictly depends on it: &lt;strong&gt;although the function does not use it, it is a fundamental part of its ergonomics&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This, in my opinion, is the reason why all the &lt;code&gt;Reader&lt;/code&gt; examples you see around are ones involving App configuration and global contexts.&lt;/p&gt;

&lt;p&gt;While db location, secrets, and even i18n are usually details of an app that can be safely hidden from the surface of your internal APIs, other runtime values are usually strictly tied to the behavior of your implementations and, therefore, should not be hidden. It is a matter of ergonomics.    &lt;/p&gt;

</description>
      <category>reader</category>
      <category>monad</category>
      <category>fpts</category>
    </item>
  </channel>
</rss>
