<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Programming on Jonathan's Blog</title><link>https://jonathan-frere.com/tags/programming/</link><description>Recent content in Programming on Jonathan's Blog</description><generator>Hugo</generator><language>en-gb</language><copyright>This work is licensed under CC BY-SA 4.0</copyright><lastBuildDate>Fri, 06 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://jonathan-frere.com/tags/programming/index.xml" rel="self" type="application/rss+xml"/><item><title>Pushing and Pulling: Three Reactivity Algorithms</title><link>https://jonathan-frere.com/posts/reactivity-algorithms/</link><pubDate>Fri, 06 Mar 2026 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/reactivity-algorithms/</guid><description>&lt;p>It&amp;rsquo;s looking like I&amp;rsquo;m going to need to build a reactive engine for work, so I&amp;rsquo;m going to prepare for that by writing down what I know about them. I want to look at three ways of building reactive engines: push reactivity, pull reactivity, and the hybrid push/pull combination that is used in a bunch of web frameworks.&lt;/p>
&lt;h2 id="the-problem-statement">
 &lt;a href="#the-problem-statement">The Problem Statement&lt;/a>
&lt;/h2>

&lt;p>The simplest way to visualise reactivity, in my opinion, is as a spreadsheet. You have a series of input cells, containing your initial data, and a series of output cells containing the final results. In between are many more cells containing intermediate computations that need to be done to figure out the final results.&lt;/p></description><content:encoded><![CDATA[<p>It&rsquo;s looking like I&rsquo;m going to need to build a reactive engine for work, so I&rsquo;m going to prepare for that by writing down what I know about them. I want to look at three ways of building reactive engines: push reactivity, pull reactivity, and the hybrid push/pull combination that is used in a bunch of web frameworks.</p>
<h2 id="the-problem-statement">
  <a href="#the-problem-statement">The Problem Statement</a>
</h2>

<p>The simplest way to visualise reactivity, in my opinion, is as a spreadsheet. You have a series of input cells, containing your initial data, and a series of output cells containing the final results. In between are many more cells containing intermediate computations that need to be done to figure out the final results.</p>
<picture>
    <source media="(prefers-color-scheme: dark)"
                type="image/svg+xml"
                srcset="./overview-dark.svg">
    <source media="(prefers-color-scheme: light)"
                type="image/svg+xml"
                srcset="./overview.svg">
    <img src="./overview.svg" alt="A diagram showing an example reactive graph.  There are three input nodes at the top of the graph.  Below that are five nodes for intermediate computations, and below that are four output nodes.  Arrows join various combinations of nodes from top to bottom, indicating the dependencies each node requires." />
</picture>
<p>When one of the input cells changes, all the cells that depend on it need to react to that change — the aforementioned reactivity. In practice, though, this is the bare minimum requirement. When building reactive systems, there are usually some additional requirements we impose that make the problem harder:</p>
<ol>
<li>Each cell is recalculated at most once. We don&rsquo;t do any calculations that are immediately discarded. (&ldquo;Efficient&rdquo;)</li>
<li>We only update cells that actually need to be updated. Any cells that aren&rsquo;t affected by the input are left untouched. (&ldquo;Fine-grained&rdquo;)</li>
<li>Whenever cells change, all the cells change at the same time. There&rsquo;s never a moment when an intermediate computed value has updated, but the output cell is still showing a result based on the previous input. (&ldquo;Glitchless&rdquo;)</li>
<li>Each time a node is updated, it may dynamically add or remove dependencies (&ldquo;Dynamic&rdquo;)</li>
</ol>
<p>The first two requirements (&ldquo;Efficient&rdquo; and &ldquo;Fine-grained&rdquo;) are important for performance. Imagine a large spreadsheet with millions of cells containing formulas — it would be a huge waste of resources to recalculate every single cell, every time any input changes. Similarly, you don&rsquo;t want to calculate the value of a cell multiple times if you can help it. In general, we want to do the minimum amount of work possible.</p>
<p>The third requirement (&ldquo;Glitchless&rdquo;) is important for correctness. We don&rsquo;t want intermediate states to be observable — if this were possible, then we can end up with invalid states. Consider two neighbouring cells, one that contains a country&rsquo;s ISO country code (UK, DE, BE, etc), and another that contains the full name of that country. We don&rsquo;t want to be able to observe the state where the two cells are out-of-sync with each other.</p>
<p>The fourth requirement (&ldquo;Dynamic&rdquo;) ensures that we only create dependencies when they are actually needed. This is easiest to see with conditional formulas, so something like <code>IF(&lt;condition&gt;, slow_calculation(B1))</code>. If the condition is true, this formula returns the value of (and therefore depends on) the cell B1. But if the condition is false, the formula returns nothing — and if B1 changes, this cell should not be updated. This is a dynamic dependency — the dependency only exists if <code>&lt;condition&gt;</code> is true.</p>
<p>These requirements will hopefully become more clear as we start trying out different algorithms, and seeing examples of their successes and failure modes. Before we get too deep in the weeds, though, I want to emphasise that not all reactive systems are the same, and some don&rsquo;t need all of these requirements. For example, lots of simple reactive systems work just fine with static dependencies only, trading off some efficiency wins for implementation simplicity. Similarly, glitches are only important if they are actually observed, so some reactive systems will be glitch-y by default, but provide tools for syncing nodes together if the user actually needs them to be in sync.</p>
<p>But for the sake of this article, let&rsquo;s assume we need all these things and look at some approaches to implementing reactivity.</p>
<h2 id="push-based-reactivity">
  <a href="#push-based-reactivity">Push-Based Reactivity</a>
</h2>

<p>In push-based reactivity, when a node updates, it notifies (and updates) all of its dependents. We can visualise this as the update being pushed down the chain of dependencies, until it reaches the final node to be updated.</p>
<picture>
    <source media="(prefers-color-scheme: dark)"
                type="image/svg+xml"
                srcset="./push-dark.svg">
    <source media="(prefers-color-scheme: light)"
                type="image/svg+xml"
                srcset="./push.svg">
    <img src="./push.svg" alt="A diagram showing a different example reactive graph, running left to right.  There are two input nodes, one of which is marked with an asterisk.  Arrows run from these input nodes through various intermediate computation nodes into output nodes.  From the node with an asterisk, all arrows are highlighted with an additional arrow indicating the direction of the pushed updates (i.e. from the input towards the outputs)." />
</picture>
<p>This is a simple, and therefore very common approach. Generally, most event systems, streams, and observables follow this rough pattern. Even promises/futures/async/await can be thought of as a one-time-only push-based reactive tree — each <code>.then</code>/<code>.map</code>/<code>await</code> call creates a listener to the previous step, and then when the initial promise resolves, the update is pushed through the rest of the system.</p>
<p>The single biggest advantage of push-based reactivity is that it is fine-grained. Each time an input changes, we only notify those dependencies that will actually need to be updated. Every other node in the system can remain in a state of blissful ignorance. This is great if we&rsquo;ve got a lot of inputs that update independently from each other — our spreadsheet is a good example here, as are most GUIs.</p>
<p>However, push-based systems typically are not particularly efficient, and it&rsquo;s only with additional work that we can fix that. Let&rsquo;s look at an example of a graph that creates unnecessary work.</p>
<picture>
    <source media="(prefers-color-scheme: dark)"
                type="image/svg+xml"
                srcset="./fail-case-dark.svg">
    <source media="(prefers-color-scheme: light)"
                type="image/svg+xml"
                srcset="./fail-case.svg">
    <img src="./fail-case.svg" alt="A diagram a simple arrangement of four nodes.  On the left is node A.  Two arrows run from node A to nodes B and C respectively.  An additional arrow runs from node C to node B.  Finally, two arrows run from nodes B and C to node D on the right." />
</picture>
<p>According to our push-based system, we update the first node in our graph (A). This pushes a signal to (A)&rsquo;s dependents that they should now update. In this case, both (B) and (C) update. However, (B) depends on both (A) and (C), so when (C) updates, (B) needs to update again, and we discard any previous work we&rsquo;ve done there. Similarly, based on just a single update to (A), (D) will receive three different signals to update.</p>
<p>We can improve this somewhat if we make sure we always perform updates in a particular order. Consider a different approach to the same graph above:</p>
<ol>
<li>We update (A), and push a signal to (B) and (C) to update.</li>
<li>(B) delays updating for now, knowing there are other dependencies to update first. Meanwhile, (C) updates, and pushes a signal on to (B) and (D).</li>
<li>(B) now updates, as both (A) and (C) are now ready. Once finished, it pushes a signal on to (D).</li>
<li>(D) updates last of all.</li>
</ol>
<p>In this version, each node only updates once. We could do this, because we could see the entire dependency graph, and calculate the optimum route<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> through it. If we know the entire graph, we can always calculate the optimum route, but it&rsquo;s not always a given that we will know the entire graph.</p>
<p>Part of the value of push-based systems is that each node only needs to keep track of its own dependencies and dependents, which makes analysing each node locally easy, but analysing the system as a whole hard. In the extreme case, you might dynamically create and destroy nodes in the tree depending on previous values — this doesn&rsquo;t make sense for our spreadsheet analogy, but is essentially what&rsquo;s happening with RxJS&rsquo;s <code>switchMap</code> operator. Essentially, the more dynamism we want in our system, the harder it is to achieve efficient updates, and the more we want efficient updates, the more we need to specify our dependency graphs up-front.</p>
<p>The other challenge for push-based reactivity is glitches. As I mentioned earlier, glitches are when we can observe two nodes being out of sync with each other. In push-based reactivity, this is very easy to achieve — any code that runs after the first node has been updated, but before the final node has been updated has the opportunity to &ldquo;see&rdquo; glitches.</p>
<p>We can avoid this in two ways. Firstly, we can declare that any code that observes two nodes must depend on those nodes, and then apply the topological sort we described earlier. Alternatively, we can declare that any code that might be able to observe two nodes can only be run after all nodes have finished running<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. These both work, but again they require us to be able to observe the full dependency tree and topologically sort all nodes.</p>
<p>The other problem is that in practice, it&rsquo;s surprisingly easy to write code that implicitly observes some state without having the proper dependencies, at which point glitches appear again. There&rsquo;s typically no easy way to fully prevent these cases from cropping up, so some amount of vigilance is required to make sure everything is working.</p>
<h2 id="pull-based-reactivity">
  <a href="#pull-based-reactivity">Pull-Based Reactivity</a>
</h2>

<p>If what we&rsquo;ve described above is push-based reactivity, we can draw a diagram of everything happening in reverse and call it pull-based reactivity. But that doesn&rsquo;t necessarily give us an intuition for what pull-based reactivity actually is.</p>
<picture>
    <source media="(prefers-color-scheme: dark)"
                type="image/svg+xml"
                srcset="./pull-dark.svg">
    <source media="(prefers-color-scheme: light)"
                type="image/svg+xml"
                srcset="./pull.svg">
    <img src="./pull.svg" alt="A diagram showing the same graph as in the 'push' example, running left to right.  One of the input nodes is again marked with an asterisk.  There are still arrows connecting the nodes left to right, but now the additional arrows indicating the flow of the pull-based reactivity are running from the right-hand (output) nodes towards the asterisked input node on the left." />
</picture>
<p>In push-based reactivity, once a node has finished updating, it calls its dependents. In pull-based reactivity, therefore, we would expect each node to call its dependencies. And because you need your dependencies to update before you can update, we can see how this works: each node updates all of its dependencies, and then updates its own value.</p>
<p>In essence, pull-based reactivity is basically just a stack of function calls. I call a function, and it calls more functions if it needs to, then it returns a result. I can nest these functions recursively as much as I need, and the dependencies will all automatically be calculated for me.</p>
<p>This isn&rsquo;t quite reactive yet though. We still need some way of triggering the functions to be re-run when state changes.</p>
<p>The easiest possible system is that we just re-run everything. Going back to our spreadsheet, every time we update a cell, we go through every cell in the sheet and calculate its value fresh. When a cell references another cell (e.g. <code>=B8</code>), we first calculate the value of the dependency, then carry on calculating the initial cell&rsquo;s value. Eventually, we will recursively have updated every cell in the sheet.</p>
<p>You may be able to see some problems with this system, but let&rsquo;s put those to one side for now, and look at why we might want this kind of system.</p>
<p>The first benefit is that it&rsquo;s a lot easier to make our code glitchless. Every time we change the input, we make one recursive pass over all nodes, updating them to their new values. As long as we don&rsquo;t change the input during that pass, all of the nodes will see inputs that are consistent with each other. In single-threaded runtimes like JavaScript, this condition is very easy to achieve, and even if we introduce concurrency, we only need simple locking primitives to ensure that we wait until the pass is finished before making changes to the inputs.</p>
<p>The second benefit is that we get dynamic dependencies for free. If pull-based reactivity is just a call stack, then it&rsquo;s very easy to conditionally call (i.e. conditionally depend on) some input. We don&rsquo;t need to maintain an internal list of which dependencies a node is subscribed to or vice versa, we just fetch values as needed.</p>
<p>But there are problems — in fact, there are two big ones that mean this approach tends to work best in very specific circumstances.</p>
<p>The first problem is wasted work again. If cell A1 references B8, and cell A2 <em>also</em> references B8, then when we update all the cells, we still only want to evaluate B8 once, and then reference it in both A1 and A2. We can do this through caching — whenever we calculate a cell&rsquo;s value, we store it somewhere, and then all future cell references can used the stored value instead of recalculating.</p>
<p>I&rsquo;m not going to go into the depths of caching in pull-based reactivity, but as the famous aphorism reminds us, one of the hardest things in computer science is cache invalidation. And typically, the more efficient a cache is at reducing work, the harder cache invalidation becomes. So an easy approach might be generation counters, where every time we change any input, all cached values are invalidated immediately, and a harder approach might be an LRU cache of all a node&rsquo;s dependencies where we need to consider how many entries to cache, and how to determine equality<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</p>
<p>However, there is a second problem to deal with. Right now, we don&rsquo;t know which cells are actually going to change, so we&rsquo;re updating all of them. The actual pull-reactivity diagram probably looks something more like this:</p>
<picture>
    <source media="(prefers-color-scheme: dark)"
                type="image/svg+xml"
                srcset="./pull-corrected-dark.svg">
    <source media="(prefers-color-scheme: light)"
                type="image/svg+xml"
                srcset="./pull-corrected.svg">
    <img src="./pull-corrected.svg" alt="A diagram showing the same graph as in the 'push' example, running left to right.  One of the input nodes is again marked with an asterisk.  There are still arrows connecting the nodes left to right, but now the additional arrows indicating the flow of the pull-based reactivity are running from the right-hand (output) nodes towards the asterisked input node on the left." />
</picture>
<p>Ideally, we&rsquo;d only update the cells that change, and leave the rest alone. Unfortunately, this turns out to be surprisingly hard.</p>
<p>We can change the problem a bit. React, for example, uses a pull-based reactivity system, but can isolate certain components in the rendered tree and say &ldquo;only this component and all its children should update&rdquo;.  This means that instead of having to re-render the entire world, it only needs to re-render a given component and its children.  The mechanism by which this works is interesting, but I&rsquo;ll explore that in a follow-up post because this one is already getting too long!</p>
<p>In general, though, we can&rsquo;t solve this problem with pull-only reactivity. The input node that gets updated just doesn&rsquo;t have the information to tell us what its dependants are, and therefore what output nodes are eventually going to need to change. But we could try a different approach, where we do try and store that information. A combination of pushing and pulling — some kind of <del>suicide squad</del> push-pull reactivity?</p>
<h2 id="push-pull-reactivity">
  <a href="#push-pull-reactivity">Push-Pull Reactivity</a>
</h2>

<p>Push-pull reactivity is so named because it does both things: first we push, and then we pull. However, rather than doing the same thing twice, our push and our pull will have different purposes.</p>
<p>Let&rsquo;s start with pushing. Consider a tree of nodes. If we update one of the input nodes, our goal now is to find out which child (and output) nodes need to be updated. We&rsquo;re not actually going to do the updating, we&rsquo;re just going to find out which ones need updating.</p>
<picture>
    <source media="(prefers-color-scheme: dark)"
                type="image/svg+xml"
                srcset="./push-pull-dark.svg">
    <source media="(prefers-color-scheme: light)"
                type="image/svg+xml"
                srcset="./push-pull.svg">
    <img src="./push-pull.svg" alt="A diagram showing the same graph as in the 'push' and 'pull' examples, running left to right.  Arrows run from the asterisked input node on the left to the downstream nodes on the right.  Each of the downstream nodes is now also marked with an asterisk." />
</picture>
<p>We can do this by adding a boolean <code>dirty</code> flag to each node. If it&rsquo;s set to true, then this is a node that needs to be recalculated. Otherwise, it&rsquo;s up-to-date. Let&rsquo;s start with these flags all set to false — we have an up-to-date tree. Now, when we update the input node, we can iterate over all the children of that node, and follow a simple algorithm:</p>
<ol>
<li>If the current node is already marked dirty, we don&rsquo;t need to do anything and can skip it.</li>
<li>We mark the current node as dirty.</li>
<li>If the node is an <em>output</em> node, we add it to a list of outputs that need to be updated<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</li>
<li>Otherwise, we recursively visit all the children of the current node and apply this same algorithm to them.</li>
</ol>
<p>Eventually, we&rsquo;ll have a tree with mixed dirty and clean nodes, where only the dirty nodes need updating. Importantly, unlike the original push-based reactivity, the order that we visit the nodes isn&rsquo;t important<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>. This means we don&rsquo;t need to figure out the optimal path through the entire tree, and can use a simpler recursive algorithm, as long as we make sure to skip any nodes that were already marked as dirty.</p>
<picture>
    <source media="(prefers-color-scheme: dark)"
                type="image/svg+xml"
                srcset="./push-pull-2-dark.svg">
    <source media="(prefers-color-scheme: light)"
                type="image/svg+xml"
                srcset="./push-pull-2.svg">
    <img src="./push-pull-2.svg" alt="The same diagram as before with the additional asterisks from the push part of the push-pull algorithm, but now the arrows indicating the flow of the algorithm are reversed, going from right to left.  The arrows only visit the nodes with asterisks (the dirty nodes) and don't touch any of the other nodes." />
</picture>
<p>Now let&rsquo;s try pulling. Last time, one of the issues with pull-based reactivity was that we didn&rsquo;t know which nodes needed to be updated. But now we do know that — any dirty output node needs to be updated. We even made a list of these nodes while we were marking the nodes as dirty!</p>
<p>So now, for every one of those output nodes, we do the same thing we were doing in the pull step. But we add a couple of additional checks to our logic:</p>
<ul>
<li>If the node we&rsquo;re looking at is <em>clean</em>, we return the value of that node. We know that the existing value doesn&rsquo;t need to be recalculated because it&rsquo;s not been marked as dirty, so it&rsquo;s not downstream of any changed inputs.</li>
<li>If the node we&rsquo;re looking at is <em>dirty</em>, we calculate the result, mark the node as clean, and store the calculated result alongside the node.</li>
</ul>
<p>Once we&rsquo;ve finished our push and our pull processes, we&rsquo;ll end up with an all-clean tree of nodes, and we&rsquo;ll have updated all of our output nodes.</p>
<p>Let&rsquo;s look at our requirements again, and see how well push-pull reactivity does.</p>
<ul>
<li>Efficiency: When we push, we only visit each node once. When we pull, we again only visit each node once. This is about as efficient as things can get.</li>
<li>Fine-grained: When we push, we make a list of exactly the nodes that need to be updated. When we pull, we only recalculate those nodes and leave all the others alone.</li>
<li>Glitchless: Because the recalculation happens during the pull step, we share the same benefits of pull-based reactivity here, which means that if we can guarantee that we don&rsquo;t change any input during the pull step, then the calculation must be glitchless.</li>
<li>Dynamic: Pulling is always dynamic, as we discussed before. But because we don&rsquo;t need any global ordering of nodes, it&rsquo;s very easy to have a dynamic push step as well, as each node only needs to keep a list of its upstream and downstream immediate neighbours.  This structure is typically much easier to manipulate than maintaining a globally ordered list (and a lot cheaper than performing a fresh topological sort every time we want to evaluate nodes).</li>
</ul>
<p>Nice!</p>
<h2 id="conclusion">
  <a href="#conclusion">Conclusion</a>
</h2>

<p>These are the three broad categories of reactivity system that I&rsquo;m familiar with — ones where a node gets updated by a signal from above, ones where a node gets updated on demand from below, and hybrid approaches<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>.</p>
<p>For the purposes I use reactivity<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup>, push-pull reactivity is a really nice tool. The O(n) nature makes it remain fairly efficient as the size of the application grows (especially bearing in mind that the &rsquo;n&rsquo; there is the number of nodes that need to be updated, which is likely to be a small subset of the total nodes in the system). It&rsquo;s also very easy to understand what&rsquo;s happening.</p>
<p>That said, it&rsquo;s also got its issues. For example, an assumption throughout this post is that it&rsquo;s possible to do the entire &ldquo;pull&rdquo; logic in a single tick, between updates to the input nodes. If that isn&rsquo;t possible, you might need to convert a long-running operation into a state machine that gets updated in the background, but this can become complicated in general<sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup>.</p>
<p>Throughout writing this, I ended up in all sorts of tangents that I&rsquo;ve ended up deleting because they made everything too long and convoluted — I will try and put some of these tangents in a future follow-up post, because I think they&rsquo;re interesting.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>This is known as a topological sort — a way of sorting a graph such that we visit all nodes exactly once, and we always visit a node&rsquo;s dependencies before we visit the node itself.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Essentially, we wrap all observing code in a special node that depends on all other nodes, and therefore must always be updated last.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>And of course, you can mix and match these caching strategies within the same graph. One node might be entirely trivial to calculate, and not worth caching at all, while another might require the most heavy-duty caching you can get your hands on. Some nodes might need to always be up-to-date, but maybe others can take a stale-while-revalidate approach (being wary of glitches in that case!).&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>For our spreadsheet example, this step just generates a list of all dirty nodes, because every node (i.e. cell) is kind of an output node and an input node at the same time. In that case, you&rsquo;d probably instead create a list of all nodes with no children. However, in a GUI framework, you might have &ldquo;effect&rdquo; nodes that are responsible for updating UI components — these are also leaves in the tree, but they&rsquo;re specifically <em>output</em> leaves, because they form the observable part of our reactivity graph. This also means that an intermediate node that has no output won&rsquo;t ever end up in this list, and therefore won&rsquo;t get updated. This is something I&rsquo;ll write about more in a follow-up post!&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>If you&rsquo;re not convinced by this, try it out. Use the diagram from the push-based reactivity section and try out the dirty algorithm in any order you like. You can even try out the difference between depth-first and breadth-first versions of the algorithm — it&rsquo;ll change the order of the nodes you visit, but you&rsquo;ll still visit all of them exactly once.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>If you know of other approaches, please let me know! My definitions here aren&rsquo;t particularly rigorous, and I suspect there are other approaches, or even just alternative forms of the approaches I&rsquo;ve described here, that have different characteristics.&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p>Mainly web/GUI development and more recently work on spreadsheet engines, hence all the spreadsheet examples here because that&rsquo;s been on my mind a lot.&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p>On the other hand, it can also simplify, by ensuring that the developer has to handle the various failure states that can occur with these sorts of long-running operations. For web development, where lots of processes involve asynchronous communication with a backend or waiting for user interaction, I find the state machine approach is often clearer about intent, if more verbose.&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Additional Thoughts about the Command Pattern</title><link>https://jonathan-frere.com/posts/command-pattern-followup/</link><pubDate>Sat, 29 Nov 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/command-pattern-followup/</guid><description>&lt;p>A couple of weeks ago, I wrote a post on my employer&amp;rsquo;s blog titled &lt;a href="https://www.esveo.com/en/blog/undo-redo-and-the-command-pattern/">Undo, Redo, and the Command Pattern&lt;/a>, which I ended up quite pleased with.&lt;/p>
&lt;p>Here, I wanted to add a couple of additional thoughts based on some of the discussions and things I&amp;rsquo;ve read since writing that post.&lt;/p>
&lt;p>Firstly, undo/redo isn&amp;rsquo;t the only use for the command pattern! This is something I wish I&amp;rsquo;d made more explicit in that post. Perhaps a more general way of seeing commands is &amp;ldquo;functions with metadata in a consistent shape&amp;rdquo;. In our case, the metadata was the &lt;code>undo&lt;/code> function, i.e. the inverse function to our original function. But you could do all sorts of other things as well:&lt;/p></description><content:encoded><![CDATA[<p>A couple of weeks ago, I wrote a post on my employer&rsquo;s blog titled <a href="https://www.esveo.com/en/blog/undo-redo-and-the-command-pattern/">Undo, Redo, and the Command Pattern</a>, which I ended up quite pleased with.</p>
<p>Here, I wanted to add a couple of additional thoughts based on some of the discussions and things I&rsquo;ve read since writing that post.</p>
<p>Firstly, undo/redo isn&rsquo;t the only use for the command pattern!  This is something I wish I&rsquo;d made more explicit in that post.  Perhaps a more general way of seeing commands is &ldquo;functions with metadata in a consistent shape&rdquo;.  In our case, the metadata was the <code>undo</code> function, i.e. the inverse function to our original function.  But you could do all sorts of other things as well:</p>
<ul>
<li>User-readable data, such as the name of the command and a description of what it&rsquo;s done.  We use this in our undo/redo system to show a timeline of actions that the user has taken in the UI, so that they can jump back and forth, and quickly undo chunks of work.</li>
<li>Parameters for a rate-limiting algorithm.  Say you&rsquo;ve got a handful of routes that need to be rate-limited, but at different rates — you can define each route as a command object with details about how often it can be called, and then provide a generic route handler that finds the correct command, applies the correct limits, and calls it or returns an error as needed.</li>
<li>Metadata about the function&rsquo;s arguments.  In another place in our application, we have a bunch of built-in functions that the user can call.  Each function declares what parameters it takes, which means we can programmatically create a UI where the user can configure the functions.</li>
</ul>
<p>Secondly, I think it&rsquo;s really important to see examples of patterns being used in practice.  When I was researching about the command pattern, there were lots of articles that described the pattern in very abstract terms, or with a bunch of class diagrams for an OO-style implementation.  Of course, design patterns are always going to be somewhat abstract<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> but it can be difficult to get a sense of why you&rsquo;d use a particular pattern without already having seen it in practice.</p>
<p>In the <a href="https://lobste.rs/s/lwepwh/undo_redo_command_pattern">comments on Lobste.rs</a>, someone posted a link to <a href="https://gameprogrammingpatterns.com/command.html">Game Programming Patterns</a>, and their treatment of the command pattern.  This is a fantastic resource, and they do a great job of starting with a real problem and explaining how the pattern helps.</p>
<p>A while back, I saw someone ask whether there was a test suite for design patterns — some set of tests that you could apply to a class to test whether it successfully implemented the builder pattern, or the command pattern, or whatever else.  I wonder if this kind of approach comes from seeing too many descriptions of design patterns as UML diagrams only, and not as abstract ideas that can be implemented in all sorts of different ways, be that as functions, or as objects, or as closures, or whatever else.</p>
<p>One final thought: are objects themselves just another design pattern?  Consider the core idea of encapsulation: some type <code>t</code> that is bundled together with a bunch of methods of the form <code>fn(t, ...args) -&gt; result</code>.  How many different ways are there of implementing this in different languages that all behave roughly the same?  I can think of classes, closures, ml modules, abstract data types, and probably more if you pushed me.  They might look different, and have different subtleties to understand, but they feel like different implementations of the same underlying pattern.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Indeed, that&rsquo;s kind of the point of design patterns — they&rsquo;re abstract descriptions of commonalities that show up in different codebases in different ways.  They need to be abstract to cover a wide variety of codebases.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Storing Unwise Amounts of Data in JavaScript Bigints</title><link>https://jonathan-frere.com/posts/bigints-are-cool/</link><pubDate>Sun, 21 Sep 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/bigints-are-cool/</guid><description>&lt;p>This is a short note to document storing data in JS&amp;rsquo;s &lt;code>bigint&lt;/code> type. I tried this out in a project recently, and it&amp;rsquo;s not obviously a terrible idea, as long as you take into account all the caveats that make it only useful for very specific cases.&lt;/p>
&lt;h2 id="why">
 &lt;a href="#why">Why&lt;/a>
&lt;/h2>

&lt;p>This is a performance&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> thing. In the project where I was exploring this, we had a large amount of objects representing configuration values. The possible configuration keys were the same, but different objects had different keys set. This approach was causing some issues:&lt;/p></description><content:encoded><![CDATA[<p>This is a short note to document storing data in JS&rsquo;s <code>bigint</code> type.  I tried this out in a project recently, and it&rsquo;s not obviously a terrible idea, as long as you take into account all the caveats that make it only useful for very specific cases.</p>
<h2 id="why">
  <a href="#why">Why</a>
</h2>

<p>This is a performance<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> thing.  In the project where I was exploring this, we had a large amount of objects representing configuration values.  The possible configuration keys were the same, but different objects had different keys set.  This approach was causing some issues:</p>
<ul>
<li>Serialization and deserialization produced very large strings because of all the repeated keys.</li>
<li>Comparison/equality of objects was costly because of the number of keys.</li>
<li>We needed to do a lot of operations like &ldquo;find the subset of keys and values that are identical between all of these objects&rdquo;.  This was slow.</li>
<li>We often needed to update subsets of the items by adding, updating, or removing keys, so each object needed to be an independent clone.</li>
</ul>
<p>Originally, I planned on doing some sort of object interning to reduce the number of objects we needed to keep in memory at any one time.  We would keep only one copy of each unique configuration item, and just reference it in multiple locations.  The (now dead) <a href="https://github.com/tc39/proposal-record-tuple">Records and Tuples</a> proposal would have been really useful here, and its replacement, <a href="https://github.com/tc39/proposal-composites">Composites</a> looks like it might help but I didn&rsquo;t want to tie myself to an incomplete early-stage proposal.  So if I went down this route, I&rsquo;d be building something myself.</p>
<p>While looking all this up, I found Justin Fagnani&rsquo;s article <a href="https://justinfagnani.com/2024/11/09/composite-map-keys-in-javascript-with-bitsets/">Composite Map Keys in JavaScript with Bitsets</a>, which is mostly unrelated to what I&rsquo;m doing here, but did make me think of using bigints in the first place.</p>
<h2 id="how">
  <a href="#how">How</a>
</h2>

<p>The basic idea is:</p>
<ol>
<li>Define a bunch of fields, how they should be interpreted, their size, etc.  E.g. <code>{name: &quot;size&quot;, kind: &quot;uint&quot;, bits: 8}</code> to represent a number stored as a u8.  You also need to know the offset of each field, this can be calculated from the index of each field and the number of bits in the preceding fields.</li>
<li>Add functions <code>getBits(bigint, offset, bits)</code> which does bitshifting to fetch the relevant bits from the <code>bigint</code> backing store, and <code>setBits(bigint, offset, bits, value)</code> which does the opposite</li>
<li>For each field, add getters and setters that do the type conversions from e.g. JS <code>number</code> to u8.</li>
</ol>
<p>Honestly, I was impressed by how well Claude Sonnet handled this stuff.  It didn&rsquo;t produce the tidiest code, nor did it find the clearest ways of doing many things, but the basic bit-bashing was largely correct, and I wrote a lot of tests to confirm that it was working in the way I wanted.</p>
<p>In this use-case, not all keys are present at all times.  To handle this, I added an extra store <code>present</code> alongside the <code>bigint</code> backing store that was a simple bitfield where if bit <code>i</code> was 1 in the <code>present</code> store, then the <code>i</code>th field had been set in the main backing store.  Deleting a field meant simply clearing the <code>i</code>th bit.</p>
<h2 id="benefits">
  <a href="#benefits">Benefits</a>
</h2>

<ul>
<li>The memory usage of the object is about as compact as it&rsquo;s possible to be.  Booleans take up a single bit, colours can be stored as u32 values (for rgba), fields that were previously string enums are now just a couple of bits wide, etc.</li>
<li>Deserialization is very quick (basically just <code>BigInt(&quot;0x&quot; + value)</code> to convert a hexadecimal string back into our backing store).  Serialization is slightly slower because I wanted to ensure that unset fields were zeroed-out first, to ensure consistent representations.  The resulting string is pretty compact.</li>
<li>Lots of operations can take advantage of the <code>present</code> bits to optimise what they&rsquo;re doing.  For example, when checking equality, we can first check that the two <code>present</code> bits are equal to make sure that the same fields are set in both cases.  When finding the intersection of two values, we can first <code>AND</code> the present bits together, and check only the fields that are set in both values.</li>
</ul>
<p>This whole thing is surprisingly usable.</p>
<h2 id="drawbacks">
  <a href="#drawbacks">Drawbacks</a>
</h2>

<ul>
<li>Fields need to have a max width.  For example, you can&rsquo;t store an arbitrary string in the <code>bigint</code>, because you don&rsquo;t know when it will end.  If you need dynamically-sized data, then this isn&rsquo;t going to work.</li>
<li>Bit operations on <code>bigint</code>s is slow.  I mean, all things are relative, but in general, gets and sets will be faster with plain old JS objects.  HOWEVER: if you have a lot of smaller fields, you can cheat a bit and use a <code>number</code> backing store, or use a combination of a <code>number</code> store for smaller fields and a <code>bigint</code> store for larger fields.  Bit operations on <code>number</code> objects are very fast, and in my tests, gets and sets were roughly the same speed as getting/setting regular JS object fields.</li>
<li>The code is going to be <em>way</em> more complex.  Expect to write a whole bunch of tests that basic things like getting and setting a property work.  I suspect a good library or layer of abstraction could help here, but, having only done this the once, I don&rsquo;t know what that abstraction would look like yet.</li>
</ul>
<p>This might not sound like a lot of drawbacks, but they&rsquo;re all very significant compared to the more niche benefits of this approach.  I wouldn&rsquo;t recommend doing this in most cases.</p>
<h2 id="is-it-worth-it">
  <a href="#is-it-worth-it">Is It Worth It?</a>
</h2>

<p>I&rsquo;m not entirely sure yet.  This is a bit of an experimental side project at the moment, just playing around with one way of optimising one component of the main project I&rsquo;m working on.  I need to see how it feels to use this approach in practice.  The goal is not necessarily that <code>bigint</code>s by themselves will make things better, but that they&rsquo;ll enable other optimisations by having much quicker equality checking, etc, so I need to try out those other optimisations and see the results.  If you&rsquo;re reading this in a few months and still curious, reach out to me on Bluesky or something and ask me how it&rsquo;s going, and then I can update this blog post with the results.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Note: performance as in &ldquo;speed, efficiency&rdquo;, not performance as in &ldquo;performance art&rdquo;.  Although I would be interested in using obtuse programming techniques as performance art.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>This Overly Long Variable Name Could Have Been a Comment</title><link>https://jonathan-frere.com/posts/names-vs-comments/</link><pubDate>Tue, 01 Jul 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/names-vs-comments/</guid><description>&lt;p>Here&amp;rsquo;s a belief I&amp;rsquo;ve held for a while but only recently been able to put into words: explanatory comments are often easier to understand than explanatory variable or function names.&lt;/p>
&lt;p>Consider a complicated expression with multiple sub-expressions. This expression is going to be difficult for the next person reading this code to decipher; we should make it easier for them.&lt;/p>
&lt;p>There are a couple of ways to solve this. We could break down the expression into sub-expressions, and assign those sub-expressions to intermediate variables. Or we could pull the expression out into its own dedicated function. In each case, the goal is to give either part or all of the expression a dedicated name. This name helps the next reader to understand the purpose or meaning of the expression.&lt;/p></description><content:encoded><![CDATA[<p>Here&rsquo;s a belief I&rsquo;ve held for a while but only recently been able to put into words: explanatory comments are often easier to understand than explanatory variable or function names.</p>
<p>Consider a complicated expression with multiple sub-expressions.  This expression is going to be difficult for the next person reading this code to decipher; we should make it easier for them.</p>
<p>There are a couple of ways to solve this. We could break down the expression into sub-expressions, and assign those sub-expressions to intermediate variables. Or we could pull the expression out into its own dedicated function. In each case, the goal is to give either part or all of the expression a dedicated name.  This name helps the next reader to understand the purpose or meaning of the expression.</p>
<p>Unfortunately, <a href="https://steveklabnik.com/writing/against-names/">names are hard</a>.  A good, meaningful name puts the next reader in exactly the right frame of mind to understand what is going on.  A bad name can confuse the next reader and make the code less legible than before.  And finding the right name is a difficult task.  It can&rsquo;t be too long and unwieldy — being too verbose makes it hard to communicate effectively, as anyone who&rsquo;s worked with German bureaucracy can tell you.  On the other hand, it can&rsquo;t be too short or generic — naming everything <code>x</code> or <code>var</code> will rarely help future readers.</p>
<p>Sometimes, though, I can&rsquo;t find a good, obvious name.  In these cases, rather than trying to force one, I instead write a comment.  A comment gives you more space to work with, which means it can be much more exact and precise than a single name.  You can use a comment to remove potential ambiguities that a more generic name might have.  A comment also allows you the chance to provide more &ldquo;why&rdquo;-type explanation rather than just describing the &ldquo;what&rdquo;.</p>
<p>A good name is normally far better than a comment, but good names are hard to come by.  If you&rsquo;re struggling to find the right name for a particular chunk of code, consider whether the context would be better explained as a comment.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>As a brief postscript, a note about comments going out of date.  This certainly happens!  But the same is also true of names, which can easily end up out of date after a couple of rounds of refactoring.  In my experience, comments often contain more details, which means they can become (at least partially) outdated more easily, but in either case, it&rsquo;s important to check names and comments when doing refactoring work.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Side Effects in SolidJS</title><link>https://jonathan-frere.com/posts/side-effects-in-solidjs/</link><pubDate>Tue, 27 May 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/side-effects-in-solidjs/</guid><description>&lt;p>If you’re used to React, you’re probably used to using &lt;code>useEffect&lt;/code> to run side-effectful code, such as integrating with third-party libraries or setting up &lt;code>MutationObserver&lt;/code>s&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. SolidJS also has &lt;code>createEffect&lt;/code>, which works very similarly to &lt;code>useEffect&lt;/code>, but it also has some other functions, and I’ve noticed that people getting started with SolidJS often aren’t sure which function to use for any given side-effects.&lt;/p>
&lt;p>If you’re in that boat, then here is the answer in tabular form:&lt;/p></description><content:encoded><![CDATA[<p>If you’re used to React, you’re probably used to using <code>useEffect</code> to run side-effectful code, such as integrating with third-party libraries or setting up <code>MutationObserver</code>s<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.  SolidJS also has <code>createEffect</code>, which works very similarly to <code>useEffect</code>, but it also has some other functions, and I’ve noticed that people getting started with SolidJS often aren’t sure which function to use for any given side-effects.</p>
<p>If you’re in that boat, then here is the answer in tabular form:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: center">runs immediately</th>
          <th style="text-align: center">runs on mount</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>is reactive<br>(runs multiple times)</strong></td>
          <td style="text-align: center"><code>createRenderEffect</code></td>
          <td style="text-align: center"><code>createEffect</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>is not reactive<br>(only runs once)</strong></td>
          <td style="text-align: center">no function needed</td>
          <td style="text-align: center"><code>onMount</code></td>
      </tr>
  </tbody>
</table>
<p>In this post, I’ll unpack this table and explain what it means in a bit more detail.</p>
<h2 id="what-are-side-effects">
  <a href="#what-are-side-effects">What are side effects?</a>
</h2>

<p>Side effects in this context is code that:</p>
<ul>
<li>interacts with the page (i.e. isn’t deriving new values from existing inputs)</li>
<li>isn’t handled by the framework itself (e.g. adding <code>onClick</code> handlers to a button via JSX, or using async/suspense).</li>
</ul>
<p>So for the purposes of this blog post, something like this might be a side effect:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// attach a global event listener from
</span></span></span><span class="line"><span class="cl"><span class="c1">// inside a particular component
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nb">document</span><span class="p">.</span><span class="nx">addEventHandler</span><span class="p">(</span><span class="s2">&#34;keydown&#34;</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">});</span>
</span></span></code></pre></div><p>But these probably aren’t side effects:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// derive the `fullName()` signal by
</span></span></span><span class="line"><span class="cl"><span class="c1">// combining a `firstName()` and `lastName()`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">fullName</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">firstName</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="nx">lastName</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// attach an event listener to a particular
</span></span></span><span class="line"><span class="cl"><span class="c1">// element using JSX
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">&lt;</span><span class="nt">input</span> <span class="na">onKeyDown</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">}}</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// this does have side effects, but for the purposes of
</span></span></span><span class="line"><span class="cl"><span class="c1">// this post, those side effects are handled by SolidJS
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="p">[</span><span class="nx">resource</span><span class="p">]</span> <span class="o">=</span> <span class="nx">createResource</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">fetch</span><span class="p">(</span><span class="cm">/* ... */</span><span class="p">));</span>
</span></span></code></pre></div><h2 id="are-my-side-effects-reactive">
  <a href="#are-my-side-effects-reactive">Are my side effects reactive?</a>
</h2>

<p>There are broadly two types of side effect:</p>
<ul>
<li>Side effects that run once over a component’s entire lifecycle — i.e. some code that should run once when each instance of the component is first rendered, and then cleaned up when the component is unmounted, but never between.  These side effects are <em>not reactive</em>.</li>
<li>Side effects that run multiple times whenever an input changes — i.e. code that will regularly be rerun during the lifetime of the component<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</li>
</ul>
<p>For example, the global <code>keydown</code> handler from before will probably only need to run once: we set the handler when the component is mounted, and then remove it when we’re ready to clean the component up.  However, the classic <a href="https://overreacted.io/making-setinterval-declarative-with-react-hooks/"><code>useInterval</code></a> hook needs to use reactive side-effects: whenever the input parameters change, we need to clean up the old <code>setInterval</code> handler and create a new one.</p>
<h2 id="when-should-my-side-effects-run">
  <a href="#when-should-my-side-effects-run">When should my side effects run?</a>
</h2>

<p>SolidJS’s side effects can be triggered at two different times:</p>
<ul>
<li>Immediately, as the component is being created</li>
<li>Later, once the component has been mounted to the DOM and is ready to be used</li>
</ul>
<p>Some things only make sense once the component has been mounted: any code that needs to access <a href="https://docs.solidjs.com/concepts/refs"><code>ref</code></a>, for example, should run after the element has been created and attached to the DOM<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</p>
<p>Some things are not so clear-cut though.  For example <code>setInterval</code> doesn’t require any access to the DOM or to any particular elements, so it might make sense to put it in the “run immediately” category.  In practice, however, <code>setInterval</code> should normally only run once the component has been mounted.  Why?</p>
<p>The answer is server-side rendering.  When a component is rendered server-side, the DOM is never mounted per-se, so side effects that run only once mounted are never run.  However side effects that run immediately <em>are</em> run, because they will probably affect how the component will be rendered.  In fact, that’s normally the point of having them run immediately in the first place, so they can affect rendering!</p>
<p>If we put <code>setInterval</code> in the “run immediately” category, then it will be run on the server.  But the render code will never wait for the interval handler to actually start, it’ll just carry on generating HTML and sending it to the client.  And once the HTML has been generated, the component will be unmounted, the <code>setInterval</code> handler will be cleared, and the code in it probably won’t have even had the chance to run once, let alone affect how the code gets rendered<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</p>
<p>This won’t break anything (as long as the interval is correctly cleared), but it is a useless call to <code>setInterval</code>, and a useless resource that needs to be allocated and cleaned up at some point.  Therefore, if you’ve got a side effect and you’re sure it won’t affect rendering, consider running it only once the DOM has been mounted.</p>
<h2 id="bringing-it-together-as-a-table">
  <a href="#bringing-it-together-as-a-table">Bringing it together as a table</a>
</h2>

<p>If we combine the two questions above, we end up with four different cases, as shown in the table I showed earlier:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: center">runs immediately</th>
          <th style="text-align: center">runs on mount</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>is reactive<br>(runs multiple times)</strong></td>
          <td style="text-align: center"><code>createRenderEffect</code></td>
          <td style="text-align: center"><code>createEffect</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>is not reactive<br>(only runs once)</strong></td>
          <td style="text-align: center">no function needed</td>
          <td style="text-align: center"><code>onMount</code></td>
      </tr>
  </tbody>
</table>
<p>To finish up, let’s look at those four cases individually.</p>
<ul>
<li><code>createEffect</code>: The first run always happens after the component is mounted.  After that, if a signal used in the body of the effect changes, the effect will be rerun.  If no signals are used in the body, then this behaves the same as <code>onMount</code>.</li>
<li><code>onMount</code>: As the name says, this also happens after the component is mounted, but it is <em>not</em> reactive.  This is good for side effects that only need to run once that use the DOM.</li>
<li><code>createRenderEffect</code>: Reactively, this behaves the same as <code>createEffect</code>, but the first run will happen <em>immediately</em> (i.e. synchronously before the <code>createRenderEffect</code> is completed).  Similarly to <code>createEffect</code>, if no signals are used in the body of the effect, then this behaves the same as running the code in the body of the component.</li>
<li><em>no function needed</em>: Remember that the body of your component will only get called once during the component’s lifetime, so non-reactive side-effects that need to run immediately (such as instantiating a third-party library, or using <code>createUniqueId</code>) can be called as part of that body.</li>
</ul>
<h2 id="addendum-oncleanup">
  <a href="#addendum-oncleanup">Addendum: <code>onCleanup</code></a>
</h2>

<p>A lot of side effects require some sort of cleanup to happen later — for example, starting a <code>setInterval</code> timer requires cleaning up that timer when it’s no longer needed.  For that, SolidJS provides the <code>onCleanup</code> function.</p>
<p>As a rule of thumb, <code>onCleanup</code> can be called wherever there is a scope that would get cleaned up at some point.  For example, once a component is no longer being rendered, it needs to be cleaned up and removed from the DOM.  By calling <code>onCleanup</code> in the component body, you can add an extra callback that will be called when that happens.</p>
<p>For reactive effects (<code>createRenderEffect</code>/<code>createEffect</code>), calling <code>onCleanup</code> inside the effect callback will schedule a function to run when the effect is re-run, i.e. when a signal triggers the effect to restart, all <code>onCleanup</code> functions will get called, and then the new effect is run.</p>
<p>In general, put your <code>onCleanup</code> calls inside the function you use to create your side effect in the first place.  For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// NO!  Don&#39;t do this!
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">onMount</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* some side effect */</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">onCleanup</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* some clean up */</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// ----
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// YES!  Do this!
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">onMount</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="cm">/* some side effect */</span>
</span></span><span class="line"><span class="cl">  <span class="nx">onCleanup</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/* some clean up */</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>This is because generally you only want the <code>onCleanup</code> to run if the side effect was called in the first place.  As mentioned earlier, functions like <code>onMount</code> and <code>createEffect</code> will not run during SSR, but if the <code>onCleanup</code> isn’t inside one of those functions, then it will still be called during SSR, doing unexpected things.</p>
<h2 id="addendum-avoiding-effects">
  <a href="#addendum-avoiding-effects">Addendum: Avoiding effects</a>
</h2>

<p>At the start, I made the comparison to React’s <code>useEffect</code>, and in a footnote pointed out that in modern React, <code>useEffect</code> is generally discouraged — there’s often a better way.</p>
<p>In SolidJS, <code>createEffect</code> doesn’t behave in quite such surprising ways as <code>useEffect</code>, thanks in large part to the automatic dependency tracking that means that the effect normally re-runs when you’d expect it to re-run.  However, it’s still a good idea to look out for cases where you can replace <code>createEffect</code> with a better option.  When I look at <code>createEffect</code> calls, these are the things I’m looking out for:</p>
<ul>
<li>Is a signal setter being used in the body of the effect?  If so, the effect can almost certainly be replaced by <code>createMemo</code> or another form of computed signal.</li>
<li>Is an async function being called in the effect?  If so, it might be worth using <code>createResource</code> (or <code>createAsync</code> from Solid Router) instead, as this will handle some of the boilerplate for you, as well as integrating with the suspense mechanism.</li>
<li>Is the effect setting an event handler on a DOM element?  If so, use the <code>on*</code> handlers in JSX instead.  This seems obvious, but I’ve written this sort of code before, only to realise later that I’d missed an obvious and easier solution.</li>
<li>Is the function body reactive and/or would the effect work better if it was run immediately?  As discussed in this article, other functions for running side effects are available.</li>
<li>Is there a function that already handles this case in a <a href="https://primitives.solidjs.community/">Solid Primitives</a> package, or can you write your own wrapper around the effect to encapsulate it a bit better?  This one isn’t really about getting rid of effects, but rather hiding them somewhere else.  But encapsulation is good, and the Solid Primitives functions are generally useful, even if you’re just looking at the source code to get a hint of how to do something.</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>You’re probably also used to people telling you not to use <code>useEffect</code> if you can avoid it.  That’s often good advice in SolidJS as well, although perhaps not to the same extent — I’ll discuss that a bit at the end of this post.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Comparison with React time again: React does <em>not</em> explicitly distinguish between these two cases.  <code>useEffect</code> is always reactive, albeit reactive based on the explicit deps array (unlike SolidJS where dependency tracking happens automatically).  However, the “run once” case is usually modelled by an empty deps array (i.e. <code>[]</code>), and the “run many times” case is modelled by adding dependencies to that array.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Note that code that <em>sets up</em> refs should run immediately, and not later.  This distinction is very rarely important — as a general rule, if you’re accessing a ref, you’ll want the code doing that to run after the DOM has been mounted.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>My inner pedant wants you to know that with async rendering/suspense, it is possible to manufacture situations where rendering will wait until <code>setInterval</code> has been called at least once.  I can’t think of any good reason why you should do this, but technically this paragraph isn’t quite true.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Accessing Fastify Sessions via tRPC Websockets</title><link>https://jonathan-frere.com/posts/trpc-fastify-websockets/</link><pubDate>Tue, 15 Apr 2025 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/trpc-fastify-websockets/</guid><description>&lt;p>This is a quick post to point out a potential issue that might catch you out with using Fastify&amp;rsquo;s sessions mechanism alongside tRPC&amp;rsquo;s websockets transport, and how I&amp;rsquo;ve fixed it in my projects.&lt;/p>
&lt;p>The problem happens with an application that looks something like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">Fastify&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">ws&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">fastifyCookie&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">fastifySession&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">secret&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;...&amp;#34;&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">register&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">fastifyTRPCPlugin&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">prefix&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;/trpc&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">useWSS&lt;/span>: &lt;span class="kt">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">trpcOptions&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">router&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">onError&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">createContext&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">({&lt;/span> &lt;span class="nx">req&lt;/span> &lt;span class="p">})&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">req&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">session&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// logs &amp;#34;undefined&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="p">{};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>useWSS&lt;/code> parameter passed to the tRPC plugin means that it can handle both standard HTTP requests and a persistent websocket connection. Theoretically, both of these kinds of requests get handled by Fastify first, and therefore both should be initialised with a session object&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. In practice, though, the &lt;code>session&lt;/code> field is missing on all websocket-based connections, but present for all HTTP-based connections.&lt;/p></description><content:encoded><![CDATA[<p>This is a quick post to point out a potential issue that might catch you out with using Fastify&rsquo;s sessions mechanism alongside tRPC&rsquo;s websockets transport, and how I&rsquo;ve fixed it in my projects.</p>
<p>The problem happens with an application that looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">Fastify</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">ws</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifyCookie</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifySession</span><span class="p">,</span> <span class="p">{</span> <span class="nx">secret</span><span class="o">:</span> <span class="s2">&#34;...&#34;</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifyTRPCPlugin</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">prefix</span><span class="o">:</span> <span class="s2">&#34;/trpc&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">useWSS</span>: <span class="kt">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">trpcOptions</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">router</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">onError</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">createContext</span><span class="o">:</span> <span class="p">({</span> <span class="nx">req</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">session</span><span class="p">);</span> <span class="c1">// logs &#34;undefined&#34;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">return</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>The <code>useWSS</code> parameter passed to the tRPC plugin means that it can handle both standard HTTP requests and a persistent websocket connection. Theoretically, both of these kinds of requests get handled by Fastify first, and therefore both should be initialised with a session object<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. In practice, though, the <code>session</code> field is missing on all websocket-based connections, but present for all HTTP-based connections.</p>
<p>The cause is that the Fastify adapter for tRPC <a href="https://github.com/trpc/trpc/blob/7d10d7b028f1d85f6523e995ee7deb17dc886874/packages/server/src/adapters/fastify/fastifyTRPCPlugin.ts#L67">delegates to the non-Fastify-specific websocket adapter</a>. When that creates a context, the incoming <code>req</code> object is an instance of <code>IncomingMessage</code>, i.e. the underlying NodeJS request abstraction, which does <em>not</em> have the Fastify session details attached.</p>
<p>This probably should be better documented, ideally directly in the types (although that would probably be a fairly large breakage), or at least in the Fastify documentation.</p>
<p>The best solution I found is a <code>WeakMap</code> mapping <code>IncomingMessage</code> requests to <code>FastifyRequest</code> values, which have the expected <code>session</code> attribute. That looks something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="c1">// create a new scope so that the hook we add later will only
</span></span></span><span class="line"><span class="cl"><span class="c1">// affect tRPC-specific requests
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">((</span><span class="nx">app</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// use a WeakMap to avoid leaking memory by holding on to
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// requests longer than necessary
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">REQS</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WeakMap</span><span class="o">&lt;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">FastifyRequest</span> <span class="o">|</span> <span class="nx">IncomingMessage</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">FastifyRequest</span>
</span></span><span class="line"><span class="cl">  <span class="o">&gt;</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">app</span><span class="p">.</span><span class="nx">addHook</span><span class="p">(</span><span class="s2">&#34;onRequest&#34;</span><span class="p">,</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// associate each raw `IncomingMessage` (`req.raw`) with
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// the original `IncomingMessage`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">REQS</span><span class="p">.</span><span class="kr">set</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">raw</span><span class="p">,</span> <span class="nx">req</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">app</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">fastifyTRPCPlugin</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">prefix</span><span class="o">:</span> <span class="s2">&#34;/trpc&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">useWSS</span>: <span class="kt">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">trpcOptions</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">router</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">onError</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">createContext</span><span class="o">:</span> <span class="p">({</span> <span class="nx">req</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// given either a `FastifyRequest` or an
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// `IncomingMessage`, fetch the related
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// `FastifyRequest` that we saved earlier
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kr">const</span> <span class="nx">realReq</span> <span class="o">=</span> <span class="nx">REQS</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">raw</span> <span class="o">??</span> <span class="nx">req</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">realReq</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">&#34;This should never happen&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">realReq</span><span class="p">.</span><span class="nx">session</span><span class="p">);</span> <span class="c1">// logs the session object
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">return</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>Because the tRPC types aren&rsquo;t correct for the <code>req</code> parameter of the <code>createContext</code> callback, you might need to fiddle with the Typescript types to get this to work properly. Specifically, the <code>WeakMap</code> type here is technically incorrect, but means that I can do <code>REQS.get(req.raw ?? req)</code> without Typescript complaining. This does cause an ESLint error (because according to the type definitions, <code>req.raw</code> can never be null), but I&rsquo;d rather silence an ESLint error than a Typescript error.</p>
<p>I hope this helps you, or myself in six months&rsquo; time when I run into this issue again having forgotten about it completely.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Indeed, this is also what the types will tell you — if you are using Typescript, <code>req.session</code> will have the type of the Fastify session object in the example above.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Surprising Programmer Tools #53: The Sudoku</title><link>https://jonathan-frere.com/posts/useful-tools-sudoku/</link><pubDate>Thu, 24 Oct 2024 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/useful-tools-sudoku/</guid><description>&lt;p>During the Pandemic, I found the YouTube channel &lt;a href="https://www.youtube.com/c/CrackingTheCryptic">&lt;em>Cracking the Cryptic&lt;/em>&lt;/a>, which is run by two champion puzzlers, Simon and Mark, who solve various logic puzzles, focusing mainly on variant sudoku. Variant sudoku adds additional rules to a normal sudoku grid — for example killer sudoku, where all the numbers in a certain marked area need to add up to a certain number. As you add more rules, they often end up combining in weird and clever ways, and you can logically deduce more about the grid with less given information.&lt;/p></description><content:encoded><![CDATA[<p>During the Pandemic, I found the YouTube channel <a href="https://www.youtube.com/c/CrackingTheCryptic"><em>Cracking the Cryptic</em></a>, which is run by two champion puzzlers, Simon and Mark, who solve various logic puzzles, focusing mainly on variant sudoku. Variant sudoku adds additional rules to a normal sudoku grid — for example killer sudoku, where all the numbers in a certain marked area need to add up to a certain number. As you add more rules, they often end up combining in weird and clever ways, and you can logically deduce more about the grid with less given information.</p>
<p>The channel is so compelling because they don’t just focus on getting the right answer, but explain how they can make each deduction along the way to figuring out the puzzle. They often use the language of proving: it’s not enough to guess, or to believe, or even to be very confident that a particular number needs to go in a certain place, you have to <em>prove</em> that it’s correct. Generally that involves whittling away at the other options and showing that they don’t work. If we know a number needs to go in a certain row, but the rules prevent us from putting it in any other cell in that row but one, then we have <em>proved</em> that the number must go in that cell.</p>
<p>There’s still a lot of intuition involved though! With many years of experience, Simon and Mark are able to look a few lines and the grid and very quickly find which parts of the grid they should be looking at first. When I started playing along and trying to solve some of the simpler puzzles myself, this was what I found most hard, but over time I’ve found I can spot “naked singles”, “roping”, or uses of “the secret” (all real sudoku terms) just by running my eyes over the grid.</p>
<p>But that intuition is only a start, and it can be wrong (or even deliberately mislead). Intuition might tell you something like “I should think about where the number five can go in this column”, because a particular rule makes it hard to put fives in certain places. But I can’t just guess where the five will go — I need to prove that, and show that no other option is possible. There’s an interplay between using human intuition to guess where the next weak spot will be, and then taking a more mechanical approach to actually put numbers into the grid.</p>
<h2 id="so-what-does-this-have-to-do-with-programming">
  <a href="#so-what-does-this-have-to-do-with-programming">So what does this have to do with programming?</a>
</h2>

<p>Sudokus, to me, feel most useful when debugging. Not necessarily the sudoku puzzle itself (although taking a break to do a sudoku can be a great way to clear my head), but the headspace that it invokes. Debugging involves the same interplay between intuition and proof that a sudoku does, and I use a similar approach in both cases.</p>
<p>The first thing I want to do when I’m debugging is get as much of an overview of what’s going on as possible — logs, error messages, videos of what the user was doing, etc. This is like looking at the whole sudoku grid and trying to guess where you should look next. You won’t necessarily know exactly what to do, but you can build up hunches for where to look.</p>
<p>This hopefully gives me a clue as to which area of the code to start looking at. Now I want to start eliminating possibilities. What can I prove <em>isn’t</em> the cause of the problem? I find deleting or commenting out code is a fantastic tool. If I’m feeling particularly paranoid, I’ll even start deleting logs and other code that feels obviously irrelevant, just to eliminate those as options.</p>
<p>Even with a smaller set of options, there still might be multiple places to look. At this point, often I find it helpful to reason through the different options. In a sudoku puzzle, I might know that a certain cell must be 1, 4, or 9 (say). Then I can reason that through: if I made this cell 1, what would happen? What would the effects be?<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>When debugging, I do something similar. Here, though, it’s often more useful to think about <em>how</em> this bit of code might cause the effects I’ve already seen. Say there’s been issues with connection failures: how could the code I’m looking at have triggered those failures? And would it have produced the same sorts of errors, or would it have looked differently?</p>
<p>I often have cases where I think “oh, there could be a bug here, but it wouldn’t explain why XYZ also happened”, or “if this were to cause a bug, it would happen by the server crashing, but the server never crashed”. Sometimes this is even a trigger to go out and look for more evidence. Am I sure there wasn’t a server crash? Am I confident that there’s no relationship between this code and XYZ?</p>
<p>Hopefully I’m confident now that I’m in the right place. Maybe I can already see what I’ve done wrong, maybe I need to fiddle with the code some more, but let’s assume I eventually come up with a cause for the bug, and a way to solve the bug.</p>
<p>However, the final step is to prove that this really was the cause for the bug, and that the solution really is fixing the root cause. It’s not enough that I just can’t see the problem any more — that’s like putting a number into the grid because you think it’s more likely to be in one place than the other. With sudoku and with debugging, certainty is important.</p>
<p>I’ve seen some suggestions that the way to know whether or not you’ve fixed something is to find a way to trigger the bug reliably, and then add and remove the fix. If you can consistently see that the bug is gone with the fix, and present when the fix is removed, then you’ve fixed the bug. There’s some truth to this, but I think it’s only part of the story. More important is being able to say — as precisely as possible — <em>why</em> the bug occurred, and <em>how</em> the fix stopped it from happening. That’s the “proving” part: understanding at a deeper level what’s going on and how to stop it.</p>
<h2 id="a-perfect-analogy">
  <a href="#a-perfect-analogy">A perfect analogy?</a>
</h2>

<p>It’s important to remember that a sudoku is a puzzle designed to have a single solution, and usually a single path to that solution. Debugging is not part of anyone’s plan, there may not be a single cause to the problem, and there are often multiple solutions to the problem once you’ve found it. However, I’ve found the strategy of puzzling — particularly the style of sudoku solving from Cracking the Cryptic — is a useful way to approach debugging. This strategy keeps me from relying too heavily on untested assumptions, and keeps me going until I find an actual cause, and not just a vague suspicion.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>In sudoku puzzles, doing this too much is known as “bifurcation”, and it’s generally considered taboo. However (1) the difference between reasoning through different options and bifurcation is very fuzzy, and (2) we’re trying to fix a bug, not solve an elegant logic puzzle, so I think we’re allowed more leeway with brute-forcing!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>10 Years of Programming</title><link>https://jonathan-frere.com/posts/10-years-of-programming/</link><pubDate>Thu, 26 Sep 2024 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/10-years-of-programming/</guid><description>&lt;p>As of the beginning of September, I’ve been programming &amp;ldquo;with purpose&amp;rdquo; for a decade. Before then it was just a hobby — something I could do in my room while burying my head in the sand about the Physics degree I was failing at the time. But that summer, I realised maybe if I was choosing to spend all my free time coding, maybe it was worth trying to pursue that as a career instead.&lt;/p></description><content:encoded><![CDATA[<p>As of the beginning of September, I’ve been programming &ldquo;with purpose&rdquo; for a decade. Before then it was just a hobby — something I could do in my room while burying my head in the sand about the Physics degree I was failing at the time. But that summer, I realised maybe if I was choosing to spend all my free time coding, maybe it was worth trying to pursue that as a career instead.</p>
<p>Okay, so maybe ten years isn&rsquo;t all that long, but since I started studying software development properly, I’ve learned a lot, and I want to reflect on that a bit. I suspect not everything I learned is correct: come back in ten years’ time to read my critical retrospective where I point out what an absolute idiot I was/am. But in the meantime, here are some assorted thoughts on how I practice programming.</p>
<ul>
<li>
<p><strong>I write software for people.</strong> No, literally, I write code thinking about the people who will read it. When I write a blog post or an email, I’ve got a target audience in my head. Why not do the same thing with code? Is this clever type-level shenanigan really the best idea? Will my colleagues be able to quickly extend this test file with new cases? Would a comment be useful here?</p>
</li>
<li>
<p><strong>The more I automate, the less I have to think.</strong> I don’t think I can write code without an autoformatter any more. The junk that comes out of my keyboard is bad — all on one line, indentation all over the place, terrible spacing. But an autoformatter does the tedious formatting work for me. I don’t even care what that formatting is — I will accept basically anything, as long as I don’t have to think about it. See also: automatically importing functions I’m using, as well as automatically removing imports I’m no longer using.</p>
</li>
<li>
<p><strong>The more I automate, the less I have to think: Round 2.</strong> This goes doubly if the stuff I’m automating is stuff I only rarely do. I have a few projects that I occasionally do stuff with — a LaTeX CV that I only update when I’m looking for a job, a website that only needs occasional changes, etc. Automation (a Makefile, a CI build/deploy pipeline, etc) means I don’t have to reverse engineer the project every time I come to work on it again.</p>
</li>
<li>
<p><strong>Some things aren’t automatable.</strong> Whenever I commit my code, I diff my code and try and review it to see if I’ve made silly mistakes, left debugging code in, forgotten to refactor something, etc. Then, when I create a pull request, I do the same thing again. Linting isn’t a good substitute for this — it can catch some of the basic stuff, sure, but it won’t catch anything. I haven’t (yet) found a way to automate away simple diligence.</p>
</li>
<li>
<p><strong>The right programming language is important, but probably less so than I’d like to believe.</strong> When I first learned to program, I used Python, and then I ended up in the frontend world and started writing a lot of Javascript, then Typescript, and it just hasn’t really stopped. And you know what? Javascript is not a great language. But it’s good enough. I write a lot of my own stuff in Rust and miss features of Javascript, then spend my day job missing things in Rust (or Python, or whatever else).</p>
</li>
<li>
<p><strong>Types are non-negotiable for large projects.</strong> Okay, yeah, all programming languages have something good about them, even the bad ones, but the more people you work with, the more tools you need to communicate how code works. And types are possibly the single most effective tool to communicate how code works. Tests are cool, documentation is great, but both can be ignored or overridden. Types (okay, well-written types) stick around and enforce their rules on the codebase.</p>
</li>
<li>
<p><strong>I like tests when they’re good.</strong> I’ve <a href="https://jonathan-frere.com/posts/why-test/">written before</a> about how I didn’t really get testing until I understood how to write a good test. I’m currently rewriting a core module in a system at work, and having 100 or so tests that each test one aspect of this module, that I can slowly reenable as the new functionality comes online — it makes my life easier, and gives me more confidence that my new version behaves the same as the old.</p>
</li>
<li>
<p><strong>I <em>hate</em> tests when they’re bad.</strong> I still struggle to delete tests — it feels a lot like cheating — but sometimes they just aren’t helping. The accuracy and precision of tests in large codebases would be a great topic to study, because I suspect a lot of tests are never once useful in their lifetimes in a codebase.</p>
</li>
<li>
<p><strong>The simplest code is usually the hardest to write.</strong> There’s that famous quote “I’d have written a shorter letter, but I didn’t have the time”. I have similar feelings about code simplicity. Simple code isn’t about writing less code (that’s usually code that’s missing edge cases). It’s also not necessarily the easiest to read (see Torvald’s <a href="https://felipec.github.io/good-taste/parts/1.html">“good taste” example</a>, which is simple, but uses more indirection than a more naive alternative). Simple code is good, but it usually takes a lot of work to create it<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
</li>
<li>
<p><strong>Perfection is a good goal, but a bad obsession.</strong> I really like doing things the “right” way. I’m one of those people who’ll come up with an idea, create an empty repo for it, and then spend the next three hours getting the tests, linting, and CI working. I say that partly in jest, but also partly in pride. Perfection is also about little things like choosing the right semantic HTML element rather than adding an <code>onClick</code> handler to a <code>div</code> ; or spending a bit of extra time to get the commit history looking cleaner; or finding the O(n) algorithm instead of the O(n²) one.</p>
<p>But I&rsquo;ve also got to limit myself on these things. Sometimes it&rsquo;s not worth the extra effort. Sometimes, it&rsquo;s not even possible to get things perfect. Often, there are competing needs, and I just choose the needs that feel most important at the time. I recently saw a comment where someone listed their ideal websites, and it included things like not using CDNs, and ensuring that the site works on terminal browsers like Lynx. The perfectionist inside me understands these goals, but the pragmatist has won out, at least for this website.</p>
</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>As an aside, this is one of the issues I have with the “grug-brained developer” concept — writing simple code is not a matter of just not doing the complicated things, it’s about having enough deep knowledge and experience that you can see the simple option. This is a difficult, learned skill. To be clear, a lot of the advice given in the <a href="https://grugbrain.dev/">original document</a> is good advice, but I don’t find the “just write simple code because you aren’t smart” framing accurate or helpful.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Why Test?</title><link>https://jonathan-frere.com/posts/why-test/</link><pubDate>Sun, 23 Jun 2024 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/why-test/</guid><description>&lt;p>Why do you write tests?&lt;/p>
&lt;p>I&amp;rsquo;ve been thinking about this question a lot recently. I’ve been trying to motivate some teammates that tests are worth writing. But I&amp;rsquo;m going to convince them of that, I need to be able to answer that question for myself, right?&lt;/p>
&lt;p>Tests sometimes get portrayed as one of the chores of software development. As a new developer, that’s how I saw tests for a long time: something I did because it was what I was told to do — besides, if I got the coverage to 100%, I got a little green checkbox to put on my README.md file on Github. I knew that tests were good, because they make Good Code™ — I just didn&amp;rsquo;t know how that happened, or why my tests were still so painful to work with!&lt;/p></description><content:encoded><![CDATA[<p>Why do you write tests?</p>
<p>I&rsquo;ve been thinking about this question a lot recently. I’ve been trying to motivate some teammates that tests are worth writing. But I&rsquo;m going to convince them of that, I need to be able to answer that question for myself, right?</p>
<p>Tests sometimes get portrayed as one of the chores of software development. As a new developer, that’s how I saw tests for a long time: something I did because it was what I was told to do — besides, if I got the coverage to 100%, I got a little green checkbox to put on my README.md file on Github. I knew that tests were good, because they make Good Code™ — I just didn&rsquo;t know how that happened, or why my tests were still so painful to work with!</p>
<p>But over time, I&rsquo;ve found better ways of writing tests, tests that are easier to write and work with. And once I started writing better tests, I found they also became more useful to me, and I wanted to write them more — not because of some coverage metric, but because I was getting real value out of them.</p>
<p>Now, trying to articulate the &ldquo;why&rdquo; of testing to others, it&rsquo;s been interesting to explore where that value is coming from. The more I write tests, the more they&rsquo;ve become another tool in my toolbox — another way of developing faster and more confidently. It’s like learning all the shortcuts in your IDE or editor of choice, or figuring out the underlying model behind Git: the better you can use the tool, the more useful the tool is when you’re developing.</p>
<p>In this post, I want to explore testing as a tool in the process of building software. I’m going to divide my test-writing process into two parts: testing as a tool for faster development, and testing as a tool for future refactoring. I’ll talk about each part individually, and then explore how the two parts work together. Throughout this, I want to argue that testing is not just about correctness, but also that it can be an integral part of the development and design process.</p>
<h2 id="testing-for-faster-development">
  <a href="#testing-for-faster-development">Testing for Faster Development</a>
</h2>

<p>When I started programming, I did testing like this: I would write my code, and then I’d run it. And that was pretty much the full test. I’d run the program I’d written a few times with different arguments or inputs and make sure it was doing what I expected.</p>
<p>This strategy works really well at first. You try out your code by using it — how can there be any purer approach? And it’s really easy to get started too. No boilerplate, no extra frameworks; just run the code and poke around a bit until you’re confident that it works.</p>
<p>Unfortunately, as a strategy it also falls apart quite quickly too! The more states there are to test, the longer the testing process takes, and the higher the chance of forgetting an important case. Without a proper strategy, it’s very easy to go around in circles, fixing one thing only to break another thing in the process.</p>
<p>Solving this situation was my first introduction to automated testing: tools like <a href="https://docs.pytest.org/">pytest</a> gave me a way to run lots of tests at once, so that while I was making changes, I could see immediately when something was broken. The immediate feedback made it easier to develop quickly — the faster I could see what effect my changes had had, the faster I could decide if those changes made sense, and iterate on them further.</p>
<p>These days, it’s that desire for immediate feedback that often drives me to start writing tests. Right now, for example, I’m working on a project that involves tracking focus (i.e. which pane of the UI is the user interacting with at any point in time). Handling all the events and possibilities there involves a lot of edge cases, but writing tests for all of the edge cases that I come across means that I can see at a glance if what I’ve fixed, what I’ve broken, and what’s stayed the same.</p>
<p>It also makes it easier to try different things out. I can write exploratory code very quickly: once I’ve defined my goal, I can try out different ways of achieving that goal. Is it the <code>focus</code> event that does what I want, or the <code>focusin</code>? I can try both out and see which one has the effect I was after. Does this function automatically clean up after itself? Let’s find out by writing a quick test.</p>
<p>Development tests need to be quick, both to run and to write. The faster they run, the faster you get feedback (and the more you can run at once). But being able to write new tests quickly is also key. Writing tests adds to development time, but also adds a certain amount of context-switching between code and test, which we ideally want to reduce.</p>
<p>In my experience, there are a couple of keys to writing simple tests. Firstly, you need simple code (and in particular simple interfaces<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>). A test that requires priming three different mocks with precise behaviours is going to take a lot longer to write than a test that involves passing a couple of arguments to a function.</p>
<p>Secondly, it’s important to find good abstractions inside the tests. Abstraction in tests can often be seen as sacrilegious, but if tests are part of the codebase, then we should write them like code, including (cautiously) using abstractions. But I want to save some of my thoughts on that for a future blog post.</p>
<h2 id="testing-for-future-refactoring">
  <a href="#testing-for-future-refactoring">Testing for Future Refactoring</a>
</h2>

<p>The goal for refactoring is to keep the outward-facing interface of a unit (say, a module, a class, a function, etc) the same, while rewriting the internals to be more maintainable. This naturally raises the question: How do define that outward-facing interface of a module in the first place?</p>
<p>One answer is tests. If you’re adding tests to a unit for development purposes as you go along, over time you’ll build up a collection of examples of how that unit works. For example, a test that asserts that <code>add(1, 2)</code> results in <code>3</code> tells me a bit about the outward-facing interface of the <code>add</code> function<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. That’s a useful way of defining this interface, in large part because we can automatically run these tests regularly to make sure that the interface remains the same.</p>
<p>However, using tests to define our interface brings with it a couple of difficulties that we need to deal with.</p>
<p>The first difficulty is figuring which areas of a unit to test: what is part of the outward-facing interface, and what are internal details that aren&rsquo;t really relevant? In one of my first jobs, I worked on a codebase that had plenty of tests, but those tests included assertions for the exact message, context, and order of every single log call. Those tests were painful to work with — even small changes might change some aspect of the logs, which meant continually updating dozens of tests.</p>
<p>Tests that check internal details like this make refactoring harder. Maybe I decide to work around the tests to keep them passing, even though I know no code depends on the behaviour they&rsquo;re checking. Maybe I make the changes regardless of the tests, and now need to update a bunch of tests to match the new observed behaviour. Either way, it&rsquo;s more effort to make the change, and the tests — the tools that should be helping me — are working against me.</p>
<p>The second difficulty is what to do when an interface really should change. If each test makes a claim about the outward-facing behaviour of a unit, what happens when we want to update that behaviour? There are some contexts where we want to avoid changes at all costs — publishing a module for other teams to use, for example. But often the team writing the unit also wrote all of the places where it was used. In that case, it might be easier to update all the call-sites rather than trying to work around an existing interface.</p>
<p>In this case, having tests break is good (otherwise are the tests really telling us what&rsquo;s going on?), but it&rsquo;s still work, time, and effort to fix them. A good test, therefore, is also easy to update. Similarly to testing for development, one tool here is abstraction. Describing test goals at a higher level (e.g. &ldquo;Which suggestions would I get if I typed in this text, and left the cursor at this point?&rdquo;) allows a chance to abstract the precise mechanics of that code, while still maintaining the same tests.</p>
<p>The third difficulty is figuring out where to stop testing. If I fully tested every single function, every method and class, then I&rsquo;d never be able to change my code without needing to update a whole bunch of tests to match. At this point, tests are slowing me down rather than speeding up.</p>
<p>When I&rsquo;m refactoring, the best tests are the ones that are written against interfaces that are unlikely to change (or at least, unlikely to change beyond what can be fixed with a bit of find-and-replace and some manual poking around). In particular, modules that represent core business logic are generally unlikely to change significantly — if your application is a spreadsheet, then the module handling the reactive engine that binds all the cells together is going to need to remain relatively consistent. This can also be true for smaller modules that narrowly focus on one piece of functionality.</p>
<h2 id="design-combining-development-and-refactoring">
  <a href="#design-combining-development-and-refactoring">Design: Combining Development and Refactoring</a>
</h2>

<p>I’ve presented these two ideas as if they were two different testing processes, and in a way they are: if you were to only do testing for development, you’d probably choose to optimise a different set of things to if you were only doing testing for refactoring. But in practice, most of the tests I write serve both needs. After all, it would be a lot of effort to develop an entire test suite as I’m developing my code, only to delete it all and rewrite it for future refactoring purposes once I’ve finished.</p>
<p>I think that combining development and refactoring into one set of tests is about good software design.</p>
<p>In Test-Driven-Development (or TDD), there’s a big emphasis on tests as a tool for design. But often that connection between testing and design is explained poorly, or not at all. I regularly see references to TDD having the &ldquo;refactor&rdquo; stage, or an argument about how testing things helps us break them down into modules, but I think we can be more specific about this.</p>
<p>My theory is that good, clean code comes from a balancing of short-term and long-term needs, and the development/refactoring divide brings both of those needs to the surface. My short-term, development tests push me to write simple code. If it takes me thirty lines of code to get my code set up properly before I can even start testing, then development is going to be a very slow process! But my long-term, refactoring tests push me to write code that has clear public boundaries. After all, I don’t want to rewrite my tests every time I make a change to the implementation.</p>
<p>If I concentrate too hard on one kind of test or the other, then I will run into issues. If I’m only testing for development, then my code might be easy to get running, but I’ll probably need to delete all the tests next Wednesday when I make a slight internal change that breaks all of them. If I’m only testing for the sake of refactoring, then I can construct a labyrinthine maze of interfaces, dependencies, services, and end up with a kind of <a href="https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition">Enterprise FizzBuzz</a>-style mess.</p>
<p>It’s the combination of testing for now <em>and</em> for the future that makes tests useful as a tool for software design.</p>
<h2 id="conclusion">
  <a href="#conclusion">Conclusion</a>
</h2>

<p>In this post, I’ve tried to present my approach to testing as, principally, a tool for making my life as a software developer easier: it allows me to write code more quickly by providing a way to check that what I’m writing works; it allows me to refactor more confidently by enforcing that what I’m writing adheres to a certain interface; and it encourages better design through the natural pressures that come from the tests I’m writing.</p>
<p>Like I said at the start, the value here isn’t just some arbitrary vision of what Good Code™ should look like, or even correctness. (I’d go as far as to say that making code correct often involves a lot more than just tests, and tests are just one small part of that, but I’ll bang the static typing drum some other time.) Writing tests makes me faster overall<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>, and more confident in my work. I made the comparison earlier to an IDE, and it feels similar. As a developer, an IDE isn&rsquo;t necessary, but it will highlight my code, identify unused variables, allow me to navigate the codebase I’m working on easily, and generally make my life easier. Tests are a form of that that have the added convenience of being shared by my entire team.</p>
<blockquote>
<p>A huge thanks to <a href="https://matklad.github.io/">matklad</a>, who kindly looked over a draft of this post and offered his thoughts.</p>
</blockquote>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I don’t want to keep on bringing up A Philosophy of Software Design (an excellent book by John Ousterhout that I have <a href="https://jonathan-frere.com/posts/philosophy-software-design/">written about before</a>), but this does remind me of one of his specific principles, which is that it’s more important for a module to have a simple interface than a simple implementation. This is certainly true for testing, where it’s usually a lot easier to add new test cases to cover the complexities of the implementation than it is to have each case need to worry about all the complexities of the interface.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>You may (correctly) argue that knowing that <code>add(1, 2)</code> equals <code>3</code> tells us very little about the function itself — there are lots of different functions that will pass this test but won’t do a very good job of adding two numbers together. <code>add(a, b): return 3</code> , for example, passes this test, but is probably not working as expected!</p>
<p>There are ways around this — property-based testing, for example, tests that a given property of a function is true using random inputs, which gives us more information than a single test case. But I find that most of the time, the edge cases that are worth testing are pretty clear, and it’s the edge cases that do the most to defining what the interface of a module is.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>The corollary of that is that when writing tests really slows me down, I tend to write a lot fewer of them and only when I feel like they’re adding a lot of value. For example, I tend to only tests UI components when the logic gets complex, otherwise the value I get from testing is minimal compared to the work I need to put in to get the tests running.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>New Disposable APIs in Javascript</title><link>https://jonathan-frere.com/posts/disposables-in-javascript/</link><pubDate>Mon, 06 May 2024 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/disposables-in-javascript/</guid><description>&lt;p>Javascript’s new &amp;ldquo;Explicit Resource Management&amp;rdquo; proposal adds the &lt;code>using&lt;/code> statement, a way to automatically close resources after you’ve finished using them. But as part of the same proposal, a number of other APIs have been added that make &lt;code>using&lt;/code> even more useful. I couldn’t find a lot of documentation out there when I was trying to figure out how these APIs work, so this article is a bit of an overview of getting started with &lt;code>using&lt;/code>, &lt;code>Disposable&lt;/code>s, and explicit resource management.&lt;/p></description><content:encoded><![CDATA[<p>Javascript’s new &ldquo;Explicit Resource Management&rdquo; proposal adds the <code>using</code> statement, a way to automatically close resources after you’ve finished using them. But as part of the same proposal, a number of other APIs have been added that make <code>using</code> even more useful. I couldn’t find a lot of documentation out there when I was trying to figure out how these APIs work, so this article is a bit of an overview of getting started with <code>using</code>, <code>Disposable</code>s, and explicit resource management.</p>
<h2 id="the-journey-to-using-using">
  <a href="#the-journey-to-using-using">The Journey to Using <code>using</code></a>
</h2>

<p>Many classes or objects represent some sort of resource, such as an open file or a database connection, that requires some cleanup logic when that resource is no longer in use. In NodeJS, the convention is typically to put this cleanup in a <code>close()</code> function. For example, the <code>Server</code> class in <code>node:http</code> has a <code>close()</code> method that stops new connections and closes existing ones.</p>
<p>The problem with <code>close</code> alone is that it’s easy not to call it. Sometimes it&rsquo;s a matter of forgetting, but often errors and exceptions can trip us up. Consider this function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">saveMessageInDatabase</span><span class="p">(</span><span class="nx">message</span>: <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">conn</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DatabaseConnection</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">{</span> <span class="nx">sender</span><span class="p">,</span> <span class="nx">recipient</span><span class="p">,</span> <span class="nx">content</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">parseMessage</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">insert</span><span class="p">({</span> <span class="nx">sender</span><span class="p">,</span> <span class="nx">recipient</span><span class="p">,</span> <span class="nx">content</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This creates a database connection at the start of the function, and closes it at the end. But we have a problem if <code>parseMessage</code> or <code>conn.insert(...)</code> throw an error — in this situation, the <code>saveMessageInDatabase</code> function will stop without closing the connection, leaving unclosed resources hanging around.</p>
<p>The first step to solving this is to formalise how a resource gets closed. We can do this using the <code>Disposable</code> interface or protocol:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This is very similar to methods like <code>.close()</code>, <code>.cancel()</code>, and so on, but we use the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#well-known_symbols">well-known symbol</a> <code>Symbol.dispose</code> instead. This helps the runtime to distinguish between objects that have been intentionally made disposable (using this symbol), and objects that happen to have a certain name (e.g. <code>door.close()</code>).</p>
<p>With this in place, we can define the <code>using</code> syntax. <code>using</code> can be used in much the same way as <code>const</code>, and behaves very similarly in most respects.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="c1">// was: const varName = new MyDisposableObject();
</span></span></span><span class="line"><span class="cl"><span class="c1">// now:
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">using</span> <span class="nx">varName</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MyDisposableObject</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">varName</span><span class="p">.</span><span class="nx">method</span><span class="p">();</span>
</span></span></code></pre></div><p>However, <code>using</code> has a couple of restrictions in addition to the normal behaviour of <code>const</code>:</p>
<ul>
<li>With <code>using</code>, the variable <em>must</em> implement the <code>Disposable</code> protocol — i.e. it must have a <code>Symbol.dispose</code> method that can be called without arguments.</li>
<li>With <code>using</code>, you cannot destructure the variable you’re interested in (e.g. <code>using { field1, field2 } = disposable()</code>).</li>
</ul>
<p>When we leave the scope where a <code>using</code> variable was defined (i.e. when we return from the function in which <code>using</code> was used, or leave the if-block, or an exception gets thrown, etc), then the <code>Symbol.dispose</code> method will be called.</p>
<p>In addition, the dispose methods will be called in the reverse order to the way they were defined. So the object that was created first will be disposed of last. This reverse order is deliberate: we don’t want the database to be cleaned up while other resources are still using it!</p>
<p>An example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">create</span><span class="p">(</span><span class="nx">data</span>: <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`creating disposable object with data </span><span class="si">${</span><span class="nx">data</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">data</span>: <span class="kt">data</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`disposing disposable object with data </span><span class="si">${</span><span class="nx">data</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="p">},</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">data1</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="s2">&#34;first&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">data2</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="s2">&#34;second&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`using </span><span class="si">${</span><span class="nx">data1</span><span class="p">.</span><span class="nx">data</span><span class="si">}</span><span class="sb"> and </span><span class="si">${</span><span class="nx">data2</span><span class="p">.</span><span class="nx">data</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;before main&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">main</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;after main&#34;</span><span class="p">);</span>
</span></span></code></pre></div><p>This will produce the following logs:</p>
<pre tabindex="0"><code>before main
creating disposable object with data first
creating disposable object with data second
using first and second
disposing disposable object with data second
disposing disposable object with data first
after main
</code></pre><h2 id="async-disposables">
  <a href="#async-disposables">Async Disposables</a>
</h2>

<p>Often, when we want to dispose of a resource in Javascript, that cleanup/close/disposal operation will need to be asynchonous — for example due to waiting for connections to be cleaned up or data to be flushed.</p>
<p>So in addition to the standard <code>Disposable</code> protocol, there’s a second one, <code>AsyncDisposable</code>. This uses the <code>Symbol.asyncDispose</code> method, which returns a promise that should resolve when the resource is completely closed.</p>
<p>To use an async disposable, we have the <code>await using</code> syntax, which does the same thing as a normal <code>using</code> declaration, but, well, asynchronously. It must be called inside an <code>async</code> function (i.e. it needs to be called in a place where normal <code>await</code> is allowed).</p>
<p>The <code>await using</code> syntax can also handle non-async <code>Disposable</code> objects, which means if you don’t know whether a given resource is going to be asynchronously or synchronously disposed, you can use <code>await using</code> and cover both options.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: left"><code>await using</code></th>
          <th style="text-align: left"><code>using</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>Usable In:</strong></td>
          <td style="text-align: left">async functions only</td>
          <td style="text-align: left">async and sync functions</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Protocol:</strong></td>
          <td style="text-align: left"><code>AsyncDisposable</code> + <code>Disposable</code></td>
          <td style="text-align: left">only <code>Disposable</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Symbol:</strong></td>
          <td style="text-align: left"><code>Symbol.asyncDispose</code>/<code>Symbol.dispose</code></td>
          <td style="text-align: left"><code>Symbol.dispose</code></td>
      </tr>
  </tbody>
</table>
<h2 id="collections-of-disposables">
  <a href="#collections-of-disposables">Collections of Disposables</a>
</h2>

<p>Sometimes it&rsquo;s not enough to use function scope to handle resources. We might have a class or object that owns and manages a number of different resources. It would be useful if we could group all of its resources together in a similar way to <code>using</code>, but as a class variable or as part of a closure.</p>
<p>One convenient way of doing this is using the <code>DisposableStack</code> and <code>AsyncDisposableStack</code> classes. These represent stacks of resources managed by the <code>DisposableStack</code> or <code>AsyncDisposableStack</code> object — if we clean up the stack, all the resources that it manages will also get cleaned up. They can be created using the <code>new</code> operator, and provide three different methods for adding resources to the stack:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span> <span class="c1">// or ` = new AsyncDisposableStack()`
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// .use() takes a resource, adds it to the resources managed by the stack,
</span></span></span><span class="line"><span class="cl"><span class="c1">// and returns the resource so it can be used elsewhere.
</span></span></span><span class="line"><span class="cl"><span class="c1">// The resource must be a disposable item using the `Symbol.dispose` method
</span></span></span><span class="line"><span class="cl"><span class="c1">// (or `Symbol.asyncDispose` if using `AsyncDisposableStack`).
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">resource1</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="k">new</span> <span class="nx">MyResource</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// `.defer()` schedules a callback to take place when the stack gets disposed.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">handle</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;running&#34;</span><span class="p">),</span> <span class="mi">5000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">stack</span><span class="p">.</span><span class="nx">defer</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">handle</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// .adopt() combines the above two behaviours: it takes a resource and a
</span></span></span><span class="line"><span class="cl"><span class="c1">// disposal callback, and calls the callback with the resource as its argument
</span></span></span><span class="line"><span class="cl"><span class="c1">// when the stack gets disposed.  The resource does _not_ need to implement
</span></span></span><span class="line"><span class="cl"><span class="c1">// the disposable protocol.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">resource2</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">adopt</span><span class="p">(</span><span class="k">new</span> <span class="nx">OtherResource</span><span class="p">(),</span> <span class="p">(</span><span class="nx">r</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">r</span><span class="p">.</span><span class="nx">close</span><span class="p">());</span>
</span></span></code></pre></div><p>Stacks are themselves disposable, so can be disposed of using the <code>Symbol.dispose</code> or <code>Symbol.asyncDispose</code> methods. For convenience, this method is also exposed simple as <code>.dispose()</code> or <code>.asyncDispose()</code>. As mentioned earlier, this method (either using <code>Symbol.dispose</code>/<code>Symbol.asyncDispose</code> or via the alias method) will dispose of all of the resources managed by this stack. Similarly to the <code>using</code> declaration, the resources will be cleaned up in reverse order to prevent issues where resources depend on each other.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right"></th>
          <th style="text-align: left"><code>AsyncDisposableStack</code></th>
          <th style="text-align: left"><code>DisposableStack</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>Implements:</strong></td>
          <td style="text-align: left"><code>AsyncDisposable</code></td>
          <td style="text-align: left"><code>Disposable</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Manages:</strong></td>
          <td style="text-align: left"><code>AsyncDisposable</code> + <code>Disposable</code></td>
          <td style="text-align: left">only <code>Disposable</code></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>Dispose With:</strong></td>
          <td style="text-align: left"><code>.disposeAsync()</code></td>
          <td style="text-align: left"><code>.dispose()</code></td>
      </tr>
  </tbody>
</table>
<h2 id="useful-patterns-with-explicit-resource-management">
  <a href="#useful-patterns-with-explicit-resource-management">Useful Patterns with Explicit Resource Management</a>
</h2>

<p>Hopefully by now it should be clear what disposable resources are, how they can be manipulated, etc. But it still took me a while to get my head around some typical patterns with disposables, how they can be manipulated, and some best practices. So here are a few short sections which explain a couple of ideas that are now possible, and the best ways to achieve some common goals.</p>
<h3 id="anonymous-defers">
  <a href="#anonymous-defers">Anonymous Defers</a>
</h3>

<p>If you’re coming from other languages with features similar to using, such as Go with its <code>defer</code> statement, then you may be surprised that <code>using</code> is really a variable declaration — it’s basically the same as <code>const</code> or <code>let</code>, but it also automatically cleans up resources when the function has completed.</p>
<p>As a result, every time you use <code>using</code>, you need to declare a variable name. But often you don’t want to specify a variable name — e.g. if you want to defer a callback until the end of the function. It’s possible to do something like <code>using _ = ...</code>, using _ as a kind of informal placeholder, but this only works once per function body.</p>
<p>The best solution I’ve found is <code>DisposableStack</code> (or <code>AsyncDisposableStack</code>) and the <code>defer</code> method:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">	<span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;starting function&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nx">stack</span><span class="p">.</span><span class="nx">defer</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;ending function&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;during function body&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="disposable-timeouts-and-intervals">
  <a href="#disposable-timeouts-and-intervals">Disposable Timeouts and Intervals</a>
</h3>

<p>The specification gives a list of various browser and JS APIs that will be retrofitted with the disposable mechanism, but one API that is noticeably missing is the <code>setInterval</code> and <code>setTimeout</code> functions. Currently, they can be cancelled using the <code>clearInterval</code> and <code>clearTimeout</code> functions, and we can use <code>defer</code> to integrate them into a disposable stack:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">	<span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="kr">const</span> <span class="nx">handle</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="cm">/* ... */</span><span class="p">},</span> <span class="mi">5000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nx">stack</span><span class="p">.</span><span class="nx">defer</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">handle</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>In fact, if you’re using NodeJS, you can go one better. The NodeJS timers (i.e. <code>setInterval</code> and friends) already return an object (<a href="https://nodejs.org/api/timers.html#class-timeout"><code>Timeout</code></a>) with lots of useful functions like <code>.unref()</code>. Recent versions of v18 and upwards now also include a <code>Symbol.dispose</code> key for these objects, which means you can simplify the above code to this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">	<span class="nx">using</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="cm">/* ... */</span><span class="p">},</span> <span class="mi">5000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>And in the browser, we can write a similar utility function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">interval</span><span class="p">(...</span><span class="nx">args</span>: <span class="kt">Parameters</span><span class="p">&lt;</span><span class="nt">typeof</span> <span class="na">setInterval</span><span class="p">&gt;)</span><span class="o">:</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">handle</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span> <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">handle</span><span class="p">)</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="the-use-and-move-maneuver">
  <a href="#the-use-and-move-maneuver">The Use-and-Move Maneuver</a>
</h3>

<p>One more subtle but incredibly powerful method in the <code>DisposableStack</code> arsenal is <code>.move()</code>. This creates a new stack, moves all of the resources in the current stack into the new stack, and then marks the original stack as disposed. None of the resources will be disposed except for the original stack.</p>
<p>This is a powerful tool for anywhere where you’re creating resources for use elsewhere (so you want to put them in a stack), but the very act of creating resources is something that might fail (so you want to be <code>using</code> that stack when you create them.</p>
<p>Consider this example, which can cause resource leakages:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">badOpenFiles</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">fileList</span>: <span class="kt">string</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="o">:</span> <span class="p">{</span> <span class="nx">files</span>: <span class="kt">File</span><span class="p">[]</span> <span class="p">}</span> <span class="o">&amp;</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">files</span> <span class="o">=</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="p">(</span><span class="kr">const</span> <span class="nx">fileName</span> <span class="k">of</span> <span class="nx">fileList</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">files</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">open</span><span class="p">(</span><span class="nx">fileName</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">files</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">dispose</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>If I call this with a list of files, it’ll open all of those files and return them as single disposable object, that when it gets disposed of, closes all the files again.</p>
<p>But let’s say I call this with the file list <code>[&quot;file1.txt&quot;, &quot;file2.txt&quot;, &quot;file-does-not-exist.txt&quot;, &quot;file4.txt&quot;]</code>. Now, the first two files get created and added to the stack, but the third one causes an error, which exists the function. But because the stack was never added to a <code>using</code> declaration anywhere, those files will never be closed, which causes resource leakage.</p>
<p>The <code>.move()</code> function allows us to do this instead:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">openFiles</span><span class="p">(</span><span class="nx">fileList</span>: <span class="kt">string</span><span class="p">[])</span><span class="o">:</span> <span class="p">{</span> <span class="nx">files</span>: <span class="kt">File</span><span class="p">[]</span> <span class="p">}</span> <span class="o">&amp;</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Note we use the stack here, which means this stack will be cleaned up
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// when we return from the function.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="kr">const</span> <span class="nx">files</span> <span class="o">=</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">	<span class="k">for</span> <span class="p">(</span><span class="kr">const</span> <span class="nx">fileName</span> <span class="k">of</span> <span class="nx">fileList</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">files</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">open</span><span class="p">(</span><span class="nx">fileName</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="c1">// We&#39;ve successfully created all the files with no errors.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="c1">// Move the opened file resources out of the stack, and into a new
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="c1">// one that won&#39;t get closed at the end of this function.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="kr">const</span> <span class="nx">closer</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">move</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">files</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">dispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">closer</span><span class="p">.</span><span class="nx">dispose</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="the-disposable-wrapper">
  <a href="#the-disposable-wrapper">The Disposable Wrapper</a>
</h3>

<p>Right now, <code>Disposable</code>s are still relatively new, and so it&rsquo;s not unlikely that the library you&rsquo;re working with doesn&rsquo;t support them, opting instead for a <code>.close()</code> method or something similar. But Javascript is a dynamic language, so it&rsquo;s not too hard to get these tools to behave. Here&rsquo;s an example for MongoDB, which at the time of writing does not support <code>using</code> or any of the disposable protocols:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">createMongoClient</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">connection</span>: <span class="kt">string</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">options?</span>: <span class="kt">MongoClientOptions</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="o">:</span> <span class="nx">MongoClient</span> <span class="o">&amp;</span> <span class="nx">Disposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">client</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MongoClient</span><span class="p">(</span><span class="nx">connection</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="nx">client</span><span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">])</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">&#34;this code is unnecessary&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="nx">client</span><span class="p">,</span> <span class="p">{</span> <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">]</span><span class="o">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">client</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This will add a <code>Symbol.asyncDispose</code> method to the client, meaning you can use it in <code>await using</code> declarations and with <code>AsyncDisposableStack#use()</code>. In addition, if you ever update to a version of MongoDB that does implement the <code>AsyncDisposable</code> protocol, you&rsquo;ll get an error reminding you to delete the code.</p>
<h3 id="awaiting-signals">
  <a href="#awaiting-signals">Awaiting Signals</a>
</h3>

<p>A common pattern for NodeJS servers is to start up the web server, and then add event handlers for the OS&rsquo;s &ldquo;quit&rdquo; signals (e.g. <code>SIGINT</code>). Inside these handlers, we can shut the server down, clean up resources, etc.</p>
<p>This works fine, but the control flow can be difficult to follow, and we have to manually call the <code>Symbol.dispose</code> and <code>Symbol.asyncDispose</code> methods where that&rsquo;s relevant. It would be nice if there was a way to tie the lifetime of the application to the lifetime of a single function, so that when that function exits, the server will also automatically exit, closing and disposing of all resources along the way.</p>
<p>Enter NodeJS&rsquo;s <code>once</code> function, which converts an event into a promise<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">once</span> <span class="p">}</span> <span class="kr">from</span> <span class="s2">&#34;node:events&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// waits until the `SIGINT` signal has been triggered, e.g. from Ctrl-C
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">await</span> <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGINT&#34;</span><span class="p">);</span>
</span></span></code></pre></div><p>Using this, we can write a <code>main()</code> function that lives for the entire length of the application, and quits when the application is stopped, automatically cleaning up any resources after itself:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">using</span> <span class="nx">resource</span> <span class="o">=</span> <span class="nx">createResource</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// ... etc, for as many resources as make sense
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">  <span class="c1">// alternatively, use the &#34;Disposable Wrapper&#34; pattern from earlier
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">adopt</span><span class="p">(</span><span class="nx">express</span><span class="p">(),</span> <span class="nx">server</span> <span class="o">=&gt;</span> <span class="nx">server</span><span class="p">.</span><span class="nx">close</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// add routes, use resources, etc
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">server</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="cm">/* ... */</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;starting application on port 5000&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">5000</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;application started&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">Promise</span><span class="p">.</span><span class="nx">race</span><span class="p">([</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGINT&#34;</span><span class="p">),</span> <span class="c1">// Ctrl-C
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGTERM&#34;</span><span class="p">),</span> <span class="c1">// OS/k8s/etc requested termination
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// etc.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;shutting down application&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Because all of our resources are managed either by <code>using</code> directly, or by the <code>stack</code> which is in turn tied to the application&rsquo;s lifespan, we don&rsquo;t need to manually close anything after the signals have been handled — everything will automatically be gracefully shutdown.</p>
<h2 id="using-explicit-resource-management-today">
  <a href="#using-explicit-resource-management-today">Using Explicit Resource Management Today</a>
</h2>

<p>Right now, explicit resource management is a stage three proposal — that means that the specification has been completed and approved, and browsers and other tools are encouraged to start implementing the proposal, and trying the feature out in practice<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<p>This means that if you want to try this feature out right now, you&rsquo;re going to need to transpile the syntax to a format supported by older browsers, and provide a polyfill for the various global objects that the feature requires.</p>
<p>In terms of transpiling, both Typescript and Babel support the <code>using ...</code> syntax. For Typescript, you&rsquo;ll need <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management">version 5.2 or greater</a> to handle the syntax. In the <code>tsconfig.json</code> file, the <code>target</code> should be <code>ES2022</code> or lower in order to do the transpilation (otherwise Typescript will leave the syntax unchanged), and the <code>lib</code> setting should include <code>esnext.disposable</code> (or alternatively the whole <code>esnext</code> bundle of types) to ensure that the right set of types is included. For Babel, including the <code>stage-3</code> preset, or explicitly adding the <a href="https://babeljs.io/docs/babel-plugin-proposal-explicit-resource-management"><code>@babel/plugin-proposal-explicit-resource-management</code> plugin</a> should ensure that everything gets compiled correctly.</p>
<p>Neither Typescript nor Babel include a polyfill for the various global types discussed here, which means you&rsquo;ll also need a polyfill. For this, there are various options, including <a href="https://www.npmjs.com/package/disposablestack">disposablestack</a>, which I&rsquo;ve been using, and CoreJS.</p>
<h2 id="bringing-it-all-together">
  <a href="#bringing-it-all-together">Bringing It All Together</a>
</h2>

<p>Let’s say we’re writing something on the backend, and there’s a lot of interactions with users. We want a class that handles all of our user-based logic:</p>
<ul>
<li>It can create/read/update/delete our user objects in the database</li>
<li>It automatically deletes users that haven’t been active in the last five minutes (we’re <em>very</em> GDPR conscious here, we don’t keep data a second longer than we need to)</li>
<li>It provides a stream of all the new users inserted into the database, so that elsewhere we can send them a lovely greeting message.</li>
</ul>
<p>We’ll use dependency injection so that we don’t need to create the database connection ourselves, but some of the resources will be managed by the user service. We can use the <code>AsyncDisposableStack</code> to group those resources together, and we&rsquo;ll add a <code>Symbol.asyncDispose</code> method that delegates to the stack&rsquo;s dispose method to handle that disposal. We can even implement Typescript&rsquo;s <code>AsyncDisposable</code> interface to make sure that we get everything right:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">class</span> <span class="nx">UserService</span> <span class="kr">implements</span> <span class="nx">AsyncDisposable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">conn</span>: <span class="kt">DB.Conn</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">intervalHandle</span>: <span class="kt">NodeJS.Timeout</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="err">#</span><span class="nx">streamHandle</span>: <span class="kt">DB.StreamHandle</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">constructor</span><span class="p">(</span><span class="nx">conn</span>: <span class="kt">DB.Conn</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Our DB connection, passed in via dependency injection -- so we don&#39;t want
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// to add this to the set of resources managed by this service!
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">conn</span> <span class="o">=</span> <span class="nx">conn</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Remember, NodeJS&#39;s `Timeout` class already has a `Symbol.dispose` method,
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// so we can add that to the stack
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">timeoutHandle</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="k">this</span><span class="p">.</span><span class="nx">deleteInactiveUsers</span><span class="p">(),</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// For resources that don&#39;t have the right methods, `.adopt()` is the
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// easiest way to add an &#34;on dispose&#34; cleanup function
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">streamHandle</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">stack</span><span class="p">.</span><span class="nx">adopt</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">createNewUserStream</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Closing this stream is an async operation, hence why we&#39;re using
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="c1">// Symbol.asyncDispose, AsyncDisposableStack, etc.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="kr">async</span> <span class="p">(</span><span class="nx">stream</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">await</span> <span class="nx">stream</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">]()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">stack</span><span class="p">.</span><span class="nx">dispose</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// ... methods and implementation details
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>Now we need to actually construct all of our resources somewhere. We can add a <code>createResources</code> function that creates the resources, returns a disposable object that cleans up all of the resources together, and also ensures that if an error occurs during resource construction, everything will still get cleaned up gracefully — this is the power of the stack!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">async</span> <span class="kd">function</span> <span class="nx">createResources</span><span class="p">(</span><span class="nx">config</span>: <span class="kt">Config</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">MyDbDriver</span><span class="p">(</span><span class="nx">config</span><span class="p">.</span><span class="nx">connectionString</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">conn</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">connect</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// When the stack disposes of its resources, the `UserService` will be cleaned
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// up before the `conn`, which prevents errors where the `UserService` is
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// trying to use a connection that doesn&#39;t exist anymore.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">userService</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="k">new</span> <span class="nx">UserService</span><span class="p">(</span><span class="nx">conn</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Now all the resources have been set up, use .move() to create a new stack
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// and return a dispose method based on the new stack.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kr">const</span> <span class="nx">closer</span> <span class="o">=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">move</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">userService</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">asyncDispose</span><span class="p">]</span><span class="o">:</span> <span class="kr">async</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">await</span> <span class="nx">closer</span><span class="p">.</span><span class="nx">dispose</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Now finally, we need to plug all of this into our server implementation, and make sure that everything gets cleaned up when the server gracefully exits. We can use signals and promises to catch the events that should trigger a shutdown, and use the <code>using</code> declarations to automatically clean up any resources.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">main() {</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">config</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">loadConfig</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">resources</span> <span class="o">=</span> <span class="nx">createResources</span><span class="p">(</span><span class="nx">config</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">using</span> <span class="nx">stack</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AsyncDisposableStack</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// create wrapper functions around APIs that don&#39;t yet support disposables
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">using</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">createFastify</span><span class="p">({});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">server</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="cm">/* route using resources.userService */</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">({</span> <span class="nx">port</span>: <span class="kt">3000</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;server running on port 3000&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// use `once` to turn one-time events into promises
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="k">await</span> <span class="nx">Promise</span><span class="p">.</span><span class="nx">race</span><span class="p">([</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGINT&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGTERM&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">once</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="s2">&#34;SIGHUP&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">logger</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="s2">&#34;server terminated, closing down&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// resources will all be cleaned up here
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><h2 id="more-resources">
  <a href="#more-resources">More Resources</a>
</h2>

<p>There&rsquo;s a lot more information out there about the explicit resource management proposal, but given how Google isn&rsquo;t working as well as it once was, here are some links to help you find it:</p>
<ul>
<li><a href="https://github.com/tc39/proposal-explicit-resource-management">The original proposal</a> in the TC39 GitHub organisation. The documentation is a bit technically-focussed here, but the issues provide a lot of good context for the APIs, and a number of examples that explain why certain decisions were made.</li>
<li><a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html">Typescript 5.2&rsquo;s release notes</a> include a section about resource management, how to use it, and how to get it working in Typescript.</li>
<li>Various tickets/bugs/issues about implementing explicit resource management:
<ul>
<li><a href="https://issues.chromium.org/issues/42203506">Chrome</a></li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1569081">Firefox</a></li>
<li><a href="https://bugs.webkit.org/show_bug.cgi?id=248707">Safari</a></li>
</ul>
</li>
<li>Prior art in other languages:
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using">C#&rsquo;s <code>using</code> statement</a> is a big influence here.</li>
<li><a href="https://gobyexample.com/defer">Go&rsquo;s <code>defer</code> statement</a> inspired the <code>.defer</code> method.</li>
<li><a href="https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack">Python&rsquo;s <code>ExitStack</code></a> is an explicit inspiration for the <code>DisposableStack</code> and <code>AsyncDisposableStack</code> classes.</li>
</ul>
</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Note that if you don&rsquo;t have access to NodeJS, you can replicate this functionality using <code>new Promise(...)</code> manually, although this can be tricky to do properly as it&rsquo;s difficult to ensure that resources get correctly cleaned up once an event has been triggered.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>For the people who like that sort of thing, you can see the tickets where this is being implemented for <a href="https://issues.chromium.org/issues/42203506">Chrome</a>, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1569081">Firefox</a>, and <a href="https://bugs.webkit.org/show_bug.cgi?id=248707">Safari</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>How I Do Dependency Injection With Closures</title><link>https://jonathan-frere.com/posts/how-i-do-dependency-injection-with-closures/</link><pubDate>Tue, 31 Oct 2023 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/how-i-do-dependency-injection-with-closures/</guid><description>&lt;blockquote>
&lt;p>You can also find an edited and updated version of this post that I wrote for my employer&amp;rsquo;s blog &lt;a href="https://www.esveo.com/en/blog/dependency-injection-with-closures/">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>A &lt;a href="https://www.reddit.com/r/Python/comments/17k9oai/autowired_my_minimalistic_approach_to_dependency/k77cv83/?context=10000">discussion&lt;/a> came up on Reddit recently about DI, where I mentioned that one way that I&amp;rsquo;ve done DI recently for web frameworks that don&amp;rsquo;t naturally support it to using closures. Someone asked for an example, so I figured I&amp;rsquo;d explain what that looks like and where it might work (or not work). The original question was about Python, but I&amp;rsquo;ll give Python and Javascript examples.&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>You can also find an edited and updated version of this post that I wrote for my employer&rsquo;s blog <a href="https://www.esveo.com/en/blog/dependency-injection-with-closures/">here</a>.</p>
</blockquote>
<p>A <a href="https://www.reddit.com/r/Python/comments/17k9oai/autowired_my_minimalistic_approach_to_dependency/k77cv83/?context=10000">discussion</a> came up on Reddit recently about DI, where I mentioned that one way that I&rsquo;ve done DI recently for web frameworks that don&rsquo;t naturally support it to using closures. Someone asked for an example, so I figured I&rsquo;d explain what that looks like and where it might work (or not work). The original question was about Python, but I&rsquo;ll give Python and Javascript examples.</p>
<p>I&rsquo;m going to start with some context of my dependency injection philosophy, but if you want to skip that, you can jump straight to some examples <a href="#di--closures">here</a>.</p>
<h2 id="why-di">
  <a href="#why-di">Why DI</a>
</h2>

<p>The problem I&rsquo;m trying to solve here is DI, or dependency injection. I have a function, class, or in this case route handler that needs access to a given resource, such as a database connection. As I do that, I have three aims:</p>
<ol>
<li>I want to wrap the database connection in an explicit interface to allow encapsulation — I don&rsquo;t want my routes to have to know how the database is structured, I just want them to be able to load and save e.g. <code>User</code> objects.</li>
<li>I want to be able to parameterize the database connection. When I run the code from my local machine, I want it to point to a local database, and when I run the code on production, I want it talking to the live database. That should happen automatically based on configuration files or environment variables.</li>
<li>I want to prevent code from having to construct its own dependencies (i.e. I want inversion of control). I don&rsquo;t want to create the database connection inside the route handler, I want that to happen outside the route and the result be passed to the route handler in some way.</li>
</ol>
<p>The solution to this is dependency injection, or DI. When I first started programming, this term confused me for a bit, because I&rsquo;d see lots of &ldquo;DI frameworks&rdquo; or similar tools, and I assumed that DI meant the act of using decorators or annotations to automatically inject parameters into the right place. This is not the case — those tools are often useful, but DI is more about how you write your code in the first place. For example, here are two Python functions, one of which uses DI:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">emails</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Function 1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_emails</span><span class="p">(</span><span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">emails</span><span class="o">.</span><span class="n">EmailMailer</span><span class="p">()</span><span class="o">.</span><span class="n">send_email</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">email_address</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">send_emails</span><span class="p">(</span><span class="n">User</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">),</span> <span class="s2">&#34;this is an email&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Function 2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_emails</span><span class="p">(</span><span class="n">mailer</span><span class="p">:</span> <span class="n">EmailMailer</span><span class="p">,</span> <span class="n">user</span><span class="p">:</span> <span class="n">User</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">mailer</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">email_address</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">mailer</span> <span class="o">=</span> <span class="n">emails</span><span class="o">.</span><span class="n">EmailMailer</span><span class="p">(</span><span class="o">**</span><span class="n">email_params</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">send_emails</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">mailer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">user</span><span class="o">=</span><span class="n">User</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s2">&#34;...&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="n">message</span><span class="o">=</span><span class="s2">&#34;this is an email&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></div><p>I think this is a good example, because you can see the advantages and disadvantages of DI. In this example, the second function uses DI, and the first function does not. The thing that jumps out the most to me is that the DI example is much more verbose — it takes more code, and it makes function signatures more complicated because they&rsquo;re taking more parameters. Partly that&rsquo;s just how I&rsquo;ve written these examples, but I do think DI adds complexity — useful complexity, but complexity nonetheless. You don&rsquo;t need DI if it&rsquo;s not adding value.</p>
<p>However, there are some benefits visible in the second function. By making the <code>EmailMailer</code> object explicit and bringing it out of the <code>send_emails</code> function, we can now more easily pass parameters to it. If multiple functions are all using the <code>EmailMailer</code> object, and we need to change how we configure it, then now we can do that configuration in one place, rather than at every place that it&rsquo;s used. (Alternatively, before we might have used some global configuration, but with DI, we can be more explicit.)</p>
<p>We can also swap out the mailer object that we use. I think this is often oversold as an advantage (how often do you really swap out implementations like this?) but it&rsquo;s often useful for testing. If we want to test the first <code>send_emails</code> function, we&rsquo;d have to mock a bunch of global imports, but with the second, we can just call the function with a mocked parameter.</p>
<p>The most important thing to notice here is that Function 2 uses dependency injection without going near a DI framework — without even using a single decorator! At its core, DI is just moving things from being constructed inside functions, to being constructed outside functions, and then figuring out how best to pass them back in.</p>
<p>Note that I&rsquo;ve used functions here, but classes work in much the same way. Typically, parameters can be passed to the class constructor (<code>__init__()</code>, <code>constructor()</code>, etc), and then attach as instance attributes (<code>self.param</code>, <code>this.#param</code>, etc). I&rsquo;m not going to use that style in this example, but I often use it for service objects.</p>
<p>With that out of the way, this is a way of doing DI via closures.</p>
<h2 id="di--closures">
  <a href="#di--closures">DI &amp; Closures</a>
</h2>

<p>Here&rsquo;s a couple examples of route definitions in FastAPI/Python and in Express/JS:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@app.get</span><span class="p">(</span><span class="s2">&#34;/items/</span><span class="si">{item_id}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">read_item</span><span class="p">(</span><span class="n">item_id</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ... TODO: get item value from a database somewhere</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="o">...</span><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">express</span> <span class="nx">from</span> <span class="s2">&#34;express&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">&#34;/items/:itemId&#34;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// ... TODO: get item value from a database somewhere
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span> <span class="nx">value</span><span class="o">:</span> <span class="cm">/* ... */</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>As discussed above, dependency injection is about passing parameters to functions. But in the two functions here, that&rsquo;s difficult, because the parameters are fixed, and we don&rsquo;t actually call the functions. For example, with the Express example, Express will always call our route handler with the <code>req</code> and <code>res</code>. There&rsquo;s no place to inject any services or dependencies of our own.</p>
<p>One option might be to attach our dependencies to the parameters. This is common in Express, where middleware can be used to dynamically add a <code>req.users</code> or <code>req.conn</code> attribute that can be accessed inside the routes. However, this can be error-prone, not least because it isn&rsquo;t compatible with Typescript unless you start modifying global types.</p>
<p>An easier option, at least for simple cases, is often just to use closures to capture the dependencies. Here are some examples to show what I mean:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">add_routes</span><span class="p">(</span><span class="n">app</span><span class="p">:</span> <span class="n">FastAPI</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">item_store</span><span class="p">:</span> <span class="n">ItemStore</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@app.get</span><span class="p">(</span><span class="s2">&#34;/items/</span><span class="si">{item_id}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">async</span> <span class="k">def</span> <span class="nf">read_item</span><span class="p">(</span><span class="n">item_id</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">item</span> <span class="o">=</span> <span class="k">await</span> <span class="n">item_store</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">item_id</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;value&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">value</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">item_store</span> <span class="o">=</span> <span class="n">ItemStore</span><span class="p">(</span><span class="n">db</span><span class="o">=...</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">add_routes</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">item_store</span><span class="o">=</span><span class="n">item_store</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">express</span> <span class="kr">from</span> <span class="s2">&#34;express&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">addRoutes</span><span class="p">(</span><span class="nx">app</span>: <span class="kt">Express</span><span class="p">,</span> <span class="nx">itemStore</span>: <span class="kt">ItemStore</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">app</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s2">&#34;items/:itemId&#34;</span><span class="p">,</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">item</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">itemStore</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="nx">item_id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span> <span class="nx">value</span>: <span class="kt">item.value</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">itemStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ItemStore</span><span class="p">(</span><span class="nx">db</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">addRoutes</span><span class="p">(</span><span class="nx">app</span><span class="p">,</span> <span class="nx">itemStore</span><span class="p">);</span>
</span></span></code></pre></div><p>The basic idea is that we move the route definitions from being defined at the top-level to being defined inside a function. The inner functions are now closures — when the function is called, the inner functions will have access to variables defined in the outer scope (in this case the parameters), and so can access the dependencies they need. We can then create all the dependencies, as well as the main app beforehand, and pass them to the <code>addRoutes</code> function.</p>
<p>In practice, I often have a <code>create_context()</code> function that loads configuration from somewhere, creates all the dependencies, and returns <code>Context</code> object or <a href="https://docs.python.org/3/library/typing.html#typing.TypedDict">typed dictionary</a> which contains all of the dependencies with keys. Then I can pass that whole context object to builder functions like <code>add_routes()</code>, rather than specifying all the dependencies individually.</p>
<p>Sometimes I also move the <code>app = FastAPI()</code>/<code>const app = express()</code> line inside the builder function, and have it return the entire app. I don&rsquo;t think one is better than the other, and which I use depends mostly on my mood.</p>
<h2 id="where-this-works-well-or-doesnt">
  <a href="#where-this-works-well-or-doesnt">Where This Works Well, or Doesn&rsquo;t</a>
</h2>

<p>I&rsquo;ve used web routing as an example here, but I find this works well enough in any situation where I can&rsquo;t easily pass something in via function parameters. Most languages I use — even quite static ones like Rust — allow functions to be defined within other functions like this. The key requirement is good support of closures, but this is also fairly standard at this point.</p>
<p>There is an issue if you also want to export the functions somehow. With the <code>FastAPI</code> example above, if we wanted to import the <code>read_item</code> function somewhere else and call it, that becomes very hard with closures. In this case, that&rsquo;s not a problem, but I&rsquo;ve run into contexts where it&rsquo;s more of an issue. In cases like that, I try to decouple the function entirely from any dependencies it needs, and just pass in raw data.</p>
<p>I&rsquo;ve also noticed that this can be harder to implement correctly in some cases with Rust, if the lifetimes don&rsquo;t match or the type is difficult to name correctly. Typically Rc/Arc + Clone for services solves most issues, and sometimes boxing up the return value is necessary.</p>
<h2 id="alternatives">
  <a href="#alternatives">Alternatives</a>
</h2>

<p>Of course this isn&rsquo;t the only way! Here are some other options that I also have in mind when deciding how to get my dependencies injected.</p>
<ul>
<li>No dependency injection at all — I find this works really well up to a point, and then it stops working fast, usually around the point I&rsquo;m configuring multiple DBs/external services, and want to get everything running in multiple environments. But simple is better the complicated, and no DI is simpler than DI.</li>
<li>Using module-level values. In Javascript, for example, I can export a value, as in <code>export const USERS = new UserService()</code>. Similar things are possible in Python and most other more dynamic scripting languages. This can be used instead of DI, and most languages have some way of mocking static module exports, so you can still swap in test implementations. But I find this often ends up quite hacky, and the dependency nest can get quite deep, so I try to avoid this these days.</li>
<li>A lot of frameworks provide some kind of app context field or value, which can be dynamically updated with different services or connections. Personally, I find it hard to keep track of what&rsquo;s on the context and what isn&rsquo;t, and I&rsquo;ve rarely found a simple way of handling this when I&rsquo;m using types.</li>
<li>FastAPI has something it calls DI, but is really just request extractor — it is called for each request, it is passed the request, and it extracts the details it needs. I personally haven&rsquo;t had much success using this feature for DI proper. That said, other frameworks do provide a full DI framework. If it&rsquo;s built into the framework, then I tend to follow the &ldquo;when it Rome, do as the Romans&rdquo; principle.</li>
<li>If all else fails, there are lots of DI libraries. I tend to avoid these, because it&rsquo;s added complexity when just passing in functions works well enough. But sometimes you get to the point where constructing all your services and dependencies up front doesn&rsquo;t cut it, and you need something more powerful. I&rsquo;ve not reached that point myself, but most of the projects I&rsquo;ve worked on have been relatively small.</li>
</ul>
<h2 id="conclusion">
  <a href="#conclusion">Conclusion</a>
</h2>

<p>I hope this was helpful, this is just one strategy that I&rsquo;ve found useful for doing simple DI without having to lean into frameworks or have annotation/decorator-based magic.</p>
]]></content:encoded></item><item><title>Book Review: A Philosophy of Software Design</title><link>https://jonathan-frere.com/posts/philosophy-software-design/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://jonathan-frere.com/posts/philosophy-software-design/</guid><description>&lt;p>This review is largely in response to the article &amp;ldquo;&lt;a href="https://qntm.org/clean">It&amp;rsquo;s probably time to stop recommending Clean Code&lt;/a>&amp;rdquo;, and the ensuing &lt;a href="https://www.reddit.com/r/programming/comments/hhlvqq/its_probably_time_to_stop_recommending_clean_code/">Reddit discussion&lt;/a>. A lot of really interesting points were brought up, but the big question that the author themself wasn&amp;rsquo;t able to answer was: &amp;ldquo;What should we recommend instead?&amp;rdquo;&lt;/p>
&lt;p>I believe the book we should be recommending is &lt;em>A Philosophy of Software Design&lt;/em> by John Ousterhout. In this post I want to spend a bit of time reviewing it and giving an overview of the contents, and then I want to explain why, in my opinion, it is such a good recommendation.&lt;/p></description><content:encoded><![CDATA[<p>This review is largely in response to the article &ldquo;<a href="https://qntm.org/clean">It&rsquo;s probably time to stop recommending Clean Code</a>&rdquo;, and the ensuing <a href="https://www.reddit.com/r/programming/comments/hhlvqq/its_probably_time_to_stop_recommending_clean_code/">Reddit discussion</a>. A lot of really interesting points were brought up, but the big question that the author themself wasn&rsquo;t able to answer was: &ldquo;What should we recommend instead?&rdquo;</p>
<p>I believe the book we should be recommending is <em>A Philosophy of Software Design</em> by John Ousterhout. In this post I want to spend a bit of time reviewing it and giving an overview of the contents, and then I want to explain why, in my opinion, it is such a good recommendation.</p>
<h2 id="an-empirical-philosophy-book">
  <a href="#an-empirical-philosophy-book">An Empirical Philosophy Book</a>
</h2>

<p>The elevator pitch of John Ousterhout&rsquo;s book <em>A Philosophy of Software Design</em> is fairly simple: he is a university professor (albeit one with almost two decades of experience in the &ldquo;real world&rdquo;, also the inventor of Tcl, creator of RAFT, company founder amongst <a href="https://www.reddit.com/r/programming/comments/lb8zrn/an_alternative_to_clean_code_a_philosophy_of/glt3e4n/">other things</a>), who each year teaches students how to actually design software in a practical, hands-on course where the students are expected to design and modify &ldquo;a substantial piece of software&rdquo; in an iterative way, hopefully understanding more about the practice of software design each time around.</p>
<p>The book, then, is a synthesis of the pieces of wisdom that Ousterhout has himself learned from his own experiences, tempered and refined by the practical examples he has been able to draw from his students. In this way, it has a (somewhat) scientific, research-based approach, where the author&rsquo;s assertions are backed up with examples from student projects that worked (or didn&rsquo;t).</p>
<p>At it&rsquo;s core, though, this is still philosophy - the book doesn&rsquo;t just list the things that worked well, and the things that worked poorly. Instead, Ousterhout attempts in each chapter to divine broader truths that apply to software design in general. There are no lists of what to do and what not to do, but instead principles to follow, red flags to be aware of, and warnings against taking anything too far.</p>
<h2 id="structure">
  <a href="#structure">Structure</a>
</h2>

<p>The book is split into a series of chapters, each of which generally explores a single principle. These range from the very high level (&ldquo;Working Code Isn&rsquo;t Enough&rdquo;, &ldquo;Modules Should Be Deep&rdquo;) to the more practical questions (&ldquo;Choosing Names&rdquo;). The whole book is relatively short (about 180 pages), and many chapters flow together nicely, which means that it&rsquo;s quite easy to go from cover-to-cover, rather than approach the book as a reference manual. That said, the final pages provide summaries of the design principles and red flags found in the book, making it easy to reference key parts of the book.</p>
<p>Within each chapter, Ousterhout generally starts by stating a problem or motivation that software engineers will face, and then defining a principle to solve this. The rest of the chapter is then a discussion of the principle, the dangers of alternative approaches, the red flags that indicate that the principle needs to be applied (or in some cases avoided), and some notes about taking ideas too far.</p>
<p>The examples are often based on problems that Ousterhout has given his classes, which means that they generally feel meaty enough to be worth discussing. An example of a text editor appears in Chapter 6, but is extended in Chapters 7, 8, 9, and 10 in different contexts. Enough is omitted from most examples to make the point clear, but enough is kept in to give the feeling of real code.</p>
<h2 id="ousterhouts-principles">
  <a href="#ousterhouts-principles">Ousterhout&rsquo;s Principles</a>
</h2>

<p>The overriding theme throughout the book is that good code <em>looks</em> good. Ousterhout thinks very much in terms of abstraction and interfaces - where &ldquo;interfaces&rdquo; refers to the contact points between different units of abstraction, rather than any similarly-named construct in any particular language. Most of the book is dedicated to figuring out how to spot bad abstractions and rework them into good abstractions.</p>
<p>To a certain extent, this feels at odds with certain common mantras in software engineering circles today, where we encourage enough other to Keep It Simple, Stupid, and worry about premature abstractions. <em>Philosophy</em> seems to worry less about the dangers of over-abstraction, and more concerned with how to make sure that the chosen abstraction is a good one.</p>
<p>This approach makes for a more positive experience than in many other programming circles - rather than being warned into a very conservative approach, Ousterhout encourages his readers to go out and make abstractions, but to be careful about designing the correct ones.</p>
<p>This isn&rsquo;t to say that the book isn&rsquo;t also cautionary - in the summary pages at the back, the list of red flags gets more page space than the list of principles, and throughout the book these red flags mark out moments when readers are given the go ahead to use these abstraction techniques. There are also warnings about when a principle might be used too much.</p>
<h2 id="everyones-a-critic">
  <a href="#everyones-a-critic">Everyone&rsquo;s a Critic</a>
</h2>

<p>Beyond the mild danger of encouraging excess abstraction, the biggest issue in <em>Philosophy</em> is probably the missing parts - the topic of testing gets a single page in Chapter 19 (Software Trends), and ideas about effective use of a type system to avoid issues are largely ignored. Ousterhout&rsquo;s principles will still apply in these areas, but it would be nice to see some more specific discussion of these areas.</p>
<h2 id="the-target-audience">
  <a href="#the-target-audience">The Target Audience</a>
</h2>

<p>It can be a bit unclear at times to whom Ousterhout writes. A lot of the examples clearly relate to his students, and the projects that they come from have a somewhat academic feel - a text editor here, and an HTTP protocol parser there. The code in the examples is generally object-oriented (Java and occasional C++), although it generally feels like it could be replaced with most imperative/OO languages without much of an effect.</p>
<p>The use of the phrase &ldquo;software design&rdquo; might make one think more of broader software architecture, but Ousterhout uses it more to describe the design of individual modules and functions <em>within</em> a program, rather than the broader architecture of the program itself (although he occasionally touches on that).</p>
<p>More functionally-minded people might think they can simply side-step a lot of the discussion here, in the same way that they can when discussing the Gang of Four&rsquo;s design patterns, but the principle &ldquo;design errors out of existence&rdquo; (Chapter 10) and its corollary &ldquo;design special cases out of existence&rdquo; should ring bells for people in this area who are also aware of the principle of making illegal states unrepresentable.</p>
<p>Ultimately, I think this book aims at a space that is slightly deeper than a lot of existing software literature. Where books like <em>Design Patterns</em>, Fowler&rsquo;s <em>Refactoring</em>, and the aforementioned <em>Clean Code</em> are aimed at more traditional &ldquo;enterprise&rdquo; software development, <em>Philosophy</em> feels more widely applicable, albeit at the cost of being more abstract and difficult to apply.</p>
<p>In general, I think <em>Philosophy</em> is a good read if you are both (a) working with software regularly, and (b) conscious of the inherent maintenance cost in software, and aiming to minimise it.</p>
<h2 id="a-book-to-recommend">
  <a href="#a-book-to-recommend">A Book to Recommend</a>
</h2>

<p>The original question I wanted to answer was what we, as software engineers, should recommend over books like <em>Clean Code</em>. As I said, my answer to that question is <em>A Philosophy of Software Design</em>.</p>
<p>Software engineering (indeed, engineering in general) is not a science, insofar as there are no (or at least very few) exact answers. Everything from the database you use to your choice of testing strategy will be dependent on the context of the software you&rsquo;re writing. This means that the advice that we give to each other will probably be very context-specific. In general, you probably shouldn&rsquo;t use a NoSQL database, but in a lot of specific contexts you probably should.</p>
<p>This isn&rsquo;t a problem if we don&rsquo;t run into these exceptional cases often, but engineering is all about exceptional cases - if there were no exceptional cases, we wouldn&rsquo;t need to write any new software, because our existing tools would do the job. This is where books like <em>Philosophy</em> come in - rather than give situational advice, it attempts to define wider principles that the reader will then need to apply to different situations.</p>
<p>Take, for example, my favourite principle: &ldquo;Modules should be deep&rdquo; (explored in Chapter 4). The idea is that an individual unit of abstraction should do a lot of work (i.e. be deep, and contain a lot of complexity), but it should have a relatively simple interface (i.e. be narrow). Essentially, if you&rsquo;re going to abstract something, make sure your abstraction is deep.</p>
<p>Notice that this principle says nothing about functions, classes, lines, blocks, parameters, or anything specific to a single language or paradigm. However, when we apply it, for example to the Java code Robert C. Martin talks about in <em>Clean Code</em>, we can derive some of his ideas from this principle. Assuming a function is our unit of abstraction (for now, at least), the parameters are its interface, therefore we should reduce the number of parameters to the minimum necessary.</p>
<p>However, because our principle is more general, we can actually correct some of the mistakes Martin makes. Martin talks about removing parameters by adding private fields to the class that the method belongs to. When we think in terms of interfaces, we notice that this <em>hasn&rsquo;t decreased the interface at all</em> - we&rsquo;ve lost a parameter, but we&rsquo;ve gained a private field, and in the process made things harder for the consumer of our abstraction.</p>
<h2 id="teaching-principles-over-rules">
  <a href="#teaching-principles-over-rules">Teaching Principles Over Rules</a>
</h2>

<p>When I recommend books, I generally hope that the other person will learn something from the book I have suggested. If I were to recommend <em>Clean Code</em>, I would hope that the reader would learn something about how to write clean Java code, but I suspect they would mainly learn how to write code like Robert C. Martin - or more accurately, like someone copying Robert C. Martin&rsquo;s actions without always understanding why he&rsquo;s taking them.</p>
<p>I do not feel this way about <em>A Philosophy of Software Design</em>. When I recommend it, I expect that the reader will not just learn something about Java, but instead something about how to design good abstractions, identify weak abstractions, and write code that is broadly maintainable long into the future.</p>
<h2 id="updates-from-the-future">
  <a href="#updates-from-the-future">Updates from the future</a>
</h2>

<ul>
<li>2021-02-03: Someone on Reddit pointed out that I didn&rsquo;t sell John Ousterhout enough: he is a very remarkable man. I have updated my description of him to link to that comment, and added some further explanation of his work to the post.</li>
</ul>
]]></content:encoded></item></channel></rss>