<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Oscar Ablinger]]></title><description><![CDATA[I'm a Software Engineer, PO, Blogger and more. My blogs feature mostly technical articles about Clean Code, Java, Functional Programming, useful scripts and wha]]></description><link>https://blog.oscarablinger.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 08 Sep 2026 12:52:32 GMT</lastBuildDate><atom:link href="https://blog.oscarablinger.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Objectively Best Way to Indent your Code]]></title><description><![CDATA[Tabs or spaces?
Every programmer was at some point confronted by this career-defining choice. But with this post today I'll expand the horizon and finally settle the debate.
So let's go over the different ways to indent your code and their pros and c...]]></description><link>https://blog.oscarablinger.dev/the-objectively-best-way-to-indent-your-code</link><guid isPermaLink="true">https://blog.oscarablinger.dev/the-objectively-best-way-to-indent-your-code</guid><category><![CDATA[Programming Tips]]></category><category><![CDATA[styling]]></category><category><![CDATA[styleguide]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Fri, 01 Apr 2022 16:14:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648489486595/AWQ7O3sD8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Tabs or spaces?</p>
<p>Every programmer was at some point confronted by this career-defining choice. But with this post today I'll expand the horizon and finally settle the debate.</p>
<p>So let's go over the different ways to indent your code and their pros and cons.</p>
<p><em>All of the pretty code images here were made using <a target="_blank" href="carbon.now.sh">carbon</a>.</em></p>
<h2 id="heading-tabs">Tabs</h2>
<p>Indenting as ASCII intended.
The pros of this technique are plenty:</p>
<ul>
<li>Every reader of the code can decide how much space it wants the IDE to attribute to one tab: 1, 5 or even 7 (sadly fractions are not supported by most).</li>
<li>The resulting file size is smaller, ensuring that you can stay as productive as possible.</li>
<li>You feel good giving purpose to the 10th ASCII character.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828316378/aTAkMDFLR.png" alt="An image of code using tabs" /><em>An image of code with tabs.</em></p>
<h2 id="heading-spaces">Spaces</h2>
<p>Ah, the default for most editors.
And also slightly more common than tabs in my objective experience.</p>
<p>The main advantage of this style is that you can force the reader of your code to use the same length of indentation that you used.
I know I listed the opposite point as an advantage of using tabs, but we all know that in the end you cannot trust users – not even the users of an IDE.</p>
<p>Developers new to the discussion often bring up that this style requires you to press the space bar repeatedly.
But of course noone actually does that – that's what auto-clickers are for.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828335106/5k9-my4ke.png" alt="An image of code using spaces." /><em>An image of code with spaces.</em></p>
<h2 id="heading-mixing-tabs-and-spaces">Mixing tabs and spaces</h2>
<p>Okay, hear me out: You can use tabs and spaces for different kinds of indentation.</p>
<p>For instance you could use tabs to indent blocks and then use spaces when you need something at a specific position, like when aligning the second parameter with the first.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828354913/6i1TOGKiz.png" alt="An image of code using tabs and spaces." /><em>An image of code with tabs and spaces.</em></p>
<p>This allows other people to still choose their own length for the tabs, but ensure that elements are still aligned when you want them to be.</p>
<p>Personally I also advocate to use tabs instead of spaces in between parameters, because that will create more visually pleasing code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828377335/h-3jf7CAD.png" alt="An image of code using tabs between parameters." /><em>An image of code with tabs between parameters.</em></p>
<h2 id="heading-mixing-and-mashing">Mixing and mashing</h2>
<p>For those that hate to be restricted by style guides and want to rebel against the bourgeoisie of coding, you can just do whatever you want and sometimes use tabs and sometimes use spaces.</p>
<p>This might seem weird, but if you look at the first projects of software engineers, you'll find that this is pretty common before they learn otherwise.</p>
<p>So it might just be the most natural of all of the indenting methods.</p>
<p>Plus, it turns programming into a small game, when, in every line, you'll wonder whether spaces or tabs were used.</p>
<p><a target="_blank" href="https://link.springer.com/article/10.1007/s10648-019-09498-w">And gamification improves cognitive, motivational and behavioral learning</a>, so this method will also make you a better programmer in the long run.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828397749/5iX5uKswn.png" alt="An image of code with one line using a tab and the other using spaces. Can you guess which is which?" /><em>An image of code with one line using a tab and the other using spaces. Can you guess which is which?</em></p>
<p>Lastly, you can actually fit two programs into one: Since the whitespace is ignored by most programing languages, you can use them <a target="_blank" href="https://esolangs.org/wiki/Whitespace">to implement a separate program</a>.</p>
<p>That makes for a great easter egg!</p>
<h2 id="heading-comments">Comments</h2>
<p>Instead of adding another program, you could also just try to use the space more efficiently.
Since you'll likely decide to indent anyways, why let that space go to waste?</p>
<p>You can use block comments to add more useful information about what's happening in each line.
That's especially useful for beginners so you don't forget to comment your code.</p>
<p>Since you don't want to use up too much space with full text comments all the time, I'd recommend using some well-defined short names.</p>
<p>Here are some suggestions by me:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Short Name</td><td>What it describes</td></tr>
</thead>
<tbody>
<tr>
<td><code>=</code></td><td>Variable assignment</td></tr>
<tr>
<td><code>^</code></td><td>Function call</td></tr>
<tr>
<td><code>↑</code></td><td>stdout output</td></tr>
<tr>
<td><code>⏎</code></td><td>Return statement</td></tr>
<tr>
<td><code>}</code></td><td>End of a block</td></tr>
<tr>
<td><code>π</code></td><td>π</td></tr>
<tr>
<td><code>∫</code></td><td>Function definition</td></tr>
<tr>
<td><code>λ</code></td><td>Lambda definition</td></tr>
</tbody>
</table>
</div><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828412877/4ffqyhXli.png" alt="An image of code with indentation comments." /><em>An image of code with indentation comments.</em></p>
<p>This also increases searchability of your code since you can just search for "⏎" and find all of the returns in the file.</p>
<h2 id="heading-semicolons">Semicolons</h2>
<p>More and more language now move to a cleaner no-semicolons-required style.</p>
<p>Sadly some languages still haven't caught up.</p>
<p>But when you're using semicolons as indentation, you'll never have to worry about seeing one at the end of your statement ever again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828433621/ewtIfCjA9.png" alt="An image of code with semicolons as indentation." /><em>An image of code with semicolons as indentation.</em></p>
<p>Sadly some languages set (in my opinion) unreasonable restrictions on code when using this indentation style.</p>
<p>Java for instance will only allow you to use one indentation level for the line after a <code>return</code> statement.
Otherwise it will complain about "unreachable code".</p>
<p>In those cases I'd recommend using a pre-compiler job that runs all of the files through a simple <code>sed -r "s/;+/;/g"</code> call, which will fix some of the errors.</p>
<p>Most languages also won't let you chain calls over multiple lines anymore.</p>
<p>I do see this as an absolute win, however, since I believe that no method should consist of more than one statement, anyways.
That's usually a code smell.</p>
<p>Other languages will outright refuse to compile code indented like this completely.</p>
<p>While I don't believe that languages should unnecessarily restrict programmers, we're sometimes forced to work with such archaic languages.
In that case, you could try to write a simple pre-compiler, publish it and then never maintain it for 3 years while racking up over a hundred thousand weekly downloads on NPM.</p>
<h2 id="heading-right-to-left-indentation">Right-to-left indentation</h2>
<p>With i18n becoming more and more important, more any more programs introduce a RTL mode in which the text changes to be aligned from right-to-left.</p>
<p>Maybe it's time to also make that move in the code itself and <a target="_blank" href="https://www.reddit.com/r/ProgrammerHumor/comments/svf9qx/okay_lets_end_this_tabs_vs_space_debate_once_and/">indent to the right side instead</a>?</p>
<p>The main advantage of this is that the maximum line width now becomes more than a suggestion and actually has to be respected.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828447416/zc0r1eck4.png" alt="An image of code with RTL indentation." /><em>An image of code with RTL indentation.</em></p>
<h2 id="heading-no-indentation">No Indentation</h2>
<p>An often overlooked way of indentation is simply not indenting.</p>
<p>Has anyone ever checked if indentation actually improves readability? I know I haven't.</p>
<p>In fact, having no indentation forces you to read every line and ensures that you don't miss anything, reducing errors in the process.</p>
<p>Of course, we also save precious disk space.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648828476165/B9eZmoQpG.png" alt="An image of code with no indentation." /><em>An image of code with no indentation.</em></p>
<h2 id="heading-blank-space">Blank space</h2>
<p>What's better than no indentation?
<em>Nothing!</em></p>
<p>Blank space is the <code>null</code> to your empty list.</p>
<p>While most editors don't yet support this style, the up-and-coming OSS editor <a target="_blank" href="https://ms-paint-i.de/">MEPaintIDE</a> is pioneering this brand new way of styling your code.</p>
<p>Instead of doing the cumbersome, arduous, laborious work of inserting characters, you <a target="_blank" href="https://www.youtube.com/watch?v=A_pTGhOyPbw">should take your code and push it somewhere else</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648488694039/FMAlYktwu.png" alt="Code indented using blank space." /><em>Code indented using blank space. <a target="_blank" href="https://www.youtube.com/watch?v=e-ORhEE9VVg">I got a blank space, baby.</a></em></p>
<h2 id="heading-summary">Summary</h2>
<p>I think after this in-depth analysis we can agree that Paint is the best tool for beautiful indentation.</p>
<p>And I hope I could convince you that, at the very least, you shouldn't let people choose their indentation completely freely.</p>
]]></content:encoded></item><item><title><![CDATA[Why Kotlin's Better Types Matter a Lot]]></title><description><![CDATA[Kotlin has lots of advantages over Java, but one that I find easily overlooked is their two special classes: data classes and inline classes.
Data classes seem at first just like some minor time save during development, but I believe they can also le...]]></description><link>https://blog.oscarablinger.dev/why-kotlins-better-types-matter-a-lot</link><guid isPermaLink="true">https://blog.oscarablinger.dev/why-kotlins-better-types-matter-a-lot</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Java]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Sun, 17 Oct 2021 22:30:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634160412587/bXQZlQQ2s.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Kotlin has lots of advantages over Java, but one that I find easily overlooked is their two special classes: data classes and inline classes.
Data classes seem at first just like some minor time save during development, but I believe they can also lead to better code.
And inline classes are so often overlooked completely.</p>
<p>So let's look at why I think that these two classes actually have an impact on good code.</p>
<p><em>Cover image created by the author using <a target="_blank" href="https://carbon.now.sh/">Carbon</a>.</em></p>
<h2 id="data-classes-lead-to-cleaner-code">Data classes lead to cleaner code</h2>
<p>Kotlin's data classes are essentially just a quicker way to create POJOs.
They generate getters, setters, <code>hashcode</code>, <code>equals</code> and <code>toString</code> automatically for you.
Java 17 introduced something similar in the form of records, <a target="_blank" href="https://blog.oscarablinger.dev/the-difference-between-kotlins-data-classes-and-java-16-records">although there are some slight differences</a>. Pretty much everything I'll say about them, also apply to records.</p>
<p>For those that don't know, the following is a data class:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span></span>(<span class="hljs-keyword">val</span> name: String, <span class="hljs-keyword">var</span> age: <span class="hljs-built_in">Int</span>)
</code></pre>
<p>Without it, in pre-17 Java we'd have to write the following:</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">equals</span><span class="hljs-params">(Object o)</span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span> == o) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">if</span> (o == <span class="hljs-keyword">null</span> || getClass() != o.getClass()) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        Person person = (Person) o;
        <span class="hljs-keyword">return</span> age == person.age &amp;&amp; Objects.equals(name, person.name);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hashCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Objects.hash(name, age);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Person{"</span> +
                <span class="hljs-string">"name='"</span> + name + <span class="hljs-string">'\''</span> +
                <span class="hljs-string">", age="</span> + age +
                <span class="hljs-string">'}'</span>;
    }
}
</code></pre><p>The obvious part is that we save a lot of code that has to be written and, worse than that, <em>read</em>.
But the less obvious, but much more important difference is that changing something requires a lot of changes – some of which are easy to miss and likely won't cause any tests to fail.
It's pretty easy to add a field and forget to also add it to the <code>hashCode</code> or <code>equals</code> method.</p>
<p>Making it hard to change or create a class also discourages programmers from doing so.
For instance, in 99% of the cases having a boolean value in the constructor of a class means that that class should be split into two different ones.
Yet, you'll find that in any bigger code base, simply because adding a boolean field takes around 5 minutes, while creating another class could take up to 20 if it's big.
While 15 minutes might seem like a small price to pay for cleaner architecture, very few will actually choose that option.</p>
<h2 id="inline-classes-can-make-cleaner-code-performant-or-even-viable">Inline classes can make cleaner code performant (or even viable)</h2>
<p>Inline classes are essentially as close to custom value types as you can currently get on the JVM.
Let's say you have the following inline class: (example taken from the <a target="_blank" href="https://kotlinlang.org/docs/inline-classes.html#members">kotlin documentation</a>).</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@JvmInline</span>
value <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Name</span></span>(<span class="hljs-keyword">val</span> s: String) {
    <span class="hljs-keyword">init</span> {
        require(s.length &gt; <span class="hljs-number">0</span>) { }
    }

    <span class="hljs-keyword">val</span> length: <span class="hljs-built_in">Int</span>
        <span class="hljs-keyword">get</span>() = s.length

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">greet</span><span class="hljs-params">()</span></span> {
        println(<span class="hljs-string">"Hello, <span class="hljs-variable">$s</span>"</span>)
    }
}
</code></pre>
<p>Kotlin will then try to prevent the creation of an object as much as possible and instead use the raw type (in this case <code>String</code>).
Instance method calls as well as property getters will then instead be compiled to static method calls.</p>
<p>The main reason why I like this is that it finally allows a performant way to implement <a target="_blank" href="https://darrenhobbs.com/2007/04/11/tiny-types/">tiny types</a>.
While I'm a big fan of that idea, I could never use it in any serious project since my job demands high performance standards, where the object churn of that technique in Java would be a very real problem.
Nevertheless, I believe that the benefits are huge.
And with the quick way to create a new class and the possibility to do that without creating an extreme amount of instances, this now becomes a very real and easy-to-implement style.</p>
<h3 id="downsides-of-inline-classes">Downsides of inline classes</h3>
<p>Sadly, I also see some downsides to inline classes:</p>
<ol>
<li><strong>They only work with one parameter.</strong> This is a major limitation, which means that when you need to group multiple values together, you'll still need to create an object every time.</li>
<li><strong>It sometimes provides false security.</strong> When "instantiating" an inline class it's easy to think that it will never actually be created. However, in some cases that's not true. Mainly when it is being used as one of its interfaces or when it is used in a generic method.</li>
<li><strong>They have to be final.</strong> Although I don't think this is a big problem as I don't see many reasons to extend a class with only one input field.</li>
</ol>
<h2 id="summary">Summary</h2>
<p>When comparing Java and Kotlin, data types and inline classes are usually just quickly mentioned as nice-to-haves.
But I think that is really underselling them.
They not only provide ways to reduce boilerplate code, but are also safer to use, can allow for a performant usage of tiny types and similar clean code styles and reduce the friction to crafting cleaner code – and friction is the enemy of good software.</p>
]]></content:encoded></item><item><title><![CDATA[The Most Important Thing about a Software is not that it Works]]></title><description><![CDATA[I see so much focus on how to create the perfect piece of software: easily maintained, extremely extensible, blazing fast and with beautiful idiomatic code. And all that is fine, but it's really just the last step when creating a program or feature.
...]]></description><link>https://blog.oscarablinger.dev/the-most-important-thing-about-a-software-is-not-that-it-works</link><guid isPermaLink="true">https://blog.oscarablinger.dev/the-most-important-thing-about-a-software-is-not-that-it-works</guid><category><![CDATA[software development]]></category><category><![CDATA[features]]></category><category><![CDATA[APIs]]></category><category><![CDATA[api]]></category><category><![CDATA[software]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Sun, 10 Oct 2021 13:08:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633863599360/XxiGRQP_x.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I see so much focus on how to create the perfect piece of software: easily maintained, extremely extensible, blazing fast and with beautiful idiomatic code. And all that is fine, but it's really just the last step when creating a program or feature.</p>
<p><em>Title photo created by <a target="_blank" href="https://picjumbo.com/author/viktorhanacek/">Victor</a> on <a target="_blank" href="https://picjumbo.com">picjumbo</a>.</em></p>
<h2 id="the-perfect-software-that-noone-uses">The perfect software that noone uses</h2>
<p>I think we've all been there: You're randomly browsing the web and then find a interesting project. And it has everything you could want: It's fast, it looks good and has an extensive amount of features, even some that you wouldn't even have thought of.</p>
<p>But you're not gonna use it. Why? <strong>Because you have no need to.</strong> Maybe you want bar charts and the software only makes pie charts.</p>
<p>The problem is that you'd rather use imperfect, buggy software that in the end solves one of your pain points than use a perfect software, that does something else.
But as a developer it's often easy to forget that.</p>
<h2 id="youve-done-this-before">You've done this before</h2>
<blockquote>
<p>Make things that people want to use.</p>
</blockquote>
<p>That seems obvious doesn't it? Yet it's surprisingly common to disregard this.</p>
<p>Filling a specific need is the basis of every entrepreneurial endeavor, but more often than that I've seen it disregarded in APIs.
Too often I've seen what should be a simple API turned into a complex one by the addition of too many (unnecessary) features.</p>
<p>I know that I'm guilty of doing this myself before: Sometimes it's so easy to make something more powerful than it needs to be that it's hard to resist.
But there is multiple problems with doing that:</p>
<ul>
<li>It needs more time to develop.</li>
<li>The API becomes harder to understand.</li>
<li>The code itself becomes harder to understand.</li>
<li>The API will be harder to extend. Even when the added complexity is making it more extensible, if you need to change it in a way that was not foreseen, you'll now have to extend a more complex system and maybe even need to do extra work to support the additional features that might not even be in use.</li>
</ul>
<p>Especially when your API is far away from your actual end user, it becomes easy to forget about the internal user.
Yet, I find user-focus just as important when they are your colleagues than when they are your paying customer.</p>
<h2 id="how-can-we-stop-over-engineering">How can we stop over-engineering?</h2>
<p>This might be different for each person, but the processes in most software development frameworks like scrum already try to have built-in safeguards against this. Sometimes even explicitly in the form of non-requirements.</p>
<p>Personally, I try to follow the following steps even in private projects:</p>
<ol>
<li>Specify exactly what I want to solve in this iteration. Usually this takes the form of a bullet list of 2-6 use cases.</li>
<li>See if it makes sense to split it up.</li>
<li>Write down how I would like to put my use cases into code.</li>
<li>Write the necessary interface for these code samples.</li>
<li>Think through how it would work and, if needed, add more inputs or outputs to the interfaces (e.g. you need user credentials after all; or you might have another error that you should report).</li>
<li>Implement these interfaces. If I realize that I can't, <strong>I go back to step 3 and not any later step</strong>.</li>
</ol>
<p>These steps help me to keep the focus on the actual requirements and not some potential requirements.
I find it especially important to return to step 3 if you're stuck at step 6.
Because that is the easiest way to make changes that negatively influence the API usage afterwards.</p>
<p>And since it can be frustrating to not get to implement the "cool but unnecessary" ideas, I like to write them down.
That way I don't feel like I'm completely disregarding them, but that I can simply implement them at a later point if I decide that they are useful additions.</p>
<p>These steps should of course be fitted into your current framework – for instance in scrum you'd probably make a refinement somewhere between step 1 and 4 depending on the style of the product owner.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This topic might be one of those things where you can feel the seniority of developers. Most lists about the mistakes of junior developers include a form of "don't do too much".
I guess, once you've written enough cool code that no one ever used, it becomes less fun?</p>
<p>Anyways, one of the more important skills of software engineers, I find, is to have a good top-down view. Don't just understand how to make things work the best, but also understand how to help your user the best.</p>
]]></content:encoded></item><item><title><![CDATA[The Difference between Kotlin’s Data Classes and Java 16 Records]]></title><description><![CDATA[When Java first introduced records as a preview in Java 14 and later released it with Java 16, it reminded many of Kotlin’s data classes. While they address the same problem in a very similar manner, there are a few differences in how they are handle...]]></description><link>https://blog.oscarablinger.dev/the-difference-between-kotlins-data-classes-and-java-16-records</link><guid isPermaLink="true">https://blog.oscarablinger.dev/the-difference-between-kotlins-data-classes-and-java-16-records</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Java]]></category><category><![CDATA[data structures]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Sun, 05 Sep 2021 22:22:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809821644/xJafwxoP0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When Java first introduced records as a preview in Java 14 and later released it with Java 16, it reminded many of Kotlin’s data classes. While they address the same problem in a very similar manner, there are a few differences in how they are handled.</p>
<p>I’ll list them roughly in the order of most relevant to more fringe. I tried to find all of the differences that exist, but if I missed something, feel free to comment about it.</p>
<p><em>Title photo by <a target="_blank" href="https://unsplash.com/@trommelkopf?utm_source=medium&amp;utm_medium=referral">Steve Harvey</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></em></p>
<h2 id="examples-and-why-they-matter">Examples &amp; why they matter</h2>
<p>Before getting into the differences, I want to show some examples. If you already know how they work, you can skip this section.</p>
<p>Java’s records use the new key word <code>record</code>:</p>
<pre><code><span class="hljs-type">record</span> <span class="hljs-type">Name</span>(String firstName, String lastName) { }
</code></pre><p>Meanwhile, Kotlin’s data classes use the modifier <code>data</code> in front of the class:</p>
<pre><code><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Name</span></span>(<span class="hljs-keyword">val</span> firstName: String, <span class="hljs-keyword">val</span> lastName: String)
</code></pre><p>Both automatically create most of the boilerplate code that you’d otherwise have to create: getters, setters, <code>equals</code>, <code>hashcode</code> and <code>toString</code>.</p>
<p>This not only helps reduce boilerplate code, but can also make refactoring safer, since now you don’t have to remember to add a new field to the now auto-generated methods.</p>
<h2 id="final-classes">Final classes</h2>
<p>Both records and data classes will compile to final classes. For Kotlin, this is the default for all classes, but data classes cannot be declared <code>open</code>.</p>
<h2 id="mutable-members">Mutable members</h2>
<p>Java’s records are completely immutable. With data classes, however, you can specify which fields are mutable and which are not (as usual with the <code>var</code> vs <code>val</code> keywords). For example, in the following code, <code>id</code> cannot be reassigned, but <code>name</code> can be:</p>
<pre><code><span class="hljs-type">record</span> Person(val id: <span class="hljs-type">Int</span>, var <span class="hljs-type">name</span>: <span class="hljs-type">Name</span>)
</code></pre><p>In the case of immutable fields, it will mark them as <code>final</code> in the resulting code. Java’s records always have <code>final</code> fields.</p>
<h2 id="non-constructor-fields">Non-constructor fields</h2>
<p>Records do not allow you to define additional instance fields, only static ones. With data classes, however, you can. These are, of course, not included in the automatically generated methods, but can be useful for some eagerly created values:</p>
<pre><code><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Name</span></span>(<span class="hljs-keyword">val</span> firstName: String, <span class="hljs-keyword">val</span> lastName: String) {
    <span class="hljs-keyword">val</span> fullName = firstName + <span class="hljs-string">' '</span> + lastName
}
</code></pre><h2 id="javalangrecord">java.lang.Record</h2>
<p>Java’s records now always implement the new class <code>[java.lang.Record</code>](https://download.java.net/java/early_access/jdk17/docs/api/java.base/java/lang/Record.html). This abstract class doesn’t add any interesting methods by itself, but can be used to catch all records.</p>
<p>This super class also means that <strong>records cannot extend other classes</strong> — although they can still implement interfaces. Data classes do not have this restriction.</p>
<h2 id="destructuring">Destructuring</h2>
<p>Kotlin already supports destructuring for data classes. For Java, <a target="_blank" href="https://cr.openjdk.java.net/~briangoetz/amber/serialization.html#sidebar-pattern-matching">there is currently a proposal floating around</a>, but no current version of Java (including Java 17) supports this syntax.</p>
<h3 id="kotlins-destructuring">Kotlin’s destructuring</h3>
<p>Kotlin has destructuring built into it’s assignment syntax. Given the <code>Person</code> class from before, I can now do the following:</p>
<pre><code>val (id, <span class="hljs-type">name</span>) = Person(<span class="hljs-number">0</span>, <span class="hljs-type">Name</span>("Oscar", "Ablinger"))
</code></pre><p>This will be compiled to two different assignment statements utilizing another set of auto-generated methods. It’s essentially syntactic sugar for the following two statements:</p>
<pre><code><span class="hljs-keyword">val</span> id = person.component1()
<span class="hljs-keyword">val</span> name = person.component2()
</code></pre><p>These two are typed, so the resulting variables will update their types when changing the field types. They also don’t have to be exhaustive, so when you add another filed, then the same code will still work.</p>
<p>This, however, means that if you add a field as anything but the last element and it shares the type with the field it replaced, <strong>the code will compile and no error will be given!</strong> This a a very hard to track down source of bugs.</p>
<h2 id="tostring">toString</h2>
<p>While both get an auto-generated <code>toString</code> method, the results look slightly different for Java and Kotlin. Java will generate the following string:</p>
<pre><code><span class="hljs-type">record</span> <span class="hljs-type">Name</span>(String firstName, String lastName) { }

<span class="hljs-built_in">new</span> <span class="hljs-type">Name</span>("Oscar", "Ablinger").toString();
// <span class="hljs-type">Name</span>[firstName=Oscar, lastName=Ablinger]
</code></pre><p>Kotlin generates a similar string:</p>
<pre><code><span class="hljs-selector-tag">data</span> <span class="hljs-selector-tag">class</span> <span class="hljs-selector-tag">Name</span>(val <span class="hljs-attribute">firstName</span>: String, val <span class="hljs-attribute">lastName</span>: String)

<span class="hljs-selector-tag">Name</span>(<span class="hljs-string">"Oscar"</span>, <span class="hljs-string">"Ablinger"</span>)<span class="hljs-selector-class">.toString</span>()
<span class="hljs-comment">// Name(firstName=Oscar, lastName=Ablinger)</span>
</code></pre><p>As you can see, the only real difference is that Java uses square brackets while Kotlin uses parenthesis. Annoyingly enough, the default <code>toString</code> that IntelliJ generates for classes uses braces.</p>
<p>You could also use this generated string as basis for your style guide for the <code>toString</code> method.</p>
<h2 id="reflection">Reflection</h2>
<p>Data classes are essentially just syntactic sugar over normal classes. Therefore, once compiled, it’s pretty much impossible to tell them apart from other classes.</p>
<p>Records however can be easily recognized using reflection. Not only because they always implement the <code>java.lang.Record</code> type, but also thanks to two new methods added to <code>Class</code>: <code>[isRecord</code>](https://download.java.net/java/early_access/jdk17/docs/api/java.base/java/lang/Class.html#isRecord()) and <code>[getRecordComponents</code>](https://download.java.net/java/early_access/jdk17/docs/api/java.base/java/lang/Class.html#getRecordComponents()).</p>
<p><code>isRecord</code> simply returns <code>true</code> if the class is a record and <code>false</code> otherwise.</p>
<p><code>getRecordComponents</code> returns information about all of the fields of the record or <code>null</code> if it’s not a record. The term “component” is simply used to refer to the non-static fields of a record. Using this you have access to the same information that you’d expect from methods: annotations, name, type and more.</p>
<h2 id="getters">Getters</h2>
<p>Kotlin generates getters after the well-known pattern with <code>get</code> prefix. Records now dropped this prefix and instead name the methods the same as the field.</p>
<h2 id="implementations">Implementations</h2>
<p>I already wrote about the different results of the <code>toString</code> methods. Additionally, the implementation of all of the methods is also done differently.</p>
<p>While the Kotlin compiler simply generates the code for each of the methods, Java outsources the actual code to a static method. The implementation of those methods simply call the <code>[ObjectMethods.bootstrap</code>](https://download.java.net/java/early_access/jdk17/docs/api/java.base/java/lang/runtime/ObjectMethods.html#bootstrap(java.lang.invoke.MethodHandles.Lookup,java.lang.String,java.lang.invoke.TypeDescriptor,java.lang.Class,java.lang.String,java.lang.invoke.MethodHandle...)) method with the necessary information. I assume this is done to reduce the byte size of records as much as possible.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In the end, data classes and records are pretty similar in their usage. But while data classes are simply syntactic sugar, records add a lot to the Java standard library. Nonetheless, data classes do allow for more features than records. Whether that’s a strictly good thing is a different debate.</p>
]]></content:encoded></item><item><title><![CDATA[The ultimate guide to Futures in Java and Guava]]></title><description><![CDATA[In Java 8 CompletableFuture was introduced to finally bring a better way to work with asynchronous logic into Java. Meanwhile Guava has created its own solutions for this problem.
Now, which one should you use?
First let me start by pointing out that...]]></description><link>https://blog.oscarablinger.dev/the-ultimate-guide-to-futures-in-java-and-guava</link><guid isPermaLink="true">https://blog.oscarablinger.dev/the-ultimate-guide-to-futures-in-java-and-guava</guid><category><![CDATA[Java]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Future]]></category><category><![CDATA[asynchronous]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Tue, 24 Aug 2021 00:10:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633822903380/P4oknkHn9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Java 8 <a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html"><code>CompletableFuture</code></a> was introduced to finally bring a better way to work with asynchronous logic into Java. Meanwhile Guava has created its own solutions for this problem.</p>
<p>Now, which one should you use?</p>
<p>First let me start by pointing out that Guava has many classes that interact with futures and are meant to be used along-side each other. So most of those classes don’t necessarily step on each others toes.</p>
<p>But first, let’s look at the vanilla Java implementations:</p>
<p><em>Title photo by <a target="_blank" href="https://unsplash.com/@dizzyd718?utm_source=medium&amp;utm_medium=referral">Drew Graham</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></em></p>
<h2 id="future">Future</h2>
<p><a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html"><code>Future</code></a> is the base interface and is used by Java’s own <code>CompletableFuture</code> and most of the interfaces and classes of Guava. It’s been around since Java 5.</p>
<p>The interface is very rudimentary, only offering methods to check its status, cancel it or gett the result in a blocking way (optionally with timeout). This works for the simplest cases, but if you want to work with multiple <code>Future</code>s at once or maybe even chain operations, this interface alone quickly becomes tedious.</p>
<p>Some example code taken from the java documentation:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ArchiveSearcher</span> </span>{ <span class="hljs-keyword">String</span> search(<span class="hljs-keyword">String</span> target); }
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> </span>{

    ExecutorService executor = ...
    ArchiveSearcher searcher = ...

    <span class="hljs-keyword">void</span> showSearch(<span class="hljs-keyword">final</span> <span class="hljs-keyword">String</span>) throws InterruptedException {

        Future&lt;<span class="hljs-keyword">String</span>&gt; future
          = executor.submit(<span class="hljs-keyword">new</span> <span class="hljs-keyword">Callable</span>&lt;<span class="hljs-keyword">String</span>&gt;() {
            <span class="hljs-keyword">public</span> <span class="hljs-keyword">String</span> call() {
                <span class="hljs-keyword">return</span> searcher.search(target);
            }});

        displayOtherThings(); <span class="hljs-comment">// do other things while searching</span>

        <span class="hljs-keyword">try</span> {
            displayText(future.get()); <span class="hljs-comment">// use future</span>
        } <span class="hljs-keyword">catch</span> (ExecutionException ex) { cleanup(); <span class="hljs-keyword">return</span>; }
    }
}
</code></pre><h2 id="completablefuture">CompletableFuture</h2>
<p>In Java 8 <a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html"><code>CompletableFuture</code></a> and its interface <code>CompletableTask</code> were added to allow more powerful operations with futures. Those two are so tightly coupled that the interface can essentially be ignored.</p>
<p><code>CompletableFuture</code> implements <code>Future</code> and also offers some more methods to work with the result:</p>
<ul>
<li><p><code>thenAccept</code> allows you to register a function that will be called upon completion and whose result will be used for a new <code>CompletableFuture</code> that is returned from this method.</p>
</li>
<li><p><code>exceptionally</code> does the same as <code>thenAccept</code>, except that it is called when the <code>CompletableFuture</code> is completed exceptionally.</p>
</li>
<li><p><code>handle</code> allows you to handle both the success value as well as the exception in the same function.</p>
</li>
<li><p><code>join</code> will block until the <code>CompletableFuture</code> completes and either return the value or throw any of the occurring exceptions.</p>
</li>
</ul>
<p>It also offers you some convenience methods to create <code>CompletableFutures</code>:</p>
<ul>
<li><p><code>supplyAsync</code> let’s you specify a Supplier that will be called asynchronously and whose result will be the result of the <code>CompletableFuture</code> once finished.</p>
</li>
<li><p><code>completedFuture</code> will immediately return a successfully completed future. It’s counterpart <code>failedFuture</code> was added in Java 9.</p>
</li>
</ul>
<p>Some example code:</p>
<pre><code><span class="hljs-keyword">public</span> CompletableFuture&lt;<span class="hljs-keyword">List</span>&lt;User&gt;&gt; loadActiveUsers() {

    <span class="hljs-keyword">return</span> httpClient.&lt;<span class="hljs-keyword">List</span>&lt;User&gt;&gt;sendAsync(request, bodyHandler)
        .thenApply(this::filterListOfUsersForActiveOnes)
        .exceptionally(<span class="hljs-built_in">throwable</span> -&gt; {
            LOG.warn(<span class="hljs-built_in">throwable</span>);
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">List</span>.of();
       });
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> displayListOfActiveUsers() {

    <span class="hljs-keyword">try</span> {
        CompletableFuture&lt;&gt; activeUsersFuture = loadActiveUsers();
        displayOtherStuff();

        <span class="hljs-keyword">try</span> {
            displayActiveUsers(activeUsersFuture.join());
        } <span class="hljs-keyword">catch</span> (CompletionException e) {
            LOG.<span class="hljs-built_in">error</span>(e);

            displayNoUsers();
        }
    }
}
</code></pre><h3 id="problems-with-completablefuture">Problems with <code>CompletableFuture</code></h3>
<p>While the fluent style of <code>CompletableFuture</code> is certainly a great improvement to the bare-bones approach of <code>Future</code>, it still has its quirks.</p>
<p>For one it’s easy to forget that it can also be canceled. This means that if you return a <code>CompletableFuture</code> <strong>the caller can cancel it! </strong>This might leave you with resources not being properly closed or an unexpected state. The easiest way to avoid this is to wrap your <code>CompletableFuture</code> in another one.</p>
<p>Another problem is also that exceptions are handled slightly inconsistently, which the documentation doesn’t mention:</p>
<pre><code>NullPointerException <span class="hljs-built_in">exception</span> = <span class="hljs-keyword">new</span> NullPointerException(<span class="hljs-string">":("</span>);

CompletableFuture.failedFuture(<span class="hljs-built_in">exception</span>)
    .exceptionally(<span class="hljs-built_in">throwable</span> -&gt; {
        <span class="hljs-comment">// here throwable is the exception from above</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    });

CompletableFuture.failedFuture(<span class="hljs-built_in">exception</span>)
    .thenApply(<span class="hljs-keyword">Object</span>::toString)
    .exceptionally(<span class="hljs-built_in">throwable</span> -&gt; {
        <span class="hljs-comment">// here throwable is a CompletionException that wraps the</span>
        <span class="hljs-comment">//  exception from above</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    });
</code></pre><p>Lastly, handling only specific exceptions isn’t that easy. The function in <code>exceptionally</code> receives an instance of <code>Throwable</code>, which is a checked exception. This means you can’t re-throw it without first wrapping it in a <code>RuntimeException</code>, preferably a <code>CompletionException</code>.</p>
<p>While a <code>CompletionException</code> thrown in one of those methods is directly returned (for instance when using <code>join</code>), nested ones are not unwrapped. This means that you’ll likely end up with some boilerplate code like this:</p>
<pre><code>.exceptionally(<span class="hljs-built_in">throwable</span> -&gt; {
    <span class="hljs-keyword">while</span> (<span class="hljs-built_in">throwable</span> <span class="hljs-keyword">instanceof</span> CompletionException) {
        <span class="hljs-built_in">throwable</span> = <span class="hljs-built_in">throwable</span>.getCause();
    }

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">throwable</span> <span class="hljs-keyword">instanceof</span> NullPointerException) {
        <span class="hljs-comment">// handle the exception I care about</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> CompletionException(<span class="hljs-built_in">throwable</span>);
    }
})
</code></pre><h2 id="futures">Futures</h2>
<p>Moving away from the Java standard library, Guava’s static class <a target="_blank" href="https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/Futures.html"><code>Futures</code></a> contains methods to more effectively work with Futures. It does so mostly by utilizing the <code>ListenableFuture</code> interface that we’ll look at next.</p>
<p>Notably, however, it also has a <code>transform</code> method that allows you to create a new future based on another one and a function. The new future will complete with the result of the provided one being transformed by the given function. This essentially mimics the way that <code>CompletableFuture.thenApply</code> works.</p>
<p>This class should be your first stop when trying to work with futures and Guava!</p>
<h2 id="listenablefuture">ListenableFuture</h2>
<p><a target="_blank" href="https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFuture.html"><code>ListenableFuture</code></a> is a simple interface in Guava that implements <code>Future</code> and only adds one method: <code>addListener</code>.</p>
<p>This method allows you to register listeners that are called once the future completes. Albeit they do not directly get the result, you may get it using the <code>get</code> method of the <code>ListenableFuture</code> itself.</p>
<p>This interface is the main one utilized in the <code>Futures</code> class. It is also implemented by most of Guava’s future classes.</p>
<h3 id="listenablefuturetask">ListenableFutureTask</h3>
<p><a target="_blank" href="https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFutureTask.html">This class</a> is essentially a bare-bones implementation of the <code>ListenableFuture</code> interface. It has two factory methods using <code>Callable</code> or <code>Runnable</code> but otherwise only implements the methods of its interface.</p>
<h3 id="settablefuture">SettableFuture</h3>
<p><a target="_blank" href="https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/SettableFuture.html"><code>SettableFuture</code></a> extends the methods of the <code>ListenableFuture</code> interface with setter methods. You can set its success value, exception or even set it based on another future.</p>
<p>This class is mainly useful for when you already have a thread on which you want to complete your future.</p>
<h3 id="abstractfuture">AbstractFuture</h3>
<p>As the name implies <a target="_blank" href="https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/AbstractFuture.html"><code>AbstractFuture</code></a> is an abstract implementation of the <code>ListenableFuture</code> interface. Beyond the already mentioned <code>addListener</code> and setters, it also has some methods that expose its internal state.</p>
<p>It’s unlikely that you’ll need this class, but it can be used to implement your own versions of <code>ListenableFuture</code>.</p>
<h2 id="fluentfuture">FluentFuture</h2>
<p><code>FluentFuture</code> is the most similar to Java’s <code>CompletableFuture</code>. It implements <code>ListenableFuture</code> and also offers mapping methods in <code>transform</code> and <code>catching</code>.</p>
<p>In this case <code>catching</code> allows catching specific exceptions, not just a <code>Throwable</code>. This enables a more selective approach to exception handling where the theoretical possibility of checked exceptions doesn’t result in a lot of boilerplate code.</p>
<p>Some example code taken from its documentation:</p>
<pre><code>ListenableFuture&lt;<span class="hljs-type">Boolean</span>&gt; adminIsLoggedIn =
     FluentFuture.<span class="hljs-keyword">from</span>(usersDatabase.getAdminUser())
         .<span class="hljs-keyword">transform</span>(<span class="hljs-keyword">User</span>::getId, directExecutor())
         .<span class="hljs-keyword">transform</span>(ActivityService::isLoggedIn, threadPool)
         .catching(RpcException.<span class="hljs-keyword">class</span>, e -&gt; <span class="hljs-keyword">false</span>, directExecutor());
</code></pre><h2 id="closingfuture">ClosingFuture</h2>
<p><a target="_blank" href="https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ClosingFuture.html"><code>ClosingFuture</code></a> is similar to <code>FluentFuture</code>, but acts more as a builder than a future itself. It offers methods to transform values, catch exceptions and combining multiple of them. At the end a <code>ClosingFuture</code> always has to be “finished”.</p>
<p>There is currently two ways you can finish it:</p>
<ul>
<li><p><code>finishToFuture</code> will return a <code>FluentFuture</code> that will complete once all of the steps defined by the <code>ClosingFuture</code> are completed.</p>
</li>
<li><p><code>finishToValueAndCloser</code> will call a callback once finished.</p>
</li>
</ul>
<p>An example from its documentation:</p>
<pre><code class="lang-java">FluentFuture&lt;UserName&gt; userName =
     ClosingFuture.submit(
             closer -&gt; closer.eventuallyClose(database.newTransaction(), closingExecutor),
             executor)
         .transformAsync((closer, transaction) -&gt; transaction.queryClosingFuture(<span class="hljs-string">"..."</span>), executor)
         .transform((closer, result) -&gt; result.get(<span class="hljs-string">"userName"</span>), directExecutor())
         .catching(DBException.class, e -&gt; <span class="hljs-string">"no user"</span>, directExecutor())
         .finishToFuture();
</code></pre>
<h2 id="conclusion">Conclusion</h2>
<p>When working with vanilla Java, your best bet is <code>CompletableFuture</code>. Once you also have Guava, you have a myriad of options to choose from. All of them fill slightly different niches and are meant for different levels of detail.</p>
<p>In the end, Guava’s many classes can quickly become overwhelming and confusing.</p>
<p>Personally, I’ll probably try out <code>ClosingFuture</code> and <code>FluentFuture</code> a bit more, but stick with <code>CompletableFuture</code> for now — mainly because I can safely stick it in APIs without having to worry about introducing a new dependency.</p>
]]></content:encoded></item><item><title><![CDATA[Who did it better? Guava or Java?]]></title><description><![CDATA[Guava is one of if not the most popular Java libraries. But it has been around for a long time and Java has since implemented many features comparable to those found in Guava. The question is now, which one did it better?
Title photo by Juan Camilo G...]]></description><link>https://blog.oscarablinger.dev/who-did-it-better-guava-or-java</link><guid isPermaLink="true">https://blog.oscarablinger.dev/who-did-it-better-guava-or-java</guid><category><![CDATA[Java]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Libraries]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Mon, 16 Aug 2021 16:05:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809854654/XMVdKJ-tD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://guava.dev/">Guava</a> is one of if not the most popular Java libraries. But it has been around for a long time and Java has since implemented many features comparable to those found in Guava. The question is now, which one did it better?</p>
<p><em>Title photo by <a target="_blank" href="https://unsplash.com/@jcguarinpenaranda?utm_source=medium&amp;utm_medium=referral">Juan Camilo Guarin P</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></em></p>
<h2 id="immutable-collections">Immutable Collections</h2>
<p>Guava has immutable implementations for all of Java’s common collections and of course its own collections. While Java does not have interfaces for it, it offers two methods to create immutable collections: <code>[Collections.unmodifiableXXX</code>](https://docs.oracle.com/javase/9/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-) to wrap existing collections and <code>[XXX.of</code>](https://docs.oracle.com/javase/9/docs/api/java/util/List.html#of--) to create new ones.</p>
<p>I’ll take the example of <code>ImmutableList</code>, <code>Collections.unmodifiableList</code> and <code>List.of</code> for this post to simplify it, but the same things apply to all other versions.</p>
<h3 id="an-additional-dependency">An additional dependency</h3>
<p>Using Guava will introduce a new dependency to your code. In my opinion it’s well worth it. Even if you choose to go with Java’s implementations for the examples here, Guava still offers many utilities that make it worthwhile.</p>
<p>A different story is including Guava classes in your public API. In that case you’d force every user of that API to use Guava <em>and your specific version of it</em>. You’re also locked out from removing it as a dependency.</p>
<p>This <em>might</em> be fine for libraries where you know that the users will also be using Guava, but even there it should generally be avoided.</p>
<h3 id="an-explicit-tell">An explicit tell</h3>
<p>When you see <code>ImmutableList</code> somewhere, you know that that value is immutable. Not so much with Java’s methods, which will simply return a <code>List</code>.</p>
<p>This explicit tell is very useful:</p>
<ul>
<li><p><strong>In parameters:</strong> The caller is guaranteed that the method won’t mutate the list. On the other hand, the user must first wrap their collection in an immutable one.</p>
</li>
<li><p><strong>In return values:</strong> The caller knows that this collection shouldn’t be mutated. It also helps the implementation since you can often avoid to create new instances and only update the list when needed. And you don’t have to look at the documentation of a method to figure out whether mutating the returned collection is fine.</p>
</li>
<li><p><strong>In fields and variables:</strong> When reading the code, it is immediately apparent that this field or variable isn’t and shouldn’t be mutated. This can help with some of the mental overhead. It also catches some potential errors at “linting-time”.</p>
</li>
</ul>
<h3 id="less-defensive-copies">Less defensive copies</h3>
<p>In order to better guarantee that a given list is not changed in a given context, it is common to create defensive copies. “Defensive copies” refers to the practice of first creating an immutable version of a given collection and then operating strictly on that one.</p>
<p>This practice can help ensure that a list isn’t mutated when it shouldn’t be. However, this will only be noticed at runtime and costs some runtime compared to using the list directly.</p>
<p>Using the immutable version directly as parameter might force the user to create an immutable version instead, but it also signals to them that it can be reused in other methods that also don’t mutate the list. This might result in less copies being generated, but it will definitely result in more clarity, since I don’t need to see the implementation in order to know whether the list will be mutated.</p>
<h3 id="immutablelist-is-truly-immutable">ImmutableList is truly immutable</h3>
<p>Java’s <code>Collections.unmodifiableList</code> will only provide an immutable <strong>view </strong>on a collection. This is an important distinction.</p>
<p>First an foremost, this means that they aren’t truly immutable: They will change if the original instance is changed.</p>
<p>It also means that they won’t be able to take advantage of the immutability as much as Guava’s implementations can. They must still include unncessary concurrency checks, might allocate unnecessary space and more.</p>
<p>These differences are somewhat less relevant for the <code>List.of</code> method, which will create a new list anyways — even if the overload is used that takes an array of strings. However, it’s important to note that I couldn’t find this mentioned in any official documentation, so, technically, there is no guarantee that this will stay this way or is the same in all implementations.</p>
<p>Neither <code>ImmutableList</code> nor Java’s unmodifiable list prevent their elements from being modified, though. For that you’d have to create a deep copy. <a target="_blank" href="https://blog.wacekdziewulski.ovh/2019/10/28/java-unmodifiable-immutable-copyof/">During my research, I stumbled upon this nice blog post outlining the differences in those approaches in a nice, visual way.</a></p>
<h3 id="immutablelist-is-a-list">ImmutableList is a List</h3>
<p>This is maybe less of an argument for Guava’s implementation and more so an important note: <code>ImmutableList</code> implements the <code>List</code> interface.</p>
<p>This means that you can use an instance of <code>ImmutableList</code> everywhere that you could use an unmodifiable list from Java.</p>
<p>There is one case to watch out for, though: When the called method creates a defensive copy using the Java methods. In that case it will create a new instance instead of reusing the old one, when you pass an <code>ImmutableList</code>. When provided Java’s unmodifiable list, it would instead simply use that instance directly.</p>
<p>The same is true in reverse: <code>ImmutableList.copyOf</code> will not create a new instance if a <code>ImmutableList</code> is passed to it, but will if an unmodifiable list is passed instead.</p>
<p>Implementing the <code>List</code> interface also means that they share one of the big problems: You can still call methods that would modify a collection. It will then only fail at runtime, not compile time. This is mitigated better by Guava’s version since they actively mark those methods as <code>deprecated</code>, which will show up in most editors. Of course this only works when using the raw <code>ImmutableList</code> and not when using it as <code>List</code>.</p>
<h3 id="verdict">Verdict</h3>
<p>I believe that Guava’s collections bring a lot of value compared to the Java standard library methods, so I would always use those if Guava is in the project. I might even consider adding Guava just for them, but luckily Guava has plenty of other good features that make justifying adding it pretty easy.</p>
<h2 id="optional">Optional</h2>
<p>Before Java added Optional, Guava did. In this case, the probably best comparison is the one found <a target="_blank" href="https://guava.dev/releases/19.0/api/docs/com/google/common/base/Optional.html">in Guava’s own documentation</a>:</p>
<blockquote>
<p>A new <code>Optional</code> class was added for Java 8. The two classes are extremely similar, but incompatible (they cannot share a common supertype). <em>All</em> known differences are listed either here or with the relevant methods below.</p>
<ul>
<li>This class is serializable; <code>java.util.Optional</code> is not.</li>
<li><code>java.util.Optional</code> has the additional methods <code>ifPresent</code>, <code>filter</code>, <code>flatMap</code>, and <code>orElseThrow</code>.</li>
<li><code>java.util</code> offers the primitive-specialized versions <code>OptionalInt</code>, <code>OptionalLong</code> and <code>OptionalDouble</code>, the use of which is recommended; Guava does not have these.
<strong>There are no plans to deprecate this class in the foreseeable future.</strong> However, we do gently recommend that you prefer the new, standard Java class whenever possible.</li>
</ul>
</blockquote>
<p>So by Google’s own recommendation, you should opt for the Java library version. I tend to agree, mainly because you can use that version safely in public APIs. The extra methods (mainly <code>filter</code> and <code>flatMap</code>) are a nice bonus, too.</p>
<p>Weirdly enough, for some reason, those two methods together with <code>map</code> are missing from their primitive counterparts. I guess Oracle didn’t think them useful enough.</p>
<h2 id="charset-vs-standardcharset">Charset vs StandardCharset</h2>
<p>These two are virtually the same. Both provide the same list of charsets as static fields: UTF-8, UTF-16, UTF-16BE, UTF-16LE, US-ASCII and ISO-8859–1.</p>
<p>It also helps that <a target="_blank" href="https://guava.dev/releases/19.0/api/docs/com/google/common/base/Charsets.html">Guava’s documentation</a> has this sentence for each of the constants:</p>
<blockquote>
<p><strong>Note for Java 7 and later:</strong> this constant should be treated as deprecated; use <code>StandardCharsets.XXX</code> instead.</p>
</blockquote>
<p>So, for the same reason as with <code>Optional</code>, I’d recommend using Java’s versions instead.</p>
<h2 id="summary">Summary</h2>
<p>In summary, I’d go with Guava’s version of immutable collections, but with the standard library versions of <code>Optional</code> and charsets. For the later two, there is just not enough reason to use a library over the existing one.</p>
<p>To recap, the reasons for the immutable collections are:</p>
<ul>
<li><p>An explicit tell that something is immutable.</p>
</li>
<li><p>They can be used as a simple <code>List</code> just the same as Java’s implementation.</p>
</li>
<li><p>They aren’t modified if the source collection is modified (if one exists).</p>
</li>
<li><p>They can use the immutability to their advantage when implementing the collections. This means sometimes better runtime of methods and less required memory.</p>
</li>
</ul>
<p>However, they also have some negatives:</p>
<ul>
<li><p>They require an extra dependency, which is especially problematic if you want to use the classes/methods in public APIs.</p>
</li>
<li><p>They still have the same problems that come from implementing <code>List</code>.</p>
</li>
</ul>
<p>One last note: Guava also has its own ways to work with futures, while Java now has <code>CompletableFuture</code>. This topic deserves its own blog post, however, <a target="_blank" href="https://oscarablinger.medium.com/the-ultimate-guide-to-futures-in-java-and-guava-c53263dd69dc">so I have written one here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[The Error of Exceptions]]></title><description><![CDATA[When my classmates and I first learned about exceptions (in C++), I thought “Cool, I don’t have to return -1 and nullptr any more”. But a while later a friend brought up a good question: What’s the difference between exceptions and gotos?
Title Image...]]></description><link>https://blog.oscarablinger.dev/the-error-of-exceptions</link><guid isPermaLink="true">https://blog.oscarablinger.dev/the-error-of-exceptions</guid><category><![CDATA[Java]]></category><category><![CDATA[clean code]]></category><category><![CDATA[opinion pieces]]></category><category><![CDATA[error handling]]></category><category><![CDATA[Bugs and Errors]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Thu, 05 Aug 2021 08:02:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809826765/zhDdUxa54.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When my classmates and I first learned about exceptions (in C++), I thought “Cool, I don’t have to return <code>-1</code> and <code>nullptr</code> any more”. But a while later a friend brought up a good question: What’s the difference between exceptions and <code>goto</code>s?</p>
<p><em>Title Image made by the author using <a target="_blank" href="https://mermaid-js.github.io">mermaid.js</a></em></p>
<h2 id="the-problem-of-exceptions">The Problem of Exceptions</h2>
<p>Look at the following Java code and tell me what it could return:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getCurrentUsername</span><span class="hljs-params">()</span> </span>{
    User user = getCurrentUser();
    <span class="hljs-keyword">return</span> user.getUsername();
}
</code></pre>
<p>On the first look, this method could return a <code>String</code>, <code>null</code> or throw a <code>NullPointerException</code>, if <code>getCurrentUser</code> returns <code>null</code>.</p>
<p>But that’s not all, it could also throw any other unchecked exception. Maybe <code>getCurrentUser</code> returns an <code>IllegalStateException</code>, because some initialization is missing?</p>
<p>For the username it might be harmless, but what about the following?</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">unloadAllCachesOfUser</span><span class="hljs-params">(UserId userId)</span> </span>{
    Collection&lt;Cache&gt; caches = getCachesOfUser(userId);
    <span class="hljs-keyword">if</span> (caches != <span class="hljs-keyword">null</span>) {
        <span class="hljs-keyword">for</span> (Cache cache : caches) {
            cache.unload();
        }
    }
}
</code></pre>
<p>This kind of code can easily sneak through code reviews. But what if any one of the cache unloads throws an exception? In that case all of the other caches wouldn’t be unloaded and if <code>Cache</code> is an interface, it isn’t even clear what exceptions could be thrown.</p>
<p>This mistake is so common that many languages nowadays have a version of the <code>[try-with-resourses</code>](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) statement. Usually, they are used for file streams or connections to ensure that they are closed properly. But it’s easy to overlook for other cases, where it’s fine <em>most</em> of the time. Be honest: how often do you think about “What if this method throws an exception?”</p>
<h2 id="exceptions-are-worse-than-gotos-in-some-ways">Exceptions are worse than gotos (in some ways)</h2>
<p>Back to the original story. I don’t know what answer we came up with back then, but this is what I’d say now:</p>
<p>They are similar, but there are a few differences:</p>
<ol>
<li><p>I can send some data with it,</p>
</li>
<li><p>I can contain it when calling a method (by wrapping it in a <code>try-catch</code>), and</p>
</li>
<li><p><strong>I don’t know where I’ll be going.</strong></p>
</li>
</ol>
<p>The last one is a pretty big deal: When you see a <code>throw</code> statement, you don’t immediately know, what code will be executed next. Worse even, sometimes you can’t know, because the method could be called from multiple sources.</p>
<p>When writing a method this is perfectly fine — the method does one thing and that’s all we should care about. We should ignore the context around it for the most part anyway.</p>
<p>But when reviewing code, this can quickly become hard to understand/read. And how would I make sure that all callers of my method properly handle it?</p>
<p>Which leads to the problem of the previous example: <strong>How do I know what exceptions a method can return?</strong> And the answer is, that I’d have to read all of the code that that method might use and look for <code>throw</code> statements. Then I need to see if they’re handled or not. Even some libraries with otherwise good documentation like to keep an air of mystery around which exceptions are thrown and when.</p>
<h2 id="exceptions-are-better-than-gotos-in-some-ways">Exceptions are better than gotos (in some ways)</h2>
<p>So why are exceptions then commonly accepted, while <code>goto</code>s are almost universally avoided?</p>
<p>The answer is the first two points in the previous section. If used correctly, exceptions aren’t that bad.</p>
<h3 id="you-can-catch-exceptions">You can catch exceptions</h3>
<p>Unlike <code>goto</code>s, the caller of a function can actually interact with exceptions. You can ensure that even if an exception is thrown, you get a chance to close a file stream, close a connection or still execute some code to prevent an illegal state.</p>
<p>This already mitigates a big part of the danger of <code>goto</code>s as I can make sure that certain code is executed in any event.</p>
<h3 id="you-can-send-some-data-with-it">You can send some data with it</h3>
<p>Sending additional information about why this jump outside of the regular flow is made can give considerate context to it. Instead of just telling you which code should be executed next, it tells you what happened.</p>
<p>Of course, this can be abused. Exceptions can now also be used as an additional return value of functions — and sadly, often are. There is this idea to not use exceptions for flow control, but all exceptions necessarily control the flow of a program. You just need to make sure that an exception is actually the exception.</p>
<h2 id="the-alternative">The alternative</h2>
<p>So what should we’ve learned instead to replace all of the <code>-1</code>s and <code>nullptr</code>s?</p>
<p>One of my favorite things to make an API safer and easier to use is extending its domain. What I mean by that is that it takes any error states and handles them the same way that it would success returns: It accepts it as valid input and presents it to the user, in the same way, encouraging and sometimes forcing a user to gracefully handle them both.</p>
<p>This can be done generically with the <code>Result</code> type (also sometimes called <code>Throw</code> or <code>Either</code>). A very basic implementation is below:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Result</span>&lt;<span class="hljs-title">T</span>&gt; </span>{
    <span class="hljs-keyword">private</span> Object value;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> isSuccess;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Result</span><span class="hljs-params">(Object value, <span class="hljs-keyword">boolean</span> isSuccess)</span> </span>{
        <span class="hljs-keyword">this</span>.value = value;
        <span class="hljs-keyword">this</span>.isSuccess = isSuccess;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> &lt;T&gt; <span class="hljs-function">Result&lt;T&gt; <span class="hljs-title">success</span><span class="hljs-params">(T successValue)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Result(successValue, <span class="hljs-keyword">true</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> &lt;T&gt; <span class="hljs-function">Result&lt;T&gt; <span class="hljs-title">failure</span><span class="hljs-params">(Throwable ex)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Result(ex, <span class="hljs-keyword">false</span>);
    }

    <span class="hljs-keyword">public</span> &lt;R&gt; <span class="hljs-function">Result&lt;R&gt; <span class="hljs-title">flatMap</span><span class="hljs-params">(Function&lt;T, Result&lt;R&gt;&gt; transform)</span> </span>{
        <span class="hljs-keyword">if</span> (isSuccess) {
            <span class="hljs-keyword">return</span> transform.apply((T)value);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> (Result&lt;R&gt;) <span class="hljs-keyword">this</span>;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFailure</span><span class="hljs-params">(Consumer&lt;Throwable&gt; handler)</span> </span>{
        <span class="hljs-keyword">if</span> (!isSuccess) {
            handler.accept((Throwable)value);
        }
    }
}
</code></pre>
<p>The implementation is very basic and if you want to use it, you’d probably want to add more utility functions, but the idea is there: The user gets a <code>Result</code> instance, so he already knows that it could either have a success state or a failure state, and as such, he cannot forget about either of them.</p>
<p>Ideally, you wouldn’t use a generic <code>Throwable</code> but actual objects that are tailored to the different errors that can appear in any given function. In a way, <code>Optional</code> (also often called <code>Maybe</code> in other languages) are a special form of <code>Result</code>.</p>
<p>This approach has many advantages:</p>
<ul>
<li><p>Users cannot forget about errors,</p>
</li>
<li><p>the api can explicitly list all possible errors and their values without bloating the function itself or relying on documentation and</p>
</li>
<li><p>it is more apparent where failures are handled.</p>
</li>
</ul>
<p>This <a target="_blank" href="https://medium.com/codex/you-already-know-monads-2065f6309971">monadic</a> way of handling exceptional states can already be found in many newer apis: Linq in C#, Streams in Java, Promises in JavaScript and many more</p>
<h3 id="so-should-you-replace-all-exceptions-with-results">So, should you replace all exceptions with results?</h3>
<p>If we want to wrap a function that potentially throws errors with the result type, it would look like this:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> Result&lt;String&gt; <span class="hljs-title">wrappedFunction</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">return</span> Result.success(unwrappedFunction());
    } <span class="hljs-keyword">catch</span>(Throwable ex) {
        <span class="hljs-keyword">return</span> Result.failure(ex);
    }
}
</code></pre>
<p>That’s quite a bit of boilerplate code that would have to be repeated for almost every third party function and functions from the standard library. Sure, you can create a generic wrapping function, but is it really worth it?</p>
<p>Honestly, for most cases I don’t think so. I try to avoid creating new exceptions whenever possible, but I wouldn’t go through the effort of wrapping already existing functions just so I can avoid them. If anything, this should’ve been addressed by the language itself.</p>
<h3 id="not-every-exception-is-worth-caring-about">Not every exception is worth caring about</h3>
<p>Code like <code>b/c</code> might throw an <code>ArithmeticException</code> if <code>c</code> is <code>0</code>. But we need to address this only if we didn’t first check that this cannot be the case. With exceptions we can ignore it by just simply doing nothing. Most likely we’ll eventually fall into a catch-all that logs the issue and tells the programmer to check this.</p>
<p>With the <code>Result</code> type, we have to explicitly ignore it, so we’re automatically prompted to check whether that’s possible. This might result in some additional unnecessary code, but it makes it just a bit more resilient.</p>
<h2 id="summary">Summary</h2>
<p>If we’d learned about <code>Result</code> types rather than exceptions, I believe, our reaction would’ve largely been the same. They might even be slightly easier to learn and as such would’ve been introduced earlier.</p>
<p>That doesn’t mean that exceptions are actually as bad as <code>goto</code>s. But they are frighteningly close for how common they are. And I’ve definitely wasted hours before when trying to figure out what exceptions a library method might throw. And of course I’ve also overlooked some of them before.</p>
<p>Maybe even worse, exceptions can easily be misused as a way to return multiple different return values. And sadly, I’ve seen this done before.</p>
<p>Personally, I wish that more languages would adopt this more “functional” style of error handling instead of exceptions (like rust already did). I believe that many errors can be prevented in this way.</p>
<h2 id="resources">Resources</h2>
<p>If you want to play with my cache example and <code>Return</code> a bit, you can do so on <a target="_blank" href="https://www.online-java.com/g76FuKnpqs">this online-java doodle</a>.</p>
<p>If you want to play around with my beautiful mermaid diagram, you can <a target="_blank" href="https://mermaid-js.github.io/mermaid-live-editor/edit#eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBIC0tPiBCXG4gICAgQiAtLT4gQ1xuICAgIEIgLS0-IERcbiAgICBEIC0tPiBFXG4gICAgRSAtLT4gQ1xuICAgIEMgLS0-IEFcbiAgICBEIC0tPiBBXG4gICAgQSAtLT4gRlxuICAgIEYgLS0-IEVcbiAgICBFIC0tPiBCXG4gICAgRyAtLT4gQVxuICAgIEYgLS0-IEdcbiAgICBHIC0tPiBDXG4gICAgIiwibWVybWFpZCI6IntcbiAgXCJ0aGVtZVwiOiBcImRlZmF1bHRcIlxufSIsInVwZGF0ZUVkaXRvciI6ZmFsc2UsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjpmYWxzZX0">press this link</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to automatically create fixup commits]]></title><description><![CDATA[Let’s say you’ve submitted a pull request with nice atomic commits and your colleagues have found a few improvements. They are easy to implement, but if you want a nice history, you now have to figure out to which commit you should add them. Usually ...]]></description><link>https://blog.oscarablinger.dev/how-to-automatically-create-fixup-commits</link><guid isPermaLink="true">https://blog.oscarablinger.dev/how-to-automatically-create-fixup-commits</guid><category><![CDATA[Git]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[GitLab]]></category><category><![CDATA[Bitbucket]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Mon, 26 Jul 2021 20:38:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809868940/wqdLwfJ3v.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let’s say you’ve submitted a pull request with nice<a target="_blank" href="https://blog.oscarablinger.dev/ensure-atomic-commits-in-the-ci"> atomic commits</a> and your colleagues have found a few improvements. They are easy to implement, but if you want a nice history, you now have to figure out to which commit you should add them. Usually that’s just the last commit where the file was changed. But it still takes a while to find that — or you let this script do the work.</p>
<p><img src="https://cdn-images-1.medium.com/max/2180/1*DKh_vfileueNLqKCqNn5rg.png" alt="Made by the author using [carbon.sh](https://cdn.hashnode.com/res/hashnode/image/upload/v1633809858519/2jm_n2wSf.html)" /><em>Made by the author using <a target="_blank" href="https://carbon.now.sh">carbon.sh</a></em></p>
<h2 id="usage">Usage</h2>
<p>Before showing you the script, I first want to show you what you can do with it.</p>
<p>By default this script automatically figures out the commit a changed file was last modified in and creates fixup commits for them. There will only be one fixup commit for one original commit, even if multiple changed files were modified in the same one.</p>
<p>You should be able to squash all of the generated commits without a merge conflict (using <code>git rebase -i</code>).</p>
<p>Additionally, you can also tweak its behavior a bit with some options:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809860593/I0pcFOdga.png" alt /></p>
<ul>
<li><p>The plain text parameter “root”: This script will only look at commits starting from (but excluding) the root commit. This can be used to ensure that no fixup commits will be created for commits that aren’t on the current branch. Files that were last changed in or before this commit will simply be left uncommitted.</p>
</li>
<li><p><code>-n | --dry-run</code>: If dry run is specified no lasting changes are made. Instead it will just output which files it would assign to which commits.</p>
</li>
<li><p><code>-d | --default-root</code> Specifies the default root. If both the default root and root are specified, only root is considered. This is meant for a git alias, where you can specify <code>main</code> or <code>master</code> as default and still overwrite it when using the alias.</p>
</li>
<li><p><code>-M&amp;lt;n&amp;gt; | --find-renames[=&amp;lt;n&amp;gt;]</code>: If specified, will attempt to also assign renames. The format is the same as for <a target="_blank" href="https://git-scm.com/docs/git-diff#Documentation/git-diff.txt--Mltngt">git diff</a>.</p>
</li>
</ul>
<p>For example, let’s look at the following command:</p>
<pre><code><span class="hljs-keyword">assign</span> -n -d main -M master
</code></pre><p>This will cause the script to list the commits for all changed files (instead of creating commits thanks to <code>-n</code>) including renamed files (due to <code>-M</code>). It will not list files if their last changed commit was made before or in the commit that the current <code>master</code> is on (would be <code>main</code> with just the <code>-d</code> option, but it was overwritten by the last parameter).</p>
<p>See the next chapter for an example output.</p>
<h2 id="example">Example</h2>
<p>To test this, I also made a small script that creates a git repository and adds some commits to it.</p>
<pre><code><span class="hljs-meta">#!/bin/sh</span>

rm -rf repo
mkdir repo
<span class="hljs-built_in">cd</span> repo

git init

<span class="hljs-built_in">echo</span> <span class="hljs-string">"* text eol=lf"</span> &gt; .gitattributes
git add .
git commit -m <span class="hljs-string">"initial commit"</span>
git checkout -b <span class="hljs-string">"feature-branch"</span>

<span class="hljs-built_in">echo</span> a &gt; A
git add .
git commit -m <span class="hljs-string">"A"</span>

<span class="hljs-built_in">echo</span> b &gt; B
git add .
git commit -m <span class="hljs-string">"B"</span>

<span class="hljs-built_in">echo</span> with spaces &gt; <span class="hljs-string">"file with spaces"</span>
git add .
git commit -m <span class="hljs-string">"file with spaces"</span>

<span class="hljs-built_in">echo</span> aAndC &gt;&gt; B
<span class="hljs-built_in">echo</span> c &gt; C
git add .
git commit -m <span class="hljs-string">"B and C"</span>

<span class="hljs-built_in">echo</span> change &gt; A
<span class="hljs-built_in">echo</span> change &gt; B
<span class="hljs-built_in">echo</span> change &gt; C
mv <span class="hljs-string">"file with spaces"</span> <span class="hljs-string">"other file with spaces"</span>
</code></pre><p>This will create a few commits and some uncommitted changes:</p>
<p><img src="https://cdn-images-1.medium.com/max/2000/1*Y9nIK4HHQGF2i8i3HCrDig.png" alt="Screenshot of the [git for windows](https://cdn.hashnode.com/res/hashnode/image/upload/v1633809862416/yFLBsSJqP.html) bash made by the author" /><em>Screenshot of the <a target="_blank" href="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809864294/IlsQmQ7Co.html">git for windows</a> bash made by the author</em></p>
<p>If I now execute <code>assign -M -d main -n</code> in that repository, the output will look like this:</p>
<p><img src="https://cdn-images-1.medium.com/max/2000/1*nteBXVGkt-97eJ4LQzg9Ng.png" alt="Screenshot of the [git for windows](https://gitforwindows.org/) bash made by the author" /><em>Screenshot of the <a target="_blank" href="https://gitforwindows.org/">git for windows</a> bash made by the author</em></p>
<p>Note that in this screenshot, I already took advantage of a git alias that I’ll show you in the end.</p>
<h2 id="the-code">The code</h2>
<p>Okay, enough explanation, here is the code:</p>
<pre><code class="lang-shell">#!/bin/bash

# Usage information:
#   assign [-n | --dry-run] [-d | --default-root] [-M[&lt;n&gt;] | --find-renames[=&lt;n&gt;]] [&lt;root&gt;]
# 
#   -n | --dry-run:
#       If dry run is specified no lasting changes are made.
#       Instead it will just output which files it would assign to which commits
#   -d | --default-root:
#       Specifies the default root.
#       If both the default root and root are specified, only root is considered.
#       This is meant for a git alias, where you can specify 'main' or 'master' as default
#       and still overwrite it when using the alias.
#   -M[&lt;n&gt;] | --find-renames[=&lt;n&gt;]:
#       If specified, will attempt to also assign renames.
#       The format is the same as for git diff.
#       (see https://git-scm.com/docs/git-diff#Documentation/git-diff.txt--Mltngt)
#   root:
#       This script will only look at commits starting from (but excluding) the root commit.
#       This can be used to ensure that no fixup commits will be created for commits that
#       aren't on the current branch.
#       Files that were last changed in or before this commit will simply be left uncomitted.

# Default options
DRY_RUN=false
DEFAULT_ROOT=""
ROOT=""
FIND_RENAMES=()

# Read potential options
while [ "$1" != "" ];
do
    case $1 in
        -n | --dry-run)
            DRY_RUN=true
            ;;
        -d | --default-root)
            shift
            DEFAULT_ROOT="$1"
            ;;
        -M* | --find-renames*)
            FIND_RENAMES=("$1")
            ;;
        -*)
            printf "unrecognised option: %s" "$1"
            exit 1
            ;;
        *)
            if [[ $ROOT == "" ]];
            then
                ROOT="$1"
            else
                printf "Cannot specify root twice (specified both '%s' and '%s')" "${ROOT}" "$1"
                exit 1
            fi
            ;;
    esac
    shift
done

if [[ $DEFAULT_ROOT != "" &amp;&amp; $ROOT == "" ]];
then
    ROOT="${DEFAULT_ROOT}"
fi

# For each changed file find the commit in which it was last changed.
# lastCommits is an associative array with the commit hash as key and
# a newline separated list of the file names as value.
declare -A lastCommits
IFS=$'\n'; for file in $(git diff --name-only);
do
    if [[ $ROOT != "" ]];
    then
        commit=$(git log -1 --format="format:%H" "${ROOT}.." -- "${file}")

        # When a root is specified, a file could have no changes before that.
        # We simply ignore that file then.
        if [[ $commit != "" ]];
        then
            lastCommits[$commit]+="$file"$'\n'
        fi
    else
        commit=$(git log -1 --format="format:%H" -- "${file}")
        lastCommits["$commit"]+="$file"$'\n'
    fi
done

declare -A renamedFiles=()
if (( ${#FIND_RENAMES[@]} ));
then
    # first add all files indvidually as intent-to-add
    intentToAdd=$(git ls-files -oX .gitignore)
    for file in $intentToAdd;
    do
        git add -N "$file"
    done

    # get all renames and save them into an associative array
    while IFS=$'\t' read -r origFile newFile;
    do
        renamedFiles["$origFile"]="$newFile"
    done &lt; &lt;(git diff --name-status --diff-filter=R "${FIND_RENAMES[@]}" | cut -f 2,3)

    # remove intent-to-add
    for file in $intentToAdd;
    do
        git reset -q -- "$file"
    done
fi

# For each commit in lastCommits, we now add all of the associated
# files and then create a fixup commit for the respective commit

add_file() {
    if [[ $DRY_RUN == false ]];
    then
        git add "$1"
    else
        printf "\t%s\n" "$1"
    fi
}


IFS=$'\n'
for commit in "${!lastCommits[@]}";
do
    if [[ $DRY_RUN == true ]];
    then
        printf "%s\n" "$(git log -1 --color --format="format:%C(auto)%h%d%Creset: (%aN) %s" "${commit}")"
    fi

    for file in ${lastCommits[$commit]};
    do
        add_file "$file"
        if [[ -v "renamedFiles[${file}]" ]];
        then
            add_file "${renamedFiles[${file}]}"
        fi
    done

    if [[ $DRY_RUN == false ]];
    then
        git commit --fixup "${commit}"
    fi
done
unset IFS
</code></pre>
<p>It’s a lot, but luckily you can just copy-paste it into a file on your computer. And instead of always calling the file directly, I’d recommend making a git alias for it.</p>
<p>I did this by adding the following to my <code>~/.gitconfig</code> file:</p>
<pre><code><span class="hljs-section">[alias]</span>
 <span class="hljs-attr">a</span> = assign
 <span class="hljs-attr">assign</span> = !bash -c <span class="hljs-string">'~/.gitscripts/assign -M -d "$(git merge-base HEAD main)" "$@"'</span> -
 <span class="hljs-attr">assign-all</span> = !bash -c <span class="hljs-string">'~/.gitscripts/assign -M "$@"'</span> -
</code></pre><p>Of course you might want to change the default options for your aliases a bit (e.g. changing <code>main</code> to <code>master</code>), but I find that those are the most sensible defaults for me. Just don’t forget to replace the path to your script (in my case I saved it as <code>~/.gitscripts/assign</code>).</p>
<p><em>Oh, and no guarantees if your file names have newlines or tabs in them.</em></p>
<h2 id="explanation">Explanation</h2>
<p>If you just want to use it, you can stop reading now. But if you’re curious how it works, here is an incremental explanation:</p>
<h3 id="the-simplest-script">The simplest script</h3>
<p>At first I just wanted to have a script that automatically creates fixup commits based on the last commit a changed file was modified in. I came up with a simple 5-line script:</p>
<pre><code><span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> $(git diff --name-only);
<span class="hljs-keyword">do</span>
    git add <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>
    git commit --fixup <span class="hljs-string">"<span class="hljs-subst">$(git log -1 --format=<span class="hljs-string">"format:%H"</span> -- <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>)</span>"</span>
<span class="hljs-keyword">done</span>
</code></pre><p>Pretty simple, right? Go through each changed file, add it and create a fixup commit.</p>
<h3 id="the-simple-script">The simple script</h3>
<p>But the previous script will potentially create multiple fixup commits for the same commit. I thought that was ugly, so instead of directly adding and committing, we’re first creating a map of commits to its changed files.</p>
<pre><code><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment"># For each changed file find the commit in which it was last changed.</span>
<span class="hljs-comment"># lastCommits is an associative array with the commit hash as key and</span>
<span class="hljs-comment"># a newline separated list of the file names as value.</span>
<span class="hljs-built_in">declare</span> -A lastCommits
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> $(git diff --name-only);
<span class="hljs-keyword">do</span>
    commit=$(git <span class="hljs-built_in">log</span> -1 --format=<span class="hljs-string">"format:%H"</span> -- <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>)
    lastCommits[<span class="hljs-variable">$commit</span>]+=<span class="hljs-string">"<span class="hljs-variable">$file</span>"</span>$<span class="hljs-string">'\n'</span>
<span class="hljs-keyword">done</span>

<span class="hljs-comment"># For each commit in lastCommits, we now add all of the associated</span>
<span class="hljs-comment"># files and then create a fixup commit for the respective commit</span>
IFS=$<span class="hljs-string">'\n'</span>
<span class="hljs-keyword">for</span> commit <span class="hljs-keyword">in</span> <span class="hljs-string">"<span class="hljs-variable">${!lastCommits[@]}</span>"</span>;
<span class="hljs-keyword">do</span>
    <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> <span class="hljs-variable">${lastCommits[$commit]}</span>;
    <span class="hljs-keyword">do</span>
        git add <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>
    <span class="hljs-keyword">done</span>

    git commit --fixup <span class="hljs-string">"<span class="hljs-variable">$commit</span>"</span>
<span class="hljs-keyword">done</span>
<span class="hljs-built_in">unset</span> IFS
</code></pre><h3 id="adding-some-options">Adding some options</h3>
<p>Next I wanted the ability to have a dry run for the times, where I’m not sure whether the last commit is actually the correct one. So I added a bit more command parsing boilerplate at the beginning and some if statements.</p>
<pre><code><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment"># Default options</span>
DRY_RUN=<span class="hljs-literal">false</span>

<span class="hljs-comment"># Read potential options</span>
<span class="hljs-keyword">while</span> [ <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span> != <span class="hljs-string">""</span> ];
<span class="hljs-keyword">do</span>
    <span class="hljs-keyword">case</span> <span class="hljs-variable">$1</span> <span class="hljs-keyword">in</span>
        -n | --dry-run)
            DRY_RUN=<span class="hljs-literal">true</span>
            ;;
        *)
            <span class="hljs-built_in">printf</span> <span class="hljs-string">"unrecognised option: %s"</span> <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
            <span class="hljs-built_in">exit</span> 1
            ;;
    <span class="hljs-keyword">esac</span>
    <span class="hljs-built_in">shift</span>
<span class="hljs-keyword">done</span>

<span class="hljs-comment"># For each changed file find the commit in which it was last changed.</span>
<span class="hljs-comment"># lastCommits is an associative array with the commit hash as key and</span>
<span class="hljs-comment"># a newline separated list of the file names as value.</span>
<span class="hljs-built_in">declare</span> -A lastCommits
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> $(git diff --name-only);
<span class="hljs-keyword">do</span>
    commit=$(git <span class="hljs-built_in">log</span> -1 --format=<span class="hljs-string">"format:%H"</span> -- <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>)
    lastCommits[<span class="hljs-variable">$commit</span>]+=<span class="hljs-string">"<span class="hljs-variable">$file</span>"</span>$<span class="hljs-string">'\n'</span>
<span class="hljs-keyword">done</span>

<span class="hljs-comment"># For each commit in lastCommits, we now add all of the associated</span>
<span class="hljs-comment"># files and then create a fixup commit for the respective commit</span>
IFS=$<span class="hljs-string">'\n'</span>
<span class="hljs-keyword">for</span> commit <span class="hljs-keyword">in</span> <span class="hljs-string">"<span class="hljs-variable">${!lastCommits[@]}</span>"</span>;
<span class="hljs-keyword">do</span>
    <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$DRY_RUN</span> == <span class="hljs-literal">true</span> ]];
    <span class="hljs-keyword">then</span>
        <span class="hljs-built_in">printf</span> <span class="hljs-string">"commit %s:\n"</span> <span class="hljs-string">"<span class="hljs-variable">${commit}</span>"</span>
    <span class="hljs-keyword">fi</span>

<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> <span class="hljs-variable">${lastCommits[$commit]}</span>;
    <span class="hljs-keyword">do</span>
        <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$DRY_RUN</span> == <span class="hljs-literal">false</span> ]];
        <span class="hljs-keyword">then</span>
            git add <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>
        <span class="hljs-keyword">else</span>
            <span class="hljs-built_in">printf</span> <span class="hljs-string">"\t%s\n"</span> <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>
        <span class="hljs-keyword">fi</span>
    <span class="hljs-keyword">done</span>

<span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$DRY_RUN</span> == <span class="hljs-literal">false</span> ]];
    <span class="hljs-keyword">then</span>
        git commit --fixup <span class="hljs-string">"<span class="hljs-variable">${commit}</span>"</span>
    <span class="hljs-keyword">fi</span>
<span class="hljs-keyword">done</span>
<span class="hljs-built_in">unset</span> IFS
</code></pre><h3 id="adding-the-root-options">Adding the root options</h3>
<p>In order to add the <code>root</code> option(s), I extended the boilerplate code at the beginning. After the options are read, the <code>root</code> is set to either the default root or the specific root.</p>
<p>Now, when figuring out which files belong to which commit in the first loop, we just also specify the root commit (if we have one). This will cause <code>git log</code> to return empty if it finds no relevant commit after the specified commit.</p>
<p>No other changes are required.</p>
<pre><code><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment"># Default options</span>
DRY_RUN=<span class="hljs-literal">false</span>
DEFAULT_ROOT=<span class="hljs-string">""</span>
ROOT=<span class="hljs-string">""</span>

<span class="hljs-comment"># Read potential options</span>
<span class="hljs-keyword">while</span> [ <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span> != <span class="hljs-string">""</span> ];
<span class="hljs-keyword">do</span>
    <span class="hljs-keyword">case</span> <span class="hljs-variable">$1</span> <span class="hljs-keyword">in</span>
        -n | --dry-run)
            DRY_RUN=<span class="hljs-literal">true</span>
            ;;
        -d | --default-root)
            <span class="hljs-built_in">shift</span>
            DEFAULT_ROOT=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
            ;;
        -*)
            <span class="hljs-built_in">printf</span> <span class="hljs-string">"unrecognised option: %s"</span> <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
            <span class="hljs-built_in">exit</span> 1
            ;;
        *)
            <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$ROOT</span> == <span class="hljs-string">""</span> ]];
            <span class="hljs-keyword">then</span>
                ROOT=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
            <span class="hljs-keyword">else</span>
                <span class="hljs-built_in">printf</span> <span class="hljs-string">"Cannot specify root twice (specified both '%s' and '%s')"</span> <span class="hljs-string">"<span class="hljs-variable">${ROOT}</span>"</span> <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
                <span class="hljs-built_in">exit</span> 1
            <span class="hljs-keyword">fi</span>
            ;;
    <span class="hljs-keyword">esac</span>
    <span class="hljs-built_in">shift</span>
<span class="hljs-keyword">done</span>

<span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$DEFAULT_ROOT</span> != <span class="hljs-string">""</span> &amp;&amp; <span class="hljs-variable">$ROOT</span> == <span class="hljs-string">""</span> ]];
<span class="hljs-keyword">then</span>
    ROOT=<span class="hljs-string">"<span class="hljs-variable">${DEFAULT_ROOT}</span>"</span>
<span class="hljs-keyword">fi</span>

<span class="hljs-comment"># For each changed file find the commit in which it was last changed.</span>
<span class="hljs-comment"># lastCommits is an associative array with the commit hash as key and</span>
<span class="hljs-comment"># a newline separated list of the file names as value.</span>
<span class="hljs-built_in">declare</span> -A lastCommits
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> $(git diff --name-only);
<span class="hljs-keyword">do</span>
    <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$ROOT</span> != <span class="hljs-string">""</span> ]];
    <span class="hljs-keyword">then</span>
        commit=$(git <span class="hljs-built_in">log</span> -1 --format=<span class="hljs-string">"format:%H"</span> <span class="hljs-string">"<span class="hljs-variable">${ROOT}</span>.."</span> -- <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>)

        <span class="hljs-comment"># When a root is specified, a file could have no changes before that.</span>
        <span class="hljs-comment"># We simply ignore that file then.</span>
        <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$commit</span> != <span class="hljs-string">""</span> ]];
        <span class="hljs-keyword">then</span>
            lastCommits[<span class="hljs-variable">$commit</span>]+=<span class="hljs-string">"<span class="hljs-variable">$file</span>"</span>$<span class="hljs-string">'\n'</span>
        <span class="hljs-keyword">fi</span>
    <span class="hljs-keyword">else</span>
        commit=$(git <span class="hljs-built_in">log</span> -1 --format=<span class="hljs-string">"format:%H"</span> -- <span class="hljs-string">"<span class="hljs-variable">${file}</span>"</span>)
        lastCommits[<span class="hljs-variable">$commit</span>]+=<span class="hljs-string">"<span class="hljs-variable">$file</span>"</span>$<span class="hljs-string">'\n'</span>
    <span class="hljs-keyword">fi</span>
<span class="hljs-keyword">done</span>
</code></pre><h3 id="adding-find-renames">Adding find-renames</h3>
<p>The previous script works pretty well already. The only annoying thing is that if I rename a file, it will only create a fixup commit for the deletion of the original file, but not for the adding of the “new” file.</p>
<p>So I added a new option:</p>
<pre><code><span class="hljs-comment"># Default options</span>
DRY_RUN=<span class="hljs-literal">false</span>
DEFAULT_ROOT=<span class="hljs-string">""</span>
ROOT=<span class="hljs-string">""</span>
FIND_RENAMES=()

<span class="hljs-comment"># Read potential options</span>
<span class="hljs-keyword">while</span> [ <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span> != <span class="hljs-string">""</span> ];
<span class="hljs-keyword">do</span>
    <span class="hljs-keyword">case</span> <span class="hljs-variable">$1</span> <span class="hljs-keyword">in</span>
        -n | --dry-run)
            DRY_RUN=<span class="hljs-literal">true</span>
            ;;
        -d | --default-root)
            <span class="hljs-built_in">shift</span>
            DEFAULT_ROOT=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
            ;;
        -M* | --find-renames*)
            FIND_RENAMES=(<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>)
            ;;
        -*)
            <span class="hljs-built_in">printf</span> <span class="hljs-string">"unrecognised option: %s"</span> <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
            <span class="hljs-built_in">exit</span> 1
            ;;
        *)
            <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$ROOT</span> == <span class="hljs-string">""</span> ]];
            <span class="hljs-keyword">then</span>
                ROOT=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
            <span class="hljs-keyword">else</span>
                <span class="hljs-built_in">printf</span> <span class="hljs-string">"Cannot specify root twice (specified both '%s' and '%s')"</span> <span class="hljs-string">"<span class="hljs-variable">${ROOT}</span>"</span> <span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
                <span class="hljs-built_in">exit</span> 1
            <span class="hljs-keyword">fi</span>
            ;;
    <span class="hljs-keyword">esac</span>
    <span class="hljs-built_in">shift</span>
<span class="hljs-keyword">done</span>
</code></pre><p>Note that the variable <code>FIND_RENAMES</code> is either empty or has the whole, unchanged parameter. This means that I can just provide it as-is to <code>git diff</code> and you can automatically use all of the features from that command.</p>
<p>So, after we’ve already assigned each changed file it’s commit, we now also want to figure out if there are any renames according to git. To do this, we first need to find all unstaged files. Then we tell git that we intent to add them (using <code>git add -N</code>). Afterwards git will check whether it’s a renamed file or not. And we can ask whether it is by using <code>git diff --name-status</code> and filter for renames using <code>--diff-filter=R</code>.</p>
<p>We then simply save which file was renamed to what.</p>
<pre><code><span class="hljs-built_in">declare</span> -A renamedFiles=()
<span class="hljs-keyword">if</span> (( <span class="hljs-variable">${#FIND_RENAMES[@]}</span> ));
<span class="hljs-keyword">then</span>
    <span class="hljs-comment"># first add all files indvidually as intent-to-add</span>
    intentToAdd=$(git ls-files -o)
    <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> <span class="hljs-variable">$intentToAdd</span>;
    <span class="hljs-keyword">do</span>
        git add -N <span class="hljs-string">"<span class="hljs-variable">$file</span>"</span>
    <span class="hljs-keyword">done</span>

<span class="hljs-comment"># get all renames and save them into an associative array</span>
    <span class="hljs-keyword">while</span> IFS=$<span class="hljs-string">'\t'</span> <span class="hljs-built_in">read</span> -r origFile newFile;
    <span class="hljs-keyword">do</span>
        renamedFiles[<span class="hljs-string">"<span class="hljs-variable">$origFile</span>"</span>]=<span class="hljs-string">"<span class="hljs-variable">$newFile</span>"</span>
    <span class="hljs-keyword">done</span> &lt; &lt;(git diff --name-status --diff-filter=R <span class="hljs-string">"<span class="hljs-variable">${FIND_RENAMES[@]}</span>"</span> | cut -f 2,3)

    <span class="hljs-comment"># remove intent-to-add</span>
    <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> <span class="hljs-variable">$intentToAdd</span>;
    <span class="hljs-keyword">do</span>
        git reset -q -- <span class="hljs-string">"<span class="hljs-variable">$file</span>"</span>
    <span class="hljs-keyword">done</span>
<span class="hljs-keyword">fi</span>
</code></pre><p>And when adding the files, we now also add all renamed files:</p>
<pre><code><span class="hljs-attribute">if</span> [[ -v <span class="hljs-string">"renamedFiles[<span class="hljs-variable">${file}</span>]"</span> ]];
<span class="hljs-attribute">then</span>
    add_file <span class="hljs-string">"<span class="hljs-variable">${renamedFiles[${file}</span>]}"</span>
fi
</code></pre><p>And that’s it.</p>
<p><img src="https://cdn-images-1.medium.com/max/8512/0*LwE81p9pgEMGSTZV" alt="Photo by [Alex](https://cdn.hashnode.com/res/hashnode/image/upload/v1633809867125/9eCN0B9K2.html) on [Unsplash](https://unsplash.com?utm_source=medium&amp;utm_medium=referral)" /><em>Photo by <a target="_blank" href="https://unsplash.com/@alx_andru?utm_source=medium&amp;utm_medium=referral">Alex</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></em></p>
]]></content:encoded></item><item><title><![CDATA[Ensure atomic commits in the CI]]></title><description><![CDATA[The idea of atomic commits has been considered best practice by many people. It essentially means that every commit on the master branch should at least be able to be built successfully. Some also include that it can “start” successfully, some also i...]]></description><link>https://blog.oscarablinger.dev/ensure-atomic-commits-in-the-ci</link><guid isPermaLink="true">https://blog.oscarablinger.dev/ensure-atomic-commits-in-the-ci</guid><category><![CDATA[Continuous Integration]]></category><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[GitLab]]></category><category><![CDATA[Bitbucket]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Mon, 19 Jul 2021 09:03:08 GMT</pubDate><content:encoded><![CDATA[<p>The idea of atomic commits has been considered best practice by many people. It essentially means that every commit on the master branch should at least be able to be built successfully. Some also include that it can “start” successfully, some also include that all tests have to be able to be run successful.</p>
<p>If you just want a shell command to ensure that, you can do it with the following command:</p>
<pre><code>git rebase --<span class="hljs-keyword">exec</span> <span class="hljs-string">"&lt;atomic commit check command&gt;"</span> &lt;base commit&gt;
</code></pre><p>This command will check out¹ every commit between the base commit and the current commit (not including the base commit itself) and execute the given check command after each checkout. The command only returns successfully if all commands executed successfully.</p>
<p>In most cases you want to use it together with <code>merge-base</code> and your main/master branch like this:</p>
<pre><code>git rebase --<span class="hljs-keyword">exec</span> <span class="hljs-string">"&lt;atomic commit check command&gt;"</span> $(git merge-base HEAD main)
</code></pre><p>This will find the “best common ancestor for a merge” aka the most recent common ancestor² and execute the command for each commit from there. This ensures that if your branch isn’t up to date with <code>main</code>, we don’t just rebase on top of <code>main</code> and change the actual branch.</p>
<p>Depending on your technology stack and definition of atomic commits, you can use different check commands with it. For example you could use <code>gradle check</code> or <code>npm run build</code>.</p>
<p>¹You might call it “switching” instead now, since the never command <code>switch</code> is now recommended over the old <code>checkout</code></p>
<p>²If you keep a clean history. <a target="_blank" href="https://www.linux.org/docs/man1/git-merge-base.html">With criss-cross merges, there could be more than one “best common ancestor”</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Aho-Corasick]]></title><description><![CDATA[Find all occurrences of a finite set of strings in a given search string in linear time!
Photo by Priscilla Du Preez on Unsplash
The Aho-Corasick algorithms allows you to find any amount of substrings and their position in a given search string. It d...]]></description><link>https://blog.oscarablinger.dev/aho-corasick-explained</link><guid isPermaLink="true">https://blog.oscarablinger.dev/aho-corasick-explained</guid><category><![CDATA[algorithms]]></category><category><![CDATA[programmer]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Competitive programming]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Tue, 13 Jul 2021 23:26:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809788703/y0Xw7gL1z.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Find all occurrences of a finite set of strings in a given search string in linear time!</p>
<p><img src="https://cdn-images-1.medium.com/max/10944/0*EQ2Vvn9Q1onWNiOM" alt="Photo by [Priscilla Du Preez](https://cdn.hashnode.com/res/hashnode/image/upload/v1633809778534/dXiFoko7Y.html) on [Unsplash](https://unsplash.com?utm_source=medium&amp;utm_medium=referral)" /><em>Photo by <a target="_blank" href="https://unsplash.com/@priscilladupreez?utm_source=medium&amp;utm_medium=referral">Priscilla Du Preez</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></em></p>
<p>The Aho-Corasick algorithms allows you to find any amount of substrings and their position in a given search string. It does so in linear time. If the substrings are known beforehand, it is also possible to prepare them to later find matches in input strings faster.</p>
<h2 id="characteristics">Characteristics</h2>
<ul>
<li><p>Inputs are a finite set of <strong>search strings </strong>(the “dictionary”) and the <strong>input string</strong> in which those dictionary strings are searched for.</p>
</li>
<li><p>Output is a list of <strong>matched strings and their index</strong> in the input string. The list may include the same dictionary entries multiple times if they were found at multiple indices. The list is also sorted ascending by the index.</p>
</li>
<li><p>Runtime complexity is <strong>O(L₁ + L₂ + M)</strong> without preparation or <strong>O(L₁ + M)</strong> if you prepare the dictionary beforehand. L₁ is the length of the input string; L₂ is the sum of the lengths of all search strings; and M is the amount of matches that a search string will produce. Preparation has a runtime complexity of<strong> O(L₂)</strong>.</p>
</li>
<li><p>Space complexity is <strong>O(L₂)</strong> in the worst case, but can be better if the dictionary strings share a lot of common prefixes.</p>
</li>
<li><p>The Aho-Corasick algorithm was developed by <strong>Alfred V. Aho</strong> and <strong>Margaret J. Corasick</strong> in their paper “Efficient string matching: An aid to bibliographic search”</p>
</li>
</ul>
<h2 id="principle">Principle</h2>
<p>The basic idea behind the Aho-Corasick is to first convert the dictionary into a <a target="_blank" href="https://en.wikipedia.org/wiki/Trie">trie</a>, where each node represents a prefix of a dictionary entry (or the entry itself). A trie is a special form of tree where all nodes represent strings and the children of each node contain the parent’s string plus an additional character at the end. The root node is the empty string (here represented by <em>ε</em>). Let’s look at an example.</p>
<h3 id="basic-trie">Basic Trie</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809780362/2rJfaxdHA.png" alt="Image made by the author" /><em>Image made by the author</em></p>
<p>All examples in this blog post will use a dictionary with the following dictionary:</p>
<ul>
<li><p>abba</p>
</li>
<li><p>bb</p>
</li>
<li><p>bar</p>
</li>
<li><p>ar</p>
</li>
<li><p>foobar</p>
</li>
</ul>
<p>Those will result in the trie shown on the side (or top on mobile). The dictionary entry <em>abba</em>, for instance, was transformed into the four left-most nodes.</p>
<p>All nodes representing strings in the dictionary are also specifically marked so that we can recognize them when traversing over them. In the images, I marked them in green.</p>
<p>Using that trie we can now easily find out that the input string “<em>bar” </em>matches an entry in our dictionary by starting at the root and traversing over <em>b</em> to <em>a</em> to <em>r</em>.</p>
<h3 id="suffix-links">Suffix Links</h3>
<p>But looking at the input string “abar” we’d first traverse from <em>a</em> to <em>b</em> and then find out that we do not have a matching child. In that case we want to jump to the longest suffix of our current string (<em>ab</em>) that is in our tree: <em>b</em>. Note that the empty string is always the shortest suffix of every string. So if there is no longer substring in our tree, we’ll end up back at the root.</p>
<p>Since each node in the trie always has the same longest suffix, we can just remember those connections and include them in our initial tree creation. I’ve added those connections in the following image:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809782379/od8iM98bW.png" alt="Image made by the author" /><em>Image made by the author</em></p>
<h3 id="dictionary-suffix-links">Dictionary Suffix Links</h3>
<p>The last problem that we have now is that we might miss some entries in our dictionary. Let’s take for example the input string “<em>foobar</em>”. We’ll successfully find the words <em>foo</em> and <em>foobar </em>since we directly traverse of their nodes. But we won’t find the dictionary strings <em>bar</em> and <em>ar</em> without an additional (the last) trick.</p>
<p>We add another link from each node to the longest suffix <strong>that is in the dictionary</strong> — the so-called “dictionary suffix links”. Now, whenever we traverse a node, we simply follow the dictionary suffix links (the green arrows in the image) to find all dictionary strings for that node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809784468/kKmpc0GZs.png" alt="Image made by the author" /><em>Image made by the author</em></p>
<p>To summarize, each node now has three different kind of links to other nodes:</p>
<ul>
<li><p>Any amount of <strong>child links</strong></p>
</li>
<li><p>One <strong>suffix link </strong>to the node with the longest shared suffix</p>
</li>
<li><p>At most one <strong>dictionary suffix link </strong>to the node with the longest shared suffix that also represents a dictionary entry</p>
</li>
</ul>
<h2 id="an-example">An Example</h2>
<p>Now let’s try with the input string “<em>aabbTfoobar</em>”. This will require the use of all three links.</p>
<p><em>Warning: the trie is going to look pretty full now with the path drawn on it. I go through it step-by-step, so bear with me. You can also just try to do it yourself first.</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809786940/VJ4FWGiGz.png" alt="Image made by the author" /><em>Image made by the author</em></p>
<ol>
<li><p>We start at <em>ε</em> and move to <em>(a)</em>.</p>
</li>
<li><p>The node <em>(a) </em>doesn’t have a child with the string <em>b</em>, so we go back to the root and see if it has a matching child. It has. And we and up back at the same node.</p>
</li>
<li><p>We move to the child <em>(ab)</em>.</p>
</li>
<li><p>We move to the child <em>(abb)</em>. This node has a dictionary suffix link, so we follow it and find the dictionary entry <em>bb</em>.</p>
</li>
<li><p>The node doesn’t have a child for “T”, but it has a suffix link. So we follow that link to <em>(bb)</em>. Since that node doesn’t have a fitting child either, we move to its suffix link <em>(b)</em>. Again, no match and this time no suffix link, so we move to <em>(ε)</em>. When <em>(ε)</em> has no fitting child, we just stay on it and still advance in the string.</p>
</li>
<li><p>We move to the child <em>(f)</em>.</p>
</li>
<li><p>We move to the child <em>(fo)</em>.</p>
</li>
<li><p>We move to the child <em>(foo) </em>and find the dictionary entry <em>foo</em>.</p>
</li>
<li><p>We move to the child <em>(foob)</em>.</p>
</li>
<li><p>We move to the child <em>(fooba)</em>.</p>
</li>
<li><p>We move to the child <em>(fooobar)</em> and find the dictionary entry <em>foobar</em>. Since the node also has a dictionary suffix link, we follow it and find the dictionary entry <em>bar</em>. Again, that node has a dictionary suffix link, so we find <em>ar</em>.</p>
</li>
</ol>
<p>…and then we’re done. And we found all substrings in our dictionary.</p>
]]></content:encoded></item><item><title><![CDATA[You already know Monads]]></title><description><![CDATA[Instead of explaining the abstract theory behind monads, I’ll just show you some Java code that you already understand. And using this practical approach you’ll realize that you’ve in all likelihood already used monads a few times.
Oh and if you pref...]]></description><link>https://blog.oscarablinger.dev/you-already-know-monads</link><guid isPermaLink="true">https://blog.oscarablinger.dev/you-already-know-monads</guid><category><![CDATA[Functional Programming]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[Java]]></category><category><![CDATA[data structures]]></category><dc:creator><![CDATA[Oscar Ablinger]]></dc:creator><pubDate>Mon, 14 Jun 2021 19:18:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633809801889/pwZ83Jlyb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Instead of explaining the abstract theory behind monads, I’ll just show you some Java code that you already understand. And using this practical approach you’ll realize that you’ve in all likelihood already used monads a few times.</p>
<p><a target="_blank" href="https://youtu.be/w0fhQCzy2g0?t=1308">Oh and if you prefer to listen to me instead, this post is based on a lightning talk I gave, where I (try to) explain them in 7 minutes.</a></p>
<h2 id="what-are-monads">What are Monads?</h2>
<p>Monads are just classes that implement the following two methods:</p>
<ul>
<li><p><code>[of</code>](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#of-T...-) (in explanations usually called <code>unit</code> or <code>return</code>) and</p>
</li>
<li><p><code>[flatMap</code>](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#flatMap-java.util.function.Function-) (usually called <code>bind</code>)</p>
</li>
</ul>
<p><code>of</code> should simply take some values and return a wrapper for it (the monad). <code>flatMap</code> then allows accessing those values by applying a function to all of them, taking the monads returned by those functions and combining (aka “flattening”) them into one again.</p>
<p>Using that, the simplest possible monad is the following:</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Monad</span>&lt;<span class="hljs-title">T</span>&gt; {
    <span class="hljs-keyword">private</span> T <span class="hljs-keyword">value</span>;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Monad</span>(<span class="hljs-params">T <span class="hljs-keyword">value</span></span>)</span> {
        <span class="hljs-keyword">this</span>.<span class="hljs-keyword">value</span> = <span class="hljs-keyword">value</span>;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> &lt;T&gt; <span class="hljs-function">Monad&lt;T&gt; <span class="hljs-title">of</span>(<span class="hljs-params">T <span class="hljs-keyword">value</span></span>)</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Monad&lt;&gt;(<span class="hljs-keyword">value</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span>&lt;R&gt; Monad&lt;R&gt; <span class="hljs-title">flatMap</span>(<span class="hljs-params">Function&lt;T, Monad&lt;R&gt;&gt; f</span>)</span>{
        <span class="hljs-keyword">return</span> f.apply(<span class="hljs-keyword">value</span>);
    }
}
</code></pre><h3 id="so-thats-it">So that’s it?</h3>
<p>Mostly, but obviously you can’t just name the methods a certain way and have a monad. There are rules for how these two methods need to work together.</p>
<p>The good news is that if you implement those methods as described above (and as they are commonly understood), you’ll already fulfill all of them. But here they are anyways:</p>
<ol>
<li><p>The <code>of</code> method is a <strong>left-identity</strong> for <code>flatMap</code>,</p>
</li>
<li><p>the <code>of</code> method is a <strong>right-identity </strong>for <code>flatMap</code> and</p>
</li>
<li><p>the <code>flatMap</code> method is <strong>associative</strong>.</p>
</li>
</ol>
<p>Or, in code:</p>
<pre><code><span class="hljs-comment">// using</span>
Monad&lt;V&gt; m;
V x;
<span class="hljs-function"><span class="hljs-keyword">Function</span>&lt;<span class="hljs-title">V</span>, <span class="hljs-title">Monad</span>&lt;<span class="hljs-title">V</span>&gt;&gt; <span class="hljs-title">f</span></span>;
<span class="hljs-function"><span class="hljs-keyword">Function</span>&lt;<span class="hljs-title">V</span>, <span class="hljs-title">Monad</span>&lt;<span class="hljs-title">V</span>&gt;&gt; <span class="hljs-title">g</span></span>;

<span class="hljs-comment">// rule 1: of is left-identity of flatMap</span>
of(x).flatMap(f) .equals(f.apply(x))

<span class="hljs-comment">// rule 2</span>
m.flatMap(Monad::of) .equals(m)

<span class="hljs-comment">// rule 3</span>
m.flatMap(f).flatMap(h)
    .equals(m.flatMap(v -&gt; g.apply(v).flatmap(h)))
</code></pre><h2 id="why-should-i-care">Why should I care?</h2>
<p>Now you know what monads are and how you can create one, but why is there even a name for it?</p>
<p>If you were using a heavily functional language, then this wouldn’t even really be a question since the tools and problems you’ll have when programming functionally will likely naturally result in you creating some monads¹. That’s where monads are from originally.</p>
<p>That being said, they can also be tremendously useful outside of those languages and in fact many new APIs feature monads.</p>
<h3 id="include-error-states-in-your-domain">Include (error) states in your domain</h3>
<p>The best APIs try to stop you from making mistakes. One of the ways that this is done is explicitly including the error state in its return values. When multiple function calls in a row could return an error, this also has the added bonus of making the resulting code prettier.</p>
<p>Let’s look at an example using Optional:</p>
<pre><code><span class="hljs-keyword">public</span> Optional&lt;<span class="hljs-keyword">Integer</span>&gt; doSomething(Stream&lt;<span class="hljs-keyword">Integer</span>&gt; stream) {
    <span class="hljs-keyword">return</span> stream
        .findFirst()
        .flatMap(this::integerHalf)
        .flatMap(v -&gt; Optional.of(v*<span class="hljs-number">5</span>));
}

<span class="hljs-keyword">public</span> Optional&lt;<span class="hljs-keyword">Integer</span>&gt; integerHalf(<span class="hljs-keyword">Integer</span> i) {
    <span class="hljs-keyword">if</span> (i%<span class="hljs-number">2</span> == <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> Optional.of(i/<span class="hljs-number">2</span>);
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> Optional.<span class="hljs-keyword">empty</span>();
    }
}
</code></pre><p>In this example, we not only had the option to return an “error” at any time, but afterwards we don’t immediately have to check for it. Instead this can be done at a later point<em>.</em></p>
<p>Monads can also be used to take care of non-error states. This is often used in collections or asynchronous programming (see <code>[CompletableFuture</code>](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)), where it also prevents callback-hell.</p>
<h3 id="allow-the-use-of-more-generic-functions">Allow the use of more generic functions</h3>
<p>Take the above function <code>integerHalf</code> for example: We can use this on plain integers and also on any monad like <code>Optional</code> or <code>Stream</code> using the <code>flatMap</code> method.</p>
<p>This ease of access to the underlying information while not leaving the domain of the Monad can create amazing APIs that prevent many errors.</p>
<h2 id="do-you-know-some-monads">Do you know some monads?</h2>
<p>I’ve already mentioned the three most common monads in Java:</p>
<ul>
<li><p><code>Optional</code>,</p>
</li>
<li><p><code>Stream</code> and</p>
</li>
<li><p><code>CompletableFuture</code></p>
</li>
</ul>
<p>but I’m sure you’ve encountered a few more already. Leave a comment if you know another good example.</p>
<h2 id="further-links">Further links</h2>
<ul>
<li><p><a target="_blank" href="https://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html">Maybe the best explanation of the theory behind monads (and functors and applicatives) — with pictures!</a></p>
</li>
<li><p>¹<a target="_blank" href="https://stackoverflow.com/questions/28139259/why-do-we-need-monads/28139260#28139260">A great explanation of why monads naturally arise when programming functionally</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=w0fhQCzy2g0&amp;t=1308s">My 7-minute lightning talk about this topic</a></p>
</li>
</ul>
<p><img src="https://cdn-images-1.medium.com/max/8920/1*tZBl7GSRnm4FQ2tiyyqG_Q.jpeg" alt="Accurate image of a monad (Photo by: [Nicole De Khors](https://cdn.hashnode.com/res/hashnode/image/upload/v1633809799941/lLUTmqBXr.html))" /><em>Accurate image of a monad (Photo by: <a target="_blank" href="https://burst.shopify.com/@ndekhors">Nicole De Khors</a>)</em></p>
]]></content:encoded></item></channel></rss>