<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <description> </description>
    <link>https://www.hodler.co/</link>
    <atom:link href="https://www.hodler.co/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>The years 2023-2025 in books</title>
        <description>&lt;p&gt;Books read between 2023 and 2025.&lt;/p&gt;

&lt;p&gt;Again. Close to zero commute if we discard planes. And less of an interest in reading books in general. A trend I’ll reverse in 2026.&lt;/p&gt;

&lt;p&gt;As previously I’ll rate the books from one to three stars. Three of three (3/3) stars being what I thoroughly have enjoyed and would recommend to others who are into the topic of the book or enjoy a good read in general. Giving a book one star neither states the book is bad or I do not agree with it, rather it is something I personally did not enjoy too much.&lt;/p&gt;

&lt;h2 id=&quot;2023&quot;&gt;2023&lt;/h2&gt;

&lt;h3 id=&quot;project-hail-mary---andy-weir-33&quot;&gt;Project Hail Mary - Andy Weir (3/3)&lt;/h3&gt;

&lt;p&gt;Plain amazing. Made the flight from El Salvador back to Germany fly by like nothing.&lt;/p&gt;

&lt;h3 id=&quot;when-money-dies---adam-fergusson-23&quot;&gt;When Money Dies - Adam Fergusson (2/3)&lt;/h3&gt;

&lt;p&gt;The inflationary spiral in Austria after WW2. Often recommended in Bitcoin circles.&lt;/p&gt;

&lt;h3 id=&quot;heat-2---michael-mann-23&quot;&gt;Heat 2 - Michael Mann (2/3)&lt;/h3&gt;

&lt;p&gt;Had to read it as I’m a huge fan of the 1995 movie &lt;a href=&quot;https://www.imdb.com/title/tt0113277/&quot;&gt;Heat&lt;/a&gt;.
Lots of good parts. I’m waiting for the upcoming movie.&lt;/p&gt;

&lt;h3 id=&quot;elon-musk---walter-isaacson-33&quot;&gt;Elon Musk - Walter Isaacson (3/3)&lt;/h3&gt;

&lt;p&gt;Inspiring. And insane how much the contents would have to be expanded to contain what has happened in the years after the publish date.&lt;/p&gt;

&lt;h3 id=&quot;fahrenheit-451---ray-bradbury-23&quot;&gt;Fahrenheit 451 - Ray Bradbury (2/3)&lt;/h3&gt;

&lt;p&gt;Quick read on censorship.&lt;/p&gt;

&lt;h2 id=&quot;2024&quot;&gt;2024&lt;/h2&gt;

&lt;h3 id=&quot;wild---cheryl-strayed-23&quot;&gt;Wild - Cheryl Strayed (2/3)&lt;/h3&gt;

&lt;p&gt;Back in 2014 I watched the &lt;a href=&quot;https://www.imdb.com/title/tt2305051&quot;&gt;movie&lt;/a&gt;. Didn’t realize it was based on a book back then. Good read!&lt;/p&gt;

&lt;h3 id=&quot;seveneves---neal-stephenson-23&quot;&gt;Seveneves - Neal Stephenson (2/3)&lt;/h3&gt;

&lt;p&gt;The whole story and idea is awesome. Would be a 3/3 but the beginning was quite slow and the end too boring for my taste.&lt;/p&gt;

&lt;p&gt;The slow beginning led me to only finish the book on my third attempt. I tried to read it 2 times in the last 10 years.&lt;/p&gt;

&lt;h2 id=&quot;2025&quot;&gt;2025&lt;/h2&gt;

&lt;p&gt;Only one. But a great one. One of the greatest I have read.&lt;/p&gt;

&lt;h3 id=&quot;musashi---eiji-yoshikawa-33&quot;&gt;Musashi - Eiji Yoshikawa (3/3)&lt;/h3&gt;
&lt;p&gt;Life and deeds of swordsman Miyamoto Musashi.&lt;/p&gt;

&lt;p&gt;In 2021 I read about half of Taiko. Same author. Published 2 years after Musashi in 1937. Back then some suggested to do it before Musashi to be historically aligned. Taiko takes place before Musashi. I don’t think this is necessary. Musashi was the superior book.&lt;/p&gt;

&lt;p&gt;Even if one doesn’t read Musashi it makes sense to look at his rules:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Accept everything just the way it is&lt;/li&gt;
  &lt;li&gt;Do not seek pleasure for its own sake&lt;/li&gt;
  &lt;li&gt;Do not depend on partial feelings&lt;/li&gt;
  &lt;li&gt;Think lightly of yourself and deeply of the world&lt;/li&gt;
  &lt;li&gt;Be detached from desire throughout your life&lt;/li&gt;
  &lt;li&gt;Do not regret what you have done&lt;/li&gt;
  &lt;li&gt;Never be jealous&lt;/li&gt;
  &lt;li&gt;Never let yourself be saddened by a separation&lt;/li&gt;
  &lt;li&gt;Resentment and complaint are inappropriate&lt;/li&gt;
  &lt;li&gt;Do not let yourself be guided by lust or love&lt;/li&gt;
  &lt;li&gt;In all things, have no preferences&lt;/li&gt;
  &lt;li&gt;Be indifferent to where you live&lt;/li&gt;
  &lt;li&gt;Do not pursue the taste of good food&lt;/li&gt;
  &lt;li&gt;Do not hold onto possessions you no longer need&lt;/li&gt;
  &lt;li&gt;Do not act following customary beliefs&lt;/li&gt;
  &lt;li&gt;Do not collect weapons or practice with weapons beyond what is useful&lt;/li&gt;
  &lt;li&gt;Do not fear death&lt;/li&gt;
  &lt;li&gt;Do not seek to possess goods or fiefs for old age&lt;/li&gt;
  &lt;li&gt;Respect Buddha and the gods without counting on their help&lt;/li&gt;
  &lt;li&gt;You may abandon your own body, but preserve your honor&lt;/li&gt;
  &lt;li&gt;Never stray from the Way&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Mon, 12 Jan 2026 11:11:11 +0000</pubDate>
        <link>https://www.hodler.co/2026/01/12/years-2023-2025-in-books/</link>
        <guid isPermaLink="true">https://www.hodler.co/2026/01/12/years-2023-2025-in-books/</guid>
      </item>
    
      <item>
        <title>The year 2022 in books</title>
        <description>&lt;p&gt;Books read in 2022. Zero commute by train. When travelling, or moving, by car I find myself listening to podcasts and music rather than audiobooks. I was able to read 12 books. A lot less than in previous years.&lt;/p&gt;

&lt;p&gt;As previously I’ll rate the books from one to three stars. Three of three (3/3) stars being what I thoroughly have enjoyed and would recommend to others who are into the topic of the book or enjoy a good read in general. Giving a book one star neither states the book is bad or I do not agree with it, rather it is something I personally did not enjoy too much.&lt;/p&gt;

&lt;h3 id=&quot;argentarius---vom-gelde---33&quot;&gt;Argentarius - Vom Gelde - 3/3&lt;/h3&gt;
&lt;p&gt;The author explains to his son how money works. Written over 100 years ago. Fully applicable to today.&lt;/p&gt;

&lt;h3 id=&quot;liebe-deinen-nächsten-or-flotsam-in-english---erich-maria-remarque---33&quot;&gt;Liebe deinen Nächsten (or “Flotsam” in English) - Erich Maria Remarque - 3/3&lt;/h3&gt;
&lt;p&gt;Why the title isn’t “Treibgut” (flotsam in German) is beyond me.
Especially when reading it during evasive travels.&lt;/p&gt;

&lt;h3 id=&quot;hunger---knut-hamsun---23&quot;&gt;Hunger - Knut Hamsun - 2/3&lt;/h3&gt;
&lt;p&gt;A struggling artist in Norway. Written over 100 years ago.&lt;/p&gt;

&lt;h3 id=&quot;kinder-von-hoy---grit-lemke---23&quot;&gt;Kinder von Hoy - Grit Lemke - 2/3&lt;/h3&gt;
&lt;p&gt;An introduction to youth live in the former DDR.&lt;/p&gt;

&lt;h3 id=&quot;too-loud-a-solitude---bohumil-hrabal---13&quot;&gt;Too Loud a Solitude - Bohumil Hrabal - 1/3&lt;/h3&gt;
&lt;p&gt;The rating could be off. I wasn’t too focussed on the book while reading and found myself moving pages without remembering what is in it. Should give this another go in the future.&lt;/p&gt;

&lt;h3 id=&quot;gothic-violence---mike-ma---23&quot;&gt;Gothic Violence - Mike Ma - 2/3&lt;/h3&gt;
&lt;p&gt;Lots of short essays. Some “meh” some great.&lt;/p&gt;

&lt;h3 id=&quot;alles-was-wir-nicht-erinnern---christiane-hoffmann---23---audiobook&quot;&gt;Alles was wir nicht erinnern - Christiane Hoffmann - 2/3 - Audiobook&lt;/h3&gt;
&lt;p&gt;The author travels along the escape route of her parents from what is now Poland to their home in Germany after the second world war.&lt;/p&gt;

&lt;h3 id=&quot;the-corrections---jonathan-franzen---33&quot;&gt;The Corrections - Jonathan Franzen - 3/3&lt;/h3&gt;
&lt;p&gt;Heard it is a book you should read in your thirties. Applied to me.&lt;/p&gt;

&lt;h3 id=&quot;speculator-book-1-high-ground-series---doug-casey-and-john-hunt---23---audiobook&quot;&gt;Speculator (Book 1 High Ground Series) - Doug Casey and John Hunt - 2/3 - Audiobook&lt;/h3&gt;
&lt;p&gt;Action packed story on gold mining and speculation in Africa.&lt;/p&gt;

&lt;h3 id=&quot;drug-lord-book-2-high-ground-series---doug-casey-and-john-hunt---23---audiobook&quot;&gt;Drug Lord (Book 2 High Ground Series) - Doug Casey and John Hunt - 2/3 - Audiobook&lt;/h3&gt;
&lt;p&gt;Novel on drugs and the FDA and everything in between.&lt;/p&gt;

&lt;h3 id=&quot;the-white-pill---michael-malice---23&quot;&gt;The White Pill - Michael Malice - 2/3&lt;/h3&gt;
&lt;p&gt;A refresher on communist history from Lenin to the end of the USSR.&lt;/p&gt;

&lt;h3 id=&quot;the-stranger---albert-camus---33&quot;&gt;The Stranger - Albert Camus - 3/3&lt;/h3&gt;
&lt;p&gt;I knew nothing about the book when reading it. Luckily I did not even read the text on the back. Almost read this in one sitting. It’s great.&lt;/p&gt;

</description>
        <pubDate>Sun, 01 Jan 2023 11:11:11 +0000</pubDate>
        <link>https://www.hodler.co/2023/01/01/year-in-books-2022/</link>
        <guid isPermaLink="true">https://www.hodler.co/2023/01/01/year-in-books-2022/</guid>
      </item>
    
      <item>
        <title>On Purity</title>
        <description>&lt;h3 id=&quot;three-examples&quot;&gt;Three examples.&lt;/h3&gt;

&lt;p&gt;Is this a &lt;em&gt;pure&lt;/em&gt; function?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;num1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;num2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;num1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;num2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;How about this?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getCurrentMonthIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getMonth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Or this?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Well, what is a pure function?&lt;/p&gt;

&lt;h3 id=&quot;definition&quot;&gt;Definition&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;A function is pure when given the same input, we &lt;strong&gt;always&lt;/strong&gt; get the same output&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;example-1&quot;&gt;Example 1&lt;/h3&gt;
&lt;p&gt;Given 2 and 3 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add&lt;/code&gt; will always yield 5&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; add&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2,3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
5&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Thus ✅. A pure function&lt;/p&gt;

&lt;h3 id=&quot;example-2&quot;&gt;Example 2&lt;/h3&gt;
&lt;p&gt;Given no input &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getCurrentMonthIndex&lt;/code&gt; will return us &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9&lt;/code&gt; as long as we are in October.
As soon as we enter November it will return the number &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; getCurrentMonthIndex&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
9&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Same input - not same output.&lt;/p&gt;

&lt;p&gt;Thus ❌. Not a pure function&lt;/p&gt;

&lt;h3 id=&quot;example-3&quot;&gt;Example 3&lt;/h3&gt;

&lt;p&gt;Given the String &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;hello&quot;&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt; will always print &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;hello&quot;&lt;/code&gt; to the console.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; log&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
hello&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Same input, same output. A pure function?&lt;/p&gt;

&lt;p&gt;What if?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; const console &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;broken&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; log&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Uncaught TypeError: console.log is not a &lt;span class=&quot;k&quot;&gt;function
    &lt;/span&gt;at log &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;REPL1:1:30&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By redefining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console&lt;/code&gt; we changed the behaviour of our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt; function.
Same input. Different output. As was expected.&lt;/p&gt;

&lt;p&gt;❌ Not a pure function&lt;/p&gt;

&lt;p&gt;So - How did we find out if these functions are pure?&lt;/p&gt;

&lt;p&gt;Pretty much by reading the their implementation details.&lt;/p&gt;

&lt;p&gt;Their function body.&lt;/p&gt;

&lt;p&gt;And, of course, by testing (calling, invoking) them.&lt;/p&gt;

&lt;p&gt;Super easy to do that with one-liners. Hard with functions spanning tens, hundreds or thousands of lines in length.&lt;/p&gt;

&lt;h3 id=&quot;creating-purity&quot;&gt;Creating purity&lt;/h3&gt;

&lt;p&gt;Can we rewrite both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getCurrentMonthIndex&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt; to be pure?&lt;/p&gt;

&lt;p&gt;Of course. We only need to declare their hidden inputs.&lt;/p&gt;

&lt;p&gt;For the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getCurrentMonthIndex&lt;/code&gt; it is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new Date()&lt;/code&gt; and for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getCurrentMonthIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getMonth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getCurrentMonthIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;hello&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Is this helpful code? Is this good code?&lt;/p&gt;

&lt;p&gt;Up for the reader to decide.&lt;/p&gt;

&lt;p&gt;Have we made the hidden inputs visible?&lt;/p&gt;

&lt;p&gt;No, there is is still the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this&quot;&gt;this&lt;/a&gt; present in all JavaScript functions.
It is hidden but its there.&lt;/p&gt;

&lt;p&gt;Are the functions pure?&lt;/p&gt;

&lt;p&gt;Depends. Whether we consider them are pure or not - we probably can agree that they are &lt;em&gt;more pure&lt;/em&gt; than they were before.&lt;/p&gt;

&lt;p&gt;How did we find out if these functions are pure?&lt;/p&gt;

&lt;p&gt;We did so by reading their code. Their implementation.&lt;/p&gt;

&lt;p&gt;There is no other way of knowing!&lt;/p&gt;

&lt;p&gt;Even if we call them with multiple inputs and check the output it is hard to cover the full space of available inputs.&lt;/p&gt;

&lt;p&gt;Especially in the JavaScript case above where the input could be any type. We can add the Strings &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;4&apos; + &apos;2&apos;&lt;/code&gt; and Numbers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4 + 2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Is there an alternative where we don’t have to read the code?&lt;/p&gt;

&lt;p&gt;Let’s play with the programming language Haskell.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;n&quot;&gt;sayHello&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sayHello&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sayHello&lt;/code&gt; takes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; as an argument and returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;ghci&amp;gt; sayHello &lt;span class=&quot;s2&quot;&gt;&quot;Reader&quot;&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;Hello Reader&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;An equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.log()&lt;/code&gt; would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;putStrLn&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;ghci&amp;gt; putStrLn &lt;span class=&quot;s2&quot;&gt;&quot;Hello Reader&quot;&lt;/span&gt;
Hello Reader&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s use it inside of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sayHello&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;n&quot;&gt;sayHello&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sayHello&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;putStrLn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Running this will give us an error.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;test.hs:2:17: error:
    • Couldn&lt;span class=&quot;s1&quot;&gt;&apos;t match type: IO ()
                     with: [Char]
      Expected: String
        Actual: IO ()
    • In the expression: putStrLn (&quot;Hello &quot; ++ name)
      In an equation for ‘sayHello’:
          sayHello name = putStrLn (&quot;Hello &quot; ++ name)
  |
2 | sayHello name = putStrLn(&quot;Hello &quot; ++ name)
  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;String is expected and actual is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO ()&lt;/code&gt;. The compiler does not allow us to do that.&lt;/p&gt;

&lt;p&gt;We have to define the side-effect (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;putStrLn&lt;/code&gt;) in the function definition.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;n&quot;&gt;sayHello&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sayHello&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;putStrLn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;ghci&amp;gt; sayHello &lt;span class=&quot;s2&quot;&gt;&quot;Reader&quot;&lt;/span&gt;
Hello Reader&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So what?&lt;/p&gt;

&lt;p&gt;We don’t have to read the implementation to learn whether the function is pure or not. Only the type signature!&lt;/p&gt;

&lt;p&gt;A function taking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; as input and returning a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; as output is pure. It has to be.&lt;/p&gt;

&lt;p&gt;Haskell is considered a &lt;em&gt;purely&lt;/em&gt; functional programming language. Not because it has pure functions but because expressions in Haskell can be expressed exclusively in terms of a lambda calculus.&lt;/p&gt;

&lt;p&gt;Lambda calculus?&lt;/p&gt;

&lt;p&gt;Well, maybe something for our next post :)&lt;/p&gt;
</description>
        <pubDate>Fri, 23 Dec 2022 06:30:22 +0000</pubDate>
        <link>https://www.hodler.co/2022/12/23/purity/</link>
        <guid isPermaLink="true">https://www.hodler.co/2022/12/23/purity/</guid>
      </item>
    
      <item>
        <title>Trunk based development</title>
        <description>&lt;p&gt;At my first &lt;em&gt;real&lt;/em&gt; job, back in 2014, we were using the version control system svn for the backend. The mainline branch - think master or main in git terms - was called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trunk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every developer pushed changes straight to mainline (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trunk&lt;/code&gt;). There was no code review before adding changes to mainline. Me, having worked with git previously - in fact most projects in the company where using git already - thought this was subpar. Almost awful. Not the way things are done in modern software development.&lt;/p&gt;

&lt;p&gt;Later someone was added to the team in charge of moving us to continuous delivery. When discussing branching strategies yours truly, being an avid reader of &lt;a href=&quot;https://news.ycombinator.com/&quot;&gt;hackernews&lt;/a&gt; and all things development related, was eager to push for Gitflow.&lt;/p&gt;

&lt;p&gt;The response I got back was&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Yeah, but thats not really continuous delivery&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Boy was I shaken. Isn’t this the cool git branching model everyone is using?&lt;/p&gt;

&lt;p&gt;Back then I did not get it. Mostly because we did what most folks do. Have our own definition of what &lt;em&gt;continuous&lt;/em&gt; is supposed to be.&lt;/p&gt;

&lt;p&gt;In our case it was after every sprint. A release every two weeks - If, and only if, nothing goes wrong.&lt;/p&gt;

&lt;p&gt;Of course every two weeks is better than every few months. And every week is better than every two weeks. But not what I would consider continuous today.&lt;/p&gt;

&lt;p&gt;We ended up having feature branches, some short lived (days), some long lived (months). These changes were moved to mainline after one or more reviews.&lt;/p&gt;

&lt;p&gt;The workflow had its issues but was, from my perspective, way better than to contributing straight into mainline.&lt;/p&gt;

&lt;p&gt;Years later, when Microservices were all the rage, I watched a talk by &lt;a href=&quot;https://www.youtube.com/watch?v=lqRQYEHAtpk&amp;amp;t=2425s&quot;&gt;Sam Newman&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some of his comments on Gitflow in the talk&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Because if there is something worth doing, there is something worth doing really complicatedly&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I don’t understand all this because I’m old and quite stupid&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Every single picture that shall explain to me how Gitflow works just makes we want to kill myself&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well the last one is an exaggeration. But taking the&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I don’t understand all this because I’m old and quite stupid&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;from a guy of his calibre is quite humbling.&lt;/p&gt;

&lt;p&gt;Today I would agree.&lt;/p&gt;

&lt;p&gt;Getting to &lt;em&gt;“short lived”&lt;/em&gt; &lt;em&gt;“feature branches”&lt;/em&gt; is hard. Both due to a definition what &lt;em&gt;“short lived”&lt;/em&gt; is exactly and the common question how the whole &lt;em&gt;“feature”&lt;/em&gt; - it’s a &lt;em&gt;“feature branch”&lt;/em&gt; after all, can be implemented in a few days, or even hours.&lt;/p&gt;

&lt;p&gt;If we get quick reviews, meaning colleagues get into the review ASAP instead of once or twice a day, we might get small branches and thus small pull requests (PR)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Branch -&amp;gt; Fix a flaky test -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Fix a typo in the docs -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Refactor a method name -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Create the DB migration for the feature -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Add a failing, ignored, acceptance test for the feature -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; […] -&amp;gt; PR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if we have feature toggles in place like&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_user_sees&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;our_awesome_future_feature&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;show_new_feature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and thus only specific users, or groups, will be able to see the new functionality in production. We can split the feature into&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Branch -&amp;gt; Add a button without functionality leading to the new feature -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Create the scaffolding (UI) for the new feature -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Create the REST API for the new feature -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Integrate the REST API for the new feature -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Use our corporate design for the new feature UI -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Adapt feedback from the UX folks -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; Improve the performance -&amp;gt; PR&lt;/li&gt;
  &lt;li&gt;Branch -&amp;gt; […] -&amp;gt; PR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href=&quot;https://www.hodler.co/2021/09/07/structuring-work/&quot;&gt;Structuring work for continuous integration&lt;/a&gt; for more examples.&lt;/p&gt;

&lt;p&gt;Or as Kent Beck calls it&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;First make the change easy, then make the easy change&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we don’t get quick reviews the developers will bundle these changes into one big change. This automatically leads to longer lived feature branches.&lt;/p&gt;

&lt;p&gt;To avoid the hassle of slow reviews we can try adding a second pair of eyes right away by pair programming or even multiple pair of eyes by mob programming.&lt;/p&gt;

&lt;p&gt;Instead of having multiple branches we push small changes into main, or master, or trunk. Together as a team.&lt;/p&gt;

&lt;p&gt;That is &lt;a href=&quot;https://trunkbaseddevelopment.com/&quot;&gt;trunk based development&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Trunk can always be released. It could even be released on every push. That’s the strategy.&lt;/p&gt;

&lt;p&gt;Users will not care about unfinished features because they will not see them.&lt;/p&gt;

&lt;p&gt;Only the developers. Or any other group configured to see them. When the feature is done the flag can be removed and everyone is able to see and use it.&lt;/p&gt;
</description>
        <pubDate>Sun, 27 Mar 2022 06:30:22 +0000</pubDate>
        <link>https://www.hodler.co/2022/03/27/trunk-based-development/</link>
        <guid isPermaLink="true">https://www.hodler.co/2022/03/27/trunk-based-development/</guid>
      </item>
    
      <item>
        <title>Linting, complexity and all that jazz</title>
        <description>&lt;p&gt;Checking out a new, at least to me, python codebase where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt; stated&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;flake8 src/ tests/
black src/ tests/&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;https://flake8.pycqa.org/en/latest/index.html&quot;&gt;Flake8&lt;/a&gt; is a tool for style guide enforcement. Often called a linter. A static code analysis tool.
While &lt;a href=&quot;https://github.com/psf/black&quot;&gt;black&lt;/a&gt; is a python code formatter.&lt;/p&gt;

&lt;p&gt;Cool. Let’s run these commands.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;flake8 src/ tests/&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Executed successfully. No warnings. No errors. Thumbs up. On with&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;black src/tests&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Executed successfully. Has reformatted a single file. Cool.&lt;/p&gt;

&lt;p&gt;Before the reformat there was the following line. (Think of it as one line even if this blog setup splits it into two)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validate_action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TestRunAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TestRunAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# noqa: C901&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The reformat did apply the maximum line length rule and changed the above to&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validate_action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TestRunAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TestRunAction&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# noqa: C901&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ok cool, LGTM, commit and push.&lt;/p&gt;

&lt;p&gt;Seconds later I get back a failed pipeline result.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;src/backend/processor.py:335:5: C901 ‘Processor.validate_action’ is too complex (14)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s check &lt;a href=&quot;https://www.flake8rules.com/rules/C901.html&quot;&gt;C901&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ok, that’s what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;# noqa C901&lt;/code&gt; comment did.
It told &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flake&lt;/code&gt; to ignore the configured complexity rules for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validate_action&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Awesome now I can either:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Decrease the complexity of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validate_action&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Google where else to put the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;# noqa: C901&lt;/code&gt; comment - All while taking into account the method now being split into three lines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus I’m left wondering why there was a file checked into mainline which did not follow the code formatting rules.&lt;/p&gt;

&lt;p&gt;Turns out the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;black&lt;/code&gt; formatting is not part of the pipelines. But &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flake8&lt;/code&gt; is. Explains the failure above.&lt;/p&gt;

&lt;p&gt;Fine, the pipeline should probably not reformat the code automatically. As a result it would have to create its own reformat commits.&lt;/p&gt;

&lt;p&gt;Two additional todos get added to my backlog:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Find out how to fail the build if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;black&lt;/code&gt; has to format - need to google that - because if there is a reformat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;black&lt;/code&gt; will just reformat and exit with code 0 (success).&lt;/li&gt;
  &lt;li&gt;Create a git hook to run the command on localhost before a commit. Or to tell the editor to automatically apply &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;black&lt;/code&gt; during save.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally we notice the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt; states the two commands in the wrong order. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;black&lt;/code&gt; should have been run first to catch the error before creating a commit.&lt;/p&gt;

&lt;p&gt;A third TODO appears.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;improve documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now without having fixed the actual issue, the complexity of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validate_action&lt;/code&gt;, we have already gathered three additional todos.&lt;/p&gt;

&lt;p&gt;We enter the common dilemma on whether to be a good sport and fix these issues or to just not give a f*ck, undo the formatting, push changes and have the green build again.&lt;/p&gt;

&lt;p&gt;(And even if we give a f*ck we might want to undo the formatting - to be back to green and then to fix all the above)&lt;/p&gt;

&lt;p&gt;We could quickly improve the readability of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validate_action&lt;/code&gt;, achieved by extracting the logical parts into methods. Sadly extracting methods does not improve complexity, only readability. Great example for the difference between complexity and being complicated.&lt;/p&gt;

&lt;p&gt;Or we could change the rules to increase the max characters per line limit. Or to allow more complexity in methods. Both would have to be discussed with the team.&lt;/p&gt;

&lt;p&gt;Quickly removing the types &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TestRunAction&lt;/code&gt; to shorten the line and have the necessary space to fit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;# noqa: C901&lt;/code&gt; there?&lt;/p&gt;

&lt;p&gt;Great, making the code worse to game the linter.&lt;/p&gt;

&lt;p&gt;We can take the above as an example why forcing formatting rules on a team doesn’t just magically achieve the same formatting everywhere.
And why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flake8&lt;/code&gt; does not automatically improve code quality. It can simply be disabled as it was in the case above. As a result we get cryptic ignore statements throughout our code base that probably no one will ever fix.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So what you are saying is these tools don’t help us?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes. I believe so.&lt;/p&gt;

&lt;p&gt;Although, f*ck, it depends.&lt;/p&gt;

&lt;p&gt;If the team really cares we don’t need a linter. Errors would be caught by tests and formatting would be applied by the editor. Everyone would not want to have their code differ from what is already in the code base.&lt;/p&gt;

&lt;p&gt;If the team does not care too deeply these tools only add additional friction. Leading to ignore statements throughout the code. Increased build time plus commits such as “satisfy linter”. And of course a team that hates the rules but does not want to bother with having a discussion about changing them.&lt;/p&gt;

&lt;p&gt;Especially if there are folks on the team who peruse and try these rules with the same energy a kid would apply to the candy in a candy store. Have them all.&lt;/p&gt;

&lt;p&gt;To add insult to injury - Both tools did not help us to avoid having both snake_case (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validation_action&lt;/code&gt;) and camelCase (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentState&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Probably another rule available in the docs of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flake8&lt;/code&gt;. Haha.&lt;/p&gt;
</description>
        <pubDate>Wed, 16 Mar 2022 06:30:22 +0000</pubDate>
        <link>https://www.hodler.co/2022/03/16/linting-complexity-and-all-that-jazz/</link>
        <guid isPermaLink="true">https://www.hodler.co/2022/03/16/linting-complexity-and-all-that-jazz/</guid>
      </item>
    
      <item>
        <title>The year 2021 in books</title>
        <description>&lt;p&gt;Books read in 2021. Again almost zero commute. I was able to read 31 books.&lt;/p&gt;

&lt;p&gt;As in 2020 I’ll rate the books from one to three stars. Three of three (3/3) stars being what I thoroughly have enjoyed and would recommend to others who are into the topic of the book or enjoy a good read in general. Giving a book one star neither states the book is bad or I do not agree with it, rather it is something I personally did not enjoy too much.&lt;/p&gt;

&lt;h3 id=&quot;die-nibelungen---auguste-lechner---13&quot;&gt;Die Nibelungen - Auguste Lechner - 1/3&lt;/h3&gt;
&lt;p&gt;Common tale in germany.&lt;/p&gt;

&lt;h3 id=&quot;the-new-right-a-journey-to-the-fringe-of-american-politics---michael-malice---23&quot;&gt;The New Right: A Journey to the Fringe of American Politics - Michael Malice - 2/3&lt;/h3&gt;
&lt;p&gt;An intro to the American New Right&lt;/p&gt;

&lt;h3 id=&quot;ask-your-developer---jeff-lawson---33&quot;&gt;Ask Your Developer - Jeff Lawson - 3/3&lt;/h3&gt;
&lt;p&gt;Written as a handbook for Project Managers or Product Owners. Talk to your developers about problems instead of solutions. Telling them what the goal is instead of telling them what to do.&lt;/p&gt;

&lt;h3 id=&quot;der-himmel-kennt-keine-günstlinge---erich-maria-remarque-23&quot;&gt;Der Himmel kennt keine Günstlinge - Erich Maria Remarque 2/3&lt;/h3&gt;
&lt;p&gt;On racing and cherishing life with a carefree attitude.&lt;/p&gt;

&lt;h3 id=&quot;staff-engineer-leadership-beyond-the-management-track---will-larson-23&quot;&gt;Staff Engineer: Leadership Beyond the Management Track - Will Larson 2/3&lt;/h3&gt;
&lt;p&gt;How to stay an Individual Contributor in a software company instead of moving into management.&lt;/p&gt;

&lt;h3 id=&quot;how-to-destroy-a-tech-startup-in-three-easy-steps---lawrence-krubner---33&quot;&gt;How to destroy a tech startup in three easy steps - Lawrence Krubner - 3/3&lt;/h3&gt;
&lt;p&gt;A funny and gripping read on some, questionably true, experiences of a developer in a tech startup. Went through it in one sitting.&lt;/p&gt;

&lt;h3 id=&quot;heat---bill-buford---23&quot;&gt;Heat - Bill Buford - 2/3&lt;/h3&gt;
&lt;p&gt;The authors experiences working as a cook.&lt;/p&gt;

&lt;h3 id=&quot;white-noise---don-delillo---13&quot;&gt;White Noise - Don Delillo - 1/3&lt;/h3&gt;
&lt;p&gt;A critique of modern society.&lt;/p&gt;

&lt;h3 id=&quot;jordan-b-peterson---beyond-order---23&quot;&gt;Jordan B. Peterson - Beyond Order - 2/3&lt;/h3&gt;
&lt;p&gt;A list of rules to live by.&lt;/p&gt;

&lt;h3 id=&quot;vladimir-nabokov---pnin---23&quot;&gt;Vladimir Nabokov - Pnin - 2/3&lt;/h3&gt;
&lt;p&gt;The first Nabokov book I’ve read. About a russian professor in america during the 1950s.&lt;/p&gt;

&lt;h3 id=&quot;franz-kafka---die-verwandlung---23&quot;&gt;Franz Kafka - Die Verwandlung - 2/3&lt;/h3&gt;
&lt;p&gt;Quick read. A classic.&lt;/p&gt;

&lt;h3 id=&quot;the-anarchist-handbook---michael-malice---33&quot;&gt;The Anarchist Handbook - Michael Malice - 3/3&lt;/h3&gt;
&lt;p&gt;A collection of anarchist essays.&lt;/p&gt;

&lt;h3 id=&quot;permutation-city---greg-egan---33&quot;&gt;Permutation City - Greg Egan - 3/3&lt;/h3&gt;
&lt;p&gt;What if we live forever? But on Amazon EC2 ;)&lt;/p&gt;

&lt;h3 id=&quot;fundamentals-of-software-architecture-an-engineering-approach---mark-richards-neil-ford---33&quot;&gt;Fundamentals of Software Architecture: An Engineering Approach - Mark Richards, Neil Ford - 3/3&lt;/h3&gt;
&lt;p&gt;How to be an effective Software Architect.&lt;/p&gt;

&lt;h3 id=&quot;an-elegant-puzzle-systems-of-engineering-management---will-larson---23&quot;&gt;An Elegant Puzzle: Systems of Engineering Management - Will Larson - 2/3&lt;/h3&gt;
&lt;p&gt;An approach to management in modern software companies.&lt;/p&gt;

&lt;h3 id=&quot;a-gentle-introduction-to-unqualified-reservations---mencius-moldbug---23&quot;&gt;A Gentle Introduction to Unqualified Reservations - Mencius Moldbug - 2/3&lt;/h3&gt;
&lt;p&gt;Introduction to the “Political Red Pill”.&lt;/p&gt;

&lt;h3 id=&quot;against-the-grain-a-deep-history-of-the-earliest-states---33&quot;&gt;Against the Grain: A Deep History of the Earliest States - 3/3&lt;/h3&gt;
&lt;p&gt;Without grain there would not be modern states. Grain is easiest to tax.&lt;/p&gt;

&lt;h3 id=&quot;bronze-age-mindset---bronze-age-pervert---33&quot;&gt;Bronze Age Mindset - Bronze Age Pervert - 3/3&lt;/h3&gt;
&lt;p&gt;Recommended by George Hotz on the Lex Fridman Podcast. Criticisms of Modern Society.&lt;/p&gt;

&lt;h3 id=&quot;the-pussy---delicious-taco---13&quot;&gt;The Pussy - Delicious Taco - 1/3&lt;/h3&gt;
&lt;p&gt;A bunch of essays, or blog posts, on relationships with women. A book one gets recommended after reading Bronze Age Mindset.&lt;/p&gt;

&lt;h3 id=&quot;sun-and-steel---yukio-mishima---13&quot;&gt;Sun and Steel - Yukio Mishima - 1/3&lt;/h3&gt;
&lt;p&gt;The wikipedia article of Yukio Mishima can be read afterwards, not before.&lt;/p&gt;

&lt;h3 id=&quot;harassment-architecture---mike-ma---13&quot;&gt;Harassment Architecture - Mike Ma - 1/3&lt;/h3&gt;
&lt;p&gt;Another books revered in right wing circles.&lt;/p&gt;

&lt;h3 id=&quot;threat-modeling-designing-for-security---adam-shostack---23&quot;&gt;Threat Modeling: Designing for Security - Adam Shostack - 2/3&lt;/h3&gt;
&lt;p&gt;Techniques to apply to your software and the surrounding infrastructure to find issues.&lt;/p&gt;

&lt;h3 id=&quot;an-open-letter-to-open-minded-progressives---mencius-moldbug---23&quot;&gt;An Open Letter to Open-Minded Progressives - Mencius Moldbug - 2/3&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;By separating voters into two competing but cooperating parties, neither of which can destroy the other, the two-party system creates a government which will survive indefinitely, no matter how much happier its citizens might be without it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;die-kadetten---ernst-von-salomon---33&quot;&gt;Die Kadetten - Ernst von Salomon - 3/3&lt;/h3&gt;
&lt;p&gt;Experiences of the author in a German Kadettenanstalt during the days of the First World War.&lt;/p&gt;

&lt;h3 id=&quot;the-outlaws---ernst-von-salomon---33&quot;&gt;The Outlaws - Ernst von Salomon - 3/3&lt;/h3&gt;
&lt;p&gt;Experiences of the author in the German &lt;a href=&quot;https://en.wikipedia.org/wiki/Freikorps&quot;&gt;Freikorps&lt;/a&gt; in the aftermath of the First World War and the Murder of &lt;a href=&quot;https://en.wikipedia.org/wiki/Walther_Rathenau&quot;&gt;Walther Rathenau&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;bauern-bonzen-und-bomben---hans-fallada---23&quot;&gt;Bauern, Bonzen und Bomben - Hans Fallada - 2/3&lt;/h3&gt;
&lt;p&gt;Story about the German &lt;a href=&quot;https://en.wikipedia.org/wiki/Rural_People%27s_Movement&quot;&gt;Landvolkbewegung&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;faserland---christian-kracht---13&quot;&gt;Faserland - Christian Kracht - 1/3&lt;/h3&gt;
&lt;p&gt;A quick read on the affluent part of my parents generation while in their late twenties/early thirties in Germany.&lt;/p&gt;

&lt;h3 id=&quot;industrial-society-and-its-future---theodore-j-kaczynski---33&quot;&gt;Industrial Society and Its Future - Theodore J. Kaczynski - 3/3&lt;/h3&gt;
&lt;p&gt;A critique of modern society written around 1995.&lt;/p&gt;

&lt;h3 id=&quot;21-lessons-what-ive-learned-from-falling-down-the-bitcoin-rabbit-hole---gigi---33&quot;&gt;21 Lessons: What I’ve Learned from Falling Down the Bitcoin Rabbit Hole - Gigi - 3/3&lt;/h3&gt;
&lt;p&gt;Quick read and a great gift for “future bitcoiners”. People already in the rabbit hole won’t take too much out of it.&lt;/p&gt;

&lt;h3 id=&quot;the-end-of-all-evil---jeremy-locke---33&quot;&gt;The End of All Evil - Jeremy Locke - 3/3&lt;/h3&gt;
&lt;p&gt;The state is “not just” inefficient. It is evil.&lt;/p&gt;

&lt;h3 id=&quot;demian-die-geschichte-von-emil-sinclairs-jugend---hermann-hesse---23&quot;&gt;Demian: Die Geschichte von Emil Sinclairs Jugend - Hermann Hesse - 2/3&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Wer nicht in die Welt passt, der ist immer nahe daran, sich selber zu finden.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rough translation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“He who doesn’t fit (into our world), is always close to finding himself”&lt;/p&gt;
&lt;/blockquote&gt;

</description>
        <pubDate>Thu, 13 Jan 2022 11:11:11 +0000</pubDate>
        <link>https://www.hodler.co/2022/01/13/year-in-books-2021/</link>
        <guid isPermaLink="true">https://www.hodler.co/2022/01/13/year-in-books-2021/</guid>
      </item>
    
      <item>
        <title>Production data in test environments</title>
        <description>&lt;p&gt;The thoughtworks Technology Radar has added the technique &lt;a href=&quot;https://www.thoughtworks.com/de-de/radar/techniques/production-data-in-test-environments&quot;&gt;Production data in test environments&lt;/a&gt;. It has the status “Hold”. Short for “Don’t do that”.&lt;/p&gt;

&lt;p&gt;I was asked what my thoughts are.&lt;/p&gt;

&lt;p&gt;It seems people having issues with the technique probably do use production data in test environments. Having worked on such systems, all the listed drawbacks are true. Some are more of an issue than others.&lt;/p&gt;

&lt;p&gt;Protection of private data is important and of legal relevance. Sending &lt;em&gt;incorrect alerts&lt;/em&gt; from test systems to real clients can happen on production too. There are measures to avoid this. Previews that show who, or even a number of how many, will get the message. Or sending it to an internal group first before sending it to everyone applicable for the notification.&lt;/p&gt;

&lt;p&gt;Taking a step back.&lt;/p&gt;

&lt;p&gt;Why do people put production data into test environments?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;To fill the databases with more than only a few bytes?&lt;/li&gt;
  &lt;li&gt;To check if the queries are fast enough on larger datasets?&lt;/li&gt;
  &lt;li&gt;To check if our database migrations are successful on real data?&lt;/li&gt;
  &lt;li&gt;To actually display something in the app?&lt;/li&gt;
  &lt;li&gt;To reproduce bugs?&lt;/li&gt;
  &lt;li&gt;To make it look &lt;em&gt;real&lt;/em&gt; for demoing purposes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Valid reasons.&lt;/p&gt;

&lt;p&gt;Before we discuss using bogus or obfuscated data as an alternative let’s take another step back.&lt;/p&gt;

&lt;p&gt;Thinking from first principles - &lt;strong&gt;Why is there a test environment at all?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What if we were reproducing bugs in production?&lt;/p&gt;

&lt;p&gt;What if we demo the production app instead of an app connected to a test environment?&lt;/p&gt;

&lt;p&gt;What if we turn it around and add test data to our production environment?&lt;/p&gt;

&lt;p&gt;A fake hotel that only testers can see and book, a fake car that only testers can see and buy, a fake article that only testers can read and share.&lt;/p&gt;

&lt;p&gt;A new feature that only testers can see and use?&lt;/p&gt;

&lt;p&gt;Using a simple &lt;a href=&quot;https://en.wikipedia.org/wiki/A/B_testing&quot;&gt;A/B Test&lt;/a&gt; where one of the groups, or a third group, is developers, testers, other stakeholders, project managers or anyone else that is not the end user.&lt;/p&gt;

&lt;p&gt;I always try to add this concept to products and projects I’m working on.&lt;/p&gt;

&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;

&lt;p&gt;The roadtrips in the app below were not visible for everyone. They might just be there for testing. Instead of crossing the alps you can do a roadtrip from and to the office. Or check out how the content looks and feels before the customer sees it.&lt;/p&gt;

&lt;p&gt;All in production.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.dropbox.com/s/xdvpi1cshywgjjn/roadtrip.PNG?raw=1&quot; class=&quot;image__ios image__center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Another example.&lt;/p&gt;

&lt;p&gt;I do not drive the car below. Aside from the name the car might not even exist. Still it is mine in the production app. It is test data in production.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.dropbox.com/s/zrcs7hqhgjft1o9/pfsapp.PNG?raw=1&quot; class=&quot;image__ios image__center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Do we now have the solution for the whole production data in test environments?&lt;/p&gt;

&lt;p&gt;Guess not. It’s providing options.&lt;/p&gt;

&lt;p&gt;Having production data in test environments is an option.&lt;/p&gt;

&lt;p&gt;Having test data in production environments is an option.&lt;/p&gt;

</description>
        <pubDate>Sat, 06 Nov 2021 06:30:22 +0000</pubDate>
        <link>https://www.hodler.co/2021/11/06/prod-data-in-test-environments/</link>
        <guid isPermaLink="true">https://www.hodler.co/2021/11/06/prod-data-in-test-environments/</guid>
      </item>
    
      <item>
        <title>On dedicated DevOps</title>
        <description>&lt;p&gt;Joining a new team I was able to hear the remarks on how we have no dedicated DevOps person who is taking care of the AWS infrastructure and all the Gitlab pipelines.&lt;/p&gt;

&lt;p&gt;The conversation reminded me of an old tweet.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;“Yeah, we’ve found this great person to do all the DevOps”&lt;br /&gt;That isn’t DevOps&lt;/p&gt;&amp;mdash; Sam Newman (@samnewman) &lt;a href=&quot;https://x.com/samnewman/status/722554106166968320?ref_src=twsrc%5Etfw&quot;&gt;April 19, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;Okay… DevOps is also &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Treachery_of_Images&quot;&gt;not a pipe&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What then is DevOps?&lt;/p&gt;

&lt;p&gt;Back then I took the tweet and in my head automatically translated it into&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Every developer should be able to do operations work&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It is the responsibility of the developers to take care of Ops&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meaning a specific train of thought is required to understand the tweet. It does not tell you how to do it. Only how not to do it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/DevOps&quot;&gt;Wikipedia on DevOps&lt;/a&gt; tells us&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Most often, DevOps is characterized by key principles: shared ownership, workflow automation, and rapid feedback.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, &lt;strong&gt;shared ownership&lt;/strong&gt;. Of what though?&lt;/p&gt;

&lt;p&gt;Hopefully development and operations.&lt;/p&gt;

&lt;p&gt;There should be no dedicated DevOps person in the team. There should be no dedicated anything in the team. Dedicated anythings are always a bottleneck. Or poised to become a bottleneck in the future. Either by moving to other parts of the organisation, to other organisations, to other fields of interest, enjoying a holiday or anything else that makes them unavailable.&lt;/p&gt;

&lt;p&gt;Of course we can have a person that carries DevOps knowledge into the teams. With the goal to enable the team to take care of the DevOps work themselves at one point. Teaching them to work with AWS or Gitlab pipelines if we take the example above.&lt;/p&gt;

&lt;p&gt;Thus let’s not have a dedicated DevOps person in the team.&lt;/p&gt;

&lt;p&gt;More on the topic is described in the article &lt;a href=&quot;/2019/03/17/cross-functional-teams/&quot;&gt;Cross functional teams&lt;/a&gt;&lt;/p&gt;

</description>
        <pubDate>Mon, 27 Sep 2021 09:22:13 +0000</pubDate>
        <link>https://www.hodler.co/2021/09/27/devops/</link>
        <guid isPermaLink="true">https://www.hodler.co/2021/09/27/devops/</guid>
      </item>
    
      <item>
        <title>Structuring work for continuous integration</title>
        <description>&lt;p&gt;Consider our product has a bunch of included services. Warranty, insurance, additional drivers and more. The services are displayed in a grid. Our users might, or might not, know about them yet.&lt;/p&gt;

&lt;p&gt;What do these included services mean exactly? All we get is an icon and a title?&lt;/p&gt;

&lt;p&gt;Maybe the feedback made it clear people had further questions when looking at the services - Maybe adding additional context is a legal requirement.&lt;/p&gt;

&lt;p&gt;We decide to add more context. One approach is the common “info” ( &lt;strong&gt;i&lt;/strong&gt; ) icon or, in our case, the “Show details” (&lt;em&gt;Details anzeigen&lt;/em&gt;) button.&lt;/p&gt;

&lt;p&gt;The button on the bottom left leads to the detail view on the right.&lt;/p&gt;

&lt;p class=&quot;image__pair&quot;&gt;
&lt;img src=&quot;https://www.dropbox.com/s/i5wzoc8vl15xffo/details.PNG?raw=1&quot; class=&quot;image__ios image__ios-left&quot; /&gt;
&lt;img src=&quot;https://www.dropbox.com/s/qydqa5u79fu7qro/context.PNG?raw=1&quot; class=&quot;image__ios image__ios-right&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;All we need to do is to display some text in a view and implement a way to get there.&lt;/p&gt;

&lt;p&gt;Not too hard.&lt;/p&gt;

&lt;p&gt;The common approach developers take is&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create the button&lt;/li&gt;
  &lt;li&gt;Have the button open a modal (a sheet in iOS terminology) - Pressing Done (&lt;em&gt;Fertig&lt;/em&gt;) closes the sheet - The view on the left is displayed again.&lt;/li&gt;
  &lt;li&gt;Layout the content of the sheet&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is fine. It gets the job done.&lt;/p&gt;

&lt;p class=&quot;image__pair&quot;&gt;
&lt;img src=&quot;https://www.dropbox.com/s/uec3l2llz8yyssq/step_1.PNG?raw=1&quot; class=&quot;image__ios image__ios-left&quot; /&gt;
&lt;img src=&quot;https://www.dropbox.com/s/uwsm128xg1e7lq8/step_23.PNG?raw=1&quot; class=&quot;image__ios image__ios-right&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;Can we improve upon it?&lt;/p&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;Consider continuous integration. We merge to master as often as possible. Multiple times a day - even multiple times per hour.&lt;/p&gt;

&lt;p&gt;Using the approach above we cannot merge to master directly after creating the button. Yes, technically we can, with the result of having a master state
that cannot be released &lt;strong&gt;right now&lt;/strong&gt;. Consider someone in the team finds a bug which needs a bugfix release ASAP. Only possible after we remove the added button. The button without functionality.&lt;/p&gt;

&lt;p&gt;If a user discovers the button he will press it and nothing would happen. Step 2 (opening the sheet) is not yet implemented.&lt;/p&gt;

&lt;p&gt;Even if it was, without Step 3 (layout the sheet) the user would see a blank page.&lt;/p&gt;

&lt;p&gt;What if we were to change the order of the steps in our approach?&lt;/p&gt;

&lt;p&gt;We start with the content of the sheet. No need to commit to the sheet element yet. Maybe the designers will show up a few minutes later with the decision
to have the view use the full screen?&lt;/p&gt;

&lt;p&gt;If we layout the content first we are able to merge. Due to SwiftUI we also do not need to have a button to allow us to see our view. That is what previews are for.&lt;/p&gt;

&lt;p&gt;The current state is mergeable to master. Even if there is some pending release it would not matter. After all, the view does not have an entry point yet. We did not implement the button. No user will be able to see the view. We can collect feedback from other developers or designers on the contents of the sheet without the necessity to think on how the user gets there.&lt;/p&gt;

&lt;p&gt;As a result the approach changes to&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Layout the content of the sheet&lt;/li&gt;
  &lt;li&gt;Create the button&lt;/li&gt;
  &lt;li&gt;Have the button open the sheet&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;image__pair&quot;&gt;
&lt;img src=&quot;https://www.dropbox.com/s/f1r1lze8s5urgrr/step_3a.png?raw=1&quot; class=&quot;image__ios image__ios-left&quot; /&gt;
&lt;img src=&quot;https://www.dropbox.com/s/75jklgiwh72zqtz/step_23a.png?raw=1&quot; class=&quot;image__ios image__ios-right&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;We have split a single unit of work, which has to be merged as one, into two units of work, mergeable one by one.&lt;/p&gt;

&lt;p&gt;Is the change in question too trivial to warrant a change of our “usual” order? The statement &lt;em&gt;“We can do this in an hour”&lt;/em&gt; comes to mind. Fair enough.&lt;/p&gt;

&lt;p&gt;Consider we had to implement some logic that fetched the content of the sheet from a server. Suddenly we have to deal with http requests, API design, possible errors due to being offline or an unreachable server.&lt;/p&gt;

&lt;p&gt;What if, due to the possibility of collecting feedback earlier, we had to change the design of the sheet multiple times?&lt;/p&gt;

&lt;p&gt;A feature once considered &lt;em&gt;trivial&lt;/em&gt; before is not &lt;em&gt;trivial&lt;/em&gt; anymore.&lt;/p&gt;

</description>
        <pubDate>Tue, 07 Sep 2021 09:30:22 +0000</pubDate>
        <link>https://www.hodler.co/2021/09/07/structuring-work/</link>
        <guid isPermaLink="true">https://www.hodler.co/2021/09/07/structuring-work/</guid>
      </item>
    
      <item>
        <title>On having a favorite programming language</title>
        <description>&lt;p&gt;Sometimes I get asked &lt;em&gt;“What is your favorite programming language?”&lt;/em&gt;, &lt;em&gt;“What programming language would you use when starting to learn programming?”&lt;/em&gt;, &lt;em&gt;“What do you think of programming language $X?”&lt;/em&gt;, &lt;em&gt;“What programming languages do you use?”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let me elaborate.&lt;/p&gt;

&lt;p&gt;Back in school we got taught &lt;strong&gt;Delphi&lt;/strong&gt;. Don’t remember much about it. The programming was done through some kind of interface builder. In university I got to do &lt;strong&gt;Prolog&lt;/strong&gt; and &lt;strong&gt;Java&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Back then one was able to use Java a lot because Android was quite new. Android apps were - and still can be - written in Java.&lt;/p&gt;

&lt;p&gt;Later, after reading suggestions on prominent YouTube lectures, I was able to play with &lt;strong&gt;Scheme&lt;/strong&gt;. &lt;strong&gt;Python&lt;/strong&gt; was added when a course on using MongoDB was relying on it. The course made use of the &lt;a href=&quot;https://bottlepy.org/docs/dev/&quot;&gt;bottle&lt;/a&gt; framework. Python was also the first language where I wrote tests. Later Python was used throughout the “Programming Bitcoin” book by Jimmy Song using jupyter notebooks. Due to working with &lt;strong&gt;AngularJS&lt;/strong&gt; and &lt;strong&gt;Backbone.js&lt;/strong&gt; at my first job I was able to pick up some &lt;strong&gt;JavaScript&lt;/strong&gt;. JavaScript stuck with me and it is what I use today if I need to create a quick scripts using Node.js. By getting into &lt;strong&gt;Angular&lt;/strong&gt;, often called &lt;strong&gt;Angular2&lt;/strong&gt; at my second job I was able to work with &lt;strong&gt;TypeScript&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By following the Ethereum ecosystem for a while I got to do some programming with &lt;strong&gt;Solidity&lt;/strong&gt;. The default smart contract programming language back then.&lt;/p&gt;

&lt;p&gt;After spending way too much time on &lt;a href=&quot;https://news.ycombinator.com/&quot;&gt;hackernews&lt;/a&gt;, and seeing again and again how every programmer should know &lt;strong&gt;Assembly&lt;/strong&gt; and &lt;strong&gt;C&lt;/strong&gt; I went through a PDF for Assembly and the beginning of &lt;a href=&quot;https://learncodethehardway.org/c/&quot;&gt;Learn C the Hard Way&lt;/a&gt;. Back then the book was free and not yet finished.&lt;/p&gt;

&lt;p&gt;After functional programming started to become all the rage I got my feet wet in &lt;strong&gt;Clojure&lt;/strong&gt; by spending some time with the book &lt;a href=&quot;https://www.braveclojure.com/clojure-for-the-brave-and-true/&quot;&gt;Clojure for the Brave and True&lt;/a&gt;. Later &lt;strong&gt;Haskell&lt;/strong&gt; by working through half of the &lt;a href=&quot;https://haskellbook.com/&quot;&gt;haskell book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By following the TDD and Clean Code community I was able to see a lot of &lt;strong&gt;Ruby&lt;/strong&gt; in presentations and code snippets. Ruby was later revisted by working through Programming Languages Part A, Part B and Part C by Dan Grossman &lt;a href=&quot;https://www.coursera.org/learn/programming-languages&quot;&gt;on coursera&lt;/a&gt;. The course also made you wirte code in &lt;strong&gt;ML&lt;/strong&gt; and &lt;strong&gt;Racket&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In 2018 I had the fortune to introduce &lt;strong&gt;Kotlin&lt;/strong&gt; into a, until then, pure Java codebase. Instead of resistance the change was welcomed with open arms by fellow developers. Both the possibility to learn something new, and to be paid for it, plus the ability to write, or to be honest generate, less boilerplate.&lt;/p&gt;

&lt;p&gt;Kotlin is what I use to this day in most backend related work.&lt;/p&gt;

&lt;p&gt;As &lt;strong&gt;Rust&lt;/strong&gt; became popular, it was supposed to be the new C, I did spend some time with the book &lt;a href=&quot;https://doc.rust-lang.org/book/&quot;&gt;The Rust Programming Language&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While getting into iOS development I was able to quickly pick up &lt;strong&gt;Swift&lt;/strong&gt; and &lt;strong&gt;SwiftUI&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Once I read the statement you are only able to state you know a certain programming language if you are able to write &lt;a href=&quot;https://en.wikipedia.org/wiki/Fizz_buzz&quot;&gt;Fizz buzz&lt;/a&gt; in it. A low bar. It will only prove you remember the basic syntax. I would be able to write Fizz buzz in Java, Kotlin, JavaScript, Swift and Python. Mainly because I used all of them recently. For all the others I would have to brush up my knowledge for a few minutes.&lt;/p&gt;

&lt;p&gt;How do you learn a programming language then? You don’t need to know generics to write a simple Java command line application. You don’t need to know the difference between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; before writing an iOS app in Swift. It will become apparent at one point in your journey. Right when you need it.&lt;/p&gt;

&lt;p&gt;Neither do you &lt;em&gt;need&lt;/em&gt; to read a book on the programming language. Is reading the book helpful? Sure, you might pick up a few tricks while reading it and remember parts of the codebase you can apply it to. Is it required? No.&lt;/p&gt;

&lt;p&gt;In my day to day work I sometimes get the question during pairing &lt;em&gt;“Would this syntax work here?”&lt;/em&gt;. Even when you know the answer (Yes/No) the better answer is &lt;em&gt;“Let’s write a test and see”&lt;/em&gt;. The moment you have a test we can play around with the implementation details, learn what works and iteratively improve it if necessary.&lt;/p&gt;

&lt;p&gt;So what is my favorite programming language?&lt;/p&gt;

&lt;p&gt;I don’t have one. Saves me quite some time when discussing what to use for a new project. What I care more about is the tooling around the language. I enjoy working more with Kotlin than with Swift because I consider IntelliJ to be superior to Xcode. But then, Xcode might be a lot easier than setting up your Haskell tooling. (To be fair it has been a while I have looked into Haskell tooling). Do I thus like Kotlin more than Swift because I enjoy working with it more? Fair enough. I guess the answer is a Yes. For now.&lt;/p&gt;

&lt;p&gt;What program language would you use when starting out to learn programming?&lt;/p&gt;

&lt;p&gt;Depends on what you would want to do. The easiest might be where you have all the required tools, a browser, already installed. Thus JavaScript. Then again you are trying to solve a problem. It doesn’t really matter in the beginning. Use what your friends use, use what the guy on YouTube uses or use what your colleagues use.&lt;/p&gt;

&lt;p&gt;In the end it is all if, else, loops and pattern matching for the functionally inclined.&lt;/p&gt;

&lt;p&gt;I reject the notion of &lt;em&gt;“Do $X to become a better programmer”&lt;/em&gt;. To become a better programmer you program. You program to solve problems. Even if the problem is not having anything better to do on a lazy sunday afternoon.&lt;/p&gt;

</description>
        <pubDate>Sun, 29 Aug 2021 09:30:22 +0000</pubDate>
        <link>https://www.hodler.co/2021/08/29/on-favorite-programming-languages/</link>
        <guid isPermaLink="true">https://www.hodler.co/2021/08/29/on-favorite-programming-languages/</guid>
      </item>
    
  </channel>
</rss>
