<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title></title>
    <link rel="self" type="application/atom+xml" href="https://dimtion.fr/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://dimtion.fr"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-01T00:00:00+00:00</updated>
    <id>https://dimtion.fr/atom.xml</id>
    <entry xml:lang="en">
        <title>Logit soft-capping</title>
        <published>2026-03-01T00:00:00+00:00</published>
        <updated>2026-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/wiki/ml/soft-capping/"/>
        <id>https://dimtion.fr/wiki/ml/soft-capping/</id>
        
        <content type="html" xml:base="https://dimtion.fr/wiki/ml/soft-capping/">&lt;h2 id=&quot;logit&quot;&gt;Logit&lt;&#x2F;h2&gt;
&lt;p&gt;From &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;machine-learning&#x2F;glossary&#x2F;#logits&quot;&gt;google&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;the vector of raw (non-normalized) predictions that a classification model generates, which is ordinarily then passed to a normalization function. If the model is solving a multi-class classification problem, logits typically become an input to the softmax function. The softmax function then generates a vector of (normalized) probabilities with one value for each possible class.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;logit-soft-capping&quot;&gt;Logit soft-capping&lt;&#x2F;h2&gt;
&lt;p&gt;Logit softcapping (introduced in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;storage.googleapis.com&#x2F;deepmind-media&#x2F;gemma&#x2F;gemma-2-report.pdf&quot;&gt;Gemma 2&lt;&#x2F;a&gt;) is a technique to cap the value between $-soft\_cap$ and $+soft\_cap$:&lt;&#x2F;p&gt;
&lt;p&gt;$$
logits ← soft\_cap \cdot tanh(\frac{logits}{soft\_cap})
$$&lt;&#x2F;p&gt;
&lt;div &gt;
&lt;style&gt;
  #cap-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 13px; height: 13px;
    border-radius: 50%;
    background: var(--link-color);
    cursor: pointer;
  }
  #softcap-chart .grid line {
    stroke: var(--font-color);
    stroke-opacity: 0.1;
  }
  #softcap-chart .axis path, #softcap-chart .axis line {
    stroke: var(--font-color);
    opacity: 0.3;
    stroke-opacity: 0.3;
  }
  #softcap-chart .axis text {
    fill: var(--font-color);
    opacity: 0.8;
    font-size: 11px;
    font-family: monospace;
  }
&lt;&#x2F;style&gt;

&lt;script src=&quot;https:&#x2F;&#x2F;cdnjs.cloudflare.com&#x2F;ajax&#x2F;libs&#x2F;d3&#x2F;7.8.5&#x2F;d3.min.js&quot;&gt;&lt;&#x2F;script&gt;

&lt;div style=&quot;display:flex;flex-direction:column;&quot;&gt;
  &lt;div id=&quot;softcap-chart&quot; style=&quot;width:100%;&quot;&gt;&lt;&#x2F;div&gt;
  &lt;div style=&quot;display:flex;align-items:center;justify-content:center;gap:12px;margin-top:12px;&quot;&gt;
    &lt;label for=&quot;cap-slider&quot; style=&quot;font-size:11px;letter-spacing:0.15em;text-transform:uppercase;color:var(--font-color);opacity:1;&quot;&gt;cap&lt;&#x2F;label&gt;
    &lt;input type=&quot;range&quot; id=&quot;cap-slider&quot; min=&quot;1&quot; max=&quot;60&quot; step=&quot;0.5&quot; value=&quot;30&quot; style=&quot;-webkit-appearance:none;width:220px;height:2px;background:var(--glass-border);outline:none;border-radius:1px;&quot;&gt;
    &lt;span id=&quot;cap-val&quot; style=&quot;font-size:13px;color:var(--link-color);min-width:28px;&quot;&gt;30&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
  &#x2F;&#x2F; --- Theme ---
  function getTheme() {
    const cs = getComputedStyle(document.documentElement);
    return {
      colorLink: cs.getPropertyValue(&#x27;--link-color&#x27;).trim()      || &#x27;#5b9dd9&#x27;,
      colorAlt:  cs.getPropertyValue(&#x27;--title-color-alt&#x27;).trim() || &#x27;#ed8796&#x27;,
      colorFont: cs.getPropertyValue(&#x27;--font-color&#x27;).trim()      || &#x27;#2d3748&#x27;,
    };
  }

  const W = 520, H = 380;
  const margin = { top: 20, right: 20, bottom: 40, left: 50 };
  const w = W - margin.left - margin.right;
  const h = H - margin.top - margin.bottom;

  const svg = d3.select(&#x27;#softcap-chart&#x27;).append(&#x27;svg&#x27;)
    .attr(&#x27;viewBox&#x27;, `0 0 ${W} ${H}`)
    .attr(&#x27;width&#x27;, &#x27;100%&#x27;)
    .style(&#x27;height&#x27;, &#x27;auto&#x27;);

  const g = svg.append(&#x27;g&#x27;)
    .attr(&#x27;transform&#x27;, `translate(${margin.left},${margin.top})`);

  const xRange = 80;
  const x = d3.scaleLinear().domain([-xRange, xRange]).range([0, w]);
  const y = d3.scaleLinear().domain([-xRange, xRange]).range([h, 0]);

  g.append(&#x27;g&#x27;).attr(&#x27;class&#x27;, &#x27;grid&#x27;)
    .call(d3.axisLeft(y).tickSize(-w).tickFormat(&#x27;&#x27;).ticks(8));
  g.append(&#x27;g&#x27;).attr(&#x27;class&#x27;, &#x27;grid&#x27;)
    .attr(&#x27;transform&#x27;, `translate(0,${h})`)
    .call(d3.axisBottom(x).tickSize(-h).tickFormat(&#x27;&#x27;).ticks(8));

  g.append(&#x27;g&#x27;).attr(&#x27;class&#x27;, &#x27;axis&#x27;).call(d3.axisLeft(y).ticks(8));
  g.append(&#x27;g&#x27;).attr(&#x27;class&#x27;, &#x27;axis&#x27;).attr(&#x27;transform&#x27;, `translate(0,${h})`).call(d3.axisBottom(x).ticks(8));

  const xLabel = g.append(&#x27;text&#x27;).attr(&#x27;x&#x27;, w&#x2F;2).attr(&#x27;y&#x27;, h+36)
    .attr(&#x27;opacity&#x27;, 1).attr(&#x27;text-anchor&#x27;,&#x27;middle&#x27;)
    .style(&#x27;font-size&#x27;,&#x27;11px&#x27;).style(&#x27;font-family&#x27;,&#x27;monospace&#x27;).text(&#x27;logits (input)&#x27;);
  const yLabel = g.append(&#x27;text&#x27;).attr(&#x27;transform&#x27;,&#x27;rotate(-90)&#x27;).attr(&#x27;x&#x27;,-h&#x2F;2).attr(&#x27;y&#x27;,-40)
    .attr(&#x27;opacity&#x27;, 1).attr(&#x27;text-anchor&#x27;,&#x27;middle&#x27;)
    .style(&#x27;font-size&#x27;,&#x27;11px&#x27;).style(&#x27;font-family&#x27;,&#x27;monospace&#x27;).text(&#x27;output&#x27;);

  const pts = d3.range(-xRange, xRange + 0.2, 0.2);
  const line = fn =&gt; d3.line().x(d =&gt; x(d)).y(d =&gt; y(fn(d)));

  &#x2F;&#x2F; Identity
  const identityPath = g.append(&#x27;path&#x27;).datum(pts).attr(&#x27;fill&#x27;,&#x27;none&#x27;)
    .attr(&#x27;stroke-opacity&#x27;, 0.3).attr(&#x27;stroke-width&#x27;, 1)
    .attr(&#x27;d&#x27;, line(d =&gt; d));

  &#x2F;&#x2F; Soft-cap
  const softPath = g.append(&#x27;path&#x27;).attr(&#x27;fill&#x27;,&#x27;none&#x27;).attr(&#x27;stroke-width&#x27;, 2);

  &#x2F;&#x2F; Hard clip
  const clipPath = g.append(&#x27;path&#x27;).attr(&#x27;fill&#x27;,&#x27;none&#x27;)
    .attr(&#x27;stroke-width&#x27;, 2).attr(&#x27;stroke-dasharray&#x27;,&#x27;6,4&#x27;);

  &#x2F;&#x2F; Indicator lines
  const softLinePos = g.append(&#x27;line&#x27;).attr(&#x27;stroke-width&#x27;,0.5).attr(&#x27;stroke-dasharray&#x27;,&#x27;2,4&#x27;).attr(&#x27;opacity&#x27;,1);
  const softLineNeg = g.append(&#x27;line&#x27;).attr(&#x27;stroke-width&#x27;,0.5).attr(&#x27;stroke-dasharray&#x27;,&#x27;2,4&#x27;).attr(&#x27;opacity&#x27;,1);

  &#x2F;&#x2F; Legend
  const legend = g.append(&#x27;g&#x27;).attr(&#x27;transform&#x27;, `translate(${w - 148}, 8)`);
  const legendItems = [
    { dash: null,  label: &#x27;soft-cap&#x27;, key: &#x27;link&#x27; },
    { dash: &#x27;6,4&#x27;, label: &#x27;hard clip&#x27;,          key: &#x27;alt&#x27;  },
    { dash: null,  label: &#x27;y=x&#x27;,       key: &#x27;font&#x27; },
  ].map((item, i) =&gt; {
    const row = legend.append(&#x27;g&#x27;).attr(&#x27;transform&#x27;, `translate(0, ${i * 20})`);
    const swatch = row.append(&#x27;line&#x27;).attr(&#x27;x1&#x27;,0).attr(&#x27;x2&#x27;,22).attr(&#x27;y1&#x27;,6).attr(&#x27;y2&#x27;,6)
      .attr(&#x27;stroke-width&#x27;, 2).attr(&#x27;stroke-opacity&#x27;, 1)
      .attr(&#x27;stroke-dasharray&#x27;, item.dash || null);
    const label = row.append(&#x27;text&#x27;).attr(&#x27;x&#x27;,30).attr(&#x27;y&#x27;,10)
      .attr(&#x27;opacity&#x27;, 1).style(&#x27;font-size&#x27;,&#x27;11px&#x27;).style(&#x27;font-family&#x27;,&#x27;monospace&#x27;).text(item.label);
    return { swatch, label, key: item.key };
  });

  function update() {
    const cap = +document.getElementById(&#x27;cap-slider&#x27;).value;
    const { colorLink, colorAlt, colorFont } = getTheme();

    document.getElementById(&#x27;cap-val&#x27;).textContent = cap;

    &#x2F;&#x2F; Update paths
    identityPath.attr(&#x27;stroke&#x27;, colorFont);
    softPath.attr(&#x27;stroke&#x27;, colorLink).attr(&#x27;d&#x27;, line(d =&gt; cap * Math.tanh(d &#x2F; cap))(pts));
    clipPath.attr(&#x27;stroke&#x27;, colorAlt).attr(&#x27;d&#x27;, line(d =&gt; Math.max(-cap, Math.min(cap, d)))(pts));

    &#x2F;&#x2F; Update indicator lines
    softLinePos.attr(&#x27;stroke&#x27;, colorLink).attr(&#x27;x1&#x27;, x(-xRange)).attr(&#x27;x2&#x27;, x(xRange)).attr(&#x27;y1&#x27;, y(cap)).attr(&#x27;y2&#x27;, y(cap));
    softLineNeg.attr(&#x27;stroke&#x27;, colorLink).attr(&#x27;x1&#x27;, x(-xRange)).attr(&#x27;x2&#x27;, x(xRange)).attr(&#x27;y1&#x27;, y(-cap)).attr(&#x27;y2&#x27;, y(-cap));

    &#x2F;&#x2F; Update axis labels
    xLabel.attr(&#x27;fill&#x27;, colorFont);
    yLabel.attr(&#x27;fill&#x27;, colorFont);

    &#x2F;&#x2F; Update legend
    legendItems.forEach(({ swatch, label, key }) =&gt; {
      const color = key === &#x27;link&#x27; ? colorLink : key === &#x27;alt&#x27; ? colorAlt : colorFont;
      swatch.attr(&#x27;stroke&#x27;, color);
      label.attr(&#x27;fill&#x27;, colorFont);
    });
  }

  document.getElementById(&#x27;cap-slider&#x27;).addEventListener(&#x27;input&#x27;, update);

  &#x2F;&#x2F; Re-apply theme colors when the toggle in the navbar changes data-theme
  new MutationObserver(update).observe(document.documentElement, {
    attributes: true, attributeFilter: [&#x27;data-theme&#x27;]
  });

  &#x2F;&#x2F; Also catch OS-level preference changes
  if (window.matchMedia) {
    window.matchMedia(&#x27;(prefers-color-scheme: dark)&#x27;).addEventListener(&#x27;change&#x27;, update);
  }

  update();
})();
&lt;&#x2F;script&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;From: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2410.16682&quot;&gt;Methods of Improving LLM Training Stability&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Calcification of Technology</title>
        <published>2025-12-07T00:00:00+00:00</published>
        <updated>2025-12-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/2025/tech-calcification/"/>
        <id>https://dimtion.fr/blog/2025/tech-calcification/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/2025/tech-calcification/">&lt;p&gt;One thing to notice when studying the history of tech or the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;History_of_the_Internet&quot;&gt;internet&lt;&#x2F;a&gt; is the &lt;em&gt;winner takes all&lt;&#x2F;em&gt; trend that results in slowly making tech a higher and higher tower of complexity.&lt;&#x2F;p&gt;
&lt;p&gt;Here, I call tech calcification the observed principle that once a technology is sufficiently widespread, new capabilities of a technology are built on top of it instead of next to it. Here are a few examples:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Everything is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;labs.ripe.net&#x2F;author&#x2F;hisham_ibrahim&#x2F;schrodingers-ipv6-cat&#x2F;&quot;&gt;IPv4&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;samsaffron.com&#x2F;archive&#x2F;2015&#x2F;12&#x2F;29&#x2F;websockets-caution-required&quot;&gt;TCP&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;USB&quot;&gt;HTTP&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.netflix.com&#x2F;&quot;&gt;client-server&lt;&#x2F;a&gt; architecture.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.jsonrpc.org&#x2F;&quot;&gt;JSON&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webassembly.org&#x2F;&quot;&gt;JavaScript&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;WSL2-Linux-Kernel&quot;&gt;Linux&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Carrier-grade_NAT&quot;&gt;NATed&lt;&#x2F;a&gt; networks.&lt;&#x2F;li&gt;
&lt;li&gt;Everything is built on top of MCP…&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When a technology becomes widespread, it naturally gathers enough momentum to attract more people to work with it. The community memetic effect (or network effect [sic]) of the internet is its main driving force. For example, when enough people use a web-browser daily it is only natural that the web becomes the main software distribution platform. It is &lt;em&gt;expected&lt;&#x2F;em&gt; that a simple document browser becomes a high performance &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebGPU_API&quot;&gt;graphics renderer&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The 80s was a booming period for operating systems, with OSs specialized for micro-computing, mainframe, workstations etc… Today the market is mostly consolidated in 4 main OS (Windows, Linux, MacOS, BSD), and those can be grouped only 2 categories: POSIX &amp;amp; Windows. And now, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;WSL2-Linux-Kernel&quot;&gt;Windows is Linux&lt;&#x2F;a&gt; … Whole billion dollar sub-industries today live by specializing in securing, micro-optimizing, and spreading best practices for those 4 OS.&lt;&#x2F;p&gt;
&lt;p&gt;There are other reasons beyond just the community effect. Once a technology is widespread enough, more eyes are present to (1) improve the said technology, (2) do security assessments (3) experiment and spread said &lt;em&gt;best practices&lt;&#x2F;em&gt;. While the path is chaotic, it generally results in technologies that are somewhat &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;jarredsumner&#x2F;status&#x2F;1499225725492076544&quot;&gt;efficient&lt;&#x2F;a&gt;, very &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.espruino.com&#x2F;ESP32&quot;&gt;versatile&lt;&#x2F;a&gt;, and &lt;em&gt;mostly&lt;&#x2F;em&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;v8.dev&#x2F;blog&#x2F;sandbox&quot;&gt;secure&lt;&#x2F;a&gt;. Though, champion of none.&lt;&#x2F;p&gt;
&lt;p&gt;A calcified technology is also very difficult to replace, too many people to convince, too many devices to replace (or keep backward compatibility), too many best practices to re-learn. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;quicwg.org&#x2F;&quot;&gt;QUIC&lt;&#x2F;a&gt; protocol is a good example of a technology that while mostly superior to TCP, has &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;daniel.haxx.se&#x2F;blog&#x2F;2024&#x2F;06&#x2F;10&#x2F;http-3-in-curl-mid-2024&#x2F;&quot;&gt;difficulties&lt;&#x2F;a&gt; replacing it due to how optimized TCP+TLS implementations are. From &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.corsix.org&#x2F;content&#x2F;galois-field-instructions-2021-cpus&quot;&gt;custom CPU instructions&lt;&#x2F;a&gt;, to decade of research poured into testing all the limits of TCP, not to mention &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;httptoolkit.com&#x2F;blog&#x2F;http3-quic-open-source-support-nowhere&#x2F;&quot;&gt;millions of routers&lt;&#x2F;a&gt;, or high tower &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nodejs&#x2F;node&#x2F;issues&#x2F;57281&quot;&gt;http server stacks&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;While I wish the world would move on from some calcified technologies, that there was more OS diversity, more network protocol diversity, less cargo-cult in serialization patterns, I do value that having an &lt;em&gt;imperfect&lt;&#x2F;em&gt; building block that is set in calcium allows the larger community to innovate on top of it.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p style=&quot;text-align: end&quot;&gt;
&lt;i&gt;And no, AI will not solve this problem&lt;&#x2F;i&gt;
&lt;&#x2F;p&gt;
&lt;!--

## Problems
- efficiency is generally the loser: everything is built on top of a more and more complex stack of things. Everything is slower
- complexity 

## Calcification is good actually 
- N protocols -&gt; N+1 protocols problem
- eventually even calcified a technology still evolves (e.g. http)
- the reason why a technology becomes big and calcified is due to environmental pressure that alternatives did not consider in time
	- e.g. wasm is built on top of the web tech as it is the best app distribution platform: flash, java applet
	- e.g. web sockets have better security where blank TCP can&#x27;t provide 
	- 

## How to fix

Hard question, this is fundamentally social question, some reasons could be addressed by better education, just knowing that a layer exist, would allow engineers to see more of the options to build something new


 In each case, technologically superior alternatives exists, but because they never reached a critical adoption point, they never became the de-facto standard.

There are many reasons why this happens, and some are good, 
- security
- skills
- new engineers building on top of what they know
- legal compliance 
- once something is big, it is hard to introduce variants (e.g quic is a new protocol, and is having hard time to come in to replace TCP where needed)
- cargo cult





--&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Optimizing GutterMarks.nvim</title>
        <published>2025-11-30T00:00:00+00:00</published>
        <updated>2025-11-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/2025/optimizing-guttermarks-nvim/"/>
        <id>https://dimtion.fr/blog/2025/optimizing-guttermarks-nvim/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/2025/optimizing-guttermarks-nvim/">&lt;p&gt;A few weeks ago, I shared GutterMarks.nvim (&lt;a href=&quot;&#x2F;blog&#x2F;2025&#x2F;guttermarks-nvim&quot;&gt;blog&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;guttermarks.nvim&quot;&gt;GitHub&lt;&#x2F;a&gt;) a Neovim plugin to allow displaying the nvim marks in the gutter of a buffer. It got positive feedback, and since then I added a couple of convenient actions, and fixed a couple of minor bugs that the community had found.&lt;&#x2F;p&gt;
&lt;p&gt;One thing I spent more time recently is optimizing the performances of the plugin. In the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;guttermarks.nvim&#x2F;?tab=readme-ov-file#why-this-plugin&quot;&gt;README&lt;&#x2F;a&gt; I mention that the plugin is faster that other implementations (that I found), as I&#x27;m avoid using any timers to compute the marks. However, there is always headroom for faster and better. So I set to myself as an exercise to see how much more it could be optimized.&lt;&#x2F;p&gt;
&lt;p&gt;The first step for any optimization is: measure. I did not find any suitable Neovim benchmark suite for plugins. So I wrote a little helper &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;guttermarks.nvim&#x2F;blob&#x2F;main&#x2F;test&#x2F;bench&#x2F;helpers_bench.lua&quot;&gt;benchmark suite&lt;&#x2F;a&gt;. This is really the most basic implementation leveraging &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-mini&#x2F;mini.nvim&#x2F;blob&#x2F;main&#x2F;readmes&#x2F;mini-test.md&quot;&gt;Mini.test&lt;&#x2F;a&gt;: Create a reproducible environment, run a test N times, print results, run tests regularly to validate regression.&lt;&#x2F;p&gt;
&lt;p&gt;As this is a hobby project, I did not spent much time to remove the bias from the benchmark suite (warm-up, validate variance, remove constant factors...). If I ever do this, I may then publish this as a proper benchmark suite.&lt;&#x2F;p&gt;
&lt;p&gt;So now we have this common pattern:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;T[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;refresh with 1 local mark&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  -- Setup a buffer with 100 lines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  bench_helpers.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;setup_local_marks&lt;&#x2F;span&gt;&lt;span&gt;(child, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  -- Run the benchmark, by default 100 times:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;  local&lt;&#x2F;span&gt;&lt;span&gt; results&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; bench_helpers.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;benchmark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;refresh with 1 local mark&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    child.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;lua&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;[[require(&amp;quot;guttermarks&amp;quot;).refresh()]]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;  end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  -- Leverage MiniTest notes to display the test result:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  MiniTest.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;add_note&lt;&#x2F;span&gt;&lt;span&gt;(bench_helpers.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;format_note&lt;&#x2F;span&gt;&lt;span&gt;(results))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which prints:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;NOTE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; in test&#x2F;bench&#x2F;bench_refresh.lua&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; refresh&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; local mark: it=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;0100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;0.036ms&lt;&#x2F;span&gt;&lt;span&gt; median&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;0.034ms&lt;&#x2F;span&gt;&lt;span&gt; min&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;0.028ms&lt;&#x2F;span&gt;&lt;span&gt; max&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;0.067ms&lt;&#x2F;span&gt;&lt;span&gt; stddev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;0.007ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While not perfect, having the mean, median, min, max and sdtddev gives us a good idea of the distribution, thus helps us validating our priors and if any optimization is worthwhile.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note I&#x27;m only optimizing for latency (as opposed to memory or throughput), since for this project I&#x27;m working with the assumption that memory usage is low.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I decided to optimize the critical loop of the plugin: the &lt;code&gt;refresh()&lt;&#x2F;code&gt; function. This function goal is to list all the configured marks, and refresh the gutter with the latest values. In particular I created 2 scenarios:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Light Scenario&lt;&#x2F;strong&gt;: 3 marks in a 500 lines file, call refresh 1000 times&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Heavy Scenario&lt;&#x2F;strong&gt;: 52 marks in a 5000 lines file, call refresh 1000 times&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is the baseline that I found:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;NOTE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; in test&#x2F;bench&#x2F;bench_cache.lua&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; refresh&lt;&#x2F;span&gt;&lt;span&gt; (x1000) - light: it&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;0010&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;94.417ms&lt;&#x2F;span&gt;&lt;span&gt; median&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;94.636ms&lt;&#x2F;span&gt;&lt;span&gt; min&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;91.794ms&lt;&#x2F;span&gt;&lt;span&gt; max&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;95.743ms&lt;&#x2F;span&gt;&lt;span&gt; stddev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;1.089ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;NOTE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; in test&#x2F;bench&#x2F;bench_cache.lua&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; refresh&lt;&#x2F;span&gt;&lt;span&gt; (x1000) - heavy: it&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;0010&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;95.032ms&lt;&#x2F;span&gt;&lt;span&gt; median&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;95.293ms&lt;&#x2F;span&gt;&lt;span&gt; min&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;92.587ms&lt;&#x2F;span&gt;&lt;span&gt; max&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;97.148ms&lt;&#x2F;span&gt;&lt;span&gt; stddev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;1.431ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This reads as it takes around 94ms for nvim to call refresh 1000 times, on 10 attempts (or 94 micro-seconds per call). We note that light or heavy, it has little impact on the benchmark result, while a bit longer for the heavy test, it is negligible compared to the sdtdev.&lt;&#x2F;p&gt;
&lt;p&gt;After doing a bit of exploration I noticed that when refreshing the marks in the gutter, 2 functions where the most expensive:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Function &lt;code&gt;vim.fn.getmarklist&lt;&#x2F;code&gt; to get the list of marks (called 3 times for local, global and special marks)&lt;&#x2F;li&gt;
&lt;li&gt;Function &lt;code&gt;vim.api.nvim_buf_set_extmark&lt;&#x2F;code&gt; used to populate the gutter (called once per mark)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;One common optimization pattern is to do nothing when not necessary. So I decided to remove the call to &lt;code&gt;nvim_buf_set_extmark&lt;&#x2F;code&gt; when unnecessary.&lt;&#x2F;p&gt;
&lt;p&gt;This is done by caching the last list of marks, and compare the list with the new one before refreshing the gutter. As simple as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; M&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;refresh&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  …&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;  local&lt;&#x2F;span&gt;&lt;span&gt; cached_marks&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; M._marks_cache[bufnr]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; cached_marks&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; and&lt;&#x2F;span&gt;&lt;span&gt; utils.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;marks_equal&lt;&#x2F;span&gt;&lt;span&gt;(marks, cached_marks) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;  update_extmark&lt;&#x2F;span&gt;&lt;span&gt;(bufnr, marks)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  M._marks_cache[bufnr] &lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; marks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this cache implementation we now have the following result:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOTE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;bench&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;bench_cache.lua | &lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;refresh&lt;&#x2F;span&gt;&lt;span&gt; (x1000) with cache&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E5C890;font-style: italic;&quot;&gt; light&lt;&#x2F;span&gt;&lt;span&gt;: it&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;0010&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;47.051&lt;&#x2F;span&gt;&lt;span&gt;ms median&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;47.522&lt;&#x2F;span&gt;&lt;span&gt;ms min&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;45.241&lt;&#x2F;span&gt;&lt;span&gt;ms max&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;47.871&lt;&#x2F;span&gt;&lt;span&gt;ms stddev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;0.828&lt;&#x2F;span&gt;&lt;span&gt;ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NOTE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;bench&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;bench_cache.lua | &lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;refresh&lt;&#x2F;span&gt;&lt;span&gt; (x1000) with cache&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E5C890;font-style: italic;&quot;&gt; heavy&lt;&#x2F;span&gt;&lt;span&gt;: it&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;0010&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;47.703&lt;&#x2F;span&gt;&lt;span&gt;ms median&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;47.990&lt;&#x2F;span&gt;&lt;span&gt;ms min&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;46.070&lt;&#x2F;span&gt;&lt;span&gt;ms max&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;48.572&lt;&#x2F;span&gt;&lt;span&gt;ms stddev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;0.830&lt;&#x2F;span&gt;&lt;span&gt;ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We immediately get a &lt;code&gt;2.1x&lt;&#x2F;code&gt; speed-up on this micro-benchmark.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-few-conclusive-notes&quot;&gt;A few conclusive notes&lt;&#x2F;h3&gt;
&lt;p&gt;This only a micro-benchmark when marks are never updated, while not real it is matching the behavior where marks are rarely updated, and &lt;code&gt;refresh()&lt;&#x2F;code&gt; may be called many times between 2 marks update. A few more benchmark scenarios should be created with more mixed usage.&lt;&#x2F;p&gt;
&lt;p&gt;A few other areas to optimize I may work more in the future:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;When having to actually update the marks, we could simply update the required marks, instead of clearing the namespace.&lt;&#x2F;li&gt;
&lt;li&gt;Could we configure the aucmd to call &lt;code&gt;refresh()&lt;&#x2F;code&gt; in more meaningful situations? I wonder if we could update nvim to publish a &lt;code&gt;MarkUpdate&lt;&#x2F;code&gt; aucmd only when a marks get updated.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Now, one could ask: is it worth the effort to optimize a function that takes less than a tenth of a millisecond to execute in a text editor? I believe that, all else being equal, if all plugin authors spent time optimizing their hot loop to divide by 2 the latency with little complexity overhead, using computers would be more enjoyable day to day.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Fast comment toggle in Neovim</title>
        <published>2025-09-21T00:00:00+00:00</published>
        <updated>2025-09-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/2025/nvim-comment-toggle/"/>
        <id>https://dimtion.fr/blog/2025/nvim-comment-toggle/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/2025/nvim-comment-toggle/">&lt;p&gt;I didn&#x27;t see this mapping anywhere else in the community yet, so hear me out.&lt;&#x2F;p&gt;
&lt;p&gt;A modern &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;&quot;&gt;Neovim&lt;&#x2F;a&gt; key mapping I see often these days is the use of &lt;code&gt;&amp;lt;space&amp;gt;&lt;&#x2F;code&gt; as a &lt;code&gt;&amp;lt;leader&amp;gt;&lt;&#x2F;code&gt; key. I &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;neovim&#x2F;comments&#x2F;xbigzt&#x2F;why_space_as_leader&#x2F;&quot;&gt;believe&lt;&#x2F;a&gt; this is coming from the need to use a lot of indirect mappings behind the leader namespace, and provide efficient access. I don&#x27;t use this mapping, I feel the default leader key &lt;code&gt;\&lt;&#x2F;code&gt; is close enough to the home row to stay where it is. However, in normal mode, the &lt;code&gt;&amp;lt;space&amp;gt;&lt;&#x2F;code&gt; key remains the largest key on the keyboard with little use in Vim.&lt;&#x2F;p&gt;
&lt;p&gt;I realized that when implementing, debugging or understanding new code, one of the most common &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Read%E2%80%93eval%E2%80%93print_loop&quot;&gt;patterns&lt;&#x2F;a&gt; I would follow is: (1) build&#x2F;run code, (2) find a bug&#x2F;behavior, (3) tweak the code, (4) repeat.&lt;&#x2F;p&gt;
&lt;p&gt;While (1) and (2) mostly depend on external tooling, optimizing (3) depends on one&#x27;s text editor proficiency. One way to tweak the code efficiently is by commenting out parts of the code. This allows for quickly changing the behavior, trying an old or new expression, toggling a specific unit test case, enabling&#x2F;disabling a new feature, enable&#x2F;disable flags.&lt;&#x2F;p&gt;
&lt;p&gt;While I don&#x27;t advocate keeping commented code in final commits, commenting code in and out is a super efficient way to draft code changes. Additionally, commenting in and out code keeps all the short-term history of the code right there in the buffer. So here is my simple remap I&#x27;ve been using for a while now:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vim.keymap.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;n&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;&amp;lt;space&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;gcc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, { silent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E78284;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vim.keymap.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;v&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;&amp;lt;space&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;gc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, { silent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E78284;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Space bar as comment-in comment-out is such a good muscle memory, I do believe I&#x27;m directly more efficient in editing code day to day. Given how rarely I see this mapping, I would advocate for more people trying this mapping in the community.&lt;&#x2F;p&gt;
&lt;p&gt;Combine it with &lt;code&gt;gv&lt;&#x2F;code&gt; (redo previous visual selection) and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-treesitter&#x2F;nvim-treesitter-textobjects&#x2F;tree&#x2F;main&quot;&gt;Treesitter text objects&lt;&#x2F;a&gt; &lt;code&gt;ac&lt;&#x2F;code&gt;, &lt;code&gt;ic&lt;&#x2F;code&gt; to comment lines at the speed of light:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vim.keymap.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;({ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;x&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;o&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;}, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;ac&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;  require&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;nvim-treesitter-textobjects.select&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;select_textobject&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;@comment.outer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;textobjects&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vim.keymap.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;({ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;x&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;o&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;}, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;ic&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;  require&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;nvim-treesitter-textobjects.select&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;select_textobject&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;@comment.outer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;textobjects&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Few examples of work in progress code changes, or &lt;em&gt;things you would not see committed&lt;&#x2F;em&gt;. That I see myself very often do thanks how easy &lt;code&gt;&amp;lt;space&amp;gt;&lt;&#x2F;code&gt; is accessible.&lt;&#x2F;p&gt;
&lt;p&gt;Trying the &lt;code&gt;setup()&lt;&#x2F;code&gt; function instead of the &lt;code&gt;init()&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; configure&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  -- require(&amp;quot;guttermarks&amp;quot;).init()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;  require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;guttermarks&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Temporarily disable unit test case to restrict debugging to one function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;-- T[&amp;quot;alphabet_lower&amp;quot;][&amp;quot;is_lower&amp;quot;] = function(x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;--   eq(utils.is_lower(x), true)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;-- end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;T[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;alphabet_lower&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;is_upper&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;  eq&lt;&#x2F;span&gt;&lt;span&gt;(utils.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;is_upper&lt;&#x2F;span&gt;&lt;span&gt;(x), &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E78284;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Give it a try for a week, tell me what you think!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>GutterMarks.nvim</title>
        <published>2025-08-03T00:00:00+00:00</published>
        <updated>2025-08-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/2025/guttermarks-nvim/"/>
        <id>https://dimtion.fr/blog/2025/guttermarks-nvim/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/2025/guttermarks-nvim/">&lt;h1 id=&quot;guttermarks-nvim&quot;&gt;GutterMarks.nvim&lt;&#x2F;h1&gt;
&lt;p&gt;I love &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;doc&#x2F;user&#x2F;motion.html#_7.-marks&quot;&gt;Neovim marks&lt;&#x2F;a&gt;, this weekend, I got tired by existing neovim marks plugins. They are often complex, impose new workflows and sometimes don&#x27;t provide the basics very well out of the box: display the Marks in the buffer gutter.&lt;&#x2F;p&gt;
&lt;p&gt;For example, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;chentoast&#x2F;marks.nvim&quot;&gt;marks.nvim&lt;&#x2F;a&gt; runs a scheduled function every 150 milliseconds to refresh the existing marks, both not great for performances and slow. Further, I don&#x27;t need all the other fancy features.&lt;&#x2F;p&gt;
&lt;p&gt;So I wrote &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;guttermarks.nvim&quot;&gt;GutterMarks.nvim&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The pitch is simple: display in the Neovim gutter the existing Marks for a given buffer.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;dimtion.fr&#x2F;blog&#x2F;2025&#x2F;guttermarks-nvim&#x2F;screenshot_01.png&quot; alt=&quot;GutterMarks screenshot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There are a few &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;guttermarks.nvim&#x2F;blob&#x2F;main&#x2F;lua&#x2F;guttermarks&#x2F;default_config.lua&quot;&gt;configuration options&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Display Local, Global and Special marks (&lt;code&gt;&#x27;.&quot;^&amp;lt;&amp;gt;[]0-9&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Change the highlight groups (and thus display colors)&lt;&#x2F;li&gt;
&lt;li&gt;Exclude filetypes and buffer types&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And that&#x27;s it. Nothing fancy.&lt;&#x2F;p&gt;
&lt;p&gt;Installation is simple using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;folke&#x2F;lazy.nvim&quot;&gt;lazy.nvim&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;  &amp;quot;dimtion&#x2F;guttermarks.nvim&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  event&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;VeryLazy&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rose-pine&#x2F;neovim&quot;&gt;Rosé Pine&lt;&#x2F;a&gt; theme, I&#x27;m changing the gutter marks color using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;dotfiles&#x2F;blob&#x2F;master&#x2F;.config&#x2F;nvim&#x2F;lua&#x2F;dimtion&#x2F;plugins&#x2F;theme.lua&quot;&gt;highlight groups override&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;    &amp;quot;rose-pine&#x2F;neovim&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;rose-pine&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lazy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E78284;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    priority&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    opts&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      highlight_groups&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;        -- Blend colours against the &amp;quot;base&amp;quot; background&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        CursorLine&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { bg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;pine&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, blend&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 30&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E78284;&quot;&gt;		...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        GutterMarksLocal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { fg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;muted&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        GutterMarksGlobal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { fg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;muted&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        GutterMarksSpecial&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { fg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;muted&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I&#x27;m not planning to add much other features, in particular to keep the scope small. But if you find any bugs or nice to have improvements, don&#x27;t hesitate to file a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;guttermarks.nvim&#x2F;issues&quot;&gt;bug report&lt;&#x2F;a&gt;. Hope this plugin will find other happy users!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>LLM agents as a new automation level</title>
        <published>2025-07-13T00:00:00+00:00</published>
        <updated>2025-07-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/2025/llm-agent-oncall/"/>
        <id>https://dimtion.fr/blog/2025/llm-agent-oncall/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/2025/llm-agent-oncall/">&lt;p&gt;In high load teams, there is this common thread that appears again and again: &quot;we don&#x27;t have time to fully automate this SOP&quot;. This happens for problems that are rare (a few time a year), are low impact (only 0.0x% of clients&#x2F;requests&#x2F;$ impacted) or high engineering cost to fix. Usually, if your organization is effective, you&#x27;ll take note of the recurring problem, add it to a backlog and maybe provide a proper &quot;long term fix&quot; for the next sprint. Oftentimes this problem stays in the backlog forever.&lt;&#x2F;p&gt;
&lt;p&gt;In very productive teams, senior engineers and management fosters a culture empowering the engineers to semi-automate the mitigation for this type of recurring problems, it could be a quick python script in a shared folder, a well written SOP for newcomers, or simply tune the alert level if there is no action item.&lt;&#x2F;p&gt;
&lt;p&gt;This is beautifully summarized in the now &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;1205&#x2F;&quot;&gt;famous XKCD&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;dimtion.fr&#x2F;blog&#x2F;2025&#x2F;llm-agent-oncall&#x2F;is_it_worth_the_time_2x.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;center&gt;&lt;i&gt;Nobody cares about the top right quadrant&lt;&#x2F;i&gt;&lt;&#x2F;center&gt;
&lt;p&gt;I&#x27;d like to make the case with LLM-agent tools coming into the engineering toolkit, effective teams could leverage, them to tackle issues that were too expensive to tackle today, which could effectively improve the quality of tech products for the users.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Applying the XKCD table to engineering oncall issue mitigation, we can rank the ways of solving a recurring issue in the following order:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;dimtion.fr&#x2F;blog&#x2F;2025&#x2F;llm-agent-oncall&#x2F;llm-agent-oncall.svg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;On the left, manual mitigations are cheap do to once, this is when the oncall will bounce the fleet, or manually update a configuration to partially mitigate the issue, this can be done in a short amount of time (~15 minutes). Sometimes, this action is also a loosely defined set of investigation steps, that require fetching, combining data from multiple source before taking a decision. It generally only fixes the issue once, and the same action might be needed again if the issue happens again.&lt;&#x2F;p&gt;
&lt;p&gt;In between, there are semi-automated, or &quot;scripted mitigation&quot;. Scripted mitigations usually are created by team when a recurring issue pass a certain threshold of either complexity (too many items to fix) or a threshold of frequency. Scripts take more time to write the first time, from a few minutes to a few hours, but once created, they can save substantial time on subsequent occurrences. As examples: scripts to re-drive a few asynchronous events, scripts to update multiple objects in a database in an invalid state.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, generally, the preferred approach is a systematic bug fix or system redesign to make the error case fully disappear. Such solution range take from hours, days, or weeks of work to be implemented, depending on the complexity. For rare, low-impact issues (that still impact a few unhappy users), this type of fix is rare prioritized, unless another higher impact issue allow the team to bundle the bug fix with the other issue.&lt;&#x2F;p&gt;
&lt;p&gt;In a perfect world, teams would reach for this last solution as much as possible, but time-constrains and other priorities often time only allow to reach for a proper resolution only if the impact pass a certain threshold of impact.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The thesis I&#x27;m bringing is that LLM based tools which are getting better and better at writing code snippets, reading and compiling from unstructured data source can be (and should be) used as a new automation level in operational excellence. On the OPEX&#x2F;CAPEX spectrum, such tools allow us to close the gap between manual incident mitigation and automated mitigation:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;dimtion.fr&#x2F;blog&#x2F;2025&#x2F;llm-agent-oncall&#x2F;llm-agent-oncall-genai.svg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;LLM agents can be seen as a new tool for operational teams, serving as helpers for mitigating low-impact issues while software engineers focus most of their attention on higher-impact work during busy on-call rotations.&lt;&#x2F;p&gt;
&lt;p&gt;When writing a mitigation script would have taken a couple of hours in the past (with proper testing, edge case handling, etc.), LLM agents can give engineers a head start. They write the boilerplate, handle the core business logic of the script, and generate data for script testing before oncall can validate and execute it in a production environment. For an issue that impacts only a few user a month, the oncall Engineer may never had the time to investigate the issue. Or if they could investigate the issue, they may have judged that performing a mitigation or fix would be too much effort compared to the impact, thus leaving the issue unmitigated or partially mitigated.&lt;&#x2F;p&gt;
&lt;p&gt;Another task that takes time for software engineers is the process of following loosely defined SOPs. These SOPs are can sometime be vague, and require investigation work (otherwise they would have been automated sic). With proper guardrails, some investigation SOPs (checking multiple log streams, databases, API endpoints…) can now be half-automated. The LLM agent to do most of the legwork of combining unstructured data sources, summarizing issues, bucketizing problems, and report the findings to the oncall. In this case, the LLM serves as an approximate interpreter of the SOP, something that was qualitatively impossible in the past.&lt;&#x2F;p&gt;
&lt;p&gt;Note that high-impact operational work still benefit from GenAI tools (and for similar reasons). The point I&#x27;m making here is, by reducing the cost of investigating, analyzing and mitigating low-impact issues, LLM may be a tool that ultimately improve the overall software operational quality for high TPS systems. Such systems, often accumulate over time a big backlog of detected, but unmitigated bugs, which if were fully tackled would generally improve the service quality in a measurable way.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Finally, please consider that I&#x27;m not advocating in leaving LLM agents loose access to production environment. Before adding any agent to their workflow, teams should assess their security posture, especially in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;simonwillison.net&#x2F;2025&#x2F;Jun&#x2F;16&#x2F;the-lethal-trifecta&#x2F;&quot;&gt;new class of security issues&lt;&#x2F;a&gt; that LLM agents bring security engineering. Further, as an industry, we should recognize that LLM tools are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;metr.org&#x2F;blog&#x2F;2025-07-10-early-2025-ai-experienced-os-dev-study&#x2F;&quot;&gt;not always a net productivity gain&lt;&#x2F;a&gt;, and the same should apply when designing an agent optimized for on-call. Hopefully good engineering practices will emerge with time.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Zellij</title>
        <published>2025-05-10T00:00:00+00:00</published>
        <updated>2025-05-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/wiki/linux/zellij/"/>
        <id>https://dimtion.fr/wiki/linux/zellij/</id>
        
        <content type="html" xml:base="https://dimtion.fr/wiki/linux/zellij/">&lt;p&gt;Cache location in macos:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Library&#x2F;Caches&#x2F;org.Zellij-Contributors.Zellij&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;bug-with-session-dissapearing-after-an-update&quot;&gt;Bug with session dissapearing after an update&lt;&#x2F;h2&gt;
&lt;p&gt;See: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zellij-org&#x2F;zellij&#x2F;issues&#x2F;3371&quot;&gt;zellij#3371&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# kill all running process&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;ps&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; aux&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; -i &amp;quot;[z]ellij --server&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; awk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; {&amp;#39;print $2&amp;#39;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; xargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; kill&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Copy the old version to the new version cache:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; -r ~&#x2F;Library&#x2F;Caches&#x2F;org.Zellij-Contributors.Zellij&#x2F;{0.41.2&#x2F;,0.42.1}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# List new sessions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;zellij&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Pytorch</title>
        <published>2025-04-06T00:00:00+00:00</published>
        <updated>2025-04-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/wiki/ml/pytorch/"/>
        <id>https://dimtion.fr/wiki/ml/pytorch/</id>
        
        <content type="html" xml:base="https://dimtion.fr/wiki/ml/pytorch/">&lt;h2 id=&quot;pytorch-for-m-series-mac-metal-accelerated&quot;&gt;Pytorch for M series mac (Metal accelerated)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;using-bare-pip&quot;&gt;Using bare pip&lt;&#x2F;h3&gt;
&lt;p&gt;From &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;metal&#x2F;pytorch&#x2F;&quot;&gt;Apple documentation&lt;&#x2F;a&gt;, using simple pip:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;pip3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; install --pre torch torchvision torchaudio --extra-index-url https:&#x2F;&#x2F;download.pytorch.org&#x2F;whl&#x2F;nightly&#x2F;cpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;for-a-uv-project&quot;&gt;For a uv project&lt;&#x2F;h3&gt;
&lt;p&gt;For a Python project using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astral-sh&#x2F;uv&quot;&gt;uv&lt;&#x2F;a&gt; as a project and package manager do the following:&lt;&#x2F;p&gt;
&lt;p&gt;Add to the uv &lt;code&gt;pyproject.toml&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;tool.uv.sources&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;torch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;pytorch&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;torchvision&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;pytorch&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;torchaudio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;pytorch&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;[[&lt;&#x2F;span&gt;&lt;span&gt;tool.uv.index&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;pytorch&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;https:&#x2F;&#x2F;download.pytorch.org&#x2F;whl&#x2F;nightly&#x2F;cpu&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;explicit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uv add --prerelease allow torch torchvision torchaudio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astral-sh&#x2F;uv&#x2F;issues&#x2F;8341&quot;&gt;open issue&lt;&#x2F;a&gt; on uv github to improve a bit the CLI to automatically add explicit indexes to the &lt;code&gt;pyproject.toml&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;for-a-simple-script-one-time-projec-using-uv&quot;&gt;For a simple script&#x2F;one time projec using uv&lt;&#x2F;h3&gt;
&lt;p&gt;Run the command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;uv&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; add --prerelease allow torch torchvision torchaudio --index pytorch=https:&#x2F;&#x2F;download.pytorch.org&#x2F;whl&#x2F;nightly&#x2F;cpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ComfyUI RAW Image Loader</title>
        <published>2025-03-30T00:00:00+00:00</published>
        <updated>2025-03-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/2025/comfyui-raw-image/"/>
        <id>https://dimtion.fr/blog/2025/comfyui-raw-image/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/2025/comfyui-raw-image/">&lt;p&gt;This weekend I was trying a bit &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.comfy.org&#x2F;&quot;&gt;ComfyUI&lt;&#x2F;a&gt; to see what is happening on the stable diffusion domain. Even though it looks like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openai.com&#x2F;index&#x2F;introducing-4o-image-generation&#x2F;&quot;&gt;stable diffusion is no longer the best and greatest&lt;&#x2F;a&gt;, it is still clearly an impressive tool to generate images. Most users seem to focus on using it to either create&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.comfy.org&#x2F;tutorials&#x2F;basic&#x2F;text-to-image&quot;&gt; image from text&lt;&#x2F;a&gt;, do &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.comfy.org&#x2F;tutorials&#x2F;basic&#x2F;image-to-image&quot;&gt;style transfer&lt;&#x2F;a&gt;, or plenty of uses cases that are trendy on Twitter and other social media.&lt;&#x2F;p&gt;
&lt;p&gt;One thing I wanted to try if it is possible to use the workflows to do photo editing, and in particular, RAW image editing. It turns out that there is no plugin that exist to directly load a RAW image and insert it into a ComfyUI workflow. Most of the internet mostly care about jpeg and png images, I&#x27;m guessing.&lt;&#x2F;p&gt;
&lt;p&gt;More generally it seems that most image generation models are not meant for RAW image editing, which would be a nice project to explore another day. Anyways, as a first step I decided to experiment with ComfyUI API and came up with the most minimal possible extension: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;comfyui-raw-image&quot;&gt;ComfyUI Raw Image Loader&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This extension provides a simple node to load a RAW image from disk and convert it to a proper Torch tensor (or simply an &lt;code&gt;IMAGE&lt;&#x2F;code&gt; in ComfyUI vocabulary) that can then be used as input for any image-to-X workflow. I added a couple of features to allow brightness adjustment and how it should behave with brightness clipping.  I was able to set it up quickly thanks to the amazing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;letmaik.github.io&#x2F;rawpy&#x2F;api&#x2F;rawpy.RawPy.html&quot;&gt;pyraw&lt;&#x2F;a&gt; library.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;dimtion.fr&#x2F;blog&#x2F;2025&#x2F;comfyui-raw-image&#x2F;2025-03-30_comfyui-node-screenshot.png&quot; alt=&quot;ComfyUI Load Raw Image node&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The overall code is very simple, ComfyUI has a good documentation to create a new node, in short, the code can be summarized to:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create a Python class&lt;&#x2F;li&gt;
&lt;li&gt;Define the return and input types, with their constrains and validations&lt;&#x2F;li&gt;
&lt;li&gt;Write a main function that takes those inputs and return the specified output&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Here is a skeleton example of how to create a node extension:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E5C890;font-style: italic;&quot;&gt; LoadRawImage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;    # Define node interface metadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    RETURN_TYPES&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;IMAGE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  # What the node outputs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    FUNCTION&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;load_img&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;      # Main function to call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    CATEGORY&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;image&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;         # UI category&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DESCRIPTION&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;Load a RAW image into ComfyUI.&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt;classmethod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; INPUT_TYPES&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;cls&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;        # Define UI inputs (required and optional)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        files&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt; get_files_from_input_directory&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;            &amp;quot;required&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;: {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;image&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;: (&lt;&#x2F;span&gt;&lt;span&gt;files&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;image_upload&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; True&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;})},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;            &amp;quot;optional&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;                &amp;quot;use_auto_bright&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;BOOLEAN&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;default&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; True&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;}),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;                &amp;quot;bright_adjustment&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;FLOAT&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;default&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;min&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;max&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;}),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;                &amp;quot;highlight_mode&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;: ([&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;clip&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;blend&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;], {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;default&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;clip&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt;classmethod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; VALIDATE_INPUTS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;cls&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;        # Validate inputs before processing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; True&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; or&lt;&#x2F;span&gt;&lt;span&gt; error_message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt;classmethod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; IS_CHANGED&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;cls&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;        # Track if inputs have changed (for caching)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; hash_of_input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; load_img&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E78284;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; use_auto_bright&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; bright_adjustment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; highlight_mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;clip&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;        # Main processing function that matches FUNCTION name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;        # Process inputs and return outputs matching RETURN_TYPES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        processed_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt; process_raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; parameters...&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;processed_image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  # Return as tuple matching RETURN_TYPES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Register node(s) for ComfyUI to discover&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NODE_CLASS_MAPPINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Load Raw Image&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; LoadRawImage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I wonder if ComfyUI explored the option to use Python type annotations instead of simple strings to define inputs and outputs. At least the string approach has the advantage of being simple and universal.&lt;&#x2F;p&gt;
&lt;p&gt;In the end, I created a simple &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;stabilityai&#x2F;stable-diffusion-xl-base-1.0&quot;&gt;SDXL&lt;&#x2F;a&gt; workflow, using a refiner to change a little bit the style of an input picture. I&#x27;m experimenting a bit more to see how to generate more complex changes, and provide more control over the input image.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;dimtion.fr&#x2F;blog&#x2F;2025&#x2F;comfyui-raw-image&#x2F;2025-03-30_comfyui-workflow-screenshot.png&quot; alt=&quot;Example ComfyUI workflow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I do believe diffusion, LLMs and more generally deep learning tools, are good tools overall for people to be able to experiment too, and in a time where artists and photographers feel threaten by them, providing more tools for said people to leverage GenAI tools, will definitively be good to propagate knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;See: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;comfyui-raw-image&quot;&gt;ComfyUI Raw Image Loader&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Metonymies in software engineering</title>
        <published>2025-03-09T00:00:00+00:00</published>
        <updated>2025-03-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/2025/metonymy-swe/"/>
        <id>https://dimtion.fr/blog/2025/metonymy-swe/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/2025/metonymy-swe/">&lt;p&gt;Properly communicating in engineering is often a tradeoff between being concise and being accurate. A common tool to remain concise while remaining specific is to use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Metonymy&quot;&gt;metonymies&lt;&#x2F;a&gt;. A metonymy is a figure of speech in which a specific concept is referred by another very close word.&lt;&#x2F;p&gt;
&lt;p&gt;A common type of metonymy used is to designate a concept by a specific implementation it. For example, when one means &quot;We should use Redis to solve problem A&quot; do they mean:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We need an key value store?&lt;&#x2F;li&gt;
&lt;li&gt;We need an in-memory database?&lt;&#x2F;li&gt;
&lt;li&gt;We need a distributed database?&lt;&#x2F;li&gt;
&lt;li&gt;We need a (distributed) cache?&lt;&#x2F;li&gt;
&lt;li&gt;We need a database with feature x (sets, hyperloglog…)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Redis is arguably all of those concepts at the same time. If you are sure your co-worker (or blog reader) understands which capacity of this technology you refer to, go ahead, use the word &lt;em&gt;Redis&lt;&#x2F;em&gt;. However, be sure to insist which aspect of &lt;em&gt;Redis&lt;&#x2F;em&gt; solves problem A.&lt;&#x2F;p&gt;
&lt;p&gt;This is mostly a problem in the following situations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Some junior engineers use metonymies by lack of exposure of multiple implementations of a concept.&lt;&#x2F;li&gt;
&lt;li&gt;Confusion within the team of what the engineer exactly mean (do they refer to a key&#x2F;value store or a in-memory database?)&lt;&#x2F;li&gt;
&lt;li&gt;Using a specific technology name to often can corner one&#x27;s mental model into this specific technology instead of the more general concept.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some other examples of common metonymies that might cause confusion:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Hashmap for a Map&lt;&#x2F;li&gt;
&lt;li&gt;DynamoDB for a document database&lt;&#x2F;li&gt;
&lt;li&gt;PostgreSQL for SQL database&lt;&#x2F;li&gt;
&lt;li&gt;ReactJS for Javascript&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;Github Actions for CI&#x2F;CD&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Overall, when the concept is properly understood there is little harm to refer to it by using a specific implementation, but be aware of the mental model your listeners might have of this concept, and more importantly, question your assumptions to makes sure you don&#x27;t corner your thoughts into a specific implementation.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Falsehoods Software Developers Believe About Event-Driven Systems</title>
        <published>2024-06-30T00:00:00+00:00</published>
        <updated>2024-06-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/falsehoods-event-driven/"/>
        <id>https://dimtion.fr/blog/falsehoods-event-driven/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/falsehoods-event-driven/">&lt;p&gt;When building a distributed system, a common design pattern is to follow the
event-driven approach. Event-driven systems can range from a simple in-memory
queue to a serverless AWS Lambda with a preceding queue, or even connected
Kafka clusters. when reviewing code implementing an even driven architecture, I
see common mistakes that cause toil or even operational incidents once deployed
to production.&lt;&#x2F;p&gt;
&lt;p&gt;Here are unordered misconceptions developers have about event-driven
architectures. Use this as a checklist for design and code review.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;message-ordering&quot;&gt;Message ordering&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Events will arrive in order&lt;&#x2F;li&gt;
&lt;li&gt;Events will arrive in order, even with a single consumer&lt;&#x2F;li&gt;
&lt;li&gt;Events will arrive in order, even if specified by the producer contract&lt;&#x2F;li&gt;
&lt;li&gt;Events will arrive in order, even with days between messages&lt;&#x2F;li&gt;
&lt;li&gt;Events can always be ordered&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;message-duplication&quot;&gt;Message duplication&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Events won&#x27;t be duplicated&lt;&#x2F;li&gt;
&lt;li&gt;Events won&#x27;t be duplicated, in at-most-once delivery queues&lt;&#x2F;li&gt;
&lt;li&gt;Events won&#x27;t be duplicated, even if specified by producer contract&lt;&#x2F;li&gt;
&lt;li&gt;Events won&#x27;t be duplicated, even with de-duplication upon arrival&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;idempotency&quot;&gt;Idempotency&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Adding an idempotency key ensures idempotency&lt;&#x2F;li&gt;
&lt;li&gt;Equal idempotency keys mean identical payloads&lt;&#x2F;li&gt;
&lt;li&gt;Event timestamp is a valid idempotency key&lt;&#x2F;li&gt;
&lt;li&gt;Writing idempotent code is easy&lt;&#x2F;li&gt;
&lt;li&gt;Maintain and improve idempotent code is easy&lt;&#x2F;li&gt;
&lt;li&gt;Idempotency can be solved via adding a distributed lock and an idempotency
key&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;load-management&quot;&gt;Load management&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Low TPS systems are not subject to backlog&lt;&#x2F;li&gt;
&lt;li&gt;Low TPS systems are not subject throttling&lt;&#x2F;li&gt;
&lt;li&gt;Processing timeout of XX seconds is sufficient&lt;&#x2F;li&gt;
&lt;li&gt;Processing timeout of XX minutes is sufficient&lt;&#x2F;li&gt;
&lt;li&gt;Processing timeout of XX hours is sufficient&lt;&#x2F;li&gt;
&lt;li&gt;Upstream dependencies&#x27; timeouts are properly configured&lt;&#x2F;li&gt;
&lt;li&gt;Retry policy is properly configured&lt;&#x2F;li&gt;
&lt;li&gt;Event processing time is constant and performance will remain consistent under load&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;producer-contract&quot;&gt;Producer contract&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Event producer can be trusted to always produce valid events&lt;&#x2F;li&gt;
&lt;li&gt;Event producer can be trusted to generally produce valid events&lt;&#x2F;li&gt;
&lt;li&gt;Event producer can be trusted to produce non-conflicting events&lt;&#x2F;li&gt;
&lt;li&gt;Event producer can be trusted to not overload the consumer&lt;&#x2F;li&gt;
&lt;li&gt;Event producer can be trusted to send message on time&lt;&#x2F;li&gt;
&lt;li&gt;Event producer can be trusted to never fail&lt;&#x2F;li&gt;
&lt;li&gt;Event producer can be trusted to rarely fail&lt;&#x2F;li&gt;
&lt;li&gt;Event producer can be trusted, even if it is an internal process&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;consumer-contract&quot;&gt;Consumer contract&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Event consumer is simple enough to never fail&lt;&#x2F;li&gt;
&lt;li&gt;Event consumer does not need a scaling strategy&lt;&#x2F;li&gt;
&lt;li&gt;Event consumer downstream dependencies support idempotent calls&lt;&#x2F;li&gt;
&lt;li&gt;Events will never be dropped&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;dead-letter-queues&quot;&gt;Dead letter queues&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Dead letter queues are not necessary&lt;&#x2F;li&gt;
&lt;li&gt;Dead letter queue is properly configured&lt;&#x2F;li&gt;
&lt;li&gt;Only a handful events will end up in the dead letter queue&lt;&#x2F;li&gt;
&lt;li&gt;Even if there are many events in the DLQ, there are only a few
representative error categories&lt;&#x2F;li&gt;
&lt;li&gt;At least it will be easy to sort out the different error categories&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;recovery&quot;&gt;Recovery&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;System does not need manual recovery&lt;&#x2F;li&gt;
&lt;li&gt;Manual recovery won&#x27;t require modifying events&lt;&#x2F;li&gt;
&lt;li&gt;Manual recovery won&#x27;t require the producer to regenerate messages&lt;&#x2F;li&gt;
&lt;li&gt;Manual recovery won&#x27;t coincide with another system failure&lt;&#x2F;li&gt;
&lt;li&gt;Manual recovery will be completed within minutes&lt;&#x2F;li&gt;
&lt;li&gt;Manual recovery will be completed within hours&lt;&#x2F;li&gt;
&lt;li&gt;Manual recovery will be completed within days&lt;&#x2F;li&gt;
&lt;li&gt;Pending manual recovery, events can simply stay in the queue&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Orchestrated architectures are better and simpler&lt;&#x2F;li&gt;
&lt;li&gt;Choreographed architectures are better and simpler&lt;&#x2F;li&gt;
&lt;li&gt;Unbounded queues are better than bounded queues&lt;&#x2F;li&gt;
&lt;li&gt;Event-driven architecture are simpler to reason about&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;[list to be updated]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Trying out lazy.nvim</title>
        <published>2024-06-05T00:00:00+00:00</published>
        <updated>2024-06-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/trying-out-lazy-nvim/"/>
        <id>https://dimtion.fr/blog/trying-out-lazy-nvim/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/trying-out-lazy-nvim/">&lt;p&gt;During the few months, following the news that
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wbthomason&#x2F;packer.nvim&#x2F;commit&#x2F;16c5798b4968669174c76e978944a2c82653fe67&quot;&gt;packer.nvim&lt;&#x2F;a&gt;
is deprecated, I wanted to try out the new cool package manager in town
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;folke&#x2F;lazy.nvim&quot;&gt;lazy.nvim&lt;&#x2F;a&gt;. I spent a bit of time
migrating over my
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;dotfiles&#x2F;tree&#x2F;master&#x2F;.config&#x2F;nvim&quot;&gt;personal&lt;&#x2F;a&gt; and
work configurations over to lazy. Here are some thoughts I had during the
migration.&lt;&#x2F;p&gt;
&lt;p&gt;To give a bit of context, my journey on &lt;code&gt;&#x2F;n?vim&#x2F;&lt;&#x2F;code&gt; package managers is the
following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Vim no package manager&lt;&#x2F;li&gt;
&lt;li&gt;Vim + vim-plug&lt;&#x2F;li&gt;
&lt;li&gt;Neovim + vim-plug (VimL)&lt;&#x2F;li&gt;
&lt;li&gt;Neovim + packer.nvim (Lua)&lt;&#x2F;li&gt;
&lt;li&gt;Neovim + Lazy.nvim (Lua)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;the-good&quot;&gt;The good&lt;&#x2F;h2&gt;
&lt;p&gt;On the good part and as a first impression, lazy.nvim setup and installation is
pretty simple, just copy the lines of the self-bootstrap code, restart nvim and
it downloads and install lazy flawlessly. In case you have any issue
&lt;code&gt;:checkhealth lazy&lt;&#x2F;code&gt; has good self-check that provides insightful debugging
information. This is definitively on par with packer.nvim and from memory even
working better than vim-plug.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps the best tool lazy.nvim provides is its UI. It is very practical,
information dense and is very easy to navigate. Launch &lt;code&gt;:Lazy&lt;&#x2F;code&gt; and just follow
the UI shortcuts to jump around between which lazy-loaded plugins are launched.
Which ones are not loaded yet and what shortcut or event will launch them. The
profiler is a great tool to understand which plugin has a strong impact on
startup-time, and decide which plugins are worth spending time configure to
lazy load.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;dimtion.fr&#x2F;blog&#x2F;trying-out-lazy-nvim&#x2F;lazy-cmd-screenshot.png&quot; alt=&quot;Running :lazy&quot; &#x2F;&gt;
Also, the pining of dependencies version is a game-changer, copying from modern
package managers, it helps a lot with sharing a configuration across multiple
machines. Pining plus headless nvim, allows updating the packages in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;dotfiles&#x2F;blob&#x2F;master&#x2F;Makefile&quot;&gt;one
command line&lt;&#x2F;a&gt;,
even in a CI environment, and make sure the same version of all packages are running everywhere.&lt;&#x2F;p&gt;
&lt;p&gt;To update the neovim configuration, one can run &lt;code&gt;:Lazy&lt;&#x2F;code&gt; then press &lt;code&gt;S&lt;&#x2F;code&gt; to &quot;sync&quot; the latest dependencies, pretty convenient. alternatively, my preferred approach is to use Makefile and have this formula:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;make&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;update&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	XDG_CONFIG_HOME=.&#x2F;.config nvim --headless &amp;quot;+Lazy! update&amp;quot; +qa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	XDG_CONFIG_HOME=.&#x2F;.config nvim --headless &amp;quot;+TSUpdateSync&amp;quot; +qa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-can-improve&quot;&gt;The &#x27;can improve&#x27;&lt;&#x2F;h2&gt;
&lt;p&gt;Lazy.nvim taking a radically different approach on configuration of plugins
than other more common plugin managers, it requires a mental shift in how to
configure each plugin. Other package managers (such as plug or packer)
typically have one location where the plugins are declared, and another one
where they are configured, those package managers leverage vim plugin
infrastructure which is quite standard and common nowadays.&lt;&#x2F;p&gt;
&lt;p&gt;It results in configurations that look like such:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;-- 1. Declare loaded plugins&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;packer&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;startup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;   use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;mbbill&#x2F;undotree&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;-- 2. Configure each plugin using plugin README:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vim.keymap.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;n&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;&amp;lt;leader&amp;gt;&amp;lt;u&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, vim.cmd.UndotreeToggle, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    desc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;Show nvim undotree&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Those configuration, being standard by other plugin manager are easy to copy,
edit and understand just following each plugin README.&lt;&#x2F;p&gt;
&lt;p&gt;Lazy goes another route where it needs specific syntax to install and configure
a plugin. This is a requirement for lazy loading. This allows lazy-nvim to hook
on specific events and keymaps to launch a plugin.&lt;&#x2F;p&gt;
&lt;p&gt;The same package, configured under lazy.nvim will more look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;lazy.nvim&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;    &amp;quot;mbbill&#x2F;undotree&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lazy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E78284;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    keys&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      { &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;&amp;lt;leader&amp;gt;u&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span&gt; vim.cmd.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;UndotreeToggle&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        desc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;Show nvim undotree&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      config&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E78284;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice the specific syntax to setup new keybindings, it allows lazy-nvim to
bind those keys to the loading of the plugin, thus supporting lazy loading.&lt;&#x2F;p&gt;
&lt;p&gt;It highlights a couple of struggles I had with lazy-nvim:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Documentation is sparse while requiring a mental model shift&lt;&#x2F;li&gt;
&lt;li&gt;This syntax being non-standard does result in a ecosystem split&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;At least while I become familiar with lazy-nvim, this causes some difficulties
when configuring unknown plugins where I need to understanding
the specifics of a plugin and them map this to the proper lazy-nvim syntax.
This is similar to the layered configuration issue Nix packages have.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, during first setup it was not very clear from the documentation the
difference between &lt;code&gt;init&lt;&#x2F;code&gt;, &lt;code&gt;config&lt;&#x2F;code&gt;, &lt;code&gt;setup&lt;&#x2F;code&gt;, &lt;code&gt;opts&lt;&#x2F;code&gt; &amp;amp; &lt;code&gt;main&lt;&#x2F;code&gt;. I should
probably open a pull request to add some concrete examples, this would help the
understanding.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I am keeping Lazy-nvim for now, it is a great package manager. I am a bit
afraid of the day I&#x27;ll need to move out of it, given it&#x27;s configuration
lock-in. I haven&#x27;t tested the auto-reload feature which seems very interesting.&lt;&#x2F;p&gt;
&lt;p&gt;You can see my nvim configuration at: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimtion&#x2F;dotfiles&#x2F;tree&#x2F;master&#x2F;.config&#x2F;nvim&quot;&gt;dimtion&#x2F;dotfiles&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The magic of no maintenance</title>
        <published>2023-07-24T00:00:00+00:00</published>
        <updated>2023-07-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/the-magic-of-no-maintenance/"/>
        <id>https://dimtion.fr/blog/the-magic-of-no-maintenance/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/the-magic-of-no-maintenance/">&lt;p&gt;Recently, I&#x27;ve been revisiting some of my old side projects. I&#x27;m in the process
of consolidating all those projects onto a single server. This would help with
cost of managing all of them, and also merge all the Apache2, nginx, Traefik,
uwsgi, actix-web, and whatnot web servers configurations I tried over the last
10 years. This project is quite satisfying and feels like a form of
introspection on the different things and technologies I tried in my free time
over the years.&lt;&#x2F;p&gt;
&lt;p&gt;I thank my past self for simplifying projects on-boarding: most projects do
have a Makefile and a &lt;code&gt;deploy.sh&lt;&#x2F;code&gt; file to manage build, run, and deployment. It
makes wrapping one&#x27;s head around a forgotten project straightforward.
Most of those projects only had a single developer working on them, though, it
remains valuable to have a consistent entrypoint to spin up a polyglot tech
stack.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;There is one hurdle I encountered though, independently of what package manager
I would use, nearly none of the projects I worked on builds or runs on the
first try. There would always be a dependency that is no longer available or
incompatible with the toolchain I have on my computer in 2023. And then,
upgrading that dependency becomes a game of whack-a-mole between upgrading to a
recent-enough version, but not needing to upgrade peer-dependencies that are now
no longer compatible with those breaking changes.&lt;&#x2F;p&gt;
&lt;p&gt;In that context, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;semver.org&#x2F;&quot;&gt;semver&lt;&#x2F;a&gt; is of no help. Anything can be a
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;1172&#x2F;&quot;&gt;breaking change&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Vagrant, Cargo, requirement.txt, Opam, Dockerfile, npm, yarn, all would fail in
one way or another.&lt;&#x2F;p&gt;
&lt;p&gt;A couple of projects did build and run on the first try, and the satisfaction of
seeing the programs run without a hassle was kind of similar to doing a strike
at bowling on the first try!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;There is one exception though, and it would be for Go projects. If anything Go
got right for long-term maintainability, it would be dependency management.
Contrary to other dependency managers, go-pkg downloads the source code locally
and stores it on disk. Come back 1, 5 or 10 years later a go project will
build (assuming that the compiler remains the same).&lt;&#x2F;p&gt;
&lt;p&gt;There is a tension though, go-pkg is not the only package manager to download
the dependencies locally (all of them do it one way or another). However, given
the size of those dependencies in other languages (e.g. &lt;code&gt;node_modules&lt;&#x2F;code&gt;) go is
one of the only languages where it is considered good practice to checkout the
vendors to the VCS.&lt;&#x2F;p&gt;
&lt;p&gt;This might be utopian, but the take-out is that for small side projects to
remain maintainable over the years, strive to have all the code checked-out in
the VCS, and keep them small.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why Large Language Models Won&#x27;t Fix Google</title>
        <published>2023-04-02T00:00:00+00:00</published>
        <updated>2023-04-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/llm-google/"/>
        <id>https://dimtion.fr/blog/llm-google/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/llm-google/">&lt;p&gt;It is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=30347719&quot;&gt;common&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=29772136&quot;&gt;meme&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=29392702&quot;&gt;that&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=30946792&quot;&gt;Google&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=32201420&quot;&gt;Search&lt;&#x2F;a&gt; results quality has declined through the years.
Despite being sold by many as such, Large Language Models
(LLMs) such as ChatGPT, Bing Chat and Bard are not on a course to improve
search engines. This is not just a technical issue, but a fundamental
misunderstanding of the environment in which search engines operate.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s tackle the obvious technical limitation right away: LLMs are just
statistical token predictors. Even though they do exhibit &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2303.12712&quot;&gt;emergent properties&lt;&#x2F;a&gt;,
it is crucial to understand that their objective function is not to achieve a
reasonable truth, but rather to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Autoregressive_model&quot;&gt;predict&lt;&#x2F;a&gt; the most probable token in a sequence
based on their embedded space. In other words, if the dataset on which the
model is trained is not more &lt;em&gt;accurate&lt;&#x2F;em&gt; than the index of named search engine, no
valuable gain can be expected.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Google, being the most used search engine ever, is currently the most exposed
it ever has been to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;0xgaut&#x2F;status&#x2F;1641619593830514688&quot;&gt;SEO manipulation&lt;&#x2F;a&gt;. It is slowly losing the war on organic
content despite billions spent by the company on counter measures.&lt;&#x2F;p&gt;
&lt;p&gt;Today, ChatGPT&#x27;s exceptional ability to produce organic responses to simple
requests, demonstrates that there might be a door to a world where algorithmic
search is a problem under control. Despite
tendencies to hallucinate &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;archive.ph&#x2F;dDjke&quot;&gt;obviously&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mashable.com&#x2F;article&#x2F;google-bard-james-webb-telescope-false-fact&quot;&gt;non-obviously&lt;&#x2F;a&gt;
responses, those seem more related to the fact that data is missing from the
training set than because of malice.&lt;&#x2F;p&gt;
&lt;p&gt;This fundamentally is incorrect. ChatGPT outputs seemingly looking more organic is only due
to the fact that SEO adversarial actors have not yet caught up on how to
exploit the training, fine tuning and prompt engineering powering the
tech. Especially not at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.searchmysite.net&#x2F;posts&#x2F;almost-all-searches-on-my-independent-search-engine-are-now-from-seo-spam-bots&#x2F;&quot;&gt;industrial levels&lt;&#x2F;a&gt;
at which Google is fighting against.&lt;&#x2F;p&gt;
&lt;p&gt;Alas, our short internet memory already forgot why page-rank was considered as
revolutionary when Google was first introduced to the world: it was much more
difficult to deceive than competitive search engines.&lt;&#x2F;p&gt;
&lt;p&gt;In a world where a ChatGPT becomes the most common gateway to access the web,
adversarial actors will quickly catch up on its limits, and we&#x27;ll be back to
the good ol&#x27; mediocre results.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The more important reason why search engine accuracy has declined is due the
pressure to generate profits. Google, as a publicly traded company, derives
most of its revenue from advertising. This means that there is a financial
incentive to prioritize ads over organic search results. This has resulted over
the years in more ads appearing in search results, which can push down organic
results.&lt;&#x2F;p&gt;
&lt;p&gt;LLMs, however, do not face the same pressure to generate profits. At least not
yet. They are still seen as a technology that is being developed and improved,
and as such, they are not under the same financial pressure as traditional
search engines. However, this is likely to change once LLMs become more widely
adopted. At that point, they will face the same pressure to generate profits as
traditional search engines. This means that LLMs will likely start to
prioritize ads over organic response, just like traditional search engines.&lt;&#x2F;p&gt;
&lt;p&gt;Appendix: This is only the beginning: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;debarghya_das&#x2F;status&#x2F;1640892791923572737&quot;&gt;https:&#x2F;&#x2F;twitter.com&#x2F;debarghya_das&#x2F;status&#x2F;1640892791923572737&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;!--

In conclusion I&#x27;d like to leave the last word to ChatGPT:

&gt; Large language models are not the silver bullet for fixing
&gt; search engines. While they may improve search accuracy in the short term, they
&gt; will not be able to do so in the long run. This is because LLMs are designed to
&gt; assist search engines, not replace them. They are an add-on tool that can help
&gt; improve search results, but they cannot replace the search algorithm entirely.
&gt; Furthermore, as we have seen, LLMs are not immune to the same problems that
&gt; traditional search engines face, such as SEO optimization and profitability.
&gt; Therefore, we should not rely solely on LLMs to fix search engines. Instead, we
&gt; need to continue to develop and improve the search algorithms themselves, while
&gt; also using LLMs as a complementary tool.

## Scratchpad

TODO:
- [ ] Even if LLM search could magically be orders of magnitude cheaper than
  Page-rank like, this will not solve the profitability issue
- [ ] There is hope: there could be a paradism change in a world of
  generative ai
- [ ] Don&#x27;t forget that a lot of LLM usage is backing the prompt or fine-tune
  with &quot;old-school&quot; search engine

--&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Hold your left</title>
        <published>2022-02-03T00:00:00+00:00</published>
        <updated>2022-02-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/tips-invert-conditions/"/>
        <id>https://dimtion.fr/blog/tips-invert-conditions/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/tips-invert-conditions/">&lt;p&gt;&lt;em&gt;Error handling is hard&lt;&#x2F;em&gt;. When writing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Machine_learning&quot;&gt;throwable
code&lt;&#x2F;a&gt;, and requirements are unmet, developers generally
glance over error handling and let the script crash. However, when writing
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;ProgrammerHumor&#x2F;comments&#x2F;gf4ujl&#x2F;production_ready&#x2F;&quot;&gt;production-ready&lt;&#x2F;a&gt;
code, error handling oftentimes makes up the bulk of the source code. This has
a non-trivial impact on readability, maintainability, and debugging.&lt;&#x2F;p&gt;
&lt;p&gt;In this article, we&#x27;ll explore two very simple tricks that will help make
error-handling a breathe.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-first-example&quot;&gt;A first example&lt;&#x2F;h2&gt;
&lt;p&gt;Consider the following &lt;code&gt;update_item&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;VALID_STATUS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;ON&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;OFF&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; update_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Item&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;Update an item owned by a tenant with a new status&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;is_authorized&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        try&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; db&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;fetch_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; !item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;is_locked&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                if&lt;&#x2F;span&gt;&lt;span&gt; new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; VALID_STATUS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                    if&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;owner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span&gt; tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; new_status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; db&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;persist_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                        return&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                    else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Tenant does not own item&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                    raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; ValueError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Invalid status &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;            else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;                raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Cannot update a locked item&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        except&lt;&#x2F;span&gt;&lt;span&gt; UnknownItemException&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;            raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Cannot find item &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        except&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; ConnectionError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;            raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Error connecting to the database&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Owner is not authorized to update statuses&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code looks complicated, however, it does something simple: given a set of
business rules and user inputs, it fetches an &lt;code&gt;item&lt;&#x2F;code&gt;, check that the input is
valid and the conditions are met, and then update and persist the item.&lt;&#x2F;p&gt;
&lt;p&gt;To help refactor this code, we&#x27;ll introduce a set of rules:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rule 1: Hold your left&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rule 2: Happy path last comes last&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s jump to them and explore some examples.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rule-1-hold-your-left&quot;&gt;Rule 1: Hold your left&lt;&#x2F;h2&gt;
&lt;p&gt;This rule boils down to: when entering a conditional block, you should write as
few code as possible in the nested block, and try to bail out of the block as
soon as possible.&lt;&#x2F;p&gt;
&lt;p&gt;For example, instead of writing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; business_rule&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;        execute_routine_1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;        execute_routine_2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;        execute_routine_3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;        execute_routine_4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;        execute_routine_5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Write:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; !business_rule&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;    execute_routine_1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;    execute_routine_2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;    execute_routine_3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;    execute_routine_4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;    execute_routine_5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here the bulk of the code is located outside of the nested block. Making the
average line length shorter.&lt;&#x2F;p&gt;
&lt;p&gt;Following this rule will help remove nested blocks that are hard to follow.
Each nested block is a new state to keep in mind, which makes reasoning about
the code more complicated.&lt;&#x2F;p&gt;
&lt;p&gt;Having most of the code outside of a nested block will help the maintainer or
reviewer to understand what the code is actually about.&lt;&#x2F;p&gt;
&lt;p&gt;This rule alone is not enough to make our code more maintainable, we need to
combine it with rule 2.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-happy-path-comes-last&quot;&gt;2. Happy path comes last&lt;&#x2F;h2&gt;
&lt;p&gt;This rule is two-fold: following it will help implement code that respects
rule one. But more importantly, this rule improves code quality by making the
developer stop and think about edge cases first. The assumption being: you are
very unlikely to forget to implement the happy path, this is what stakeholders
will look at first, however, edge cases could be forgotten if their
implementation is pushed at the bottom of a function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; push_ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; Ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; speed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;notify&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Speed must be positive&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Following rule 1, we could refactor this code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; push_ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; Ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; speed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;notify&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;       return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;   # Unecessary else, hold your left!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;   raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Speed must be positive&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With rule 1 &amp;amp; 2 in mind, we can then invert the if condition, to push the happy
path at the bottom of our code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; push_ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; Ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;    # Check for the edge case first:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Speed must be positive&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;speed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; speed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;notify&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the happy path on the left-most column, it becomes obvious where to look
for the main action of a function: &lt;strong&gt;bottom-left of any code block&lt;&#x2F;strong&gt;. This can seem
counter-intuitive since the visual cortex generally scans text from top-left to
bottom-right, but you&#x27;ll notice that functions following rules 1 and 2 won&#x27;t
have a lot of nested code: the happy path will always be easy to find when you
know where to look for it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-rewrite-our-first-example&quot;&gt;Let&#x27;s rewrite our first example&lt;&#x2F;h2&gt;
&lt;p&gt;With those rules in mind, let&#x27;s rewrite our original function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;VALID_STATUS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;ON&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;OFF&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; update_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;Update an item owned by a tenant with a new status&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;    # Execute validation linearly:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; !tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;is_authorized&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Owner is not authorized to update statuses&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  # Declare item in the outerscope&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    try&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; db&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;fetch_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span&gt; UnknownItemException&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Cannot find item &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; ConnectionError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Error connecting to the database&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;is_locked&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Cannot update a locked item&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; not in&lt;&#x2F;span&gt;&lt;span&gt; VALID_STATUS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; ValueError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Invalid status &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;owner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span&gt; tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Tenant does not own item &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;    # Finally run happy path:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; new_status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; db&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;persist_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll notice that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The code is vertically longer, but horizontally narrower&lt;&#x2F;li&gt;
&lt;li&gt;Even if the code is longer, it is easier to follow: no nested conditions, can
be read in a linear fashion&lt;&#x2F;li&gt;
&lt;li&gt;The happy path is literally the last lines of the block, at the bottom of function&lt;&#x2F;li&gt;
&lt;li&gt;Conditions that are related are visually grouped using vertical &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.c2.com&#x2F;?SyntacticallySignificantWhitespaceConsideredHarmful&quot;&gt;white space
management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;a-mental-model-fence-oriented-programming&quot;&gt;A mental model: fence oriented programming&lt;&#x2F;h2&gt;
&lt;!-- 
&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;dimtion.fr&amp;#x2F;processed_images&amp;#x2F;interactive-sports-VYTQNnaboUA-unsplash.1443b96b00d1c041.jpg&quot; &#x2F;&gt;
 --&gt;
&lt;p&gt;One way to mentally visualize this coding pattern is to view each &lt;code&gt;if&lt;&#x2F;code&gt;
statement as a
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;G._K._Chesterton#Chesterton&amp;#x27;s_fence&quot;&gt;fence&lt;&#x2F;a&gt; (or
guard) that needs to be passed before continuing execution. Each fence insure
that a requirement is met before executing the
happy path. Adding or removing a requirement is simply adding or removing a new
fence.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         FENCE                      FENCE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|       |    &#x2F;             ||           &#x2F;             ||           &#x2F;                \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| start | -&amp;gt; | condition A || -- yes -&amp;gt; | condition B || -- yes -&amp;gt; | Execute action |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|       |    \     met?    ||           \    met?     ||           \                &#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            |                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            -- no -&amp;gt; | abort |         -- no -&amp;gt; | abort |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This mental model is similar to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fsharpforfunandprofit.com&#x2F;rop&#x2F;&quot;&gt;Railway Oriented
Programming&lt;&#x2F;a&gt; in functional
programming languages.&lt;&#x2F;p&gt;
&lt;p&gt;By following the two above rules, reading a piece of code the feels just like
reading a checklist of conditions to met before executing the happy path.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;update-item-checklist&quot;&gt;&lt;code&gt;update_item&lt;&#x2F;code&gt; checklist&lt;&#x2F;h3&gt;
&lt;p&gt;To learn fence oriented programming, one way is to write our code in a form of a checklist:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;☑️ Is &lt;code&gt;tenant&lt;&#x2F;code&gt; authorized to update statuses?&lt;&#x2F;li&gt;
&lt;li&gt;☑️ Is the &lt;code&gt;item&lt;&#x2F;code&gt; present in the database?&lt;&#x2F;li&gt;
&lt;li&gt;☑️ Was reading from the database successful?&lt;&#x2F;li&gt;
&lt;li&gt;☑️ Is the item unlocked?&lt;&#x2F;li&gt;
&lt;li&gt;☑️ Is the input status a valid status?&lt;&#x2F;li&gt;
&lt;li&gt;☑️ Is the tenant the owner of the item?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Writing the business logic as a checklist makes writing the code trivial then,
just a set of instructions to follow!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus-benefit-trivial-conditional-reordering&quot;&gt;Bonus benefit: trivial conditional reordering&lt;&#x2F;h2&gt;
&lt;p&gt;Some of you might have noticed, there is a minor bug in the code example
presented: &lt;code&gt;status&lt;&#x2F;code&gt; validation is executed after item retrieval, even if the item
is not needed to check the validity of the input. Depending on the database
technology and the service architecture, this could become a potential attack
vector against our service. For example, an attacker could execute a large
number of queries against our service with invalid statuses, hammering the
database with unnecessary queries.&lt;&#x2F;p&gt;
&lt;p&gt;Ignoring &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Timing_attack&quot;&gt;timing-based side-channel
attacks&lt;&#x2F;a&gt;, a simple fix would be to
reorder the checks by first doing the status validation, then fetch the item in
the database.&lt;&#x2F;p&gt;
&lt;p&gt;Using the inverted condition pattern, this reordering is as simple as moving
lines around in our function. while with our first example, doing such would
be a dance of moving the correct &lt;code&gt;if&#x2F;else&lt;&#x2F;code&gt; condition and correctly matching
indentation...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;VALID_STATUS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;ON&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; &amp;quot;OFF&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt; update_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt;tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EA999C;font-style: italic;&quot;&gt; new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;font-style: italic;&quot;&gt; str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Item&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;Update an item owned by a tenant with a new status&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;   # Executing input validation before authorization and consistency checks:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;   if&lt;&#x2F;span&gt;&lt;span&gt; new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; not in&lt;&#x2F;span&gt;&lt;span&gt; VALID_STATUS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;       raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; ValueError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Invalid status &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;new_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;    # Execute validation linearly:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; !tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;is_authorized&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Owner is not authorized to update statuses&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;  # Declare item in the outerscope&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    try&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; db&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;fetch_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span&gt; UnknownItemException&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Cannot find item &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; ConnectionError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Error connecting to the database&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;is_locked&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Cannot update a locked item&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #C6D0F512;&quot;&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;owner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span&gt; tenant&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EF9F76;font-style: italic;&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;Tenant does not own item &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;item_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;    # Finally run happy path:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; new_status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; db&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8CAAEE;&quot;&gt;persist_item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span style=&quot;color: #949CBB;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using Git Efficiently</title>
        <published>2021-01-05T00:00:00+00:00</published>
        <updated>2021-01-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://dimtion.fr/blog/average-engineer-tips/"/>
        <id>https://dimtion.fr/blog/average-engineer-tips/</id>
        
        <content type="html" xml:base="https://dimtion.fr/blog/average-engineer-tips/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;There was a debate a few months back on Twitter about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;dmartincy&#x2F;status&#x2F;1150156226761830400&quot;&gt;10x
developers&lt;&#x2F;a&gt;, if they
exist, what is the definition of such unicorn, or even if 10x developers are
only bad developers who simply look good to management.&lt;&#x2F;p&gt;
&lt;p&gt;The truth is, without any prior knowledge, if we assume that &lt;em&gt;effectiveness&lt;&#x2F;em&gt;
can be measured (whatever definition you want to put in that word), this
distribution will most likely follow a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Normal_distribution&quot;&gt;bell
curve&lt;&#x2F;a&gt; over engineers.
You the reader, and I the writer, are mathematically most likely to be in the
middle of the curve. In other words: we are average developers.&lt;&#x2F;p&gt;
&lt;p&gt;If I, an average developer, want to get more &lt;em&gt;effective&lt;&#x2F;em&gt;, instead of only
looking up at highly effective developers, we need to understand the
characteristics of an average developer. This allows us to overcome the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Survivorship_bias&quot;&gt;survivorship bias&lt;&#x2F;a&gt; when
fishing for advice.&lt;&#x2F;p&gt;
&lt;p&gt;What would an average developer look like? Depending on your definition of
&lt;em&gt;effective&lt;&#x2F;em&gt;, it could mean:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A developer that regularly makes mistakes, probably mostly stupid errors:
forgetting to push a file, adding a typo when fixing another typo, forgetting
to refresh the Github page when going through the review comments&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A developer that delivers average code: code that does the job but no more
no less, code that doesn&#x27;t handle all error cases, code that is readable but
not necessarily straightforward&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A developer that reads, reviews, and edits code written by other average
developers: code that should have been refactored 10 years ago, that was
designed in a rush for its initial use case, and is now stretched out to
its inflection point&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A developer that works in an average company that doesn&#x27;t follow every
best practice, a company that needs every new feature for yesterday&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you recognize yourself in one of those bullet points, congratulation, you
are an average developer! (Spoiler: everybody is average, just select your
metric accordingly).&lt;&#x2F;p&gt;
&lt;p&gt;That said, there are heuristics you can follow to look less average within
your peers, these tips won&#x27;t make you make fewer mistakes, or make you smarter
&lt;em&gt;per se&lt;&#x2F;em&gt;, but following them will help you introspect your biases and become a
better engineer.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve tried to make them as practical as possible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;part-1-using-git-effectively&quot;&gt;Part 1: Using git effectively&lt;&#x2F;h2&gt;
&lt;p&gt;This is probably the most important advice, doing pair-coding with junior
developers, I&#x27;ve seen so many instances of the following anti-pattern:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;change a file&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:wq &amp;lt;quit text editor&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git add -A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git commit -m &amp;quot;Fix typo&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git push&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;Click on re-request review on github&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is probably the worse set of commands you can run, 95% percent of the time
you will look fast and swift, but in the 5 other percent, you will look like a
fool in front of your colleague reviewing your pull request.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s break it down to a more careful and methodic way to create new commits.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tip-1-proofread-when-stashing-changes&quot;&gt;Tip 1: Proofread when stashing changes&lt;&#x2F;h3&gt;
&lt;p&gt;The first advice is to never, &lt;strong&gt;ever&lt;&#x2F;strong&gt;, use &lt;code&gt;git add -A&lt;&#x2F;code&gt;. With &lt;code&gt;-A&lt;&#x2F;code&gt; parameter
you never know what you are committing, you could still have a debug statement
remaining, forgot to clean up the last issue you were working on, or simply
staging files you don&#x27;t mean to commit.&lt;&#x2F;p&gt;
&lt;p&gt;When you create a commit, not only make sure to know exactly which file you are
committing, but also make sure you have read each line before staging them. A
great tool to use is git with &lt;code&gt;git add -p&lt;&#x2F;code&gt; or &lt;code&gt;git add --patch&lt;&#x2F;code&gt; in its long-form.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Prefer patch mode over --all:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; add -p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;-p&lt;&#x2F;code&gt; parameter allows you to visualize each patch of a commit you are going
to create. You&#x27;ll know exactly which change you are going to commit. Make
sure you are reading every single line of each patch!&lt;&#x2F;p&gt;
&lt;p&gt;In particular, before adding a patch, look carefully for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Typos in variable names&lt;&#x2F;li&gt;
&lt;li&gt;Remaining debug statements&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;TODO&lt;&#x2F;code&gt; statements&lt;&#x2F;li&gt;
&lt;li&gt;Read the surrounding comments and docstrings: are they still relevant and
correct with the changes you are about to commit?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Once you have staged your changes, don&#x27;t hesitate to have a quick glance at the
changes you made by running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Changes staged for commit:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; diff --staged&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Changes not staged for commit:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; diff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make sure that you did not forget any new file in the staging area!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tip-2-force-yourself-to-write-effective-git-messages&quot;&gt;Tip 2: force yourself to write effective git messages&lt;&#x2F;h3&gt;
&lt;p&gt;Now that you have reviewed the changes you made, you are ready to create a new
commit. Here again, I advise against using any shortcut like &lt;code&gt;git commit -m&lt;&#x2F;code&gt;.
Even if &lt;code&gt;-m&lt;&#x2F;code&gt; is swift, it encourages the developer to write unhelpful commit
messages.&lt;&#x2F;p&gt;
&lt;p&gt;Prefer to use &lt;code&gt;git commit&lt;&#x2F;code&gt; in verbose mode:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Always use verbose mode:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; commit -v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When writing a meaningful commit message, you will be able to see the full
change that will be created. This serves two functions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure again at a glance that you are committing what you want to commit.
You don&#x27;t need to read every line, that was done during staging, but have a
glance at the patch and trust your subconscious mind to spot any irregularity&lt;&#x2F;li&gt;
&lt;li&gt;When writing a commit message, you now have under your eyes the changes you
are about to commit. This is a great way to write a relevant commit message.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;There are already a ton of articles on how to write a great commit message, so I
won&#x27;t spend too much time on that. Basically, those good ideas can be summarized
to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Be consistent in the formatting, if possible have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.conventionalcommits.org&#x2F;en&#x2F;v1.0.0&#x2F;&quot;&gt;a
convention&lt;&#x2F;a&gt; with your team on
how commit messages should be formated&lt;&#x2F;li&gt;
&lt;li&gt;Have a commit title that explains &lt;em&gt;what&lt;&#x2F;em&gt; has been changed&lt;&#x2F;li&gt;
&lt;li&gt;When necessary have a commit body that explains &lt;em&gt;why&lt;&#x2F;em&gt; those changes have been made&lt;&#x2F;li&gt;
&lt;li&gt;Have in the title or the body of the message a reference to your project bug tracker&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When creating the commit message, especially for trivial changes, resist the
urge to set an irrelevant commit title like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fix typo&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pr changes&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;review ~1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;review ~2&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You don&#x27;t need to have a long commit message with a full body for each change,
especially if the patch is trivial. Try to force yourself to always write a
relevant commit message. This might take 5 seconds more than simply writing
&lt;code&gt;fix&lt;&#x2F;code&gt;, but this will save countless time when another teammate will find the
source of a bug in a tree of 10 000 commits.&lt;&#x2F;p&gt;
&lt;p&gt;Here are examples of better commit titles for trivial changes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;scheduler: typo rename actionHander to actionHandler&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;PROJ-12031 core: simplify deduplicate_str() implementation&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tip-3-never-ever-ever-use-push-force&quot;&gt;Tip 3: Never, ever, ever, use push --force`&lt;&#x2F;h3&gt;
&lt;p&gt;Your commit is now created locally. You can now push your changes with &lt;code&gt;git push&lt;&#x2F;code&gt;  or &lt;code&gt;git push -u origin &amp;lt;branch-name&amp;gt;&lt;&#x2F;code&gt; if you are creating a new branch.&lt;&#x2F;p&gt;
&lt;p&gt;If you really need to push force (after a &lt;code&gt;git commit -v --amend&lt;&#x2F;code&gt; or a &lt;code&gt;git rebase&lt;&#x2F;code&gt; for example) prefer &lt;code&gt;git push --force-with-lease&lt;&#x2F;code&gt; over &lt;code&gt;git push --force&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Amend some changes to an existing commit:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; commit -v --amend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Never push force:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; push --force-with-lease&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;with &lt;code&gt;force-with-lease&lt;&#x2F;code&gt;, if the remote branch has been modified from you last fetch,
git will not override the changes.  This is a great failsafe to avoid
overwriting one of your colleagues&#x27; work.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tip-4-proof-read-again-and-again&quot;&gt;Tip 4: Proof read again, and again&lt;&#x2F;h3&gt;
&lt;p&gt;If your team is using Github, when creating the Pull Request don&#x27;t hesitate to
give a last glance at the diff, seeing your change in another context than your
text editor is a great way to catch last minutes typos.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automate-your-git-workflow&quot;&gt;Automate your git workflow&lt;&#x2F;h2&gt;
&lt;p&gt;Depending on which language you are developing in, the compiler might not be
bundled with static analysis that could catch common pitfalls. For those
languages, you might already rely on a linter on top of your test suite.&lt;&#x2F;p&gt;
&lt;p&gt;Linters not only serve the role of catching code errors or style violations,
but they are also a great source of information for learning to write idiomatic
code.&lt;&#x2F;p&gt;
&lt;p&gt;This article is not about linters (that a topic for another day), however,
integrating linting and testing to your git workflow allows you to catch linter
errors sooner rather than later.&lt;&#x2F;p&gt;
&lt;p&gt;Git has a feature called
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Customizing-Git-Git-Hooks&quot;&gt;hooks&lt;&#x2F;a&gt; that allows a
developer to do actions based on different events. Those events could be
creating a new commit, pulling or pushing some changes, etc...&lt;&#x2F;p&gt;
&lt;p&gt;For example, to run your lint suite before each commit:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; EOF&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; .git&#x2F;hooks&#x2F;pre-commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;exec make lint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;chmod&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; +x .git&#x2F;hooks&#x2F;pre-commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From now on, from now on, your lint suite run each time you create a new
commit.&lt;&#x2F;p&gt;
&lt;p&gt;There are some cases when you don&#x27;t want to run the lint suite. This can be if
you know it will fail, or only want to create a temporary commit. You can skip
the hook by adding &lt;code&gt;-n&lt;&#x2F;code&gt; to &lt;code&gt;git commit&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Skip hook and commit in verbose mode:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8CAAEE;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt; commit -v -n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If your test suite is fast enough, you can also add it to a git pre-commit hook.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;you-don-t-need-to-type-that-much&quot;&gt;You don&#x27;t need to type that much&lt;&#x2F;h2&gt;
&lt;p&gt;You might have noticed, all those pieces of advice are here to slow you down
and try to give your &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Dual_process_theory&quot;&gt;system
2&lt;&#x2F;a&gt; more chances to engage.
Most mistakes happen because we are overconfidently only relying on our system 1.
However &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cacm.acm.org&#x2F;magazines&#x2F;2021&#x2F;8&#x2F;254304-what-does-saying-that-programming-is-hard-really-say-and-about-whom&#x2F;fulltext&quot;&gt;programming is
hard&lt;&#x2F;a&gt;,
and your System 1 has not evolved for to solve hard problems.&lt;&#x2F;p&gt;
&lt;p&gt;That said, you need to slow down your mind, but not necessarily your fingers.
And to avoid that and help build these habits I suggest you create bash aliases
for all those git commands. Here is an excerpt of my shell configuration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #C6D0F5; background-color: #303446;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# ~&#x2F;.bashrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; gs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git status&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; gd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git diff&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; gds&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git diff --staged&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; ga&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git add --patch&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; gc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git commit --verbose&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; gp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git push&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; gpf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git push --force-with-lease&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #949CBB;font-style: italic;&quot;&gt;# Push a new branch:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CA9EE6;&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span&gt; gpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81C8BE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;git push --set-upstream origin &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;\`&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;git rev-parse --abbrev-ref HEAD&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F4B8E4;&quot;&gt;\`&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6D189;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note the use of long-form parameters in scripts, this is a great way to
self-document each parameter.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This was part one of my serie of highly effective and practical tips to become
a better engineer. I have many more areas of engineering to cover, so stay
tuned for more tips on software engineering.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
