<?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: Jack</title>
    <description>The latest articles on DEV Community by Jack (@jackmellis).</description>
    <link>https://dev.to/jackmellis</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%2F541796%2F6be695af-3980-4f4e-bb30-d4123200a47a.png</url>
      <title>DEV Community: Jack</title>
      <link>https://dev.to/jackmellis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jackmellis"/>
    <language>en</language>
    <item>
      <title>Dependency sandboxing in node.js with Jpex</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Tue, 06 Jul 2021 21:56:20 +0000</pubDate>
      <link>https://dev.to/jackmellis/dependency-sandboxing-in-node-js-with-jpex-3mbi</link>
      <guid>https://dev.to/jackmellis/dependency-sandboxing-in-node-js-with-jpex-3mbi</guid>
      <description>&lt;h2&gt;
  
  
  React recap
&lt;/h2&gt;

&lt;p&gt;Okay so I've written about &lt;a href="https://www.npmjs.com/package/jpex"&gt;jpex&lt;/a&gt; a few times, particularly &lt;a href="https://dev.to/jackmellis/dependency-injection-in-react-with-jpex-178l"&gt;in relation to react&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essentially it allows you to do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;useResolve&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;react-jpex&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;useMyDep&lt;/span&gt; &lt;span class="o"&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;dep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useResolve&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDep&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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 this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;encase&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;react-jpex&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;useMyDep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;encase&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IDep&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="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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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;depending on your preferred flavour.&lt;/p&gt;

&lt;p&gt;Jpex uses the service locator pattern to resolve and inject dependencies, plus it's super-powered by Typescript inference for a super slick experience. But the really &lt;em&gt;really&lt;/em&gt; cool thing about it is you can test your react components with the provider component to stub your dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;
  &lt;span class="na"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jpex&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;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDep&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;mockValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// everything rendered inside this provider will use the mock value&lt;/span&gt;
    &lt;span class="c1"&gt;// everything outside of the provider will use the "real" value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentUnderTest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using jpex with node.js
&lt;/h2&gt;

&lt;p&gt;However, we're talking about node.js right now, not react. How does jpex work with node? Well at first glance it's pretty similar to the front end:&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="nx"&gt;jpex&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;jpex&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;getMyDep&lt;/span&gt; &lt;span class="o"&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;dep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDep&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;jpex&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;jpex&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;getMyDep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encase&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IDep&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="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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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;Easy right? The problem is that it's then quite hard to create a "sandboxed" environment. How do you call these functions with mocked values?&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: mocking at the test level
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;returns some value&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="nx"&gt;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDep&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;mockValue&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getMyDep&lt;/span&gt;&lt;span class="p"&gt;();&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;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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 method can be problematic because you're registering a test mock on the &lt;code&gt;global&lt;/code&gt; instance. It will then be used as the resolved value for &lt;code&gt;IDep&lt;/code&gt; everywhere in the file, unless you register it again in the next test. This sort of leaky test is a bad idea and will almost definitely cause bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: only using encase
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;returns some value&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getMyDep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encased&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockValue&lt;/span&gt;&lt;span class="p"&gt;)();&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;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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;&lt;code&gt;encase&lt;/code&gt; actually exposes the factory function so you can manually pass in your dependencies, which means you can test it safely like this. This works well for &lt;em&gt;some&lt;/em&gt; cases. But what if your function is called by another 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;someOtherFn&lt;/span&gt; &lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;getMyDep&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 you cannot test &lt;code&gt;someOtherFn&lt;/code&gt; without &lt;code&gt;getMyDep&lt;/code&gt; attempting to resolve its dependencies!&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3: the composite pattern
&lt;/h3&gt;

&lt;p&gt;Another pattern for dependency injection is the composite pattern. Essentially your entire application is made up of factory functions that must compose at app start. In this case you'd be passing the &lt;code&gt;jpex&lt;/code&gt; object through your composite chain like this:&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="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jpex&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getMyDep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encase&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IDep&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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'm not keen on this myself, it kinda defeats the point of a service locator!&lt;/p&gt;

&lt;p&gt;So if you can't actually &lt;em&gt;invert the control&lt;/em&gt; of your dependencies, is jpex just useless in node applications? Yes... until now!&lt;/p&gt;

&lt;h2&gt;
  
  
  A more robust solution to DI and testing
&lt;/h2&gt;

&lt;p&gt;I have just published a new library: &lt;a href="https://www.npmjs.com/package/@jpex-js/node"&gt;&lt;code&gt;@jpex-js/node&lt;/code&gt;&lt;/a&gt;. You use it like this:&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="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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@jpex-js/node&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;getMyDep&lt;/span&gt; &lt;span class="o"&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;dep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDep&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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight 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;encase&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;@jpex-js/node&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;getMyDep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;encase&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IDep&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="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;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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;Looks familiar right? It's essentially the same syntax as &lt;code&gt;jpex&lt;/code&gt; and &lt;code&gt;react-jpex&lt;/code&gt; so far, and works exactly the same. The magic starts to happen when you want to sandbox and stub your dependencies...&lt;/p&gt;

&lt;p&gt;The library exports a &lt;code&gt;provide&lt;/code&gt; function. What this does is creates a new instance and then every &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;encase&lt;/code&gt; call within is contextualised to this new instance. You can think of it as an equivalent to the &lt;code&gt;&amp;lt;Provider&amp;gt;&lt;/code&gt; component in &lt;code&gt;react-jpex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we attempt to write the same test as earier it might look like this:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provide&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;@jpex-js/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;returns some value&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;jpex&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;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDep&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;mockValue&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;getMyDep&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&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;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someValue&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;Regardless of whether this function used &lt;code&gt;resolve&lt;/code&gt; or &lt;code&gt;encase&lt;/code&gt;, we're able to control the dependencies it receives!&lt;/p&gt;

&lt;h2&gt;
  
  
  One more thing
&lt;/h2&gt;

&lt;p&gt;If the idea of a sandboxed DI context in which to run your tests seems cool, I should also point out that this supports asynchronous call stacks as well. Any promsies, callbacks, or timeouts, are kept within the same context:&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;provide&lt;/span&gt;&lt;span class="p"&gt;(&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;jpex&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;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDep&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;mockValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;waitFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;setTimeout&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;getMyDep&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// still retains the context&lt;/span&gt;
    &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;As the author of jpex I am definitely biased but I am a big proponant of making dependency injection a core part of javascript development, but also a slick developer experience. I've been using jpex in react applications for a few years now and I love it. And now with this library, we should be able to bring the same patterns and ease of testing to node applications as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Behind the scenes we're using node's new &lt;code&gt;async_hooks&lt;/code&gt; module and the &lt;code&gt;AsyncLocalStorage&lt;/code&gt; class. It's a really powerful concept for creating and managing contexts and there is so much potential for awesome uses of it!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>typescript</category>
      <category>node</category>
      <category>di</category>
      <category>news</category>
    </item>
    <item>
      <title>Why I'm not using Next.js</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Mon, 05 Jul 2021 15:27:09 +0000</pubDate>
      <link>https://dev.to/jackmellis/why-i-m-not-using-next-js-208n</link>
      <guid>https://dev.to/jackmellis/why-i-m-not-using-next-js-208n</guid>
      <description>&lt;p&gt;So I'm building an application. Not only am I using react, but I'm also using node. Surely I'm using next.js right? I mean, every other article I see seems to be a next.js tutorial, it's so &lt;strong&gt;in&lt;/strong&gt; right now. Well no, I'm not using it for my project.&lt;/p&gt;

&lt;h2&gt;
  
  
  n.b.
&lt;/h2&gt;

&lt;p&gt;This isn't just a next.js diss. A lot of people swear by it after all! I just wanted to write down my personal thought process for not adopting it.&lt;/p&gt;

&lt;p&gt;I really struggled to find a decent pros and cons list for using it, just pros. There are definitely downsides, frustrations, and compromises if you pick next.js. I just don't feel like anybody talks about them.&lt;/p&gt;

&lt;p&gt;On to business:&lt;/p&gt;

&lt;h2&gt;
  
  
  Super opinionated / abstracted
&lt;/h2&gt;

&lt;p&gt;There's nothing wrong with opinionated stuff per se. But the problem is in the javascript ecosystem we don't really have any standards or best practices for &lt;em&gt;anything&lt;/em&gt;. There are 100 ways to do &lt;em&gt;everything&lt;/em&gt;. Want classes and OOP? Sure! Want a strictly FP app? Go for it! Want to separate your concerns and heavily modularise your application? Why not! Want to just mash everything into a monolithic gross swiss army knife component? I mean... I suppose...&lt;/p&gt;

&lt;p&gt;This isn't like making an opinionated framework in an already-opinionated language like, say C#. If you try to make an opinionated framework in javascript, you're not saying "this follows and enforces the best practices of the language", you're saying "my way or the highway!"&lt;/p&gt;

&lt;p&gt;This first point is basically relevant to every other point in this piece so I won't spend any longer on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Webpack
&lt;/h2&gt;

&lt;p&gt;Oh man I'm only just starting to move away from webpack and now this framework is forcing me to use it! Not only is it forcing me to use it, but it's doing its best to stop me from configuring it too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weighty pages
&lt;/h2&gt;

&lt;p&gt;Next effectively forces you to do all of the "stuff" at the top level pages. Anything "next-y" or "server-y" has to be done directly in your pages. This creates &lt;em&gt;all kinds&lt;/em&gt; of coupling. Not to mention your pages are also tightly coupled to your routing. This means your routing logic is tied to your page which is tied to all of your server side, data fetching, caching, everything, all tightly coupled.&lt;/p&gt;

&lt;p&gt;I've always believed that routes should be lightweight and only concerned with which component is rendered by which route. But now I have to also stuff all of my business logic and fetching activity? No thanks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server routes are hardocded to /api
&lt;/h2&gt;

&lt;p&gt;Next.js forces you to mount all of your backend endpoints behind &lt;code&gt;/api/&lt;/code&gt;. This goes back to my very first point about this being a super duper opinionated framework, where you can't even control your endpoints. I &lt;em&gt;really&lt;/em&gt; don't want my UI framework to get to say where my api endpoints should live in my application...&lt;/p&gt;

&lt;h2&gt;
  
  
  Every fetch/mutation must be done in a "next-ey" manner
&lt;/h2&gt;

&lt;p&gt;Everything has to be written in a way that accounts for 2 completely different rendering methods, so it can run on the server, but also on the client.&lt;/p&gt;

&lt;p&gt;Once again, I can't just write my code in a way that suits my architecture or my conceived best practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exposing low level operations
&lt;/h2&gt;

&lt;p&gt;"You can now directly query the database in your react app, that's so cool!" - is that cool or is it scary? This is just asking for lazy people to directly import their db connection in a component and query it. I can't imagine some of the terrible things people have done with this kind of freedom...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I forgot I needed this bit of data. I really can't be bothered to create an abraction that retrieves the data I need in a sensible, testable context...&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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="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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/db&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;bitOfData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I'll totally come back and refactor this later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So now we're abstracting bits that, to me, don't need abstracting, like routing; and exposing low level backend functionality that we should &lt;em&gt;definitely not&lt;/em&gt; be tying into the ui? Oh man.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;p&gt;There are gotchas everywhere:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For the initial page load, getInitialProps will run on the server only. getInitialProps will then run on the client when navigating to a different route via the next/link component or by using next/router. However, if getInitialProps is used in a custom _app.js, and the page being navigated to implements getServerSideProps, then getInitialProps will run on the server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is just one piece of confusing documentation that has tripped up friends of mine. I hear stories from them every day about weird edge cases and gotchas and "because next says so" issues. Every day I feel more validated that I don't have to deal with these frustrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  BUT SEO!
&lt;/h2&gt;

&lt;p&gt;SEO is not stupid - even without Next. With a page that just uses client-side rendering and has to fetch some data first, Google's page crawler is not stupid, it knows to wait for this sort of thing. As long as I'm adding the necessary meta tags I can more of less trust that SEO will still work.&lt;/p&gt;

&lt;p&gt;The only major cost of &lt;em&gt;not&lt;/em&gt; using next.js is that I can't send contextual link previews on facebook/twitter/slack/etc. They don't process javascript so I can't dynamically add meta tags to the document.&lt;/p&gt;

&lt;p&gt;However, I don't think rewriting my entire application from the ground up, in a framework I find constrictive, just to get this single feature, is worth it. There are many many ways around this, like pre-rendering for robot useragents.&lt;/p&gt;

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

&lt;p&gt;So there you go. The tl;dr is that I'm a stubborn developer and next.js isn't the boss of me!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So if you're not using next.js I guess you'll go back to CRA then?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nope! I've only ever used CRA once and I ejected out of it after a couple of weeks. I quickly found that I couldn't do some of the more advanced stuff I wanted to do. Decisions were taken out of my hands that I didn't want to give up. Like typescript was being transpiled by a webpack loader rather than babel, but I use several babel plugins that parse typescript annotations. I also quickly realised there was - &lt;em&gt;so&lt;/em&gt; - &lt;em&gt;much&lt;/em&gt; - &lt;em&gt;stuff&lt;/em&gt; - in the webpack config that I was just never ever going to need. I stripped out hundreds of lines of code and unneeded dependencies.&lt;/p&gt;

&lt;p&gt;For this current project I decided to use &lt;code&gt;vite&lt;/code&gt;. It's still somewhat opinionated and it's super-low config but I've not yet hit an issue I couldn't easily solve with a little config.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>nextjs</category>
      <category>opinion</category>
    </item>
    <item>
      <title>Sharing contracts</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Thu, 03 Jun 2021 06:32:18 +0000</pubDate>
      <link>https://dev.to/jackmellis/sharing-contracts-4nad</link>
      <guid>https://dev.to/jackmellis/sharing-contracts-4nad</guid>
      <description>&lt;p&gt;This is a concept that really drives home how nice it is when your entire stack is written in the same language. I am using node/typescript on the backend which means I can share stuff between the ui and api.&lt;/p&gt;

&lt;p&gt;I have a separate repo that holds common stuff like error codes, request payloads and response payloads:&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="c1"&gt;// Contracts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SearchProductsRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;page&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="nl"&gt;q&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="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SearchProductsResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;nextPage&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="nl"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&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;Then I can use that to bridge the gap between api and ui:&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="c1"&gt;// API&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;searchProductsApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&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="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SearchProductsRequest&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;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SearchProductsResponse&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="c1"&gt;// req.query is strongly typed&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// res.send will throw a ts error if result doesn't match the response&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// UI&lt;/span&gt;
&lt;span class="c1"&gt;// (driver is a simple wrapper around the fetch api)&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;searchProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// data will be strongly typed&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;data&lt;/span&gt; &lt;span class="p"&gt;}&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;driver&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SearchProductsRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SearchProductsResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// will throw a ts error is args doesn't match the request&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;args&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 both sides of my application can have confidence that they will be receiving/sending the same payloads!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>typescript</category>
      <category>startup</category>
    </item>
    <item>
      <title>Developing a ui architecture</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Fri, 28 May 2021 11:04:18 +0000</pubDate>
      <link>https://dev.to/jackmellis/developing-a-ui-architecture-2agn</link>
      <guid>https://dev.to/jackmellis/developing-a-ui-architecture-2agn</guid>
      <description>&lt;p&gt;So previously I discussed at length how my backend application is archtected. If you haven't read it already I'd strongly suggest you do before continuing, as this article very much continues on the same path.&lt;/p&gt;

&lt;p&gt;So once again my frontend is based on hexaganoal architecture. It's very very similar to the pattern I explained previously, with a few small but important differences.&lt;/p&gt;

&lt;p&gt;When we talk about frontend we always focus on component organisation, and this is important, of course; but it also just as important to think about organising the non-presentational aspects of your application. I often see people making fetch requests inside components. This might be quicker to throw together and push out, but as a project grows, it becomes an absolute chore to find where in your code you are fetching data or causing side effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overall Structure:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src
│
└───ui
|
└───application
|   └───feature
|       |   useUsecaseHook.ts
|
└───core
|   |   feature.ts
|
└───infrastructure
|   └───feature
|       |   method.ts
|
└───domain
|   |   feature.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most obvious difference is the api layer has been replaced with a ui layer, for obvious reasons. I'll come back to the contents of the ui layer shortly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application
&lt;/h2&gt;

&lt;p&gt;The other difference is that the application layer is actually now just a collection of react hooks. For some reason in a react application, this just makes a lot of sense. All of your usecases are going to be tied to hooks and state. The only problem with this approach is the application layer &lt;em&gt;is&lt;/em&gt; coupled to react so you couldn't access any of the usecases outside of a react context. However, I decided this was a small architectural price to pay for convenience (given that I'll almost definitely never be using the application layer outside of react).&lt;/p&gt;

&lt;h2&gt;
  
  
  Core / Infrastructure / Domain
&lt;/h2&gt;

&lt;p&gt;I won't go into these in much detail because they are literally the same as the same areas in the backend app.&lt;/p&gt;

&lt;p&gt;The tl;dr: core is abstract interfaces, infrastructure is implementations of those interfaces (stuff that does side effects and "contacts the outside world"), and domain is pure business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI
&lt;/h2&gt;

&lt;p&gt;So what's going on in the ui layer? It's nothing extraordinary, in fact it follows a pretty common pattern that's similar to atomic design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ui
└───elements
|   |   ButtonComponent
|
└───modules
|   └───feature
|       |   CompositeComponent
|
└───pages
|   └───feature
|       | FeaturePageComponent
|
└───app
    | AppComponent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  elements
&lt;/h3&gt;

&lt;p&gt;Elements are small self-contained components that have no application logic or knowledge. Things like buttons, grids, inputs, and so on.&lt;/p&gt;

&lt;p&gt;I have maybe 2 exceptions to the rule here, which is an &lt;code&gt;Image&lt;/code&gt; component that takes a partial &lt;code&gt;src&lt;/code&gt; and computes the full url based on my app config. And an &lt;code&gt;Upload&lt;/code&gt; input element that internally handles uploading a file to the server and just returns the resulting url. Should I make these dumber and less tied to the rest of the stack? Yes. Will I? Maybe eventually 👀&lt;/p&gt;

&lt;h3&gt;
  
  
  modules
&lt;/h3&gt;

&lt;p&gt;A module is a group of &lt;code&gt;elements&lt;/code&gt; that make up part of a page. For example, if you have a search page, you might have a module for the search input area, a module for the list area, and a module for the individual list item. A module &lt;em&gt;can&lt;/em&gt; also be made up of other modules.&lt;/p&gt;

&lt;p&gt;A module &lt;strong&gt;can&lt;/strong&gt; have domain knowledge.&lt;/p&gt;

&lt;p&gt;The important part to note here is that modules are all "dumb". A module will never fetch data or send data, it won't read cookies, it won't use the application layer. Anything "smart" is done by the parent pages.&lt;/p&gt;

&lt;p&gt;What complicates this is that sometimes a module might render another module that relies on some smart stuff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Overview&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onViewMoreInfo&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductItem&lt;/span&gt;
      &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&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;function&lt;/span&gt; &lt;span class="nx"&gt;ProductItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onViewMoreInfo&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductActions&lt;/span&gt;
        &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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;function&lt;/span&gt; &lt;span class="nx"&gt;ProductActions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onViewMoreInfo&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add to basket&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;More info&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to provide the &lt;code&gt;onAddToBasket&lt;/code&gt; prop to the ProductActions component, we have to pass the prop all the way down. Prop drilling is a frustrating and tedious part of react development. This is why we often just bypass the smart/dumb construct and stick the smart logic inside &lt;code&gt;ProductActions&lt;/code&gt; instead, but this causes more issues as you start to lose track of where your smart behaviour comes from.&lt;/p&gt;

&lt;p&gt;My solution is to actually pass elements as props, so you compose your dumb components and then pass them down instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Overview&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductItem&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ProductItem&lt;/span&gt;&lt;span class="p"&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;function&lt;/span&gt; &lt;span class="nx"&gt;ProductItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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;function&lt;/span&gt; &lt;span class="nx"&gt;ProductActions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onViewMoreInfo&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onAddToBasket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add to basket&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;More info&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And at the smart level (i.e. pages) then you can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Overview&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductActions&lt;/span&gt;
    &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleAddToBasket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleViewMoreInfo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Overview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does get more complex when you have multiple components to compose, but I think it's better than mountains of prop drilling or smart components buried deep in the module layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  pages
&lt;/h3&gt;

&lt;p&gt;A page is what it says on the tin, it is the construct of an entire page or view. Pages serve three purposes: they put together multiple modules into a cohesive whole; they handle interacting with the application layer for fetching and mutating data; and they orchestrate the routing of the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A single page, composing the view from multiple modules&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ProductPage&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;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFetchItem&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;addToBasket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAddToBasket&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;viewMore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useViewMore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Overview&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductActions&lt;/span&gt;
        &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onAddToBasket&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;addToBasket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onViewMoreInfo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewMore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Overview&lt;/span&gt;&lt;span class="p"&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="c1"&gt;// A Page that stitches together other pages with routing&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ProductPages&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/product/:id"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So there it is. Just like the backend - hexagonal architecture, separation of concerns, and dependency injection form the basis of the codebase. Is it perfect? No. Is it easy to maintain and follow? I think so. Is it for everyone? Probably not!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>startup</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Developing an api architecture</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Fri, 21 May 2021 21:46:43 +0000</pubDate>
      <link>https://dev.to/jackmellis/developing-an-api-architecture-4g2j</link>
      <guid>https://dev.to/jackmellis/developing-an-api-architecture-4g2j</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I love a bit of architecture. How you structure your application is so important and if you get it wrong you'll really pay for it down the line. The problem is you often don't know you've got it wrong until it's too late. I've made this mistake so many times and iterated on solutions so much that now when I start a project I know exactly how I want it to be structured. I've developed what I consider to be a pretty robust pattern for application development.&lt;/p&gt;

&lt;p&gt;Essentially I follow a loose Hexagonal Architecture pattern. I won't go into too much detail on what hexagonal architecture is as there are tonnes of articles on the concepts and ideas already. What I will do is show how I interpret it into my own applications. Although there are lots of articles about this pattern, they are very rarely discussed in terms of a node or front end application (usually they are Java-based).&lt;/p&gt;

&lt;p&gt;For this article I'll focus on my node app. I'll cover the front end separately as although it's similar at the core, there are some necessary differences.&lt;/p&gt;

&lt;p&gt;This is roughly how my codebase is structured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src
│
└───api
|   └───route
|       |   get.ts
|       |   post.ts
|       |   delete.ts
|
└───application
|   └───feature
|       |   usecase.ts
|
└───core
|   |   feature.ts
|
└───infrastructure
|   └───feature
|       |   method.ts
|
└───domain
|   |   feature.ts
|
└───bootstrap
    |   setup.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is also termed Ports and Adapters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;application = usecases&lt;/li&gt;
&lt;li&gt;core = ports&lt;/li&gt;
&lt;li&gt;infrastructure = adapters&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So what do all of these layers mean?
&lt;/h2&gt;

&lt;p&gt;I've drawn a diagram of how this application fits into hexagonal architecture. Unfortunately diagram creating is not my strong point so I apologise in advance:&lt;/p&gt;

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

&lt;p&gt;This looks like every other HA diagram I've ever seen and until you "get it" I don't think it really helps that much. I often find it easier to convey the flow of data like this:&lt;/p&gt;

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

&lt;p&gt;At this point you might be thinking: "why are there so many steps for this one request?" and you're right. In a "basic" express app your flow would probably look more like this:&lt;/p&gt;

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

&lt;p&gt;But the problem with this is you're tightly coupling your application in every sense. You make it hard to test the individual parts, you tie your application logic into your server, you tie your database into your application logic, which in turn ties your database into your server. One of the fundamental principles of good software design is to separate your concerns.&lt;/p&gt;

&lt;p&gt;So yes this is more files and more layers of abstraction, but that's a good thing I promise!&lt;/p&gt;

&lt;p&gt;Let's dive a little deeper into each of these folders:&lt;/p&gt;

&lt;h2&gt;
  
  
  api
&lt;/h2&gt;

&lt;p&gt;My api layer contains my express routes and nothing else. You can think of this layer as being controllers in an MVC framework. The routes don't contain any logic, they purely pass the request data on to the application layer and then respond with the result. Not only does this keep the routes lean, it keeps all of my application logic agnostic of the delivery method.&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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;basket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getBasketUsecase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;basket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structure of this folder mirrors the express paths, for example: &lt;code&gt;/src/api/basket/get.ts&lt;/code&gt; equates to a GET request to &lt;code&gt;/api/basket&lt;/code&gt;. When setting up the application, I automatically find all of the files in this folder and calculate the express routes dynamically. This means I never have to manually write &lt;code&gt;app.get('/api/basket')&lt;/code&gt; as it's just inferred. This kind of auto-routing is quite common with big frameworks and things like next.js. Personally I like it and it feels like "magic" without being too "behind the scenes".&lt;/p&gt;

&lt;h2&gt;
  
  
  application
&lt;/h2&gt;

&lt;p&gt;These are my use cases. What I mean by this is that each method is an end-to-end feature. For example "get the basket", "add something to the basket", "remove something from the basket". Each use case will handle things like validating inputs, calling the necessary methods to carry out the action, validating the response, transforming data into the output type, and so on. Essentially this is the "orchestration" layer of the application.&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="nf"&gt;usecase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;validateArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&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;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeData&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;validateOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;output&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;output&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;There is almost always a 1:1 relationship between the api layer and the application layer. An api endpoint will only call one usecase, and a usecase will most likely only be used by one api endpoint. Why not just combine them into a single function? Loose coupling.&lt;/p&gt;

&lt;p&gt;For example, although I am using express for my server, I may want certain use cases to be accessed via a CLI instead/as well. The application layer does not care if a request comes via the web api, or the cli, or some other method. It just cares about the arguments it receives.&lt;/p&gt;

&lt;p&gt;The application, core, and infrastructure layers are hard to talk about in isolation (which is ironic) so the next few sections will be a bit intertwined...&lt;/p&gt;

&lt;h2&gt;
  
  
  core
&lt;/h2&gt;

&lt;p&gt;How does the application layer actually "do stuff" though? If we want to get the basket, for example, how does it do this? We wouldn't want the application layer to import the database and query it directly, this would couple our low level implementation too tightly to the high level use case.&lt;/p&gt;

&lt;p&gt;The core layer holds interfaces for all of the things the application can do. When I say &lt;em&gt;interfaces&lt;/em&gt;, I mean &lt;em&gt;typescript interfaces&lt;/em&gt;, there is no actual javascript here, purely types and interfaces.&lt;/p&gt;

&lt;p&gt;So for example, if we want to get the basket, there will be a &lt;code&gt;FetchBasket&lt;/code&gt; type that might look something like this:&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;type&lt;/span&gt; &lt;span class="nx"&gt;FetchBasket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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;IBasket&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;Our application layer operates purely on these interfaces, at no point do we import a &lt;code&gt;fetchBasket&lt;/code&gt; function. Instead, we import the interface from the core layer and use dependency injection to say "please fetch the implementation of this type". Dependency injection is really the glue that connects these layers together.&lt;/p&gt;

&lt;p&gt;For example, our get basket use case might look something like this:&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="nf"&gt;getBasketUsecase&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&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;fetchBasket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FetchBasket&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;basket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchBasket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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;basket&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 means there is a "bridge" between the application layer and the underlying implementation detail, which is really important. The above function is really easy to test because the &lt;code&gt;fetchBasket&lt;/code&gt; implementation does not exist, you can provide any implementation you want. It also means that your usecases are really clean, because all of the leg work is abstracted away and all you have to do is say "I'd like the implementation of this type please" and off you go.&lt;/p&gt;

&lt;p&gt;One awesome benefit of this is that you can write your core layer, then your usecase layer, and not even bother with the infrastructure layer until later. This is fantastic for working on new features where you know what the use case is ("the user wants to see their basket"), and you know roughly what the interface will look like ("pass the user id to the database, get the basket back"), but you're not quite sure on the implementation detail yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  infrastructure
&lt;/h2&gt;

&lt;p&gt;Now that we have our &lt;code&gt;core&lt;/code&gt; interfaces, the infrastructure layer contains all of the implementations for them. Essentially anything that causes a side effect, or &lt;em&gt;reaches&lt;/em&gt; outside of your code (like accessing the database) is infrastructure.&lt;/p&gt;

&lt;p&gt;Interestingly, infrastructure methods can rely on other core interfaces which means you can have several levels of abstraction. For example, the &lt;code&gt;fetchBasket&lt;/code&gt; implementation will probably depend on an &lt;code&gt;IDatabase&lt;/code&gt; interface, which in turn would be a wrapper around your actual database.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, I use dependency injection (specifically the service locator pattern) to register these infrastructure methods:&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;jpex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FetchBasket&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;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IDatabase&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;userId&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;basket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  bootstrap
&lt;/h2&gt;

&lt;p&gt;The bootstrap folder isn't even a layer, and it does what you think it does. We call a setup function at app start. This creates the express server, finds and registers all of our api routes, finds and registers all of our infrastructure methods, connects the database, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Misc
&lt;/h2&gt;

&lt;p&gt;There are a couple of notes I wanted to add/clarify as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I should mention that I follow a &lt;em&gt;loose&lt;/em&gt; function programming paradigm. You won't see any service/repository classes or anything like that. Everything is a function that depends on other functions. I've found that repository classes often become unwieldy, hard to maintain, cluttered with dependencies, and difficult to mock. (Plus all data is treated as immutable, but that affects the frontend much more than the backend)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I should also point out that although the top level folders aren't "domains", this &lt;em&gt;is&lt;/em&gt; still domain driven design. We've just grouped the high level concerns of our domains first. You &lt;em&gt;could&lt;/em&gt; flip this over and have &lt;code&gt;domain/infrastructure/method.ts&lt;/code&gt;, and I have tried it this way around, but you will almost definitely hit cross-domain issues that don't exist in this format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;So that is an extremely long (but honestly brief) tour of my backend architecture. It's quite a lot to wrap your head around but I have confidence (and experience) that it is an extremely clean, testable, scalable application structure.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>react</category>
      <category>architecture</category>
    </item>
    <item>
      <title>What's in a tech stack?</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Thu, 20 May 2021 14:08:24 +0000</pubDate>
      <link>https://dev.to/jackmellis/what-s-in-a-tech-stack-3p76</link>
      <guid>https://dev.to/jackmellis/what-s-in-a-tech-stack-3p76</guid>
      <description>&lt;p&gt;What's in a tech stack? We always talk about MEAN, MERN, MEVN, LAMP, but honestly I've never understood the point of these acronyms.&lt;/p&gt;

&lt;p&gt;I've been a dedicated front end engineer for 5 of my 8 years of professional development. So I've really only ever cared about one letter of these acronyms (and for LAMP I actually have zero investment). Do I care what language the backend is written in or what database we're using? I really don't! I'm using angular/react/vue/etc. and as long as I get a well formatted response from the backend I don't care.&lt;/p&gt;

&lt;p&gt;As a full stack developer, or when working on personal projects, I might have more cause to describe the stack. But I've never described myself as working on a SAC stack (SQL Server, Angular, C#), or a JERN stack (Java, Express, React, Node) (I don't even know what database we used for that one, I was so far removed from the backend it just didn't affect me), or a JRPK stack (figure that out if you can).&lt;/p&gt;

&lt;p&gt;The other problem with these acronyms is they don't tell the full story of the stack. Why do we explicitly call out Express in the MEAN stack? Is it because it's more fundamental than any other library/framework we're using? I think it's more likely that MAN is just less catchy than MEAN.&lt;/p&gt;

&lt;p&gt;So on that note, what stack am I using for my application? I'm actually owning the entire stack, so for once the entire tech stack actually does matter to me. Rather than try to create a pointless acronym I'll just list out some of the technologies/frameworks/libraries I'm using and why:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://reactjs.org/"&gt;react&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I've used Angular.js, Vue, and React over the years. And although I've always had a soft spot for Vue, the more I use both Vue and React, the more I find React to be the more complete/powerful option.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://tailwindcss.com/"&gt;tailwind&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I've used many languages in the past; sass, less, react-css, linaria, I even wrote plain css one time. But in all honestly, I &lt;em&gt;hate&lt;/em&gt; writing css - which is probably a weird thing for a front ent dev to say. There's just something really cumbersome and unmaintainable about it for me. Tailwind offers just the right amount of abstraction between writing css and using something like bootstrap.&lt;/p&gt;

&lt;p&gt;It's quite a divisive library, but almost every complaint I see about tailwind is solved by writing small components that remove the classes from my main application code. The components themselves give elements semantic meaning, not the class names - that's the secret.&lt;/p&gt;

&lt;p&gt;Most importantly for me, tailwind makes prototyping and rapid development so easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/react-hook-form"&gt;react-hook-form&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I've not been using this for long but it does the job nicely and it certainly &lt;em&gt;feels&lt;/em&gt; like it performs better than formik and redux-form.&lt;/p&gt;

&lt;p&gt;I felt its inclusion in this list was necessary because forms are like 80% of almost every front end application.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/jpex"&gt;jpex&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I can't write an article without plugging jpex of course, so here it is. Dependency injection is a pretty fundamental part of my architecture which I'll cover another time. I use jpex in both the frontend and the backend applications and it is essentially the glue that ties everything together.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/jackmellis/respite"&gt;respite&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is a state management solution I built myself. It's similar to react-query, I could have used react-query, and I have used it extensively in the past. But there were a &lt;em&gt;lot&lt;/em&gt; of inconveniences and strange decisions that would constantly irritate me.&lt;/p&gt;

&lt;p&gt;I also wanted a way to do global state that didn't involve adding another large library, as well as a way to decouple cache invalidation from the mutations.&lt;/p&gt;

&lt;p&gt;I don't expect anyone else to use respite, but the more I work with it the more I'm pleased I wrote it! I'll probably cover some of it at a later point.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://vitejs.dev/"&gt;vite&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Worth covering because 99% of apps are built with webpack. Webpack just owns the world of ui building. But I've always felt there are better ways of doing things. I originally played with snowpack when it was still in beta, but when vite came out by the guys behind Vue, I knew it would have the same super-simple api and great docs so I took the plunge.&lt;/p&gt;

&lt;p&gt;I love it and I won't be willingly going back to webpack in the future!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://nodejs.org/"&gt;node&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Node was an obvious choice as it means my entire app is written in the same language. I'm always surprised just how fast it runs too. I've used node for all sorts of cli tools and bits and pieces for many years, so it's always my go-to for most tools and apis.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://expressjs.com/"&gt;express&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I actually tried out a few alternatives to express but nothing really beats it. It baffles me how a library can just "get it right" first time! Express has been the defacto server library for... ever!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.mongodb.com/"&gt;mongo&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To be honest, I haven't 100% settled on a database for production. But during development mongo is an obvious choice. It's so simple to set up and use. And you can just start throwing data in it without having to spec out an entire schema or relational mappings.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.typescriptlang.org/"&gt;typescript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Typescript is another absolute fundamental part of the stack. I don't think I could go back to plain javascript at this point in my career. If I ever have to write javascript I immediately feel uncomfortable "What type is this variable meant to be? What parameters am I meant to pass into this function?!" - so stressful.&lt;/p&gt;

&lt;p&gt;So there you have it. And of course this doesn't tell the full story. I've tried to include the fundamentals, but there are so many baselines that we just take for granted. Babel, jest, testing-library, these are all just as important as, say, express.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm sure you're wondering where next.js is in this list, everybody uses next.js now right? Well not me! I'm a rebel and I will probably cover my reasons why in a future post!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay so officially this is the MERN stack I'm using. But that tells you nothing about my actual application at all. Personally I prefer to call this the MERRVJNTT stack.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>react</category>
      <category>startup</category>
    </item>
    <item>
      <title>Building a serious(ish) project - intro</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Thu, 20 May 2021 13:55:38 +0000</pubDate>
      <link>https://dev.to/jackmellis/building-a-serious-ish-project-intro-1ke4</link>
      <guid>https://dev.to/jackmellis/building-a-serious-ish-project-intro-1ke4</guid>
      <description>&lt;p&gt;I've been a developer for 8+ years now, working in all kinds of industries. Some full stack jobs, mostly front end jobs. I've created ~35 open source libraries over the years. I'm technically self-taught but I've also learnt &lt;em&gt;&lt;strong&gt;a lot&lt;/strong&gt;&lt;/em&gt; from some pretty smart people I've had the fortune to work with.&lt;/p&gt;

&lt;p&gt;I've finally committed to building a full stack application. I wanted to get some of my thoughts, ideas, and headaches written down as I go through this process. There are a lot of things I've picked up in my career that I just store internally, so hopefully this will force me to start sharing things a bit more!&lt;/p&gt;

&lt;p&gt;There will also almost definitely be a lot of things I've never had to deal with before, and things I'll have to learn from scratch. So I also figure it might be good to share these experiences too.&lt;/p&gt;

&lt;p&gt;This is probably the first time I've been this excited to make something, and (outside of my actual job) actually want to see it through to the end. Let's see what happens...&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>react</category>
      <category>startup</category>
    </item>
    <item>
      <title>Don't mock modules</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Tue, 04 May 2021 10:27:25 +0000</pubDate>
      <link>https://dev.to/jackmellis/don-t-mock-modules-4jof</link>
      <guid>https://dev.to/jackmellis/don-t-mock-modules-4jof</guid>
      <description>&lt;p&gt;I want to talk about a practice that has more or less become the defacto for javascript unit testing: &lt;strong&gt;mocking module imports&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I have been wary of this from when it first came about with &lt;a href="https://www.npmjs.com/package/rewire"&gt;rewire&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/proxyquire"&gt;similar libraries&lt;/a&gt;. As time has gone on my opinion has only strengthened, and with jest actively embracing mocking modules, I feel like nobody has even bothered to make a counter argument.&lt;/p&gt;

&lt;p&gt;So, this is my argument against mocking module imports.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a mocked import?
&lt;/h2&gt;

&lt;p&gt;When you're writing code, you will at some point need to access some external resource. Fetching data over the network, reading a file from disk, etc.&lt;/p&gt;

&lt;p&gt;When you're trying to test your code, you really don't want to be using these external resources. Imagine if your tests had to manage reading and writing files. You'd have to write the initial file state, run the test, tear down the file, hope there aren't any write errors or permission issues. Your tests would be slow, extremely brittle, difficult to run in a CI environment, impossible to run concurrently, and so on.&lt;/p&gt;

&lt;p&gt;So we dont want to read or write real files during our tests. Ideally we want a fake &lt;code&gt;fs&lt;/code&gt; module we can mock and assert against.&lt;/p&gt;

&lt;p&gt;The idea of mocking imports is that you can patch node's &lt;code&gt;require&lt;/code&gt; function, intercept certain calls, and potentially provide an entirely different module.&lt;/p&gt;

&lt;p&gt;Once this idea was formed, it took off and this is what we have basically done ever since. It does the job, right? I can mock the fs module in my test, and then my code will get the mock when it tries to import it. I can spy on it, I can return a mocked response from &lt;code&gt;fs.readFile&lt;/code&gt;. So what's the problem?&lt;/p&gt;

&lt;h2&gt;
  
  
  Tightly coupled to node
&lt;/h2&gt;

&lt;p&gt;Module mocking is literally a monkey patch over node's require function. It doesn't operate on documented features of node. It is, essentially, a hack. There is no guarantee that the node implementation will always be compatible with the way module mocking currently works. In fact I would highly suspect that node releases have caused module mocking libraries to fundamentally break in the past.&lt;/p&gt;

&lt;p&gt;We now also have native esmodule support in most environments, including node. But this is &lt;em&gt;not&lt;/em&gt; how esmodules are meant to be used, they weren't created with module mocking in mind.&lt;/p&gt;

&lt;p&gt;Sometimes monkey patches and hacks are a necessary evil in life, but it shouldn't form the basis of every test we write... should it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Tightly coupled to implementations
&lt;/h2&gt;

&lt;p&gt;Perhaps this is subjective, but I strongly believe a low level action like reading/writing should be kept as far away as possible from high level code. In other words: in high level code, low level actions should be abstracted.&lt;/p&gt;

&lt;p&gt;Say you're fetching an auth token and you want to store it. It's so easy to just &lt;code&gt;import cookies from 'browser-cookies'&lt;/code&gt;, call &lt;code&gt;cookies.set&lt;/code&gt; and you're done. I mean this is why javascript is so flexible right?&lt;/p&gt;

&lt;p&gt;But should your auth function really know about cookies? What if you decide you'd prefer local or session storage? Or you even decide to just keep the token in memory. Abstraction is key to clean elegant code.&lt;/p&gt;

&lt;p&gt;What does this have to do with mocking modules? It doesn't force tight coupling directly, but it does encourage this. Or perhaps it's more appropriate to say it encourages laziness.&lt;/p&gt;

&lt;p&gt;Instead of asking "how do I separate my low level implementation detail from my application?", considering structure, maintainability, and coding practices; it's too easy to just go "ah well let's just mock the entire module import and move on".&lt;/p&gt;

&lt;h2&gt;
  
  
  Leaky Tests
&lt;/h2&gt;

&lt;p&gt;When you mock a module, you're mocking the module for that entire test suite, potentially the entire test run, depending on your test runner.&lt;/p&gt;

&lt;p&gt;How many times have you had a test fail because of another test? We're now adding even more global side effects into the mix.&lt;/p&gt;

&lt;p&gt;What if every test requires a completely different response from your mocked module? What if you only want to mock part of the module? What if you want to completely undo a module mock for a single test? There are workarounds for these things, of course, but they are all workarounds and hacks, and quite often create more issues than they solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side effects
&lt;/h2&gt;

&lt;p&gt;For me, all of these points really boil down to a single fundamental problem: side effects - both intended and unintended.&lt;/p&gt;

&lt;p&gt;Using the fs module directly will cause side effects in your code. Mocking the fs module will cause side effects in your tests. Mocking global objects like &lt;code&gt;window.matchMedia&lt;/code&gt; comes with the same issues as module mocking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;I believe the solution is one that is a fundamental part of almost all languages &lt;em&gt;except&lt;/em&gt; javascript: Dependency Inversion.&lt;/p&gt;

&lt;p&gt;I'm not even suggesting you use some high level ioc container framework or injection library here. Basic dependency inversion can be done without any complexity or overhead!&lt;/p&gt;

&lt;p&gt;You want to read from a file? Provide &lt;code&gt;fs&lt;/code&gt; as a parameter. Want to check &lt;code&gt;window.matchMedia&lt;/code&gt; in your react component? Create a context provider for it - the context api is dependency inversion!&lt;/p&gt;

&lt;p&gt;When you start inverting your dependencies, unit testing becomes so much easier! And for integration/e2e testing you can just leave dependencies in place.&lt;/p&gt;

&lt;p&gt;There are libraries/frameworks out there to give you a full DI experience. I'd highly recommend at least trying one out. I have a bias, of course, for &lt;a href="https://dev.to/jackmellis/dependency-injection-in-react-with-jpex-178l"&gt;my own DI library&lt;/a&gt; but this is not a plugging article, I just want to bring attention to the fact that there is a very simple and easy solution to the issues caused by module mocking!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>jest</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The slightly misleading terminology of react hooks</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Fri, 05 Feb 2021 23:08:32 +0000</pubDate>
      <link>https://dev.to/jackmellis/the-slightly-misleading-terminology-of-react-hooks-la5</link>
      <guid>https://dev.to/jackmellis/the-slightly-misleading-terminology-of-react-hooks-la5</guid>
      <description>&lt;p&gt;So react hooks are awesome, they make components much simpler, they let you abstract your component logic and completely do away with class components.&lt;/p&gt;

&lt;p&gt;However; the names of these hooks are somewhat misleading. Especially after react went all functional on us with function components.&lt;/p&gt;

&lt;p&gt;Allow me to elaborate:&lt;/p&gt;

&lt;h2&gt;
  
  
  Side Effects
&lt;/h2&gt;

&lt;p&gt;What is a side effect? A side effect is when a function changes another part of an application outside of its own scope:&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;goHome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/home&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;Calling this function is updating the window location, which is a global variable and isn't part of its own scope, so it's a side effect.&lt;/p&gt;

&lt;p&gt;It's also worth quickly also covering side effect's partner-in-crime:&lt;/p&gt;

&lt;h2&gt;
  
  
  Idempotent
&lt;/h2&gt;

&lt;p&gt;An idempotent function will return the same value for the same set of inputs every time.&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;getPath&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;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&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 is &lt;em&gt;not&lt;/em&gt; idempotent. If the location were to change, you would get a different result.&lt;/p&gt;

&lt;p&gt;With that out of the way, let's talk about &lt;code&gt;useEffect&lt;/code&gt;:&lt;/p&gt;

&lt;h2&gt;
  
  
  useEffect
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Accepts a function that contains imperative, possibly effectful code.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/home&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;The useEffect hook &lt;em&gt;allows&lt;/em&gt; you to do effectful behaviour inside a functional component.&lt;/p&gt;

&lt;p&gt;If you do a side effect inside useEffect, react pushes that side effect to the end of the render cycle. In react terms, useEffect is about protecting the render cycle, not about removing side effects.&lt;/p&gt;

&lt;p&gt;Why is this distinction important? We often talk about react components as being "pure". A pure component should be side-effect-free and idempotent. Wrapping your side effects in useEffect does not mean your component is still pure.&lt;/p&gt;

&lt;h2&gt;
  
  
  useState
&lt;/h2&gt;

&lt;p&gt;I've seen many people say things like "we don't need smart/dumb components now we have hooks"&lt;br&gt;&lt;br&gt;
I don't want to go in-depth into patterns and architecture, but just because you're using useState instead of redux, etc, you're still introducing state into a component. This breaks a component's idempotency.&lt;/p&gt;

&lt;p&gt;For every piece of state a component manages, the harder it is to reason about, test, and control that component.&lt;br&gt;&lt;br&gt;
Tl;dr useState is no different to any other component state - it is &lt;em&gt;not&lt;/em&gt; functional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function vs Functional component
&lt;/h2&gt;

&lt;p&gt;Okay something that I only really noticed recently: we always talk about &lt;code&gt;functional&lt;/code&gt; components but actually, the docs refer to these as &lt;code&gt;function&lt;/code&gt; components. What's the difference?&lt;/p&gt;

&lt;p&gt;I believe the difference is this:&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;functional&lt;/code&gt; component adheres to the rules of Functional Programming. It is idempotent, pure, and stateless.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;function&lt;/code&gt; component is just any old component that just happens to be a function.&lt;/p&gt;

&lt;p&gt;That's a pretty big discrepancy. When we're talking about function components, do we care about whether it's a functional component?&lt;/p&gt;

&lt;p&gt;I used to believe that yes; any function component should be side-effect and state free. Now I'm not so sure.&lt;/p&gt;

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

&lt;p&gt;We've definitely got some confusing terminology here. &lt;code&gt;useEffect&lt;/code&gt; is not offering some way of keeping effects "out" of your component. And a &lt;code&gt;function&lt;/code&gt; component is not the same as a &lt;code&gt;functional&lt;/code&gt; component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I stop using hooks?
&lt;/h2&gt;

&lt;p&gt;Absolutely not. Hooks are awesome. I just want us to be mindful that hooks are not some magical construct that preserves function purity. If your component has state or causes side effects, &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; do not change this fact.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>functional</category>
    </item>
    <item>
      <title>Object.entries is awesome</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Fri, 05 Feb 2021 19:01:25 +0000</pubDate>
      <link>https://dev.to/jackmellis/object-entries-is-awesome-p3h</link>
      <guid>https://dev.to/jackmellis/object-entries-is-awesome-p3h</guid>
      <description>&lt;p&gt;Somebody asks you to loop through the properties of an object, most of us will reach for Object.keys right?&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&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;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="c1"&gt;// do something&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Somebody asks you to map the properties of an object to other values. Object.keys to the rescue again right?&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;newObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&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;newObj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;Wait, no reduce? That's so 2018! Let's be needlessly functional:&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;newObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;Nice!&lt;/p&gt;

&lt;p&gt;Thing is, Object.entries and Object.fromEntries are now widely supported. You can now achieve the same thing like this:&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;newObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;value&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;It's also trivial to just make a utility function that combines the fromEntries and entries calls:&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;mapEntries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you could then write the above like this:&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;newObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mapEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;key&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;value&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I love how simple this is, and you can do so much stuff that's always been a bit of a pain before.&lt;/p&gt;

&lt;p&gt;Want to transform keys?&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;newObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mapEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to invert an 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;const&lt;/span&gt; &lt;span class="nx"&gt;inverted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mapEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to filter properties out of an 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;const&lt;/span&gt; &lt;span class="nx"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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;span class="nx"&gt;value&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;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&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;Object.entries is awesome, have a play with it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Case Driven Testing</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Wed, 27 Jan 2021 20:35:08 +0000</pubDate>
      <link>https://dev.to/jackmellis/case-driven-testing-35o0</link>
      <guid>https://dev.to/jackmellis/case-driven-testing-35o0</guid>
      <description>&lt;p&gt;I've wanted to write about testing for a long time - front end testing has been a bugbear of mine for years. But my opinions have changed &lt;em&gt;constantly&lt;/em&gt; until recently.&lt;/p&gt;

&lt;p&gt;I used to think &lt;em&gt;"everything must have a unit test!"&lt;/em&gt; to the extent that I wrote unit tests for code that didn't even do anything. I wrote tests for dummy data even! But the point was that I didn't really give integration or end-to-end testing a second thought for a long time.&lt;/p&gt;

&lt;p&gt;Then I started paying more attention to the testing pyramid, and it became a pointless balancing act of quantifying my tests. &lt;em&gt;"This piece of code has 3 integration tests therefore it should have at least 15 unit tests and one e2e test"&lt;/em&gt; Again at the time this seemed perfectly reasonable - perhaps I couldn't see the wood for the trees.&lt;/p&gt;

&lt;p&gt;Then I started thinking in terms of the testing trophy, where we think more in terms of how much effort should be given to each area, or how much confidence it gives you. In my experience it leads most people to write almost exclusively integration tests.&lt;/p&gt;

&lt;p&gt;But recently I took a step back and it became a lot clearer than trophies and pyramids and coverage reports etc. Rather than setting out to write a certain number of a certain type of tests for a certain piece of code, you should examine the code and then think to yourself "what kind of test do I need?"&lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of test do I need?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Branches
&lt;/h3&gt;

&lt;p&gt;The main criteria I have for any piece of code is &lt;em&gt;"does it have several branches?"&lt;/em&gt;. If so, then I should attempt to write unit tests. Usually integration and e2e tests &lt;em&gt;won't&lt;/em&gt; cover every if statement or error path, so a unit test is the best way to cover all branching options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies
&lt;/h3&gt;

&lt;p&gt;The second criteria I have is &lt;em&gt;"how many other pieces of code  use this piece of code?"&lt;/em&gt;. If the answer is 1 then I consider whether it's worth testing it in isolation or if I can test it by testing the other code. For more than 1 we need to consider whether the code's coverage will potentially get lost.&lt;/p&gt;

&lt;p&gt;As an example, let's say we have a &lt;code&gt;ProjectDropdown&lt;/code&gt; component. It's pretty simple, has some integration with your form library, has a hardcoded list of projects to pick from, updates the form when you select a value, etc.&lt;br&gt;
However, this component is &lt;em&gt;only&lt;/em&gt; used by your &lt;code&gt;ProjectForm&lt;/code&gt; component. So when we write tests for the ProjectForm, will we naturally be covering all of ProjectDropdown's usecases? If so then we'll probably just be repeating ourselves. We can probably get away with just testing the form instead.&lt;br&gt;
Now, if ProjectDropdown has some different branches that won't 100% be encountered by ProjectForm's tests, then yes, it probably needs its own tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Confidence
&lt;/h3&gt;

&lt;p&gt;My third criteria is &lt;em&gt;"does a unit/integration test tell me anything about this piece of code?"&lt;/em&gt; Usually this is in terms of confidence I suppose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The example
&lt;/h2&gt;

&lt;p&gt;When I'm writing a component I usually split it into several pieces: a dumb component, a smart component, and the api layer.&lt;/p&gt;

&lt;p&gt;So the dumb component probably wants a high level unit test. We want to confirm that the expected content is available, that interacting with elements emits the expected events, that the edge cases and paths are all handled.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The word "unit" is a bit muddy for components as you're usually writing your tests from a user's perspective, but you should also be trying to isolate your component as much possible&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the api layer, how much stuff does it do? Does it have much branching? For 90% of the time the api layer will be a single function that accepts some args, makes a fetch request, and returns the response. So all a unit test would tell us is that we're sending a request and we're returning the response. We could write an integration test but will that tell us anything more than an integration of the smart component?&lt;/p&gt;

&lt;p&gt;You get the idea. A smart component would then have some integration tests that verify that it renders the dumb component, and it sends data to the api, and renders something else with the response data.&lt;/p&gt;

&lt;h2&gt;
  
  
  And then...
&lt;/h2&gt;

&lt;p&gt;Another point I should make is that it's difficult to follow this method &lt;em&gt;and&lt;/em&gt; adhere to TDD, as you have to have some understanding of your code before you decide what kind of tests to write. I find the key is to write some simple specs first that outline the general behaviour of the feature. You can refine and iterate on your tests as the implementation develops.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>react</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Do we need another state management solution?</title>
      <dc:creator>Jack</dc:creator>
      <pubDate>Thu, 31 Dec 2020 17:30:24 +0000</pubDate>
      <link>https://dev.to/jackmellis/do-we-need-another-state-management-solution-o11</link>
      <guid>https://dev.to/jackmellis/do-we-need-another-state-management-solution-o11</guid>
      <description>&lt;p&gt;So I spent several years working with redux + rxjs. Honestly epics and streams add so much cognitive complexity that it hugely affected the learning curve for new starters.&lt;/p&gt;

&lt;p&gt;We then completely scrapped redux in favour of react-query. I've used it in enterprise apps for a year and I loved it. But it still didn't quite do what I wanted. I've yet to find a situation where I want to arbitrarily refetch my data, or refetch on window focus. Maybe for a chat app or something with constantly changing data. I also wish it was lazier, and smaller, and had better refetching logic.&lt;/p&gt;

&lt;p&gt;So recently I started playing with recoil. But what starts as a very react-ey api quickly becomes convoluted and hard to read. And I also couldn't get past the whole "selectors should be idempotent" while also showing me a selector that reads from a database!&lt;/p&gt;

&lt;p&gt;I also started to play with relay but I quickly abandoned it as the api just felt really awkward to me.&lt;/p&gt;

&lt;p&gt;So like every npm package ever, I think "well this does 70% of what I want it to do". And like half of every npm package ever, I think "maybe I'll try writing my own version!"&lt;/p&gt;

&lt;p&gt;I started playing with a proof of concept, using it in personal projects, refining it, iterating on it, and I've actually reached a point where I genuinely enjoy using it more than other libraries.&lt;/p&gt;

&lt;p&gt;What do I do now? Do I publish it? Should I bloat npm even further with something that is really quite similar to existing products? Can I compete with Facebook et al? Do I even want to? Does the world really need yet another state management solution?&lt;/p&gt;

&lt;p&gt;That's not rhetorical, I'd genuinely like your thoughts on this!&lt;/p&gt;

</description>
      <category>react</category>
      <category>question</category>
      <category>webdev</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
