<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://fbedussi.github.io/blog//blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://fbedussi.github.io/blog//blog/" rel="alternate" type="text/html" /><updated>2026-01-14T17:13:05+00:00</updated><id>https://fbedussi.github.io/blog//blog/feed.xml</id><title type="html">No stress front end</title><subtitle>A journey to a healthier front end development</subtitle><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><entry><title type="html">Elm vs React in a real life scenario</title><link href="https://fbedussi.github.io/blog//blog/experiments/Elm-vs-React-in-a-real-life-scenario" rel="alternate" type="text/html" title="Elm vs React in a real life scenario" /><published>2026-01-12T00:00:00+00:00</published><updated>2026-01-12T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/experiments/Elm%20vs%20React%20in%20a%20real%20life%20scenario</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/experiments/Elm-vs-React-in-a-real-life-scenario"><![CDATA[<p>I discovered Elm around 2016, and I immediately fell in love with it. At the time I was working on a fairly complex e-commerce website using jQuery and a custom front-end framework using a pub/sub architecture. Our code was a mess: there was a lot of repetition, bugs seemed to reproduce overnight, and there was always a new one. It was very difficult to orchestrate the different parts of the UI. Given this state of things, Elm was a welcome ray of light. The type system, the compiler, the one-way data flow architecture—they all could have helped solve the pain points we were suffering from. I tried to push for its use in the company, but without success. After a couple of years, I switched companies and tech stacks. Now I was working full-time on React projects. I tried to push Elm even in my new workplace, but the result was the same: nobody was interested.</p>

<p>Then years passed. I worked more and more on React, and since I couldn’t use Elm, I tried to port some of its principles to React: the type system with TypeScript, the one-way data flow with Redux, and the functional paradigm, trying to embrace the functional side of JavaScript.</p>

<p>Fast forward to 2024, I switched companies once more. Now I was working full-time on Elm—hooray! But the thing is that in those 10 years or so, the JS-based ecosystem had evolved a lot, while Elm had not. A lot of the issues we used to have using jQuery to write imperative spaghetti code were solved by the plethora of declarative and reactive front-end frameworks that had emerged. The lack of static types was patched by TypeScript, and, man, TypeScript is not perfect, but its duck typing approach hits a sweet spot between safety and flexibility, and its type system is really powerful. Finally, some nice functional utilities were added to JavaScript, such as <code class="language-plaintext highlighter-rouge">map</code>, <code class="language-plaintext highlighter-rouge">filter</code>, and so on.</p>

<p>On the other hand, Elm continued to suffer from the same pain points: it lacks support for a lot of (and ever-increasing) browser APIs, it doesn’t allow interactive debugging (and this really hurts when you have to troubleshoot a weird bug in production), and it has very limited options to handle CSS. It makes it very difficult to do some trivial things, like getting a timestamp or a random number. On top of that, it is very difficult to find people who are proficient in it, or even willing to learn it. Like it or not, it has been rejected by the front-end community.</p>

<p>So in the end, our team decided that it was better to replace Elm with React (+ TypeScript). And we are doing it. One of the things that worried me was the size of the final bundle. Elm is famous for producing small assets, while React is notoriously quite heavy.</p>

<p>Here are the results of this experiment.</p>

<!--more-->

<h1 id="first-step-11-porting">First step: 1:1 porting</h1>

<p>To simplify the migration, reduce the risk of bugs, and simplify the alignment of the Elm and React codebases while they are both in use, I opted for a 1:1 port: I converted every Elm file into an equivalent React file, keeping the same architecture using Redux. I used Redux Toolkit to reduce the boilerplate code.</p>

<p>The result in terms of bundle size for this first version of the port is as follows:</p>

<ul>
  <li>Elm: 591 KB</li>
  <li>React+Redux Toolkit: 834 KB</li>
</ul>

<p>So at first glance, the theory that Elm-produced assets are smaller than those produced by React is confirmed (in this case, 41% smaller). But the story doesn’t end there. First of all, the difference in gzipped files is drastically reduced:</p>

<ul>
  <li>Elm: 183 KB</li>
  <li>React+Redux Toolkit: 204 KB</li>
</ul>

<p>We’re talking about 11%, a sign that Elm’s output is indeed very optimized, so it compresses less than React’s.</p>

<p>Then, being back in JSLand, I finally have access to tools that didn’t work with Elm. For example, <a href="https://www.npmjs.com/package/webpack-bundle-analyzer">Webpack’s Bundle Analyzer</a>. Looking inside the bundle, I could see that the libraries have the following sizes:</p>

<ul>
  <li>React 195 KB</li>
  <li>Redux + React-Redux + Redux Toolkit + Immer + Reselect: 102 KB</li>
  <li>The company Design System 229 KB</li>
  <li>LaunchDarkly SDK (external service to manage feature flags) 38 KB</li>
</ul>

<p>From this we can deduce that the actual code takes 270 KB, so it doesn’t offer much room for optimization.</p>

<p>One of the heaviest parts is, as I feared, React. But, hey, we are in JSLand here, we have options. Plenty of them, actually. So let’s try to replace React with Preact.</p>

<h1 id="second-step-replace-react-with-preact">Second step: replace React with Preact</h1>

<p>This replacement should be fine in this case, since we are talking about a micro front-end, with no server-side rendering and no use of advanced react-only features.</p>

<p>The replacement was straightforward, just a couple of lines in the <code class="language-plaintext highlighter-rouge">tsconfig.json</code> file, and it brought the bundle size down to 661KB, so only 70KB more than Elm, but with the surprise that in the gzipped files the values are reversed:</p>

<ul>
  <li>Preact 155 KB (gzipped)</li>
  <li>Elm 187 KB (gzipped)</li>
</ul>

<p>So even at this point I struggle to say that Elm provides a real advantage in terms of bundle size. But we have not finished yet. We can try to replace the entire cumbersome Redux machinery with the leaner Zustand, which should further lower the values.</p>

<h1 id="third-step-replace-redux-toolkit-with-zustand">Third step: replace Redux Toolkit with Zustand</h1>

<p>Zustand can support a pattern very similar to Redux Toolkit, so the replacement took little effort. Unfortunately, in the process I had to add <code class="language-plaintext highlighter-rouge">Dayjs</code>, a library to handle dates. I tried to do without it, but JavaScript’s native <code class="language-plaintext highlighter-rouge">Date</code> is notoriously flawed and was causing a bug.</p>

<p>So, all considered, the new bundle sizes are:</p>

<ul>
  <li>629 KB (vs 590 KB Elm version)</li>
  <li>gZipped: 147 KB (vs 182 KB Elm version)</li>
</ul>

<p>So it’s hard to say which one is the best—I would call it a draw.</p>

<h1 id="fourth-step-simplify-the-code">Fourth step: simplify the code</h1>

<p>Now I have a last step to take: write the React code in a more idiomatic way. This should remove some layers of indirection and trim some more KBs from the bundle. But I don’t expect miracles here, and I won’t be able to do that until the rollout of the React version is completed.</p>

<h1 id="conclusions">Conclusions</h1>

<p>I think this experiment is interesting because it is about a real-life scenario and application, and it doesn’t happen often that you have the chance to write the exact same application in Elm and React and be able to compare the output.</p>

<p>The results, while confirming that Elm produces really small assets, also indicate that the gap can be practically eliminated, so this should definitely be a point of attention but not a showstopper in the decision process of migrating from Elm to React.</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Experiments" /><summary type="html"><![CDATA[I discovered Elm around 2016, and I immediately fell in love with it. At the time I was working on a fairly complex e-commerce website using jQuery and a custom front-end framework using a pub/sub architecture. Our code was a mess: there was a lot of repetition, bugs seemed to reproduce overnight, and there was always a new one. It was very difficult to orchestrate the different parts of the UI. Given this state of things, Elm was a welcome ray of light. The type system, the compiler, the one-way data flow architecture—they all could have helped solve the pain points we were suffering from. I tried to push for its use in the company, but without success. After a couple of years, I switched companies and tech stacks. Now I was working full-time on React projects. I tried to push Elm even in my new workplace, but the result was the same: nobody was interested. Then years passed. I worked more and more on React, and since I couldn’t use Elm, I tried to port some of its principles to React: the type system with TypeScript, the one-way data flow with Redux, and the functional paradigm, trying to embrace the functional side of JavaScript. Fast forward to 2024, I switched companies once more. Now I was working full-time on Elm—hooray! But the thing is that in those 10 years or so, the JS-based ecosystem had evolved a lot, while Elm had not. A lot of the issues we used to have using jQuery to write imperative spaghetti code were solved by the plethora of declarative and reactive front-end frameworks that had emerged. The lack of static types was patched by TypeScript, and, man, TypeScript is not perfect, but its duck typing approach hits a sweet spot between safety and flexibility, and its type system is really powerful. Finally, some nice functional utilities were added to JavaScript, such as map, filter, and so on. On the other hand, Elm continued to suffer from the same pain points: it lacks support for a lot of (and ever-increasing) browser APIs, it doesn’t allow interactive debugging (and this really hurts when you have to troubleshoot a weird bug in production), and it has very limited options to handle CSS. It makes it very difficult to do some trivial things, like getting a timestamp or a random number. On top of that, it is very difficult to find people who are proficient in it, or even willing to learn it. Like it or not, it has been rejected by the front-end community. So in the end, our team decided that it was better to replace Elm with React (+ TypeScript). And we are doing it. One of the things that worried me was the size of the final bundle. Elm is famous for producing small assets, while React is notoriously quite heavy. Here are the results of this experiment.]]></summary></entry><entry><title type="html">Switch cases exhaustive check in TypeScript like Elm does</title><link href="https://fbedussi.github.io/blog//blog/tips/switch-exhaustive-checker" rel="alternate" type="text/html" title="Switch cases exhaustive check in TypeScript like Elm does" /><published>2025-11-06T00:00:00+00:00</published><updated>2025-11-06T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/tips/switch%20exhaustive%20checker</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/tips/switch-exhaustive-checker"><![CDATA[<p>One of the strong guarantees Elm offers is the exhaustive check that makes it impossible to forget to handle a possible branch in a <code class="language-plaintext highlighter-rouge">case</code> statement.</p>

<p>For instance, here:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="kt">T</span> <span class="o">=</span> <span class="kt">A</span> <span class="o">|</span> <span class="kt">B</span>

<span class="n">test</span> <span class="o">=</span>
    <span class="k">let</span>
        <span class="n">c</span> <span class="p">:</span> <span class="kt">T</span>
        <span class="n">c</span> <span class="o">=</span> <span class="kt">A</span>
    <span class="k">in</span>
    <span class="k">case</span> <span class="n">c</span> <span class="k">of</span>
        <span class="kt">A</span> <span class="o">-&gt;</span>
            <span class="kt">Debug</span><span class="o">.</span><span class="n">log</span> <span class="s">"</span><span class="s2">A"</span> <span class="s">"</span><span class="s2">"</span>

        <span class="kt">B</span> <span class="o">-&gt;</span> 
            <span class="kt">Debug</span><span class="o">.</span><span class="n">log</span> <span class="s">"</span><span class="s2">B"</span> <span class="s">"</span><span class="s2">"</span>
</code></pre></div></div>

<p>If we don’t handle the <code class="language-plaintext highlighter-rouge">B</code> case the compiler complains:</p>

<blockquote>
  <p>This <code class="language-plaintext highlighter-rouge">case</code> does not have branches for all possibilities.
Missing possibilities include:
 B</p>
</blockquote>

<p>This is a nice feature, because if later on we add a new variant to the type <code class="language-plaintext highlighter-rouge">T</code> the compiler will remind us to handle the new branch in the <code class="language-plaintext highlighter-rouge">case</code> statement.</p>

<p>It is possible to have something very similar also with TypeScript, both with an <a href="https://typescript-eslint.io/rules/switch-exhaustiveness-check/">eslint rule</a> and with a clever use of <code class="language-plaintext highlighter-rouge">never</code>:</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">T</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">a</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">b</span><span class="dl">'</span>

<span class="kd">const</span> <span class="nx">c</span><span class="p">:</span> <span class="nx">T</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mf">0.5</span> <span class="p">?</span> <span class="dl">'</span><span class="s1">a</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">b</span><span class="dl">'</span>

<span class="k">switch</span> <span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">case</span> <span class="dl">'</span><span class="s1">a</span><span class="dl">'</span><span class="p">:</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">a</span><span class="dl">'</span><span class="p">)</span>
    <span class="k">break</span>
  <span class="k">case</span> <span class="dl">'</span><span class="s1">b</span><span class="dl">'</span><span class="p">:</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">b</span><span class="dl">'</span><span class="p">)</span>
    <span class="k">break</span>
  <span class="k">default</span><span class="p">:</span>
    <span class="kd">const</span> <span class="nx">_exhaustiveCheck</span><span class="p">:</span> <span class="nx">never</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
<span class="p">}</span> 
</code></pre></div></div>

<p>If you forget one case (e.g. the second one) the compiler will report the error:</p>

<blockquote>
  <p>Type ‘“b”’ is not assignable to type ‘never’.</p>
</blockquote>

<p>Check it out in this <a href="https://www.typescriptlang.org/play/?#code/C4TwDgpgBAKlC8UDkBDJUA+yBGSBQeAxgPYB2AzsFIQFywJQCyKwAFgHQBOKpAJsQFsAFAEooAPigAGdgFYoAfmRoodJLgLkA7gEtghVlCGExAbzxRqKctFRIaFy9TLliAGwjs3xAOZC7Io6W2JwQKADWjoTWtrgOTs4U7p7efupIgQkhYZGWvBAAZigArm7A8U4kFFQA+hAAHqwllDoAbhAAwqwQhOF0pBDtnAyEANx4AL5QQA">live example</a>.</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Tips" /><summary type="html"><![CDATA[One of the strong guarantees Elm offers is the exhaustive check that makes it impossible to forget to handle a possible branch in a case statement. For instance, here: type T = A | B test = let c : T c = A in case c of A -&gt; Debug.log "A" "" B -&gt; Debug.log "B" "" If we don’t handle the B case the compiler complains: This case does not have branches for all possibilities. Missing possibilities include: B This is a nice feature, because if later on we add a new variant to the type T the compiler will remind us to handle the new branch in the case statement. It is possible to have something very similar also with TypeScript, both with an eslint rule and with a clever use of never: type T = 'a' | 'b' const c: T = Math.random() &gt; 0.5 ? 'a' : 'b' switch (c) { case 'a': console.log('a') break case 'b': console.log('b') break default: const _exhaustiveCheck: never = c; } If you forget one case (e.g. the second one) the compiler will report the error: Type ‘“b”’ is not assignable to type ‘never’. Check it out in this live example.]]></summary></entry><entry><title type="html">I just changed my mind about comments in code</title><link href="https://fbedussi.github.io/blog//blog/opinions/I-just-changed-my-mind-about-comments-in-code" rel="alternate" type="text/html" title="I just changed my mind about comments in code" /><published>2025-06-29T00:00:00+00:00</published><updated>2025-06-29T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/opinions/I%20just%20changed%20my%20mind%20about%20comments%20in%20code</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/opinions/I-just-changed-my-mind-about-comments-in-code"><![CDATA[<p>As with other things in life, professional growth often follows 3 steps:</p>

<ul>
  <li>blind acceptance: when you start learning something you treat what is being taught to you as the word of God. That is the way to do things.</li>
  <li>denial: after a while you start to realize that real life scenarios are very different from the ones in textbooks (or in blog posts), so they require something different from the rules you learned.</li>
  <li>compromise: when your expertise increases even more you understand that yes, reality is different from theory, but the theory can still be applied, even if with a grain of salt and not in a mechanical way</li>
</ul>

<p>I followed this path even about comments in code.</p>

<!--more-->

<p>When I started learning programming (deh, it was so loooooong ago) every programming book said that comments were good. Comments made the code more readable. So I wrote comments. A lot of comments.</p>

<p>Then, reading both my code and others’ code, I realized that comments made more harm than good. First of all comments were often used to clarify obscure code. But in that case the real solution is to write code that is not obscure in the first place. Write clear code. Write self documented code. Second, when reading a comment there is no way to know if the comment is still relevant or if it is now outdated. Basically you can never trust a comment. There is always the chance that it went out of sync with the code. The code itself is the only source of truth.</p>

<p>So I made a U turn and started to write no comments at all. I even deleted all the comments every time I was refactoring existing code. Less is more. Let the code speak by itself.</p>

<p>And I went on with this “no comment policy” for quite a long time. Until recently I read “<a href="https://www.goodreads.com/en/book/show/39996759-a-philosophy-of-software-design">A philosophy of Software Design</a>”. This book made me realize a very simple truth: yes you can (and should) write code in such a way that is very clear <strong>what</strong> it is doing, but sometimes it cannot tell <strong>why</strong> it is doing it. This is where you need comments. So comments should never be a duplication of the code, they should be at an upper level of abstraction.</p>

<p>Let’s make an example, this code is probably obscure enough:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>for (let i=0;i &lt; items.length; i++) {
    for (const property in items[i]) {
        if (items[i][property] === undefined) {
            delete items[i][property]
        }
    }
}
</code></pre></div></div>

<p>that is better to clarify with a comment:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// remove undefined fields from items
for (let i=0;i &lt; items.length; i++) {
    for (const property in items[i]) {
        if (items[i][property] === undefined) {
            delete items[i][property]
        }
    }
}
</code></pre></div></div>

<p>but it is even better to rewrite it to be self documenting:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function removeUndefinedFields(obj) {
    Object.entries(obj).forEach(([key, value]) =&gt; {
        if (value === undefined) {
            delete obj[key]
        }
    })
    return obj
}

const sanitizedItems = items.map(item =&gt; removeUndefinedFields(item))
</code></pre></div></div>

<p>It’s slightly longer, but it’s much easier to understand what is going on. We even have a clue of why we are removing <code class="language-plaintext highlighter-rouge">undefined</code> fields, we are kind of sanitizing the data. But why exactly do we need this sanitization? If we don’t know this crucial piece of information we cannot answer the questions that may arise during a refactoring:</p>
<ul>
  <li>Do we still need this step?</li>
  <li>Can we delete it?</li>
  <li>Should we make it more robust stripping also <code class="language-plaintext highlighter-rouge">null</code> fields?</li>
</ul>

<p>This is why we need to add this comment:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// undefined fields cause errors when saving to Firebase
const sanitizedItems = items.map(item =&gt; removeUndefinedFields(item))
</code></pre></div></div>

<p>Ah! Now we have all the answers:</p>
<ul>
  <li>Do we still need this step? If we are still using Firebase to save data, and if Firebase still doesn’t allow <code class="language-plaintext highlighter-rouge">undefined</code> fields, yes, we need it</li>
  <li>Can we delete it? It depends on the answer to the first question</li>
  <li>Should we make it more robust stripping also <code class="language-plaintext highlighter-rouge">null</code> fields? No, this is not needed and may cause regressions</li>
</ul>

<p>So, yes, comments are often abused, like in:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// initializing the count variable
const count = 0
</code></pre></div></div>

<p>These comments are useless in the best case scenario, harmful in the worst one. They should be avoided and even deleted if you or someone else already wrote them. But there is definitely a use case for comments every time we need to document why we are doing something, or why we are doing it in a way that may seem odd at first glance. And God knows how often this happens in real life coding. So yes, books were right after all, comments can improve code readability, even in practice.</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Opinions" /><summary type="html"><![CDATA[As with other things in life, professional growth often follows 3 steps: blind acceptance: when you start learning something you treat what is being taught to you as the word of God. That is the way to do things. denial: after a while you start to realize that real life scenarios are very different from the ones in textbooks (or in blog posts), so they require something different from the rules you learned. compromise: when your expertise increases even more you understand that yes, reality is different from theory, but the theory can still be applied, even if with a grain of salt and not in a mechanical way I followed this path even about comments in code.]]></summary></entry><entry><title type="html">The @font-face rule does not work in the shadow DOM</title><link href="https://fbedussi.github.io/blog//blog/til/The-font-face-rule-does-not-work-in-the-shadow-DOM" rel="alternate" type="text/html" title="The @font-face rule does not work in the shadow DOM" /><published>2025-04-01T00:00:00+00:00</published><updated>2025-04-01T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/til/The%20font-face%20rule%20does%20not%20work%20in%20the%20shadow%20DOM</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/til/The-font-face-rule-does-not-work-in-the-shadow-DOM"><![CDATA[<p>Yesterday I found out that <a href="https://fbedussi.github.io/blog/til/The-style-inside-the-shadow-DOM-is-less-isolated-than-I-thought">the shadow DOM is less isolated than I thought</a>, but there’s another quirk that completely bewildered me: the <code class="language-plaintext highlighter-rouge">@font-face</code> rule does not work in the shadow DOM. Yes, it’s that simple and that frustrating.</p>

<!--more-->

<p>Here’s a live demo demonstrating the issue:</p>

<iframe height="300" style="width: 100%;" scrolling="no" title="@font-face does not work in shadow DOM" src="https://codepen.io/fbedussi/embed/WbNYmyR?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href="https://codepen.io/fbedussi/pen/WbNYmyR">
  @font-face does not work in shadow DOM</a> by Francesco Bedussi (<a href="https://codepen.io/fbedussi">@fbedussi</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>

<p>This is apparently a <a href="https://issues.chromium.org/issues/41085401">long-standing issue</a> due to the technical complexities in implementing support for the <code class="language-plaintext highlighter-rouge">@font-face</code> rule in the shadow tree, even though the <a href="https://drafts.csswg.org/css-scoping/#shadow-names">CSS specifications</a> define that it should work.</p>

<p>The only workaround is to declare the fonts at the document level, outside of any shadow DOM. This defeats one of the main purposes of using shadow DOM: creating truly encapsulated, self-contained components.</p>

<p>Another nail in the coffin of the shadow DOM, unfortunately. For projects requiring custom fonts in components, this limitation can be a deal-breaker.</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="TIL" /><summary type="html"><![CDATA[Yesterday I found out that the shadow DOM is less isolated than I thought, but there’s another quirk that completely bewildered me: the @font-face rule does not work in the shadow DOM. Yes, it’s that simple and that frustrating.]]></summary></entry><entry><title type="html">The style inside the shadow DOM is less isolated than I thought</title><link href="https://fbedussi.github.io/blog//blog/til/The-style-inside-the-shadow-DOM-is-less-isolated-than-I-tought" rel="alternate" type="text/html" title="The style inside the shadow DOM is less isolated than I thought" /><published>2025-03-23T00:00:00+00:00</published><updated>2025-03-23T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/til/The%20style%20inside%20the%20shadow%20DOM%20is%20less%20isolated%20than%20I%20tought</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/til/The-style-inside-the-shadow-DOM-is-less-isolated-than-I-tought"><![CDATA[<p>Over the years, I’ve experimented with the shadow DOM several times but never had the chance to use it in a real project. One of the main limitations that held me back was my understanding that styles inside the shadow DOM are completely isolated from outside styles. This would make it difficult to build components as part of the same application, where you typically want components to share at least some common styling. So I made a mental note to use shadow DOM only when I needed 100% style isolation.</p>

<p>Today that day finally came! I had a perfect use case requiring complete isolation! I eagerly pulled the shadow DOM from my toolbox where it had been waiting for so long. But wait—what’s happening? Why is the text inside my shadow DOM adopting styles from outside?</p>

<!--more-->

<p>It turns out my mental model of how shadow DOM works was flawed. The style encapsulation is strong but not absolute. I already knew that custom properties (CSS variables) can pierce the shadow boundary, but I discovered that inheritable properties also flow through. There are many <a href="https://gist.github.com/dcneiner/1137601">inheritable properties</a>, with the most commonly used being those related to typography:</p>

<ul>
  <li>color</li>
  <li>font-family</li>
  <li>font-size</li>
  <li>font-style</li>
  <li>font-variant</li>
  <li>font-weight</li>
  <li>font</li>
  <li>letter-spacing</li>
  <li>line-height</li>
  <li>text-align</li>
  <li>text-transform</li>
  <li>white-space</li>
  <li>word-spacing</li>
</ul>

<p>This explains why text within my shadow DOM was picking up global styles. Unfortunately, this discovery—combined with the fact that <a href="https://fbedussi.github.io/blog/til/The-font-face-rule-does-not-work-in-the-shadow-DOM"><code class="language-plaintext highlighter-rouge">@font-face</code> rules don’t work inside shadow DOM</a>—triggered a redesign of my approach. I ultimately had to abandon shadow DOM for this project and return it to my toolbox once again. One damned shadow DOM! One day you’ll be mine!</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="TIL" /><summary type="html"><![CDATA[Over the years, I’ve experimented with the shadow DOM several times but never had the chance to use it in a real project. One of the main limitations that held me back was my understanding that styles inside the shadow DOM are completely isolated from outside styles. This would make it difficult to build components as part of the same application, where you typically want components to share at least some common styling. So I made a mental note to use shadow DOM only when I needed 100% style isolation. Today that day finally came! I had a perfect use case requiring complete isolation! I eagerly pulled the shadow DOM from my toolbox where it had been waiting for so long. But wait—what’s happening? Why is the text inside my shadow DOM adopting styles from outside?]]></summary></entry><entry><title type="html">The joy of classless CSS frameworks</title><link href="https://fbedussi.github.io/blog//blog/opinions/The-joy-of-classless-CSS-frameworks" rel="alternate" type="text/html" title="The joy of classless CSS frameworks" /><published>2025-03-22T00:00:00+00:00</published><updated>2025-03-22T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/opinions/The%20joy%20of%20classless%20CSS%20frameworks</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/opinions/The-joy-of-classless-CSS-frameworks"><![CDATA[<p>Suppose you are building a simple page or application, maybe for internal or personal use. Suppose you don’t need anything fancy—just a good-looking form, some buttons, a headline here, and some text there. Oh, and I almost forgot—a nice modal to give feedback to the user. What will you do? Reach for a fully-fledged CSS framework like Bootstrap? (By the way, is it even used anymore?) Use a complete UI kit like Material UI? Those are clearly overkill. So what’s the alternative? Will you write all the CSS from scratch? That would be tedious.</p>

<p>Luckily, there’s a third way: you can use a mini CSS framework—or even better, a classless one.</p>

<!--more-->

<p>A classless CSS framework is, in essence, just a stylesheet that defines good-looking styles for standard HTML elements. All you have to do is include it in your page and write some semantic HTML—that’s it. No need for a CSS reset, almost no need for custom styling, and no need for a complex framework or component library.</p>

<p>Obviously, this approach doesn’t work for every use case, but if you’re working on a simple page or app and don’t have specific design requirements, you should really give it a try.</p>

<p>Recently, I’ve been playing around with Pico CSS. It offers different flavors, including various color schemes. You can download the CSS files or use them via a CDN. It provides a nice set of predefined UI elements and is very easy to extend, thanks to a well-structured set of CSS custom properties for things like colors and spacing.</p>

<p>To achieve a result like this, it took me just a few minutes of tweaking and around 20 lines of custom CSS:</p>

<p><img src="https://fbedussi.github.io/blog/assets/images/fake-login.png" alt="" /></p>

<p>Here’s an extract of the HTML source:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;header&gt;</span>
        <span class="nt">&lt;hgroup&gt;</span>
            <span class="nt">&lt;h1&gt;</span>Conversion Sales Flow Front End<span class="nt">&lt;/h1&gt;</span>
            <span class="nt">&lt;p&gt;</span>Fake Login<span class="nt">&lt;/p&gt;</span>
        <span class="nt">&lt;/hgroup&gt;</span>
        <span class="nt">&lt;label&gt;</span>
            <span class="nt">&lt;input</span> <span class="na">name=</span><span class="s">"use_json"</span> <span class="na">type=</span><span class="s">"checkbox"</span> <span class="na">role=</span><span class="s">"switch"</span> <span class="nt">/&gt;</span>
            Free payload
        <span class="nt">&lt;/label&gt;</span>
    <span class="nt">&lt;/header&gt;</span>

    <span class="nt">&lt;dialog&gt;</span>
        <span class="nt">&lt;article&gt;</span>
            <span class="nt">&lt;header&gt;</span>
                <span class="nt">&lt;form</span> <span class="na">method=</span><span class="s">"dialog"</span><span class="nt">&gt;</span>
                    <span class="nt">&lt;button</span> <span class="na">aria-label=</span><span class="s">"Close"</span> <span class="na">rel=</span><span class="s">"prev"</span><span class="nt">&gt;&lt;/button&gt;</span>
                <span class="nt">&lt;/form&gt;</span>
                <span class="nt">&lt;p&gt;</span>
                    <span class="nt">&lt;strong&gt;</span>Error<span class="nt">&lt;/strong&gt;</span>
                <span class="nt">&lt;/p&gt;</span>
            <span class="nt">&lt;/header&gt;</span>
            <span class="nt">&lt;p&gt;&lt;/p&gt;</span>
        <span class="nt">&lt;/article&gt;</span>
    <span class="nt">&lt;/dialog&gt;</span>

    <span class="nt">&lt;main&gt;</span>
        <span class="nt">&lt;form&gt;</span>
            <span class="nt">&lt;fieldset&gt;</span>
                <span class="nt">&lt;label&gt;</span>
                    User ID*
                    <span class="nt">&lt;input</span> <span class="na">name=</span><span class="s">"user_id"</span> <span class="na">required</span> <span class="na">value=</span><span class="s">"fake-user"</span> <span class="nt">/&gt;</span>
                <span class="nt">&lt;/label&gt;</span>

                <span class="nt">&lt;fieldset&gt;</span>
                    <span class="nt">&lt;label&gt;</span>
                        Resource id*
                        <span class="nt">&lt;input</span> <span class="na">name=</span><span class="s">"resource_id"</span> <span class="na">required</span> <span class="nt">/&gt;</span>
                    <span class="nt">&lt;/label&gt;</span>

                    <span class="nt">&lt;fieldset&gt;</span>
                        <span class="nt">&lt;legend&gt;</span>Resource type*<span class="nt">&lt;/legend&gt;</span>
                        <span class="nt">&lt;div&gt;</span>
                            <span class="nt">&lt;label&gt;</span>
                                <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"radio"</span> <span class="na">name=</span><span class="s">"resource_type"</span> <span class="na">value=</span><span class="s">"offer"</span> <span class="na">required</span> <span class="na">checked</span> <span class="nt">/&gt;</span>
                                Offer
                            <span class="nt">&lt;/label&gt;</span>
                            <span class="nt">&lt;label&gt;</span>
                                <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"radio"</span> <span class="na">name=</span><span class="s">"resource_type"</span> <span class="na">value=</span><span class="s">"quote"</span> <span class="na">required</span> <span class="nt">/&gt;</span>
                                Quote
                            <span class="nt">&lt;/label&gt;</span>
                        <span class="nt">&lt;/div&gt;</span>
                    <span class="nt">&lt;/fieldset&gt;</span>
                <span class="nt">&lt;/fieldset&gt;</span>
</code></pre></div></div>

<p>I really like it—it’s clean and concise (yes, Tailwind, I’m looking at you…). It’s also very easy to modify because you don’t have to worry too much about styling. As long as you’re writing sensible HTML, the result will automatically look good and consistent. And as I mentioned, you don’t even need a CSS reset anymore.</p>

<p>So, this is definitely one more tool in my “no-stress front-end” toolbox.</p>

<p>What do you think about classless CSS frameworks? Let me know in the comments!</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Opinions" /><summary type="html"><![CDATA[Suppose you are building a simple page or application, maybe for internal or personal use. Suppose you don’t need anything fancy—just a good-looking form, some buttons, a headline here, and some text there. Oh, and I almost forgot—a nice modal to give feedback to the user. What will you do? Reach for a fully-fledged CSS framework like Bootstrap? (By the way, is it even used anymore?) Use a complete UI kit like Material UI? Those are clearly overkill. So what’s the alternative? Will you write all the CSS from scratch? That would be tedious. Luckily, there’s a third way: you can use a mini CSS framework—or even better, a classless one.]]></summary></entry><entry><title type="html">What I learned refactoring a medium sized Elm project</title><link href="https://fbedussi.github.io/blog//blog/opinions/What-I-learned-refactoring-a-medium-sized-Elm-project" rel="alternate" type="text/html" title="What I learned refactoring a medium sized Elm project" /><published>2025-02-01T00:00:00+00:00</published><updated>2025-02-01T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/opinions/What%20I%20learned%20refactoring%20a%20medium%20sized%20Elm%20project</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/opinions/What-I-learned-refactoring-a-medium-sized-Elm-project"><![CDATA[<p>Recently I’ve been busy refactoring a medium sized Elm project. The refactor was needed because the code base had grown over the years and had become very contrived and difficult to understand. That is why it was difficult to change and evolve.</p>

<p>During this activity I learned some lessons that I’d like to share. Probably not everyone will agree on every point, but let me know in the comments if you have different opinions.</p>

<!--more-->

<h2 id="1-start-a-big-refactor-only-if-you-have-a-solid-functional-test-suite">1. Start a big refactor only if you have a solid functional test suite</h2>

<p>I’ve been able to complete this big refactor only because the project had a quite comprehensive suite of functional tests, written in Cypress, and so totally independent from the implementation.</p>

<p>Unfortunately the compiler alone is not enough. No matter what someone says, “if it compiles, it works” is just not true. To successfully refactor a non trivial code base you need both: a good compiler and a good set of tests that do not depend on the implementation, so they will not break when the implementation changes. In the front end world this means tests that run in the browser against the actual page/app. Cypress, Playwright or another tool, it doesn’t matter, as long as they check that the final result is not broken.</p>

<h2 id="2-proceed-in-tiny-steps">2. Proceed in tiny steps</h2>

<p>Change one thing at a time, and make sure the code compiles and the tests pass before taking the next step. In this way it is easier to fix any error that should happen. Every time I tried to refactor “also this, since I’m already doing that” I had to roll back, and redo the job one step at a time.</p>

<h2 id="3-do-not-persist-derived-data-in-the-model">3. Do not persist derived data in the model</h2>

<p>This is dangerous because it is basically caching data, and this brings in all the cache related issues: updating and invalidating. As long as there aren’t performance issues, derived data should be computed on the fly from a unique source of truth. If and when there are performance issue solve them with the dedicated tools (https://guide.elm-lang.org/optimization/lazy.html).</p>

<p>Just by removing derived data from the model I could delete quite a lot of code and dramatically reduce the complexity of the system.</p>

<h2 id="4-avoid-useless-code">4. Avoid useless code</h2>

<p>There is some code that is just useless, like pickers that just pick a field, without any transformation, like this:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pickText</span> <span class="p">:</span> <span class="kt">Article</span> <span class="o">-&gt;</span> <span class="kt">String</span>
<span class="n">pickText</span> <span class="p">{</span><span class="n">text</span><span class="p">}</span> <span class="o">=</span>
    <span class="n">text</span>
</code></pre></div></div>

<p>For this use case the Elm provides the field accessor function for free (<code class="language-plaintext highlighter-rouge">.text</code> in this case). True, using <code class="language-plaintext highlighter-rouge">.text</code> we are coupling the calling code with the exact name of the field, but if everything lives inside the same code base that is not a problem. If we would ever change the field name we can easily do that automatically with every editor/IDE (if the editor you are using doesn’t allow code wide rename, change it!).</p>

<p>Using the build in field accessor not only spares some lines of code, but is even mode secure, because when we write <code class="language-plaintext highlighter-rouge">.text</code> we are sure that we are actually taking the <code class="language-plaintext highlighter-rouge">text</code> field, while nothing prevents this to happen:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pickText</span> <span class="p">:</span> <span class="kt">Article</span> <span class="o">-&gt;</span> <span class="kt">String</span>
<span class="n">pickText</span> <span class="p">{</span><span class="n">title</span><span class="p">}</span> <span class="o">=</span>
    <span class="n">title</span>
</code></pre></div></div>

<p>Pickers can be used if there is some logic in accessing the data:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pickPrice</span> <span class="p">:</span> <span class="kt">Prices</span> <span class="o">-&gt;</span> <span class="kt">Int</span>
<span class="n">pickPrice</span> <span class="p">{</span> <span class="n">currentAmount</span><span class="o">,</span> <span class="n">baseAmount</span> <span class="p">}</span> <span class="o">=</span>
    <span class="k">if</span> <span class="n">currentAmount</span> <span class="o">&gt;</span> <span class="n">baseAmount</span> <span class="k">then</span>
        <span class="n">currentAmount</span>

    <span class="k">else</span>
        <span class="n">baseAmount</span>
</code></pre></div></div>

<p>Another type of useless code are functions that are basically just wrappers of other functions, like this:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">updatedAgentTools</span> <span class="o">=</span> <span class="n">updateInputAmount</span> <span class="n">agentTools</span> <span class="n">amountAsString</span>

<span class="n">updateInputAmount</span> <span class="n">agentTools</span> <span class="n">amountAsString</span> <span class="o">=</span>
    <span class="n">amountAsString</span>
        <span class="o">|&gt;</span> <span class="kt">String</span><span class="o">.</span><span class="n">toInt</span>  
        <span class="o">|&gt;</span> <span class="kt">Maybe</span><span class="o">.</span><span class="n">map</span> <span class="p">(</span><span class="n">updateAgentToolsInputAmount</span> <span class="n">agentTools</span><span class="p">)</span>
        <span class="o">|&gt;</span> <span class="kt">Maybe</span><span class="o">.</span><span class="n">withDefault</span> <span class="n">agentTools</span>

<span class="n">updateAgentToolsInputAmount</span> <span class="p">:</span> <span class="kt">AgentTools</span> <span class="o">-&gt;</span> <span class="kt">Int</span> <span class="o">-&gt;</span> <span class="kt">AgentTools</span>
<span class="n">updateAgentToolsInputAmount</span> <span class="n">agentTools</span> <span class="n">inputAmount</span> <span class="o">=</span>
    <span class="p">{</span> <span class="n">agentTools</span> <span class="o">|</span> <span class="n">inputAmount</span> <span class="o">=</span> <span class="n">inputAmount</span> <span class="p">}</span>
</code></pre></div></div>

<p>This was probably written in case the conversion from <code class="language-plaintext highlighter-rouge">String</code> to <code class="language-plaintext highlighter-rouge">Int</code> were needed more than once. But in the end that didn’t happen, and there was just a useless middle layer that can be removed:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">updatedAgentTools</span> <span class="o">=</span> <span class="n">amountAsString</span> 
                        <span class="o">|&gt;</span> <span class="kt">String</span><span class="o">.</span><span class="n">toInt</span>
                        <span class="o">|&gt;</span> <span class="kt">Maybe</span><span class="o">.</span><span class="n">map</span> <span class="p">(</span><span class="n">updateAgentToolsInputAmount</span> <span class="n">agentTools</span><span class="p">)</span>
                        <span class="o">|&gt;</span> <span class="kt">Maybe</span><span class="o">.</span><span class="n">withDefault</span> <span class="n">agentTools</span>    

<span class="n">updateAgentToolsInputAmount</span> <span class="p">:</span> <span class="kt">AgentTools</span> <span class="o">-&gt;</span> <span class="kt">Int</span> <span class="o">-&gt;</span> <span class="kt">AgentTools</span>
<span class="n">updateAgentToolsInputAmount</span> <span class="n">agentTools</span> <span class="n">inputAmount</span> <span class="o">=</span>
    <span class="p">{</span> <span class="n">agentTools</span> <span class="o">|</span> <span class="n">inputAmount</span> <span class="o">=</span> <span class="n">inputAmount</span> <span class="p">}</span>
</code></pre></div></div>

<p>Useless code is not only useless, but it is actually harmful, because it adds an extra level of indirection, making the code more opaque, and difficult to understand.</p>

<h2 id="5-avoid-module-aliases-as-much-as-possible">5. Avoid module aliases as much as possible</h2>

<p>Aliases are nasty because the same module ends up being used with different names in different parts of the code base. This too adds opacity to the system.</p>

<p>To resist the temptation to use aliases, it is useful to keep the module name short. If you have a module name as <code class="language-plaintext highlighter-rouge">View.RightSidebar.PriceRecap</code> it is tempting to alias it as <code class="language-plaintext highlighter-rouge">PriceRecap</code>. The problem is that maybe another dev will alias it as <code class="language-plaintext highlighter-rouge">RightPriceRecap</code> in another module, and it will be difficult to understand at a first glance if both aliases refer to the same module or not.</p>

<p>If you keep the module in the root its name will be just <code class="language-plaintext highlighter-rouge">PriceRecap</code>, so no need to alias it and no room for confusion. If you put it in the <code class="language-plaintext highlighter-rouge">RightSidebar</code> folder its name will be <code class="language-plaintext highlighter-rouge">RightSidebar.PriceRecap</code>, that is short enough to be used without aliasing. This is one of the reason why in Elm it is better to have a flatter file hierarchy than with other languages.</p>

<h2 id="6-avoid-opaque-types">6. Avoid opaque types</h2>

<p>Speaking about opacity, I see that a lot of devs love using opaque types everywhere. I think this is an anti pattern. Opaque types should be used sparingly because they add, well, opacity. There are definitely some use cases for them, but other than that they should be avoided.</p>

<p>Opaque types are basically useful in 2 cases. The first one is when we want to avoid consumer code to access the implementation detail behind a type. But this is really useful when we are writing a library that can be used by many external consumers. In that case it makes sense that we declare a clear and rigid interface that hides the internal implementation. Because we don’t want to force the consumers to change whenever we change our implementation. But this is not the case if we are just writing a module that is part of a unique code base. In that case it is not a problem to refactor the rest of the code if and when we will change the implementation of the module. It can even be done automatically by the IDE, for instance if we change a name. In this case opaque types do more harm than good, because they force you to write a lot of boilerplate, that can include bugs, and that adds another unnecessary level of indirection to the system making it more difficult to understand.</p>

<p>The second use case for opaque types is when you want to enforce particular logic in getting/setting the data, but if you don’t need to, just go with a regular type that can be used without fuss.</p>

<h2 id="7-organize-code-in-modules-by-type-and-not-by-concern">7. Organize code in modules by type, and not by concern</h2>

<p>This is the advice of the <a href="https://guide.elm-lang.org/webapps/modules">official guide</a>, but I see that a lot of devs apply patterns from other languages, for example separating the views, the model and the business logic in different files. In Elm this leads to unneeded extra complexity, a symptom of which is the necessity to export/import a lot of things. If you group all the code related to a specific type in the same module you’ll end up with a better isolation, that reduces the complexity of the system.</p>

<p>This is another reason to keep the file hierarchy flatter than with other languages, for example, instead of</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>my-app/
Main.elm
Model/
├─ Article.elm
├─ Comments.elm/
├─ Author.elm
Views/
├─ Page.elm
├─ Subviews/
│  ├─ Article.elm
│  ├─ Comment.elm
│  ├─ Avatar.elm
Helpers/
├─ Article.elm
├─ Comment.elm
├─ Author.elm
</code></pre></div></div>

<p>it is better to have just:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>my-app/
Main.elm
Author.elm
Article.elm
Comments.elm/
</code></pre></div></div>

<p>It is not a big deal if an Elm file is quite long, 1000 lines is still fine.</p>

<h2 id="8-avoid-too-much-functional-magic">8. Avoid too much functional magic</h2>

<p>Some functional constructs can be pretty obscure for devs that are new to functional programming, so it is probably better to avoid them, if we want to make our code base more readable, even to newcomers.</p>

<p>For instance, function composition allows to save some keystrokes, but is it really worth it?</p>

<p>Is this</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">isFoo</span> <span class="p">:</span> <span class="kt">MyType</span> <span class="o">-&gt;</span> <span class="kt">Bool</span>
<span class="n">isFoo</span> <span class="o">=</span>
    <span class="o">.</span><span class="n">slug</span> <span class="o">&gt;&gt;</span> <span class="kt">Slug</span><span class="o">.</span><span class="n">equal</span> <span class="kt">Slug</span><span class="o">.</span><span class="n">foo</span>
</code></pre></div></div>

<p>really better than this:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">isFoo</span> <span class="p">:</span> <span class="kt">MyType</span> <span class="o">-&gt;</span> <span class="kt">Bool</span>
<span class="n">isFoo</span> <span class="n">myType</span> <span class="o">=</span>
    <span class="n">myType</span><span class="o">.</span><span class="n">slug</span> <span class="o">|&gt;</span> <span class="kt">Slug</span><span class="o">.</span><span class="n">equal</span> <span class="kt">Slug</span><span class="o">.</span><span class="n">foo</span>
</code></pre></div></div>

<p>or even better:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">isFoo</span> <span class="p">:</span> <span class="kt">MyType</span> <span class="o">-&gt;</span> <span class="kt">Bool</span>
<span class="n">isFoo</span> <span class="n">myType</span> <span class="o">=</span>
    <span class="kt">Slug</span><span class="o">.</span><span class="n">equal</span> <span class="kt">Slug</span><span class="o">.</span><span class="n">foo</span> <span class="n">myType</span><span class="o">.</span><span class="n">slug</span>
</code></pre></div></div>

<p>Function composition is often used to avoid writing anonymous functions like in this case:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">List</span><span class="o">.</span><span class="n">filter</span> <span class="p">(</span><span class="o">.</span><span class="n">place</span> <span class="o">&gt;&gt;</span> <span class="o">.</span><span class="n">provinceNameShort</span> <span class="o">&gt;&gt;</span> <span class="p">(</span><span class="o">==</span><span class="p">)</span> <span class="n">provinceShort</span><span class="p">)</span> <span class="n">provinces</span>
</code></pre></div></div>

<p>but isn’t it better to be a little bit more explicit and write:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">List</span><span class="o">.</span><span class="n">filter</span> <span class="p">(</span><span class="o">\</span><span class="n">province</span> <span class="o">-&gt;</span> <span class="n">province</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">provinceNameShort</span> <span class="o">==</span> <span class="n">provinceShort</span><span class="p">)</span> <span class="n">provinces</span>
</code></pre></div></div>

<p>In the snippet above the equality operator is used as a function, this is another pattern that can be quite confusing, especially if the operator is asymmetric. If you write</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">applyDiscount</span> <span class="p">:</span> <span class="kt">Int</span> <span class="o">-&gt;</span> <span class="kt">Bool</span>
<span class="n">applyDiscount</span> <span class="n">price</span> <span class="o">=</span>
    <span class="n">price</span> 
        <span class="o">|&gt;</span> <span class="p">(</span><span class="o">&lt;</span><span class="p">)</span> <span class="mi">100</span>
</code></pre></div></div>

<p>it’s not clear at a first glance if the intention was to check if price &lt; 100 or the other way around (that is what the code is actually doing). So it’s better to stick with the normal form:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">applyDiscount</span> <span class="p">:</span> <span class="kt">Int</span> <span class="o">-&gt;</span> <span class="kt">Bool</span>
<span class="n">applyDiscount</span> <span class="n">price</span> <span class="o">=</span>
    <span class="n">price</span> <span class="o">&gt;</span> <span class="mi">100</span>
</code></pre></div></div>

<p>To avoid anonymous function sometimes we need to use the <code class="language-plaintext highlighter-rouge">flip</code> function, that, as the name suggests, inverts the order of the parameters of a function.</p>

<p>What’s really happening here?</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">joinMessageParticlesContent</span> <span class="p">:</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">MessageParticle</span> <span class="kt">Msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Html</span> <span class="kt">Msg</span><span class="p">)</span>
<span class="n">joinMessageParticlesContent</span> <span class="o">=</span>
    <span class="kt">List</span><span class="o">.</span><span class="n">concatMap</span> <span class="p">(</span><span class="n">flip</span> <span class="kt">List</span><span class="o">.</span><span class="n">append</span> <span class="p">[</span> <span class="kt">Html</span><span class="o">.</span><span class="n">br</span> <span class="p">[]</span> <span class="p">[]</span> <span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="o">.</span><span class="n">content</span><span class="p">)</span>
</code></pre></div></div>

<p>this:</p>
<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">joinMessageParticlesContent</span> <span class="p">:</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">MessageParticle</span> <span class="kt">Msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Html</span> <span class="kt">Msg</span><span class="p">)</span>
<span class="n">joinMessageParticlesContent</span> <span class="n">messageParticles</span> <span class="o">=</span>
    <span class="n">messageParticles</span> <span class="o">|&gt;</span> <span class="kt">List</span><span class="o">.</span><span class="n">concatMap</span> <span class="p">(</span><span class="o">\</span><span class="n">messageParticle</span> <span class="o">-&gt;</span> <span class="n">messageParticle</span><span class="o">.</span><span class="n">content</span> <span class="o">++</span> <span class="p">[</span> <span class="n">br</span> <span class="p">[]</span> <span class="p">[]</span> <span class="p">]</span> <span class="p">)</span>
</code></pre></div></div>

<p>It is not a case that the <code class="language-plaintext highlighter-rouge">flip</code> function has been removed from the language core.</p>

<h2 id="9-strive-for-simplicity">9. Strive for simplicity</h2>

<p>If a code base is simple, it is easy for every dev to understand it and to change it. Simple code can remain simple iteration after iteration, because if a dev truly understands the code they can refactor their work with confidence, and to get to a simple solution do you need some cycles of refactoring from the initial implementation.</p>

<p>If a code base is complex, it can only become more complex as time goes by, because once a poor dev has found a working implementation of the feature they are working on, they will not dare to refactor it to make it better, for the fear of breaking everything.</p>

<p>The biggest enemies of simplicity are premature optimization and premature abstractions. Stick with the easiest solution as long as you don’t actually need something more complex. Let’s repeat the same code some times before trying to abstract it into a common implementation.</p>

<h2 id="10-dont-overcomplicate-things-just-because-someone-says-that-this-is-the-right-way">10. Don’t overcomplicate things just because someone says that “this is the right way”</h2>

<p>For instance, you don’t need to add a tenth point to a list just because copywriting rules say that a decalogue is a compelling format!</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Opinions" /><summary type="html"><![CDATA[Recently I’ve been busy refactoring a medium sized Elm project. The refactor was needed because the code base had grown over the years and had become very contrived and difficult to understand. That is why it was difficult to change and evolve. During this activity I learned some lessons that I’d like to share. Probably not everyone will agree on every point, but let me know in the comments if you have different opinions.]]></summary></entry><entry><title type="html">The pros and cons of Elm as a Front End language</title><link href="https://fbedussi.github.io/blog//blog/opinions/The-pros-and-cons-of-Elm-as-a-Front-End-language" rel="alternate" type="text/html" title="The pros and cons of Elm as a Front End language" /><published>2024-08-09T00:00:00+00:00</published><updated>2024-08-09T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/opinions/The%20pros%20and%20cons%20of%20Elm%20as%20a%20Front%20End%20language</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/opinions/The-pros-and-cons-of-Elm-as-a-Front-End-language"><![CDATA[<p>Everybody knows that there are a lot of JavaScript Front End frameworks. Their number is so hight, in fact, that it is one of the main sources of the so called JavaScript fatigue.</p>

<p>But not everybody knows that it is possible to build web sites, single page applications and web interfaces in general even without writing a single line of JavaScript. And I’m not talking about a simple static HTML and CSS web page, but about a rich, interactive application.</p>

<p>There are some alternatives to JS, one of them is the C# based <a href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor">Blazor</a>, by Microsoft.</p>

<p>But the one I will focus on in this post is <a href="https://elm-lang.org/">Elm</a>. Elm is a Domain Specific Language to build web interfaces. It is a purely functional language and its main selling proposition is that it prevents runtime exceptions. It has a lot of nice features and some downsides. Let’s take a closer look both at pros and at cons.</p>

<!--more-->

<h2 id="pros-of-using-the-elm-language-for-the-front-end-development">Pros of using the Elm language for the Front End development</h2>

<h3 id="no-runtime-exceptions">No runtime exceptions</h3>

<p>As I said, one of the Elm main benefits is to make it almost impossible to get runtime exceptions in production. This is basically due to its strong and static type system, enforced by the compiler.</p>

<p>Of course, nowadays you can get a static type system also in the JSLand using TypeScript. But with TypeScript there are various escape latches: you can turn off the <code class="language-plaintext highlighter-rouge">strict</code> compiler option, you can use the <code class="language-plaintext highlighter-rouge">any</code> wildcard, and even if you are disciplined enough to avoid these shortcuts, errors can sneak in with values coming from the outside, for instance with responses to HTTP calls. To prevent this from happening you need to use one more tool: a data validator such as <a href="https://zod.dev/">Zod</a>. And be even more disciplined to always use it for all the incoming data.</p>

<h3 id="batteries-included">Batteries included</h3>

<p>So, a second benefit of using Elm is that it replaces a lot of different tools. Not only JavaScript, TypeScript and a validation library, but also:</p>

<ul>
  <li>A templating language (like <a href="https://handlebarsjs.com/">handlebars</a>) or a view library (like <a href="https://react.dev/">React</a>). Using plain Elm functions it is possible to write declarative, safe, data driven, HTML</li>
  <li>A client side routing library, like <a href="https://reactrouter.com/">React Router</a>. Elm has it own system to handle client side routing</li>
  <li>A state manager like <a href="https://redux.js.org/">Redux</a>. Elm has its own architecture to handle the global state. It is called <a href="https://guide.elm-lang.org/architecture/">TEA (The Elm Architecture)</a>, and actually Redux was partially based on it</li>
  <li>A way to manage the page title (with React you need an extra library, like <a href="https://www.npmjs.com/package/react-helmet">Helmet</a> to do that)</li>
  <li>A testing library like <a href="https://jestjs.io/">Jest</a>. <a href="https://package.elm-lang.org/packages/elm-explorations/test/latest">Elm has it own testing library</a> that is part of the core feature, even if the experimental one. Elm test supports also <a href="https://elmprogramming.com/fuzz-testing.html">fuzzy tests</a>, tests that are automatically repeated dozen of times using randomly generated values, with a preference for corner case values, that are more likely to produce bugs: empty strings, strings with weird symbols, zeroes, ecc.</li>
</ul>

<p>The tool chain is also much simpler than the typical JS based one. The Elm compiler takes care of building, bundling and optimizing the code. So there is no need to deal with the intricacies of the Webpack or Vite configuration.</p>

<p>Then, of course, Elm is a purely functional language, with built-in data immutability. So it replaces also:</p>
<ul>
  <li>a functional library, like <a href="https://ramdajs.com/">Ramda</a> or <a href="https://gcanti.github.io/fp-ts/">fp-ts</a></li>
  <li>an immutability library, like <a href="https://immutable-js.com/">immutable.js</a></li>
</ul>

<h3 id="opinionated">Opinionated</h3>

<p>The Elm ecosystem is much simpler than the JS one, and for features that are not strictly part of the language core there is generally only one option, or a small set of options:</p>

<ul>
  <li>There is one formatter, <a href="https://github.com/avh4/elm-format">Elm-format</a>, that cannot be configured, it always formats Elm source code according to a standard set of rules based on the <a href="https://elm-lang.org/docs/style-guide">official Elm Style Guide</a></li>
  <li>There are a couple of linters: <a href="https://github.com/stil4m/elm-analyse">Elm-analyse</a> and <a href="https://package.elm-lang.org/packages/jfmengels/elm-review/latest">Elm-review</a></li>
  <li>There is one official <a href="https://marketplace.visualstudio.com/items?itemName=Elmtooling.elm-ls-vscode">VS Code plugin</a></li>
</ul>

<p>The Elm compiler also enforces some naming rules:</p>
<ul>
  <li>File names must be PascalCase and cannot contain dots</li>
  <li>Module names must match their file name, so module Parser.Utils needs to be in file Parser/Utils.elm</li>
</ul>

<h3 id="performance">Performance</h3>

<p>The compiled Elm code is by default <a href="https://elm-lang.org/news/blazing-fast-html-round-two">quite fast</a>, and <a href="https://elm-lang.org/news/small-assets-without-the-headache">small</a>.</p>

<h3 id="semantic-versioning">Semantic versioning</h3>

<p>Thanks to its types system, Elm can enforce a strict semantic versioning for its packages, this prevents all the errors that can happen in JavaScript when updating the dependencies.</p>

<h3 id="very-stable">Very stable</h3>

<p>Elm is a very stable language that evolves very, very, slowly. It is almost frozen, compared to JS and its ecosystem. The last language release (19.1) was back in 2019. So, yes, to use it you must learn something new, but then this knowledge is capitalized.</p>

<h3 id="interoperable-with-javascript">Interoperable with JavaScript</h3>

<p>Elm is interoperable with JavaScript thanks to a dedicated message system. This allows you to use all the JS features that do not have an Elm version: like the local storage or the web sockets.</p>

<h2 id="cons-of-using-the-elm-language-for-the-front-end-development">Cons of using the Elm language for the Front End development</h2>

<p>As always, life is not a bed of roses, and Elm has also some pain points:</p>
<ul>
  <li>Currently it does not support server side rendering</li>
  <li>It cannot use all the advanced browser APIs, like the indexed DB, the view transition API, and so on. Sure, they can be used via JS, but this adds an extra layer of complexity</li>
  <li>There is not a CSS in Elm solution that uses regular CSS syntax, like <a href="https://styled-components.com/">Styled Components</a> does. There is <a href="https://github.com/rtfeldman/elm-css">Elm css</a>, but it is a complete rewrite of the CSS spec with the Elm syntax. Sure it offers all the Elm guaranties, but, hey, I already know CSS, and I don’t feel any need to learn a new syntax. Even because CSS is a fault tolerant language that cannot generate blocking runtime errors</li>
  <li>The type system is less powerful and flexible than the TypeScript one (for instance there is no <code class="language-plaintext highlighter-rouge">Partial</code>, <code class="language-plaintext highlighter-rouge">Pick</code> or <code class="language-plaintext highlighter-rouge">Omit</code>)</li>
  <li>The ecosystem is very limited, compared to the JS one</li>
  <li>It is not possible to use the dev tools to inspect and debug the source code</li>
</ul>

<p>Beside these technical issues, one thing to consider, if you are planning of using Elm at work, is also that in a team it is more difficult to hire people that knows Elm, or that are open to learn it.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Even with all its limits Elm can be a breath of fresh air, especially if you fall in one or both of these categories:</p>
<ul>
  <li>You like functional programming</li>
  <li>You are suffering some form of JavaScript fatigue</li>
</ul>

<p>Because Elm is quite the opposite of JS. If JS is constantly changing and evolving, Elm is almost frozen. If everything can be done in JS in dozens of different ways, in Elm there is usually only one right or preferred way of doing things. If JS projects require a complex stack of tools and libraries, Elm requires only a limited number of dependencies.</p>

<p>So, give it a try and let me know in the comments your opinions.</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Opinions" /><summary type="html"><![CDATA[Everybody knows that there are a lot of JavaScript Front End frameworks. Their number is so hight, in fact, that it is one of the main sources of the so called JavaScript fatigue. But not everybody knows that it is possible to build web sites, single page applications and web interfaces in general even without writing a single line of JavaScript. And I’m not talking about a simple static HTML and CSS web page, but about a rich, interactive application. There are some alternatives to JS, one of them is the C# based Blazor, by Microsoft. But the one I will focus on in this post is Elm. Elm is a Domain Specific Language to build web interfaces. It is a purely functional language and its main selling proposition is that it prevents runtime exceptions. It has a lot of nice features and some downsides. Let’s take a closer look both at pros and at cons.]]></summary></entry><entry><title type="html">How I finally succeeded in doing Test Driven Development on the Front End</title><link href="https://fbedussi.github.io/blog//blog/recipes/How-I-finally-succeeded-in-doing-Test-Driven-Development-on-the-Front-End" rel="alternate" type="text/html" title="How I finally succeeded in doing Test Driven Development on the Front End" /><published>2024-07-25T00:00:00+00:00</published><updated>2024-07-25T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/recipes/How%20I%20finally%20succeeded%20in%20doing%20Test%20Driven%20Development%20on%20the%20Front%20End</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/recipes/How-I-finally-succeeded-in-doing-Test-Driven-Development-on-the-Front-End"><![CDATA[<p>For years I’ve been hearing great things on Test Driven Development and on testing in general. But my experience with testing on the Front End has actually been a long history of misery. I’ve spent a lot of hours in writing tests, only to spent many more of them when a functional change was needed and all the tests had to be rewritten. And all this time was spent with apparently no gain. Only a ridiculous amount of regressions were caught by the tests, around 5 per year, while we were having hundreds of them. There was no relation between the amount of tests written and the amount of bugs in a feature. The most tested features had more or less the same amount of bugs as the untested ones. And finally, tests didn’t help at all with refactoring and with code evolution. On the contrary they stood in the way every time the code had to be changed. This is why I was coming to the conclusion that Test Driven Development on the Front End was impossible, and unit testing was doing more harm than good.</p>

<p>But then, on the project I’m working daily, which is big and complex, we are having some big issues, and some of them are clearly caused by a poor testing automation strategy. For instance, when we release on production we are not that confident that everything will work as intended. On the contrary past experience tells us that there will probably be some regressions. This is why at every release on production we must plan at least half a day for manual no regression testing, and some more hours for hotfixing. So, to (hope to) be ready when the business starts its day, he have to start the release process in the middle of the night. And be prepared for a lot of stressful hours of emergency work. How better would it be if at least part of this testing could be automated!</p>

<p>So, my feelings were split. On one hand I was hating automated tests. On the other one I was wanting more of them.</p>

<p>But, then, finally, I saw the light too!</p>

<p><img src="https://viralviralvideos.com/wp-content/uploads/GIF/2014/10/Blues-Brothers-Clarity-Seen-the-light-Sudden-clarity-I-have-seen-the-light-The-Light-GIF.gif" alt="" /></p>

<!--more-->

<p>Some weeks ago I was speaking with a friend, telling him my frustration on this subject. He suggested me the <a href="https://outsidein.dev/book/">Outside In React Development book</a>. I read it, and it literally changed my approach to testing.</p>

<h2 id="the-road-to-the-test-driven-development">The road to the Test Driven Development</h2>

<p>This is the chain of thoughts that in the end led me to the necessity of Test Driven Development, and specifically to the Outside In variant:</p>

<ol>
  <li>
    <p>Automated tests are needed. As I said before, when the project grows, if you don’t have a solid test automation strategy you will get into serious troubles.</p>
  </li>
  <li>
    <p>I’m saying “test automation strategy”, because it’s not only unit testing, but also stress/load testing and functional/integration/end-to-end testing. Every category of tests serves different needs. Unit tests are great to test algorithms and pure functions, functional/integration/end-to-end tests are great to test complex behaviors. Stress/load tests check that what works in test environments with few data and few users will also work in production with a lot more data and users.</p>
  </li>
  <li>
    <p>So, if your problem is that your automated tests are not catching enough regressions, probably you need more functional/integration tests, because these are the ones that check that if you change the point A, this will not break the point B. Unit tests cannot do that, because point A is tested separately from point B. But unit tests, if they don’t rely on the internal implementation, can help in refactoring a unit without changing the behavior. So, since my problems were exactly that: 
  a. My unit tests were not catching regressions
  b. My unit tests were getting in the way when I implemented functional changes
this means that I needed more high level functional tests, and less low level unit tests, and those tests should be decoupled from the implementation as much as possible.</p>
  </li>
  <li>
    <p>Writing tests can be hard, and it is harder if the code was not written to be tested in the first place. You may have function/methods that take too many arguments, do too many things, have side effects difficult to test, rely on external dependencies that are hard to mock. So, if you need to write tests (and on point 1 we assume we really need to), it is better to write the tests before the code, which is basically the Test Driven Development.</p>
  </li>
  <li>
    <p>Change the way the code is written, to make it more testable, is not a shame. On the contrary, it is a best practice. One of the aims when coding is code reuse, in other words, our code should be written in such a way that it could be used by more than one consumer. Tests are just another consumer of our code, beside the application we are developing.</p>
  </li>
</ol>

<h2 id="why-i-failed-to-do-test-driven-development-on-the-front-end">Why I failed to do Test Driven Development on the Front End</h2>

<p>Given this considerations, I can probably understand why I failed so many times to apply TDD to the Front End:</p>

<ul>
  <li>First of all, the Front End code lives in the browser, so it should be tested mainly in this environment. This means more functional tests, and maybe less so called unit test (that some times are not so unitary…). Functional tests have a lot of advantages:
    <ul>
      <li>they cover the actual behavior the user expects</li>
      <li>there are less things to mock (no need to mock all the browser related stuff, no need to mock all the dependencies of a single unit)</li>
      <li>they are easier to debug using the browser dev tools
nowadays we have some very powerful tools to test in the browser, like <a href="https://www.cypress.io/">Cypress</a> and <a href="https://playwright.dev/">Playwright</a>, so this has become a lot easier to do than, say, ten years ago.</li>
    </ul>
  </li>
  <li>Second, I was afraid to change the way I wrote the code to make it more testable. This is wrong. Instead, it is good to change the way you code to make tests easier to write. This can mean many things:</li>
  <li>Write smaller and more focused functions/methods (single purpose principle)</li>
  <li>Make dependencies explicit (dependency injection)</li>
  <li>Avoid side effects, prefer pure functions
Speaking about a React application, this means:</li>
  <li>Extract all the logic to pure helper functions, that are very easy to test, put all this helpers in a dedicated file, in order to leave the view as clean as possible</li>
  <li>
    <p>The components that are unit tested should be pure functions, all the side effects, such as data loading, data writing, dispatch of actions, ecc. should be done outside the components and triggered by callbacks passed as props. This makes the component very easy to unit test, and even to render in tools as Storybook.</p>
  </li>
  <li>Third, tests should be decoupled from the implementation as much as possible. The React Testing Library did a great job in allowing that, but there are still some details to watch out for. For instance, the React Testing Library documentation suggests that tests should mimic the real user behavior and expectations as much as possible. This is good, but can be tricky. For instance, since the user will click on button with the label “save”, we can conclude that in our test we should click on <code class="language-plaintext highlighter-rouge">&lt;button&gt;save&lt;/button&gt;</code> element. But this can be a form of coupling with the implementation. It depends if we consider that the element the user clicks is a <code class="language-plaintext highlighter-rouge">&lt;button&gt;save&lt;/button&gt;</code> is a user facing feature or an implementation details. It is probably both. But to make tests more resilient I think it is better to consider them as an implementation detail. For instance, if we replace the “save” label with an icon, should the tests break? Yes and no. If we are testing the accessibility, probably yes, but maybe we are working on a project where accessibility is not a requirement. And if we change the label to “ok”? Should the tests break? Probably not. At least not all the tests that interacts with that element. This is why I’ve come to conclude that the default way to get an element is by a test-id. The test-id is dedicated to tests and is more stable than other identifiers (classes, labels and aria-roles).</li>
</ul>

<h2 id="what-is-the-outside-in-development">What is the Outside In Development</h2>

<p>The Outside In development is a form o Test Driven Development that starts writing tests from the outside, that means write high level functional tests first. Then once we have the functional test failing, we start to think on how to implement the feature. Once we have a plan on how to develop the feature we start to write the first unit test that covers the first bit of the implementation. Once we have the first unit test failing we start to write the code that makes the unit test green. At this point we can refactor the code if needed, paying attention that the test is still green. Then we go on writing more unit tests and more code until we pass the functional test.</p>

<p>So, basically, we have 3 nested cycles:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>while (there_are_functionalities_to_implement) {
  write_a_functional_test()
  while (the_functional_test_is_red) {
    write_a_unit_test()
    while (the_unit_test_is_red) {
      write_the_code_to_make_the_unit_test_green()
    }
  }
}
</code></pre></div></div>

<h2 id="the-advantages-of-outside-in-development-compared-to-traditional-test-drive-development">The advantages of Outside In Development compared to traditional Test Drive Development</h2>

<p>The main advantage of the Outside In Development is that you start writing functional tests from the beginning and you don’t rely only on unit tests. In this way you have a strong multi level testing strategy, where each level addresses specific issues:</p>
<ul>
  <li>With functional tests you cover:
    <ul>
      <li>the high level behavior</li>
      <li>the integration between the different components and application levels</li>
      <li>all the browser related stuff</li>
    </ul>
  </li>
  <li>With unit tests you cover:
    <ul>
      <li>the single pieces of logic (e.g. algorithm, criteria for conditional rendering, data transformations and so on)</li>
      <li>all the corner cases and small details that can be too expensive to test at a functional level</li>
    </ul>
  </li>
  <li>With TypeScript you cover:
    <ul>
      <li>interface compliance</li>
      <li>general type safety</li>
    </ul>
  </li>
</ul>

<p>Working in this way is a little bit slower then developing without testing, bug faster then writing tests after the code, because the tests you write help you in writing the code, and the tests make much more sense, because they are not an afterthought.</p>

<p>The final result is:</p>
<ul>
  <li>A coverage that naturally tends to 100%, and for sure covers all the main flows</li>
  <li>Less time spent, compared to writing the tests after the code</li>
  <li>Tests that are a lot more fun to write because:
    <ul>
      <li>You don’t have to mock the entire jungle every time you are eating a banana, you can write a test as simple as you like, then write the code that makes that test green</li>
      <li>Unit tests cover almost only pure functions, so writing them is a breeze, while complex integration issues are tested at a functional level, where they are easier to handle</li>
    </ul>
  </li>
  <li>Tests are easier to maintain because they are more focused and clear, so it is easy to understand how you need to change the test if you want to change the behavior. Actually, when you will need to change the behavior you will change the tests first</li>
</ul>

<h2 id="en-example-of-how-to-practice-test-driven-development-on-the-front-end-with-the-outside-in-methodology">En example of how to practice Test Driven Development on the Front End with the Outside In methodology</h2>

<p>From a practical point of view, in a React Front End project, how can we implement the Outside In methodology?</p>

<p>Let’s make an example. Suppose we need to implement a simple login form.</p>

<p>The requirement in the user story is:</p>

<blockquote>
  <p>The user can log in to the application providing their email and password, and clicking on a login button.</p>
</blockquote>

<p>From this requirement we can derive this high level technical analysis:</p>

<blockquote>
  <p>There will be a view, containing a form with an email text field, a password field and a submit button. When the user clicks the submit button (or press enter), the system checks that both the fields are filled in with valid values and then do a POST call, sending the values to the backend. If the call succeeds the user is taken to the home page. If not, an error message is shown.</p>
</blockquote>

<p>After the high level technical analysis we realize that there are still a couple of open points: what are the “valid values”? What are the errors we need to handle?</p>

<p>We put our mind to it, maybe we talk with the Business Analyst, and in the end we come up with this answers:</p>
<ul>
  <li>The first filed is valid when it contains a syntactically valid email</li>
  <li>The second field is valid when it contains a string longer than 8 that contains uppercase and lowercase letters and numbers (I’m not suggesting that this is the right password rules… it’s just an example…)</li>
  <li>On submit we need to handle these errors:
    <ul>
      <li>Username/password not valid, in this case we need to tell the user there is a problem with the data they provided</li>
      <li>Any other error that could happen in a REST call: 500, 503, ecc. In this case we can tell the user that there has been an unexpected error, and they should retry later</li>
    </ul>
  </li>
</ul>

<p>Ok, now we can start coding. First of all we need a functional test that checks that:</p>
<ul>
  <li>When the application is open there are: a text field labelled “email”, a password field labelled “password”, a button labelled “login”</li>
</ul>

<p>To make this test pass we can write a dumb functional components that only renders these fields. We could also write a unit test for that component that checks the view output is correct, but in this case it will be a duplicate of the functional test, so we can skip it. Or maybe we can use a snapshot test, since it is so quick to write (but also so easy to ignore when it will fail…).</p>

<p>When we have the first functional test green is time for the second one:</p>
<ul>
  <li>On submit, if a user did not populate the field correctly, an error message is shown.</li>
</ul>

<p>Now, there are many ways in which the user can populate the fields with wrong values, including not populating them at all. Since unit tests run faster than functional one, in case like this we can write a functional test that checks one major case, and leave all the others, including corner cases, to unit tests.</p>

<p>So, for instance, we can write a functional test that checks that an error is shown if the email address does not have a @ char in it. Then we start writing unit tests. Since at this level we want to test all the possible corner cases we want a code where we can easily mock all the possible alternatives. What we can do is to design the view as a pure function that takes a validation function as a prop, calls it when the form is submitted, and, if it returns an error, shows that error, without calling the submit handler. In this way we will have only one test that checks only one behavior: if there is a validation error, show it and halt. As explained before, to decuple the unit tests from the implementation, the default way to select elements in the view should be by a test id. Notice that while we are still writing the tests we need to define how the validation function will report the errors, will they be Error objects? Will they be strings? If they will be instances of the Error object, will they be thrown or just returned? This is one of the ways in which writing tests help us in writing the code.</p>

<p>Now that we have a working view we can write the validation function. This will be a pure function by its nature: it takes 2 (maybe empty) strings and returns an error. So we can easily write as many unit tests as we want to cover all the possible cases: the fields are empty, the password il less than 8 char long, it does not contain a mix of uppercase and lowercase chars and numbers, it contains forbidden symbols, the email does not have a top level domain and so no, so forth. This is another case in which the tests are helping us in writing the code. Suppose we are validating using regular expressions. They are notoriously error prone, and it helps having a test that checks that the reg exp is actually doing what we intended.</p>

<p>Next we pass to the submit behavior. As usual we start with a functional test. This test should check that once the fields are populated correctly, if we submit the form, the right route will be called on the back end. If the route response is OK we land on the home page, if not, an error message is shown. We can split this check in 2 tests: one for the OK behavior and one for the KO. Here we have the first thing to mock so far: the submit route. But, please, notice how far we came without mocking anything. If we are doing a proper end to end test, and so the Front End is connected to a real Back End we could skip also this mock, but we need to understand if and how we can test both the OK and KO scenario.</p>

<p>Once we have the failing functional test we go down a level and start writing unit tests. Even in this case the view is much easier to test if it is a pure function, so it will take the submit handler as a prop, and even the navigation to the home page will be a callback passed as a prop. The unit test of the view will test only that these callbacks are called. Their implementation will be in a wrapper component, but we don’t need to unit test it, since it will be tested at the functional level. What we need to test is that, if the submit callback returns ok, then the navigation handler is called.</p>

<p>Once we have the implementation for the OK scenario, we can start with the tests for the KO scenario. In this case we need to check that if the submit callback returns an error, a message is shown and the navigation handler is not called. If we are using a library to manage the HTTP calls that handle errors we are probably done, otherwise, if we are working directly with the fetch API we need to write a helper that handle all the possible failures of the http call (404, 401, 403, 500, timeout, ecc.)</p>

<h2 id="conclusions">Conclusions</h2>

<p>With some architectural tweaks (views as pure functions and test ids on the elements), and with the Outside In methodology, it is possible to effectively practice the Test Driven Development on the Front End. While writing the code we have:</p>
<ul>
  <li>Tests that are easier to write, compared to writing them after the code</li>
  <li>Tests that help us writing he code</li>
  <li>Tests that help us refactoring the code</li>
  <li>Code units that are smaller and more focused</li>
</ul>

<p>What we end up with is:</p>
<ul>
  <li>A working application</li>
  <li>A comprehensive set of automated tests, both functional a unitarian. They will give us a good level of confidence that the application is working as intended in a given moment, both before and after a deploy</li>
</ul>

<p>When we will change the code:</p>
<ul>
  <li>The functional tests will help in catching regressions</li>
  <li>The unit tests will help in refactoring the code</li>
  <li>The tests will be small, focused, with few mocks, so they will be easy to change</li>
</ul>

<p>These are exactly the benefits promised by the TDD theory. Now, for the first time, I can confirm they are true!</p>

<p>You can check out <a href="https://github.com/fbedussi/ganpro">the project where I tested this methodology on GitHub</a>. Let me know your opinions in the comment, thanks for reading!</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Recipes" /><summary type="html"><![CDATA[For years I’ve been hearing great things on Test Driven Development and on testing in general. But my experience with testing on the Front End has actually been a long history of misery. I’ve spent a lot of hours in writing tests, only to spent many more of them when a functional change was needed and all the tests had to be rewritten. And all this time was spent with apparently no gain. Only a ridiculous amount of regressions were caught by the tests, around 5 per year, while we were having hundreds of them. There was no relation between the amount of tests written and the amount of bugs in a feature. The most tested features had more or less the same amount of bugs as the untested ones. And finally, tests didn’t help at all with refactoring and with code evolution. On the contrary they stood in the way every time the code had to be changed. This is why I was coming to the conclusion that Test Driven Development on the Front End was impossible, and unit testing was doing more harm than good. But then, on the project I’m working daily, which is big and complex, we are having some big issues, and some of them are clearly caused by a poor testing automation strategy. For instance, when we release on production we are not that confident that everything will work as intended. On the contrary past experience tells us that there will probably be some regressions. This is why at every release on production we must plan at least half a day for manual no regression testing, and some more hours for hotfixing. So, to (hope to) be ready when the business starts its day, he have to start the release process in the middle of the night. And be prepared for a lot of stressful hours of emergency work. How better would it be if at least part of this testing could be automated! So, my feelings were split. On one hand I was hating automated tests. On the other one I was wanting more of them. But, then, finally, I saw the light too!]]></summary></entry><entry><title type="html">How to build a modern SPA client side (almost) frameworkless - Part 6</title><link href="https://fbedussi.github.io/blog//blog/recipes/How-to-build-a-modern-SPA-client-side-almost-frameworkless-Part-6" rel="alternate" type="text/html" title="How to build a modern SPA client side (almost) frameworkless - Part 6" /><published>2024-07-24T00:00:00+00:00</published><updated>2024-07-24T00:00:00+00:00</updated><id>https://fbedussi.github.io/blog//blog/recipes/How%20to%20build%20a%20modern%20SPA%20client%20side%20almost%20frameworkless%20-%20Part%206</id><content type="html" xml:base="https://fbedussi.github.io/blog//blog/recipes/How-to-build-a-modern-SPA-client-side-almost-frameworkless-Part-6"><![CDATA[<p>Hi all, this is a bonus post on the “How to build a modern SPA client side (almost) frameworkless” series. Thanks to a talk by <a href="https://www.linkedin.com/in/massimoartizzu/">Massimo Artizzu</a> I learned that <a href="https://github.com/MaxArt2501/typescriptless-types-talk/tree/main">we can use JsDoc to have a sort of type system without using TypeScript</a>. Of course I knew JsDoc, but I’ve always used it just to add comments on functions. As it turns out it can do much more, and, at least for simple project, can replace TypeScript.</p>

<p><!--more--></p>

<p>The big pro is that in this way you can remain buildless, but you can have some type safety as well. Be buildless and (almost) dependency free is a big advantage in terms of security, because it minimize the risk of a supply chain attack, and in terms of maintainability, because the code that you are writing and running right now will run and be editable even in 10 years from now. There is a tradeoff between the power that a build chain and dependencies give you and the maintainability of the code base. Every project has its own sweet spot on this continuum. If you have a simple project that will live for a long time, be buildless and dependency free can be a big win.</p>

<p>The major con of this solution is that the type check is entirely delegated to the IDE, VS Code in this case. Since there isn’t a compiler, there isn’t a command line tool that che quickly spot type errors.</p>

<p>To enable the type checking by VS code you need to add a <code class="language-plaintext highlighter-rouge">jsconfig.json</code> file in the root of the project with this content:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"compilerOptions"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"checkJs"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
    </span><span class="nl">"lib"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"ESNext"</span><span class="p">,</span><span class="w"> </span><span class="s2">"DOM"</span><span class="p">],</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"exclude"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"node_modules"</span><span class="p">,</span><span class="w"> </span><span class="s2">"**/node_modules/*"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>the <code class="language-plaintext highlighter-rouge">checkJs</code> options enables the type checking on the js files, the other options are basically the same as the <code class="language-plaintext highlighter-rouge">tsconfig.json</code> file ones.</p>

<p>Then you can declare types:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * @typedef {Object} AddNotePayload
 * @property {string} title
 * @property {string} text
 */</span>

<span class="cm">/**
 * @typedef {AddNotePayload &amp; {id: string}} Note 
 */</span>
</code></pre></div></div>

<p>and use them, both for variables:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * @type {Note[]}
 */</span>
<span class="kd">const</span> <span class="nx">savedData</span> <span class="o">=</span> <span class="nx">savedDataJson</span> <span class="p">?</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">savedDataJson</span><span class="p">)</span> <span class="p">:</span> <span class="p">[]</span>
</code></pre></div></div>

<p>and for functions:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * @param {AddNotePayload} note 
 */</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">addNote</span> <span class="o">=</span> <span class="k">async</span> <span class="p">(</span><span class="nx">note</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">updatedData</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">notes</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">concat</span><span class="p">({</span>
    <span class="na">id</span><span class="p">:</span> <span class="nx">crypto</span><span class="p">.</span><span class="nx">randomUUID</span><span class="p">(),</span>
    <span class="p">...</span><span class="nx">note</span><span class="p">,</span>
  <span class="p">})</span>
  <span class="nx">notes</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">updatedData</span>
  <span class="nx">saveUpdatedData</span><span class="p">(</span><span class="nx">updatedData</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The inference works as in TypeScript, so, for instance, you can explicitly declare the return type of a function:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * 
 * @param {TemplateStringsArray} strings 
 * @param  {...string} values 
 * @returns {void}
 */</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">css</span> <span class="o">=</span> <span class="p">(</span><span class="nx">strings</span><span class="p">,</span> <span class="p">...</span><span class="nx">values</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</code></pre></div></div>

<p>or leave the engine infer that:</p>

<p><img src="https://fbedussi.github.io/blog/assets/images/spa-fl-jsdoc-inference.png" alt="" /></p>

<p>For further details you can read the <a href="https://github.com/MaxArt2501/typescriptless-types-talk/tree/main">Massimiliano’s presentation</a>, or check out the the <a href="https://github.com/fbedussi/frameworkless-spa-tutorial/tree/part4_jsdoc">dedicated branch on the demo repo</a>.</p>]]></content><author><name>Francesco Bedussi</name><email>francesco [at] francescobedussi.it</email></author><category term="Recipes" /><summary type="html"><![CDATA[Hi all, this is a bonus post on the “How to build a modern SPA client side (almost) frameworkless” series. Thanks to a talk by Massimo Artizzu I learned that we can use JsDoc to have a sort of type system without using TypeScript. Of course I knew JsDoc, but I’ve always used it just to add comments on functions. As it turns out it can do much more, and, at least for simple project, can replace TypeScript.]]></summary></entry></feed>