<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: CodeCraftr</title>
    <description>The latest articles on Forem by CodeCraftr (@codecraftr).</description>
    <link>https://forem.com/codecraftr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F669861%2F7735be50-fb22-4bfa-b25f-807110a7ce78.jpg</url>
      <title>Forem: CodeCraftr</title>
      <link>https://forem.com/codecraftr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/codecraftr"/>
    <language>en</language>
    <item>
      <title>Object-Oriented vs Functional Programming—Why Not Both?</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Sun, 01 Dec 2024 13:31:15 +0000</pubDate>
      <link>https://forem.com/codecraftr/object-oriented-vs-functional-programming-why-not-both-3o8c</link>
      <guid>https://forem.com/codecraftr/object-oriented-vs-functional-programming-why-not-both-3o8c</guid>
      <description>&lt;p&gt;Good. Bad. Right. Wrong. This. That. People love &lt;a href="https://en.wikipedia.org/wiki/Binary_opposition" rel="noopener noreferrer"&gt;binary oppositions&lt;/a&gt;, and Software Engineering is full of them. One such opposition is the discussion of object-oriented vs functional programming. However, I’d argue it doesn’t have to be either/or. With care, we can have the best of both worlds, but to do so we need to understand the strengths and weaknesses of both paradigms.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Object-Oriented Programming&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="noopener noreferrer"&gt;Object-oriented programming&lt;/a&gt;(OOP) has been a mainstay ever since the 1970s and 1980s and remains a popular paradigm to this day, found in languages like Java, C#, Python, etc.&lt;/p&gt;

&lt;p&gt;It sets itself apart by modeling your software as ‘objects’, which bring together data and possible interactions with it. A major aim is to hide the internals and expose them only via its functions.&lt;/p&gt;

&lt;p&gt;The paradigm aligns well with our natural way of thinking in terms of things, or ‘objects.’ When we perceive the world around us we tend to classify things as objects—we see a large brown thing with leaves and categorize it as a tree. In programming, this works too, especially for rich domains.&lt;/p&gt;

&lt;p&gt;OOP has advantages and disadvantages. Like any tool, its effectiveness &lt;a href="https://www.codecraftr.nl/p/it-depends?utm_source=publication-search" rel="noopener noreferrer"&gt;depends&lt;/a&gt; on how we employ it and in what context. Over the years, however, I’ve found OOP’s strengths to be as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Capturing natural concepts in code&lt;/strong&gt;. This is very useful in rich domains (such as the previous example), as it aligns well with our language and reasoning in objects and subjects. This is a major part of &lt;a href="https://martinfowler.com/bliki/DomainDrivenDesign.html" rel="noopener noreferrer"&gt;Domain-Driven Design&lt;/a&gt;, specifically &lt;a href="https://martinfowler.com/bliki/UbiquitousLanguage.html" rel="noopener noreferrer"&gt;Ubiquitous Language&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bringing data and logic together&lt;/strong&gt;. Done well, this creates high &lt;a href="https://en.wikipedia.org/wiki/Cohesion_(computer_science)" rel="noopener noreferrer"&gt;cohesion&lt;/a&gt; (things that change together belong together), which makes change easier. It can also reduce &lt;a href="https://en.wikipedia.org/wiki/Coupling_%28computer_programming%29" rel="noopener noreferrer"&gt;coupling&lt;/a&gt;, which is perhaps the &lt;a href="https://tidyfirst.substack.com/p/surprise-factory-coupling-why-software" rel="noopener noreferrer"&gt;biggest reason&lt;/a&gt; for making software hard to adapt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hiding internals&lt;/strong&gt;. Functions that follow the &lt;a href="https://martinfowler.com/bliki/TellDontAsk.html" rel="noopener noreferrer"&gt;Tell, Don’t Ask principle&lt;/a&gt;, allow you to hide much of the internal complexities from the rest of the codebase. For instance, changing the Train composition via methods such as &lt;code&gt;couple&lt;/code&gt; or &lt;code&gt;decouple&lt;/code&gt; allows you to hide how and when to update weight and length.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, there are also downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;‌Not everything is an object.&lt;/strong&gt; Real-world applications consist of more than object-like concepts such as processes. Having access to only Objects to model software might feel like putting a circle into a square hole.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mutability.&lt;/strong&gt; Mutable state adds time as a dimension of complexity to the equation—what did an object look like at a specific point in time?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Side Effects.&lt;/strong&gt; Mutating state, as well as many other interactions interleaved in code makes the outcome of it dependent on &lt;em&gt;when&lt;/em&gt; it is called. This makes it harder to reason about the program.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verbosity.&lt;/strong&gt; When all you need is a function, wrestling it into an object form can result in more code than needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s explore some Object-Oriented code. Imagine we’re creating software for train logistics. The code needs to couple and decouple train sets from an entire train. Here’s some object-oriented code to solve the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;composition&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;couple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decouple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;lengths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lengths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we’d use it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_couple_increases_weight_length&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;

    &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;couple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_decouple_decreases_weight_length_and_trainsets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;

    &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decouple&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s analyze it. We express a train as a &lt;code&gt;Train&lt;/code&gt; object with its composition as a property. Both &lt;code&gt;length&lt;/code&gt; and &lt;code&gt;weight&lt;/code&gt; can be calculated properties, which are preferable. It’s then quite natural to create interactions with that object, expressing them as &lt;code&gt;couple&lt;/code&gt; and &lt;code&gt;decouple&lt;/code&gt; a train set. Both affect the length, weight, and composition of the entire train. Consider this code sample our starting point for further comparison.&lt;/p&gt;

&lt;p&gt;Functional programming has an entirely different philosophy, bringing with it a completely different set of advantages and disadvantages. Let’s see what those are.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Functional Programming&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Functional_programming" rel="noopener noreferrer"&gt;Functional programming&lt;/a&gt;(FP) is on the rise, despite its origins tracing back to the 1950s, and there are good reasons for that. Done well, FP can make codebases easier to grasp and less prone to complex bugs.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.geeksforgeeks.org/difference-between-functional-programming-and-object-oriented-programming/" rel="noopener noreferrer"&gt;paradigm differs&lt;/a&gt; from OOP in that it treats &lt;a href="https://en.wikipedia.org/wiki/First-class_function" rel="noopener noreferrer"&gt;functions as first-class citizens&lt;/a&gt;, emphasizes the use of functions, &lt;a href="https://en.wikipedia.org/wiki/Immutable_object" rel="noopener noreferrer"&gt;immutability&lt;/a&gt; and isolating &lt;a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener noreferrer"&gt;side-effects&lt;/a&gt;. FP aligns well with calculations—inputs and outputs.&lt;/p&gt;

&lt;p&gt;I’ve learned most about FP from the excellent book &lt;a href="https://grokkingsimplicity.com/" rel="noopener noreferrer"&gt;Grokking Simplicity&lt;/a&gt;. A crucial perspective the author offers is that functional programming is all about identifying and separating &lt;em&gt;Actions, Calculations, and Data&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Actions&lt;/strong&gt; depend on when they’re used, such as database queries, API calls, and reading files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Calculations&lt;/strong&gt; always give the same result given the same inputs—it doesn’t matter when you call them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data&lt;/strong&gt; is inert and can be interpreted as is—usually describes some event.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These &lt;strong&gt;ACDs&lt;/strong&gt; of functional programming have permanently changed how I read and write code. They have caused me to be on the lookout for this distinction and pull them apart in code.&lt;/p&gt;

&lt;p&gt;Functional programming has a whole other set of benefits compared to OOP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Natural fit for processing&lt;/strong&gt;. We tend to think of calculations more naturally as functions, which makes FP a good fit for processing data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicity by locality&lt;/strong&gt;. FP can simplify code by increasing its &lt;em&gt;locality&lt;/em&gt;. Locality means ‘Can I understand this code without considering any other context?’ FP achieves this with immutability and isolating side effects. For instance, mutability forces you to consider who holds references to the same data, and both mutability and side effects force you to think on a temporal axis—when something is used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Composability.&lt;/strong&gt; Pure functions compose exceptionally well, often surprising you with new ways of being useful. The Linux command line is a great example. Tools like &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, and &lt;code&gt;sed&lt;/code&gt;, are simple in isolation, but can form surprisingly powerful new combinations by chaining them together.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testability.&lt;/strong&gt; Not having to deal with time as a dimension, as well as dealing with inputs and outputs makes testing functional code simple.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The downsides I’ve experienced are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Functions are not our natural way of thinking,&lt;/strong&gt; especially not for concepts we see as ‘objects’ in real life. A Tree is neither a function nor data to me, but rather an object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Operating upon data&lt;/strong&gt; , rather than the data and logic being self-contained. When done carelessly, this might decrease cohesion and increase coupling, making future changes to the code harder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effort up front, pay off later.&lt;/strong&gt; Code that adheres to the FP principles can be hard to design—it can feel counterintuitive. You need the state changed, but you have to out of your way to do so. You need to query a database here, why not do so where you need it? The effort is moved forward in the process. Once you’ve put in the effort, the code will remain easier to reason about, and easier to debug for the rest of its lifetime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;. FP is sometimes known for its steep learning curve, not helped by complex terminology such as Monads, Monoids, Applicatives, etc, originating from &lt;a href="https://en.wikipedia.org/wiki/Category_theory" rel="noopener noreferrer"&gt;Category Theory&lt;/a&gt;. These concepts obscure the essence of ideas, which are relatively simple at their core.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Time for some code—functional programming style. We’ll consider the same example as before: coupling and decoupling train sets on a train.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;couple_train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decouple_train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;train_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;lengths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lengths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;train_weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we’d use it as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_couple_increases_weight_length_and_trainsets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;},)&lt;/span&gt;

    &lt;span class="n"&gt;coupled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;couple_train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;train_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coupled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;train_weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coupled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coupled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_decouple_decreases_weight_length_and_trainsets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;decoupled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decouple_train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;train_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoupled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;train_weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoupled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoupled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compared to the OOP example we’ve expressed the behavior as calculations operating on immutable data. For instance, instead of a mutable &lt;a href="https://docs.python.org/3/library/stdtypes.html#lists" rel="noopener noreferrer"&gt;list&lt;/a&gt;, we’ve used a &lt;a href="https://docs.python.org/3/library/stdtypes.html#tuples" rel="noopener noreferrer"&gt;tuple&lt;/a&gt; instead. Another crucial difference is found in the usage of the code: we assign results of functions to new variables &lt;code&gt;coupled&lt;/code&gt; and &lt;code&gt;decoupled&lt;/code&gt;. No more mutating state in place. We win in predictability, but we lose the clearly expressed concepts.&lt;/p&gt;

&lt;p&gt;Could we do better? I believe so, but first, we should consider how we look at programming paradigms.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Toolbox&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There always seems to be discussion around ‘which paradigm is best’ or ‘why this paradigm is better than that one.’ But what if we look at it differently? Time to break the binary opposition.&lt;/p&gt;

&lt;p&gt;Imagine your skillset as a software engineer as a toolbox. Every skill is neatly stored in one of its drawers. Now, let’s say that you’re handed a new screwdriver. Instead of throwing out your other tools, you would let them coexist and pick the appropriate tool for the job. Sometimes using them together to get a job done neither one could have achieved alone.&lt;/p&gt;

&lt;p&gt;Each paradigm is an addition to your toolbox, not a replacement. This is why &lt;a href="https://www.codecraftr.nl/p/learning-programming-languages-with-exercism" rel="noopener noreferrer"&gt;I advocate exploring different languages&lt;/a&gt;. As we’ve seen, each paradigm has its advantages and disadvantages, and each shines in different situations. Adding a tool to our collection makes us more flexible and enables us to synthesize entirely new things out of their coexistence.&lt;/p&gt;

&lt;p&gt;More and more languages are becoming multi-paradigm, supporting different paradigms to varying degrees. Individual languages will lean more towards one or the other. For instance Scala—by default—is more functionally inclined than Java. A language being multi-paradigm can be likened to a language giving you a bigger toolbox to choose from. You can leverage FP for data processing, and OOP for rich domain modeling and join the two to get the best of both worlds.&lt;/p&gt;

&lt;p&gt;What would a union of the best of both worlds look like to me?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rich Domain Modeling&lt;/strong&gt; in the application’s core.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Objects for concepts, functions for processing&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immutability as the default&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Isolation of side effects&lt;/strong&gt; , sometimes referred to as ‘pushing side effects to the edge of the world’.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can model software using objects but still encourage locality by making them immutable and side-effect-free. Functional Object-Oriented Programming:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;couple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_set&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decouple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;lengths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lengths&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_couple_increases_weight_length&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;coupled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;couple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;coupled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;coupled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coupled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_decouple_decreases_weight_length_and_trainsets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Train&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;TrainSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="n"&gt;decoupled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decouple&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;decoupled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;decoupled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoupled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comparing this solution to the OOP and FP example, we’ve hit upon the Goldilocks zone for a problem like this. &lt;a href="https://docs.python.org/3/library/dataclasses.html" rel="noopener noreferrer"&gt;Frozen data classes&lt;/a&gt; make the objects immutable after creation, making them easy to reason about, whilst clearly capturing the concepts of &lt;code&gt;Train&lt;/code&gt; and &lt;code&gt;TrainSet&lt;/code&gt;. We compute new states by returning new &lt;code&gt;Train&lt;/code&gt;instances from &lt;code&gt;couple&lt;/code&gt; and &lt;code&gt;decouple&lt;/code&gt;. This changes the interaction for client code, as now &lt;code&gt;Train&lt;/code&gt; is returned from those methods.&lt;/p&gt;

&lt;p&gt;This happens to be the programming style I gravitate towards in programming languages supporting both OOP and FP. At least for the core of non-trivial programs solving complex domain problems.&lt;/p&gt;

&lt;p&gt;Concluding we can see that no tool is inherently good or bad. Good code can be written in any language or paradigm, but the same holds for the inverse. In the end, it isn’t the tool that decides the outcome. That responsibility lies with the one who wields it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As much as we’d like reality to be black and white, it is more nuanced than that. In this case that turns out to be a great outcome:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We don’t have to choose either Object-Oriented Programming or Functional Programming. We can have the best of both.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Used well together, these paradigms allow you to synthesize something better than either one could have done by itself. The sum of the whole is greater than its parts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The code samples are available on &lt;a href="https://github.com/rstraub/codecraftr-samples/tree/main/python/samples/functional_vs_oop" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>learning</category>
      <category>oop</category>
      <category>functional</category>
    </item>
    <item>
      <title>Craft over Art</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Thu, 21 Dec 2023 09:00:44 +0000</pubDate>
      <link>https://forem.com/codecraftr/craft-over-art-2791</link>
      <guid>https://forem.com/codecraftr/craft-over-art-2791</guid>
      <description>&lt;p&gt;What is code to you? Is it a tool? A way to make your thoughts executable? Something beautiful perhaps?&lt;/p&gt;

&lt;p&gt;Over the years, I've noticed that not all programmers look at code the same way. Some see it as a means to an end - a way to solve a problem. Others, like me, think code also holds aesthetic value. I can appreciate elegant code and find it beautiful.&lt;/p&gt;

&lt;p&gt;This raises the question, which perspective is right?&lt;/p&gt;

&lt;p&gt;I don't think either is correct. We're probably best off somewhere in the middle. I've seen code written purely to get a job done. It did, but nobody was able to work with it after. I've also seen people gold-plate solutions, endlessly polishing their solution while spending precious time and money.&lt;/p&gt;

&lt;p&gt;Ultimately, the code we write professionally should always add value - be useful. If we can make it beautiful along the way, that's great, but it's not a necessity. Constraints such as time, money, urgency, and longevity of the solution all influence whether we should invest time in improving code. It's a &lt;a href="https://www.codecraftr.nl/i/137030156/towards-trade-offs" rel="noopener noreferrer"&gt;tradeoff&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can have different views on what good code looks like. We might have different takes on "good enough." However, we can develop this judgment and make the tradeoff more deliberate. Kent Beck's excellent book &lt;a href="https://www.goodreads.com/book/show/171691901-tidy-first" rel="noopener noreferrer"&gt;Tidy First&lt;/a&gt; explains how to make this tradeoff and is a great resource to improve this skill.&lt;/p&gt;

&lt;p&gt;As for me, I used to be on the "art" side of the spectrum. I could spend ages going back and forth until things were "just right." Part of the reason might be that I didn't start programming to make my life easier. I never wrote scripts to solve my problems. I started my programming days at university, where much of what we learned was abstract and felt far removed from solving practical problems.&lt;/p&gt;

&lt;p&gt;I envy the pragmatic ones. Those who've developed an appreciation for programming because of the incredible problem-solving potential. This realization gradually dawned on me, but only after years of modeling and solving problems without value. Unfortunately, I had to light my own fire instead of it being set ablaze in a sudden epiphany of the limitless potential of software.&lt;/p&gt;

&lt;p&gt;These days, I try to consciously nudge myself towards the middle of the spectrum by posing myself questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How much value will this bring?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Could I spend my time better?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this good enough?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It helps me keep effort proportional to the payoffs.&lt;/p&gt;

&lt;p&gt;If you're on the opposite end of the spectrum, questions such as these might help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Is this understandable for others?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Could we continue working on this with reasonable effort?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What would improve this the most at what effort?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We might not be able to change our modus operandi, but we can always improve the result with some awareness.&lt;/p&gt;

&lt;p&gt;The book &lt;a href="https://www.goodreads.com/book/show/5608045-apprenticeship-patterns" rel="noopener noreferrer"&gt;Apprenticeship Patterns&lt;/a&gt; has a chapter called &lt;em&gt;Craft over Art&lt;/em&gt;, which inspired the title of this post. One sentence left a lasting impression on me. Hopefully, it will do so for you, too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Code can be beautiful, but must always be useful&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks for reading CodeCraftr! Subscribe for free to receive new posts and support my work.&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>Perfectly Imperfect Code</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Fri, 18 Aug 2023 11:01:02 +0000</pubDate>
      <link>https://forem.com/codecraftr/perfectly-imperfect-code-39op</link>
      <guid>https://forem.com/codecraftr/perfectly-imperfect-code-39op</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We should strive to write perfect code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first glance, this seems like a perfectly valid statement, something you would proudly tell others about. I used to be like this, but I came to regret it.&lt;/p&gt;

&lt;p&gt;I've always been a conscientious person, and over the years this spiraled into perfectionism. This trait, which sounds much more positive than it is, has tormented me ever since.&lt;/p&gt;

&lt;p&gt;As a software engineer, I prided myself on the "perfect" solutions I could come up with. The result? Constantly putting the bar too high, and an unhealthy amount of continuous stress and anxiety. Not something I'd recommend. Something had to change.&lt;/p&gt;

&lt;p&gt;Part of me "rehabilitating" from perfectionism was reading about it. One book in particular, &lt;em&gt;&lt;a href="https://www.goodreads.com/book/show/39692401-wabi-sabi" rel="noopener noreferrer"&gt;Wabi Sabi: Leading a Perfectly Imperfect Life&lt;/a&gt;&lt;/em&gt;, made a big impression on me. &lt;a href="https://en.wikipedia.org/wiki/Wabi-sabi" rel="noopener noreferrer"&gt;Wabi Sabi&lt;/a&gt; is a way of thinking, ingrained in the Japanese culture that broadly means seeing the beauty in imperfection, and recognizing that imperfection is the natural order of things.&lt;/p&gt;

&lt;p&gt;This got me thinking about my career and the code I wrote. I realized I got it all wrong. I should strive for &lt;em&gt;perfectly imperfect&lt;/em&gt; code instead. Let me explain why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perfect Code is an Illusion
&lt;/h2&gt;

&lt;p&gt;Let’s first dispel the illusion: code cannot be perfect.&lt;/p&gt;

&lt;p&gt;Outside of some basic metrics, we lack measures to objectively determine the &lt;a href="https://en.wikipedia.org/wiki/Software_quality" rel="noopener noreferrer"&gt;quality&lt;/a&gt; of code. Code is subjective. To me, code quality boils down to a gut feeling - one that is honed over many years of experience.&lt;/p&gt;

&lt;p&gt;Sure, we have some vague agreement on what quality code entails. It shouldn't be too many lines, it should be easy to read, etc. But interpreting these metrics is still a matter of the person reading it.&lt;/p&gt;

&lt;p&gt;The point is code I might find &lt;del&gt;perfect&lt;/del&gt; great might be horrific to you and vice versa. Beauty is in the eye of the beholder, and thus perfection eludes us. Attempting to attain it is a futile exercise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fleeting Nature of Perfect Code
&lt;/h2&gt;

&lt;p&gt;Let's say we hypothetically ended up with perfect code. We'd be confronted with the realization that this perfection would be ephemeral. Everything in our industry is in constant flux. New technologies, patterns, architectures, and perspectives emerge all the time, potentially rendering a solution in dire need of improvement. Software is &lt;em&gt;not&lt;/em&gt; static, it's organic.&lt;/p&gt;

&lt;p&gt;But there is more. As we work on solutions in software our understanding of the problem domain improves, as would our grasp on the codebase. Our perspective on the solution shifts continuously.&lt;/p&gt;

&lt;p&gt;Lastly, there is the aspect of our skill. As we improve over time, our sentiment towards solutions changes. If you revisited the code you wrote years ago, would you still consider it good? Most likely you would do things differently now. You changed, even though the code did not. And now the code is no longer considered perfect.&lt;/p&gt;

&lt;p&gt;The Greek philosopher Heraclitus expressed this long ago:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No man ever steps in the same river twice, for it's not the same river and he's not the same man.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Economics of (Im)perfection
&lt;/h2&gt;

&lt;p&gt;In the end, our software needs to deliver value. Ideally, we do this cheaply, effectively, and at a sustainable pace. The ability to constantly deliver value enables the business.&lt;/p&gt;

&lt;p&gt;Once again perfection is the enemy. Getting things to "perfect" takes disproportionately more effort than getting them to "good enough." This principle is commonly known as the &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Pareto_principle" rel="noopener noreferrer"&gt;Pareto Principle&lt;/a&gt;&lt;/em&gt; which states that 20% of the causes lead to 80% of the results.&lt;/p&gt;

&lt;p&gt;Loosely translated this means that 20% of the effort can net us 80% of the outcome. Perfection lies in the stretch from 80% to 100%, which would take up all the remaining effort. Under economic constraints, it makes much more sense to put in 20% and get more than adequate results, as opposed to aiming for that 100%. The challenge is in developing a sense of where you are on this spectrum and balancing appropriately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perfection is the Enemy of Progress
&lt;/h2&gt;

&lt;p&gt;Aiming for the perfect result can evoke doubts, overthinking, procrastination, or even inaction. Perfection inhibits progress.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Perfect is the enemy of good - Voltaire&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A profound realization in software development is that it is an exercise in learning and exploration of a complex socio-technical system. The complex nature of it all means analysis cannot reveal all the answers. Sometimes we simply need to take a step, reassess from a new vantage point and determine the next step from there.&lt;/p&gt;

&lt;p&gt;This all demands experimentation. As engineers were constantly creating, executing, and analyzing bite-sized experiments. Perfection is not conducive to this approach. It prevents it.&lt;/p&gt;

&lt;p&gt;For example, I've seen projects where consistency (perfection in a sense) was highly valued. It discouraged us from trying out different solutions in parts of the codebase as that would introduce inconsistency. The motto implicitly was "all or nothing." Many times this resulted in nothing, leaving the code seemingly perfect, even though it was only superficial veneer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beauty in Imperfection
&lt;/h2&gt;

&lt;p&gt;Wabi Sabi teaches us to see beauty in imperfection: a brittle autumn leaf or a crack in an ancient vase. These things are not perfect but can have an austere beauty. The same holds for code: if we allow ourselves to look beyond the cracks in the surface, beauty can be found.&lt;/p&gt;

&lt;p&gt;Think about all the effort that went into a piece of old or inherited code. Consider the decisions its authors made, and how they might have struggled, having only what information they had at the time. Imagine how that piece of code has been helping the business achieve its goals during its lifetime, and how many metamorphoses it has gone through over the years. You might develop a bit of reverence for that code you were so eager to dismiss at first glance.&lt;/p&gt;

&lt;p&gt;Beauty runs deeper than what's easy to observe. Imperfection is strife. Imperfection tells a story. Imperfection is the natural state of the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Long and Winding Road to Imperfection
&lt;/h2&gt;

&lt;p&gt;As software engineers, we are constantly fighting under and over-engineering. It's up to us to find the correct balance in the context we find ourselves in. Useful software will always be a matter of tradeoffs and making progress necessitates imperfection. As much as perfect code sounds like something to strive for, in reality, it is the siren's call luring you into the depths of despair.&lt;/p&gt;

&lt;p&gt;The code we write is by definition imperfect. Realizing this took me a long time to accept, but I did. From now on my code will be perfectly imperfect. Hopefully, yours will too.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Dumb Tests are Smart 🧠</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Sat, 18 Feb 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/why-dumb-tests-are-smart-842</link>
      <guid>https://forem.com/codecraftr/why-dumb-tests-are-smart-842</guid>
      <description>&lt;p&gt;Writing tests that help evolve a system is hard, and you get there by avoiding smart tests while preferring dumb ones. Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Paradox of Smart Tests 🤔
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Smart is always better than dumb, isn’t it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Maybe, but maybe not.&lt;/p&gt;

&lt;p&gt;This time we’ll look at the paradox that dumb &lt;a href="https://blog.devgenius.io/unit-test-vs-programmer-test-vs-integration-test-54c509852ab8" rel="noopener noreferrer"&gt;programmer tests&lt;/a&gt; are superior to smart ones. This paradox demands an explanation, but first, we must consider what tests should be like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Desired Qualities of Programmer Tests ☝️
&lt;/h2&gt;

&lt;p&gt;Well-written automated tests are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easy to read&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intention revealing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Focused&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put succinctly, &lt;strong&gt;programmer tests should make change easy&lt;/strong&gt;. Change to code under test and the test code itself.&lt;/p&gt;

&lt;p&gt;How do you achieve this?&lt;/p&gt;

&lt;p&gt;Write simple, straightforward, or “dumb” tests, not intricate and full of magic or “smart” ones. Let’s have a look at smart tests first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a Smart Test 🧬
&lt;/h2&gt;

&lt;p&gt;What is a smart test, then?&lt;/p&gt;

&lt;p&gt;Smart tests contain logic obscuring the true meaning of the test. For example, this logic might exist for one of these goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capturing common setup&lt;/li&gt;
&lt;li&gt;creating test in- or output&lt;/li&gt;
&lt;li&gt;reducing the amount steps in the test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These all try to &lt;strong&gt;reduce duplication&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In general, this is a good thing. The &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;DRY-principle&lt;/a&gt;&lt;/em&gt; (Don’t Repeat Yourself) is an excellent heuristic for ending up with maintainable code.&lt;/p&gt;

&lt;p&gt;But, as always, there is a cost. The cost tends to be in the form of &lt;strong&gt;code being less descriptive&lt;/strong&gt; ; it becomes less straightforward.&lt;/p&gt;

&lt;p&gt;For example, I’ve encountered tests that took me hours to understand because input data was dynamically generated, filtered, and transformed. It might save lines of code, but the reader deals with the complexity.&lt;/p&gt;

&lt;p&gt;Now we know what smart tests are, let’s see how dumb tests compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Superiority of Dumb Tests 🪄
&lt;/h2&gt;

&lt;p&gt;Dumb tests contain &lt;strong&gt;no magic&lt;/strong&gt; and require no mental gymnastics to understand. They are easy to read and intention-revealing.&lt;/p&gt;

&lt;p&gt;Great tests might be &lt;em&gt;DRY&lt;/em&gt;, but the best ones exhibit the &lt;em&gt;DAMP&lt;/em&gt; (Descriptive and Meaningful Phrases) principle. Code always exists on a &lt;a href="https://enterprisecraftsmanship.com/posts/dry-damp-unit-tests/" rel="noopener noreferrer"&gt;spectrum&lt;/a&gt; of being explicit and preventing duplication, and it is up to you to strike a good balance. Tests should value their ability to convey their meaning above all else.&lt;/p&gt;

&lt;p&gt;This is because a major goal of programmer tests is to &lt;strong&gt;explain production code&lt;/strong&gt; , as I mentioned &lt;a href="https://xebia.com/blog/why-use-tdd/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The last thing you want is to decipher the meaning of tests on top of understanding production code.&lt;/p&gt;

&lt;p&gt;There are strategies to get to tests that are both descriptive and easy to maintain, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;&lt;a href="https://www.codecraftr.nl/maintainable-tests-with-test-data-builders/" rel="noopener noreferrer"&gt;Test Data Builder Pattern&lt;/a&gt;&lt;/strong&gt;, which allows you to construct test data in a better way.&lt;/li&gt;
&lt;li&gt;A thin, &lt;strong&gt;&lt;a href="https://blog.cleancoder.com/uncle-bob/2017/03/03/TDD-Harms-Architecture.html" rel="noopener noreferrer"&gt;test-specific API&lt;/a&gt;&lt;/strong&gt; around your production code that makes steps more expressive and course-grained.&lt;/li&gt;
&lt;li&gt;Employing &lt;strong&gt;Test-Driven Development&lt;/strong&gt; , which &lt;a href="https://xebia.com/blog/tdd-is-not-about-testing/" rel="noopener noreferrer"&gt;encourages expressive tests&lt;/a&gt; from the inception of code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most bullet-proof heuristic, though, is to ask yourself whether code aids or prevents comprehension of a test for future readers. This applies to production code as well, of course!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion 📝
&lt;/h2&gt;

&lt;p&gt;Smart isn’t always better, especially when it comes to tests. Ideally, programmer tests should be easy to read and clearly state their intention, but this is hard.&lt;/p&gt;

&lt;p&gt;You get to great tests by placing yourself in the shoes of the future reader. Moreover, you make your tests &lt;em&gt;DAMP&lt;/em&gt; instead of &lt;em&gt;DRY&lt;/em&gt; by valuing being expressive over preventing duplication.&lt;/p&gt;

&lt;p&gt;The result is automated tests that form the catalyst for change instead of inhibiting it.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>programming</category>
      <category>tdd</category>
      <category>codequality</category>
    </item>
    <item>
      <title>How to Name Interfaces, Abstract Classes, and Their Implementations 🏷</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Sun, 11 Dec 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/how-to-name-interfaces-abstract-classes-and-their-implementations-3md</link>
      <guid>https://forem.com/codecraftr/how-to-name-interfaces-abstract-classes-and-their-implementations-3md</guid>
      <description>&lt;p&gt;Naming abstract types and their implementations is challenging. Learn why you should avoid names like IRepository, RepositoryImpl, and AbstractRepository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming Is Hard, Naming Abstract Types Is Even Harder 🥵
&lt;/h2&gt;

&lt;p&gt;As the saying goes, naming is one of the few truly tough problems in programming. If you’re anything like me, you probably sit behind your desk, scratching your head to find a fitting name every day.&lt;/p&gt;

&lt;p&gt;This time I want to look at a problem I repeatedly encounter: badly named abstract types and their implementations (interface/abstract class). You’ve probably experienced one of these problematic examples yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IRepository&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AbstractRepository&lt;/code&gt; or&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RepositoryImpl&lt;/code&gt;’s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can and should do better. This type of naming tends to be a symptom of one of these two causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An unnecessary abstraction&lt;/li&gt;
&lt;li&gt;Unexpressive naming&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s see what the problem with this type of naming is and, more importantly, what you can do about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Think: What Purpose Does the Abstraction Have? 🤔
&lt;/h2&gt;

&lt;p&gt;Firstly, there is the case of &lt;strong&gt;unnecessary abstraction&lt;/strong&gt;. Some programmers take the idea of “abstraction” too far and put interfaces in front of nearly everything. These tend to miss a purpose or anticipate a future scenario that might not happen, a clear violation of the &lt;a href="https://www.martinfowler.com/bliki/Yagni.html" rel="noopener noreferrer"&gt;YAGNI principle&lt;/a&gt;. Introducing abstractions should always be done deliberately.&lt;/p&gt;

&lt;p&gt;Software design is a delicate balancing act where choices must be justified. As I mentioned &lt;a href="https://www.codecraftr.nl/interfaces-defining-roles/" rel="noopener noreferrer"&gt;earlier&lt;/a&gt;, interfaces always mean you incur the cost of extra cognitive load due to adding indirection. There should always be a positive effect to offset that cost.&lt;/p&gt;

&lt;p&gt;Next time you see (or write) an &lt;code&gt;IService&lt;/code&gt; and &lt;code&gt;ServiceImpl&lt;/code&gt; think about the purpose of the abstraction. You might not need it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Think, Again: Come up with a Better Name 💡
&lt;/h2&gt;

&lt;p&gt;Secondly, this naming pattern might occur due to &lt;strong&gt;lazy naming&lt;/strong&gt;. Naming is always hard, and the path of least resistance - the brain loves to be lazy - is to call something the first thing that comes to mind.&lt;/p&gt;

&lt;p&gt;The problem is that this is rarely the best we can come up with. If you dig deep and put in more effort, you will find a better name. Future you will be grateful for it.&lt;/p&gt;

&lt;p&gt;For example, you might encounter a &lt;code&gt;Repository&lt;/code&gt;/&lt;code&gt;RepositoryImpl&lt;/code&gt; combination. What does this tell you?&lt;/p&gt;

&lt;p&gt;Very little. It only conveys that &lt;code&gt;RepositoryImpl&lt;/code&gt; implements an abstract construct &lt;code&gt;Repository&lt;/code&gt;. Crucially, these names express nothing about &lt;em&gt;what&lt;/em&gt; makes the implementor stand apart. Purely looking at the class name, I have no idea what it does. Does it write to a file? A database? In memory? Currently, you would have to look at the implementation to find out, which is bad.&lt;/p&gt;

&lt;p&gt;The solution is easy; name the implementor by what makes it unique. A name like &lt;code&gt;InMemoryRepository&lt;/code&gt;, or &lt;code&gt;FileRepository&lt;/code&gt; tells me much more at a glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  From the Trenches 🕵️
&lt;/h2&gt;

&lt;p&gt;Let’s look at a real-life example, in this case &lt;a href="https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html" rel="noopener noreferrer"&gt;Java’s collection API&lt;/a&gt;. As a reminder, it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5hipteiz8l3qrjnzqwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5hipteiz8l3qrjnzqwl.png" alt="Java Collections API Diagram" width="800" height="749"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1. Java Collections API, by Ramlmn, &lt;a href="https://creativecommons.org/licenses/by-sa/4.0" rel="noopener noreferrer"&gt;CC BY-SA 4.0&lt;/a&gt;, via Wikimedia Commons&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Do you see any &lt;code&gt;ISets&lt;/code&gt; or &lt;code&gt;ListImpls&lt;/code&gt; in this hierarchy?&lt;/p&gt;

&lt;p&gt;No. All the interfaces (yellow) have meaningful names like &lt;code&gt;Set&lt;/code&gt;, &lt;code&gt;List&lt;/code&gt; or &lt;code&gt;Queue&lt;/code&gt;. All the classes (purple) implementing them put relevant information in their name. A &lt;code&gt;TreeSet&lt;/code&gt;, &lt;code&gt;LinkedList&lt;/code&gt; or &lt;code&gt;PriorityQueue&lt;/code&gt; instantly tells you what to expect from them.&lt;/p&gt;

&lt;p&gt;Some of you might point at the abstract classes (blue) in this hierarchy, such as &lt;code&gt;AbstractQueue&lt;/code&gt;. There is a reason for this, but it is an exception to the rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exceptions to the Rule? 🚨
&lt;/h2&gt;

&lt;p&gt;In some situations, you could prefix your abstract type, but it should be your last resort. They can be useful in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skeletal implementations of abstract types.&lt;/strong&gt; The &lt;code&gt;AbstractQueue&lt;/code&gt; is an excellent example of this. It implements an interface (&lt;code&gt;Queue&lt;/code&gt;), but offers the basic setup for implementing a new type of queue. Hence it is a &lt;em&gt;skeleton implementation class&lt;/em&gt;. In these situations, there is no better name to come up with as that is its sole purpose, and the interface is already named &lt;code&gt;Queue&lt;/code&gt;. According to &lt;a href="https://www.goodreads.com/book/show/34927404-effective-java" rel="noopener noreferrer"&gt;Effective Java&lt;/a&gt;, the abstract prefix in this instance has become convention, but other names like &lt;code&gt;SkeletalQueue&lt;/code&gt; might have been more optimal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Libraries and technical limitations&lt;/strong&gt;. For example, when using a library like &lt;a href="https://immutables.github.io" rel="noopener noreferrer"&gt;Immutables&lt;/a&gt; you end up with an abstract type and concrete type for every thing you wish to represent. Both types mean the same thing, but the names must be unique, so you end up with types such as &lt;code&gt;Queue&lt;/code&gt; and &lt;code&gt;QueueImpl&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind these should be the exception to the rule. Always think long and hard before resorting to pre- or postfixing your abstract types this way. Most of the time, there are better options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion 📝
&lt;/h2&gt;

&lt;p&gt;Interfaces and abstract classes are important tools for creating abstractions in code. Expressively naming abstract types an expressive name is demanding, and not doing so hides the true meaning of types from readers. Also, think hard if the abstract type is necessary. Sometimes, you could do without it.&lt;/p&gt;

&lt;p&gt;The antidote is simple, not easy: &lt;em&gt;stop and think&lt;/em&gt;. Be kind to the future readers of your code and name interfaces and abstract classes intentionally. They will be grateful for it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What is your opinion? What is your preferred way to name these types, and why?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>oop</category>
      <category>programming</category>
      <category>java</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>The Real Reasons for Doing Test-Driven Development 💎</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Tue, 13 Sep 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/the-real-reasons-for-doing-test-driven-development-54n8</link>
      <guid>https://forem.com/codecraftr/the-real-reasons-for-doing-test-driven-development-54n8</guid>
      <description>&lt;p&gt;Why do people apply TDD? Here’s a secret: it’s &lt;em&gt;not&lt;/em&gt; for the tests. Learn about the actual goal and values hidden under the surface of Test-Driven Development.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are the Real Reasons for Doing TDD? 🧼
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://martinfowler.com/bliki/TestDrivenDevelopment.html" rel="noopener noreferrer"&gt;Test-Driven Development&lt;/a&gt; (TDD) is a &lt;a href="https://blog.cleancoder.com/uncle-bob/2014/06/17/IsTddDeadFinalThoughts.html" rel="noopener noreferrer"&gt;controversial topic&lt;/a&gt; amongst developers. After many years of doing TDD daily, I think part of the reason is that some people do not fully grasp the reasons behind TDD.&lt;/p&gt;

&lt;p&gt;Let’s get the biggest misconception out of the way first: &lt;a href="https://xebia.com/blog/tdd-is-not-about-testing/" rel="noopener noreferrer"&gt;TDD is not about testing&lt;/a&gt;. It is a vehicle to drive development.&lt;/p&gt;

&lt;p&gt;The goal, according to &lt;a href="https://amzn.to/3U30wNX" rel="noopener noreferrer"&gt;Test-Driven Development: By Example&lt;/a&gt;, is simple yet powerful:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Clean Code That Works&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I love that brief explanation, and if there is one thing you take away from reading this post, that should be it. However, specific reasons for doing TDD are best expressed in terms of Extreme Programming’s values. These are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Feedback&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Courage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Communication&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Respect&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TDD and the Values of XP 🧗
&lt;/h2&gt;

&lt;p&gt;TDD offers many &lt;a href="https://www.madetech.com/blog/9-benefits-of-test-driven-development/" rel="noopener noreferrer"&gt;benefits&lt;/a&gt;, but I prefer a different perspective that delves a little deeper. In my opinion, &lt;a href="https://en.wikipedia.org/wiki/Extreme_programming" rel="noopener noreferrer"&gt;Extreme Programming&lt;/a&gt; (XP) best describes the reasons for doing TDD.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Kent_Beck" rel="noopener noreferrer"&gt;Kent Beck&lt;/a&gt; defined &lt;a href="https://www.tutorialspoint.com/extreme_programming/extreme_programming_values_principles.htm" rel="noopener noreferrer"&gt;five values&lt;/a&gt; in &lt;a href="https://amzn.to/3d8eayN" rel="noopener noreferrer"&gt;Extreme Programming Explained&lt;/a&gt; (a book &lt;a href="//www.codecraftr.nl/books-software-craftsman-mindset"&gt;I highly recommend&lt;/a&gt;) which form the foundation of everything it entails. As you will see, TDD is also built on top of that foundation.&lt;/p&gt;

&lt;p&gt;But first, a few words about why all this even matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do Values Matter in the First Place? 🏃
&lt;/h2&gt;

&lt;p&gt;As I mentioned, TDD is the subject of quite some controversy amongst developers. Software engineers either love or hate it, and I wonder if those who don’t like it truly understand the purpose of TDD.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F26-stretching.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F26-stretching.jpg" alt="stretching cat" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stretching doesn’t make sense without knowing its purpose&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s like not wanting to stretch before going out for a run simply because you are unaware that it prevents injuries. Without that knowledge, stretching seems like a waste of time and effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The underlying values of a practice give it its meaning.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving Feedback by Using TDD 🧭
&lt;/h2&gt;

&lt;p&gt;Firstly, TDD is one of the best ways to generate feedback. Feedback on what? On each one of these attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Correctness&lt;/strong&gt;. Simply put, does the code do what you want? The crucial differentiator is that with TDD, you get this while you’re still coding up the problem. No need for print statements or playing compiler in your head to figure out what the code is doing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality&lt;/strong&gt;. A superpower of TDD. It will force you to write testable code, i.e., &lt;em&gt;loosely coupled&lt;/em&gt; and &lt;em&gt;highly cohesive&lt;/em&gt;, which means your code has a higher quality. If the testing becomes difficult, it is a &lt;a href="https://slides.com/barryosull/using-test-pain-as-a-design-guide-c930e9" rel="noopener noreferrer"&gt;tell-tale sign&lt;/a&gt; your design could use improvement. Thus, TDD is an effective way to get feedback on your code’s &lt;em&gt;internal quality&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progress&lt;/strong&gt;. Since you start specifying behavior as a failing test, you know exactly when you’re done: once the test is green. Combining this with &lt;a href="https://en.wikipedia.org/wiki/Acceptance_test-driven_development" rel="noopener noreferrer"&gt;Acceptance Test-Driven Development&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Behavior-driven_development" rel="noopener noreferrer"&gt;Behavior-Driven Development&lt;/a&gt; amplifies the feedback to the feature level.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In essence &lt;strong&gt;TDD employs tests to generate feedback&lt;/strong&gt;. Like a compass, it constantly shows you whether you’re heading in the right direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Achieving Simplicity with TDD ❤️
&lt;/h2&gt;

&lt;p&gt;Secondly, Test-Driven Development is a great way to write simpler code. Simplicity is difficult to achieve in programming, but it is equally crucial to pursue. It helps manage complexity. The definition of simplicity that I like best comes from the &lt;a href="https://agilemanifesto.org/principles.html" rel="noopener noreferrer"&gt;agile manifesto&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Simplicity–the art of maximizing the amount of work not done–is essential.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But how does TDD achieve this magical thing?&lt;/p&gt;

&lt;p&gt;Firstly, it forces you to &lt;strong&gt;express the behavior you need upfront unambiguously&lt;/strong&gt;. You should end up writing exactly the code you need, following the “&lt;a href="https://www.martinfowler.com/bliki/Yagni.html" rel="noopener noreferrer"&gt;You Aren’t Gonna Need It&lt;/a&gt;” principle. An experienced TDD’er aims to go from &lt;a href="http://www.jamesshore.com/v2/blog/2005/red-green-refactor" rel="noopener noreferrer"&gt;red to green&lt;/a&gt; as quickly as possible, and simplicity is a surefire way to do so.&lt;/p&gt;

&lt;p&gt;Furthermore, the last step in the &lt;a href="http://www.jamesshore.com/v2/blog/2005/red-green-refactor" rel="noopener noreferrer"&gt;tdd cycle&lt;/a&gt; is &lt;a href="https://www.refactoring.com" rel="noopener noreferrer"&gt;refactoring&lt;/a&gt;. &lt;strong&gt;This continuous refactoring cycle results in more readable and simpler code&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Becoming Courageous by Applying TDD 🦁
&lt;/h2&gt;

&lt;p&gt;Thirdly, TDD supplies you with a healthy dose of courage. Courage seems like an odd value to associate with TDD, but it’s the value that gets the most attention in &lt;a href="https://amzn.to/3U30wNX" rel="noopener noreferrer"&gt;Test-Driven Development: by Example&lt;/a&gt;. In the book, Kent describes &lt;strong&gt;courage as “managing fear”&lt;/strong&gt; and explains how TDD is an effective means to do so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F26-fear.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F26-fear.jpg" alt="Black Spider" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TDD is all about managing fear&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;What does fear mean?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have you ever had to change some incomprehensible code? How about code missing (good) tests? The feeling you were experiencing was probably fear. You were afraid that you might break the code. &lt;strong&gt;TDD should result in a codebase where you never have to feel this type of fear again&lt;/strong&gt; because you can rely on a solid set of tests. These give you certainty at the press of a button, &lt;em&gt;courage on demand&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another way TDD helps manage fear is when you’re unsure how to continue&lt;/strong&gt;. Sometimes you don’t know how to solve a problem, and fear will rear its ugly head. Fear makes solving problems harder. TDD allows you to &lt;a href="https://www.thedroidsonroids.com/blog/6-misconceptions-about-tdd-part-4-steps-size" rel="noopener noreferrer"&gt;shift gears&lt;/a&gt; and solve the problem one tiny step at a time. Taking these baby steps will enable you to circumvent fear and start making progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD’s Effects on Communication 🗣️
&lt;/h2&gt;

&lt;p&gt;Communication is the fourth compelling benefit of TDD. A result of TDD is a solid set of tests. When done correctly, &lt;strong&gt;well-written tests communicate the system’s behavior to its readers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tests &lt;a href="https://medium.com/pragmatic-programmers/tests-as-documentation-47381b02170b" rel="noopener noreferrer"&gt;effectively document&lt;/a&gt; the code’s intent and are my go-to place for comprehending unfamiliar code. Imagine what it would be like if your entire codebase had tests explaining what code does under specific conditions. Wouldn’t that be great?&lt;/p&gt;

&lt;p&gt;Therefore whenever I write code in a TDD fashion, I always keep the future reader of the code and the tests in mind. &lt;strong&gt;You should empathize with the reader&lt;/strong&gt;. My goal is to prevent head-scratching moments for that person, and tests allow me to achieve that goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing TDD Shows Respect 🙇
&lt;/h2&gt;

&lt;p&gt;Lastly, &lt;strong&gt;applying TDD is a sign of respect&lt;/strong&gt;. By using it, you show respect to your:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fellow team members&lt;/li&gt;
&lt;li&gt;stakeholders&lt;/li&gt;
&lt;li&gt;users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why? Think back to the goal of TDD: &lt;em&gt;clean code that works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For your team members, this means maintainable, well-documented code that is a pleasure to work with. You respect your stakeholders since you write just enough code to achieve the result they are interested in. It also enables you to maintain a sustainable pace of feature delivery by keeping technical debt in check. Finally, your users will enjoy a stable, well-crafted product with fewer defects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary 📝
&lt;/h2&gt;

&lt;p&gt;Test-Driven Development is an &lt;strong&gt;effective programming practice&lt;/strong&gt; that leads to simple, well-designed code. But applying it without understanding the underlying values makes it an empty shell. &lt;em&gt;You don’t do TDD for the sake of TDD.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;TDD follows the overarching values of XP. When applied correctly, you can expect it to improve &lt;strong&gt;communication&lt;/strong&gt; , &lt;strong&gt;simplify&lt;/strong&gt; your code, increase &lt;strong&gt;feedback&lt;/strong&gt; , &lt;strong&gt;reduce fear&lt;/strong&gt; , and show &lt;strong&gt;respect&lt;/strong&gt; to all parties involved. Doesn’t that sound amazing?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Are you doing TDD? What effects of TDD surprised you? Share your thoughts in the comment section.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading 📚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3d8eayN" rel="noopener noreferrer"&gt;Extreme Programming Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3U30wNX" rel="noopener noreferrer"&gt;Test-Driven Development: By Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3RGY5it" rel="noopener noreferrer"&gt;Growing Object-Oriented Software, Guided by Tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>programming</category>
      <category>tdd</category>
      <category>xp</category>
    </item>
    <item>
      <title>5 Books to Achieve the Mindset of a Software Craftsman 📚</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Sun, 24 Jul 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/5-must-read-books-for-apprentice-software-developers-58df</link>
      <guid>https://forem.com/codecraftr/5-must-read-books-for-apprentice-software-developers-58df</guid>
      <description>&lt;p&gt;Which books should you read as a software developer? These five titles will give you a great start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software Developers Should Read the Right Books 🎯
&lt;/h2&gt;

&lt;p&gt;Great, you’re reading books! Doing so puts you ahead of the game by a mile right there. To have an even more significant impact on your career as a software craftsman, you should not just read; you should read the &lt;em&gt;right&lt;/em&gt; books.&lt;/p&gt;

&lt;p&gt;Finding the right books to read as an apprentice is hard. You don’t yet know what is essential and what isn’t. To save you from mistakes I’ve made, I’ll share five books that accelerate your growth greatly as an ambitious software developer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/5608045-apprenticeship-patterns" rel="noopener noreferrer"&gt;Apprenticeship Patterns&lt;/a&gt;: Guidance for the Aspiring Software Craftsman&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/4099.The_Pragmatic_Programmer" rel="noopener noreferrer"&gt;The Pragmatic Programmer&lt;/a&gt;: From Journeyman to Master&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/3735293-clean-code" rel="noopener noreferrer"&gt;Clean Code&lt;/a&gt;: A Handbook of Agile Software Craftsmanship&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/67833.Extreme_Programming_Explained" rel="noopener noreferrer"&gt;Extreme Programming Explained&lt;/a&gt;: Embrace Change&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/36072.The_7_Habits_of_Highly_Effective_People" rel="noopener noreferrer"&gt;Seven Habits of Highly Effective People&lt;/a&gt;: Powerful Lessons in Personal Change&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-apprentice-books.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-apprentice-books.jpeg" alt="Five recommended books shown from the side" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The right books will accelerate your growth greatly&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Read on to learn more about what makes these books great and what benefits they can bring to your career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This List? 🤓
&lt;/h2&gt;

&lt;p&gt;When I started my career, I read many books, but their effect was marginal. My bookshelf consisted of titles filled with fleeting technologies. Unfortunately, nobody pointed out what I should be reading.&lt;/p&gt;

&lt;p&gt;The turning point for me was accidentally stumbling upon a copy of the &lt;a href="https://www.goodreads.com/book/show/4099.The_Pragmatic_Programmer" rel="noopener noreferrer"&gt;Pragmatic Programmer&lt;/a&gt;. I encountered a book containing ubiquitous concepts; they applied to any language or framework. These types of books have an &lt;strong&gt;incredible yield&lt;/strong&gt;. You read them, and like a good investment, you profit from them for years and decades. If only I had known earlier.&lt;/p&gt;

&lt;p&gt;Note that every single book in this list is excellent, and the order does not imply one book is better than the other. Feel free to read the books in any order you like!&lt;/p&gt;

&lt;p&gt;With that out of the way, let’s dive into the books.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apprenticeship Patterns 🧑‍🎓
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-apprenticeship-patterns.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-apprenticeship-patterns.jpg" alt="Apprenticeship Patterns Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Book?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How do you go about growing from an &lt;strong&gt;apprentice coder&lt;/strong&gt; to a &lt;strong&gt;master software craftsman&lt;/strong&gt;? Trial and error? No. It would help if you had a strategy, which is what Apprenticeship Patterns offers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who Is It For?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Are you an ambitious coder eager to learn? Do you struggle with your approach to growth, or are you curious to learn about more ways to do so? Apprenticeship Patterns contains the answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Growing as a software developer is hard. To make matters worse, not only do you need to learn a ton, you need approaches on &lt;strong&gt;how to grow&lt;/strong&gt;. This book provides concrete ways to do so, presented as a catalog of patterns. These patterns range from assuming the right mindset for growth to seeking out communities that help you learn.&lt;/p&gt;

&lt;p&gt;Apprenticeship Patterns showed me ways to learn that I never considered; it helped broaden my horizons. A few patterns in the book took me years to uncover, so save yourself the trouble and take the shortcut.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pragmatic Programmer 🧑‍💻
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-pragmatic-programmer.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-pragmatic-programmer.jpg" alt="The Pragmatic Programmer Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Book?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ever experienced that voice in your head whispering advice that prevented you from making a huge mistake? The Pragmatic Programmer will help you develop that consciousness for code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who Is It For?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do you want to develop a sense for when code is well- or ill-written? Are you missing guidelines for the craft of software development? Read this book.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What makes an effective developer? Technical prowess? Knowledge of a language or framework? Yes, those matter, but I’d argue &lt;strong&gt;mindset matters even more&lt;/strong&gt;. This book will teach you the mindset and heuristics that will make you a great developer. It contains lessons ranging from programming best practices to recognizing and preventing issues in code.&lt;/p&gt;

&lt;p&gt;The Pragmatic Programmer is dear to me because its lessons on mindset expressed what I was missing in other literature. It puts into words a lot of unwritten rules and ideas. Reading it was a pivotal moment in my career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Code 🧼
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-clean-code.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-clean-code.jpg" alt="Clean Code Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Book?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For who do we write code? The computer does not care if our code is understandable; &lt;em&gt;humans&lt;/em&gt; do. Clean Code contains crucial lessons on how to write maintainable code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who Is It For?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Are you looking to improve the understandability of your code? Then you will benefit from reading Clean Code. It should be one of the first books you read as an apprentice or journeyman software developer.&lt;em&gt;Last line can be better&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What makes code “clean”? Is it the elegance of its algorithm? Is it performance? Clean Code teaches this crucial heuristic: &lt;strong&gt;clean code is easy to comprehend&lt;/strong&gt; for its readers. It also answers the all-important question: why should we write clean code at all.&lt;/p&gt;

&lt;p&gt;Clean Code offers guidance on how to get from good to exceptional code, and it does so with lots of helpful examples. It begins with the tiniest details, such as variable names, progressing to how to put it together in an entire system.&lt;/p&gt;

&lt;p&gt;This book influenced my skills as a programmer so much that I decided to put it front and center in my bookcase. Years after reading, its ideas still guide how I write code daily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extreme Programming Explained 🧗
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-xp-explained.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-xp-explained.jpg" alt="Extreme Programming Explained Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Book?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agile software development is commonplace, but what is its essence? What is at the core of this mindset? In my opinion, this book provides the best answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who Is It For?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Are you curious about what agile software development entails? Do you want to know which practices allow you to &lt;strong&gt;deliver valuable software effectively&lt;/strong&gt;? Be sure to read Extreme Programming Explained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Extreme Programming Explained introduces a set of values, principles, and practices on developing software with agility. The book explains what the commodity Agile (capital A) meant to be.&lt;/p&gt;

&lt;p&gt;It truly stands out because it introduces values and principles which lead to concrete practices. These practices are critical enablers to agile software development, according to XP. Have you ever heard of Test-Driven Development? Pair Programming? Refactoring? Continuous Integration? Those are just a few of XP’s practices, and you would do well to master them.&lt;/p&gt;

&lt;p&gt;Extreme Programming Explained helped me adopt a mindset and skillset to help teams deliver software more effectively. One of my best professional experiences was in a team where we consciously lived by XP’s values, principles, and practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seven Habits of Highly Effective People 🦸
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-seven-habits.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F25-seven-habits.jpg" alt="Seven Habits of Highly Effective People Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Book?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What makes a person “effective”? Seven Habits offers timeless advice on almost any aspect of life, and its lessons will also significantly impact your career.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who Is It For?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you ever wondered how to improve as a person? Not just at work but getting better at everything you do? Seven Habits of Highly Effective People provides the answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Wait, this book has nothing to do with software! As it turns out, software development is very much about &lt;em&gt;people&lt;/em&gt;. Professional coders recognize this fact and try to improve in this aspect too.&lt;/p&gt;

&lt;p&gt;Seven Habits teaches you a set of principles that will &lt;strong&gt;improve every aspect of life&lt;/strong&gt;. Its contents range from taking control of any situation by employing proactiveness to enriching communication with others. Seven Habits weaves this together in a pleasant text full of practical wisdom.&lt;/p&gt;

&lt;p&gt;If there were just one book I could own, it would be this one. I read this book many years ago and keep returning to it. Every time I read it, I learn something new or find another aspect in my life where I can apply its wisdom. Seven Habits has affected my life as no other book has.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary 📝
&lt;/h2&gt;

&lt;p&gt;Reading is one of the best ways to skyrocket your career. However, the problem as an apprentice is finding the right books to read. These books give you the most “bang for your buck.”&lt;/p&gt;

&lt;p&gt;Though this list is by no means exhaustive, I believe it contains essential titles for any aspiring software craftsman. Who knows, you might find a career-changing book in there, just like I did!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Which books made a significant impact on your programming career? Is the list missing a title? Share your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>books</category>
      <category>career</category>
    </item>
    <item>
      <title>🕹 How To Use Exercism To Learn Programming Languages</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Mon, 13 Jun 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/how-to-use-exercism-to-learn-programming-languages-4892</link>
      <guid>https://forem.com/codecraftr/how-to-use-exercism-to-learn-programming-languages-4892</guid>
      <description>&lt;p&gt;Want to learn a new programming language, but don’t know where to start? Exercism might be what you’ve been looking for…&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Exercism Simplifies Learning a Programming Language
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;What is the last programming language you learned?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Learning a new programming language is a great way to expand your horizons and improve your skills as a developer. In the &lt;em&gt;&lt;a href="https://www.goodreads.com/book/show/4099.The_Pragmatic_Programmer?ac=1&amp;amp;from_search=true&amp;amp;qid=DWcIeeqwBr&amp;amp;rank=1" rel="noopener noreferrer"&gt;Pragmatic Programmer&lt;/a&gt;&lt;/em&gt; they even recommend you learn a new one each year! The important questions here are:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How did you go about learning it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Did your learning feel effective?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn a new programming language, you just want to get started, and get learning. You want a quick way to start practicing. Wrapping your head around the new language is challenging enough by itself!&lt;/p&gt;

&lt;p&gt;I used to learn a new language by going online, reading about the basics of a language, and then start doing &lt;a href="//www.codecraftr.nl/improving-with-codekatas"&gt;code katas&lt;/a&gt;. Recently I have found a much nicer way, using Exercism.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://exercism.org" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt; is a fun learning platform with some nice tricks up its sleeves. It excels at guiding you through mastering programming languages, but more on that later. Let’s see what Exercism is all about.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏫 How Exercism Works
&lt;/h2&gt;

&lt;p&gt;Exercism is a free, and &lt;a href="https://github.com/exercism" rel="noopener noreferrer"&gt;open source&lt;/a&gt; learning platform for Software Development. The idea behind it is to make mastering programming fun, and accessible to anyone.&lt;/p&gt;

&lt;p&gt;To use Exercism you first need to create an account, after which you can embark on your learning journey (pun intended, you’ll see). You start by enrolling in one of their language tracks, of which there are a staggering 57 at this time of writing!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F24-exercism-dash.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F24-exercism-dash.png" alt="Exercism Track Overview" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Exercism offers a lot of learning tracks&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once enrolled, you can select a track and start learning. Tracks start with the obligatory “Hello World”, after which a few basic exercises are available. This progression continues: each assignment you complete “unlocks” new ones, like levels in a game.&lt;/p&gt;

&lt;p&gt;There are two ways you can work on assignments:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;a href="https://exercism.org/docs/using/solving-exercises/using-the-online-editor" rel="noopener noreferrer"&gt;Web Editor&lt;/a&gt;, or&lt;/li&gt;
&lt;li&gt;Locally using the &lt;a href="https://exercism.org/docs/using/solving-exercises/working-locally" rel="noopener noreferrer"&gt;Exercism CLI&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Exercises usually come with a short explanation, a file to put your code in (with comments), and some tests to see if your program is working. Once you’re satisfied with your work you submit your solution.&lt;/p&gt;

&lt;p&gt;After submitting your code, automated checks like tests, and formatting checks are executed. After receiving the all-green, the exercise can be completed, and you can compare your solution to those shared by others.&lt;/p&gt;

&lt;p&gt;Besides pouring over the code of others, you can also request mentoring by a real-world volunteer. These mentors are well-versed in the language at hand. Not dissimilar to a code review, they will assess what you submitted and give you feedback on how you can improve.&lt;/p&gt;

&lt;p&gt;That’s how Exercism works, but what makes it so great for learning?&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 The Awesomeness That Is Exercism
&lt;/h2&gt;

&lt;p&gt;Exercism is one of the best ways to learn programming languages in my opinion. It’s major pro’s are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syllabuses&lt;/strong&gt; with supporting exercises offer a logical progression of core language concepts, which are introduced in a piecemeal manner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gamification&lt;/strong&gt; makes learning fun. Unlocking harder exercises, earning &lt;em&gt;reputation&lt;/em&gt; and &lt;em&gt;badges&lt;/em&gt;, and seeing your learning journey unfold makes using Exercism an enjoyable experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fun exercises&lt;/strong&gt; make for puzzles that you can’t resist. Best of all, you don’t have to search around the internet to find them (unlike with code kata’s). They’re all available in the platform, and you can even contribute new ones!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare solutions&lt;/strong&gt; easily. Want to know if there is a different, or better way to solve an exercise? Reflect on what others did! It’s built right into the platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practice reading code&lt;/strong&gt; by looking at what others did. Code reading is a crucial, often overlooked skill. One reason for this is that its hard to get started. Exercism makes it easy, because you know the &lt;em&gt;context&lt;/em&gt; of the code, and you don’t have to scour the internet for code of others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be mentored&lt;/strong&gt; by real-world, and skillful people. Finding someone who can teach you to solve solutions in an idiomatic way, who provides tailor-made feedback can give your learning journey a boost. Best of all, Exercism has this facility built in!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mentor others&lt;/strong&gt; deepening knowledge about a language you are proficient at, and grow your teaching skills. A great way to give back to the community, and a win-win for both you and the mentee.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strengthen your resume&lt;/strong&gt; by showing off your solutions, languages you’re working with, and reputation you earned. These can all easily be shared with a public profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Great tools&lt;/strong&gt; like the web editor and cli make working Exercism friction-free, allowing you to focus on your learning journey.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F24-exercism-syllabus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F24-exercism-syllabus.png" alt="Syllabus for Python" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Syllabuses structure your learning journey&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Phew… What a list. As you can see, there is a lot to like about Exercism, but I do think it has a few downsides. Let’s find out what those are.&lt;/p&gt;

&lt;h2&gt;
  
  
  👀 Exercism’s Drawbacks
&lt;/h2&gt;

&lt;p&gt;As amazing as it is, there are downsides to using Exercism. To name a few:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Varying level of language support&lt;/strong&gt;. More popular languages, like Python or Go, Exercism has better platform support, and a more in-depth learning journey. Whereas a language like Scala has a learning track that’s stripped down to the very core: exercises and the community. It pays off to see what level of support is offered for the language of your interest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test code is supplied&lt;/strong&gt;. If all you’re trying to do is learn to program in a new language that’s fine, but if you want to become a &lt;em&gt;better programmer&lt;/em&gt;, writing tests is a crucial skill to master. Exercism is not well suited for that purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ecosystem / tooling&lt;/strong&gt; knowledge are not mandatory. As Exercism offers tooling for the popular languages, that saves you from having to learn about them. That’s great starting out, but eventually that too should be part of learning a new language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Helps learn languages, not craftsmanship.&lt;/strong&gt; Exercism’s focus is on learning languages, not necessarily on writing better software. Realize that learning a language does not make you a good programmer. As the saying goes: &lt;em&gt;the ability to speak English does not make you a great writer&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F24-exercism-journey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F24-exercism-journey.png" alt="Learning Journey in Exercism" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Exercism alone does not improve your craftsmanship&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These downsides can be easily mitigated, by also doing &lt;a href="//www.codecraftr.nl/improving-with-codekatas"&gt;code katas&lt;/a&gt; and &lt;a href="https://redsquirrel.com/dave/work/a2j/patterns/BreakableToys.html" rel="noopener noreferrer"&gt;breakable toys&lt;/a&gt;. These force you to dive more into the ecosystem of a language, require you to write your own tests and become a better software craftsman altogether. How’s that for a great learning experience!&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Exercism is an effective way to get your feet wet with a new programming language. It offers learning tracks for a ton of languages, and is a lot of fun to use!&lt;/p&gt;

&lt;p&gt;The best way to use Exercism, is to use it for understanding language basics, and idioms. After that it is important to complement your learning journey with code katas and breakable toys. This way you will master a new programming language, and become a better software craftsman in no time!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What do you think about Exercism? What language will you learn using it? Let us know in the comment section!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>programming</category>
      <category>exercism</category>
    </item>
    <item>
      <title>📕 Implementing Domain-Driven Design Review</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Fri, 13 May 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/implementing-domain-driven-design-review-j0c</link>
      <guid>https://forem.com/codecraftr/implementing-domain-driven-design-review-j0c</guid>
      <description>&lt;p&gt;Implementing Domain-Driven Design aka &lt;em&gt;The Red Book&lt;/em&gt;. I held high expectations for this title, did it deliver? Find out in this review.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 About The Red Book
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/15756865-implementing-domain-driven-design" rel="noopener noreferrer"&gt;Implementing Domain-Driven Design by Vaughn Vernon&lt;/a&gt;, dubbed &lt;em&gt;The Red Book&lt;/em&gt; by the Domain-Driven Design (DDD) community, often recommended as a valuable companion to the original blue book.&lt;/p&gt;

&lt;p&gt;After reading it myself I agree. It has been a great help to solidify my knowledge about DDD, but more on that later.&lt;/p&gt;

&lt;p&gt;First thing you’ll notice: this book is hefty. Coming in at 538 pages (excluding a lengthy appendix), reading and grasping Implementing DDD will take a while.&lt;/p&gt;

&lt;p&gt;The book is composed of 14 chapters, arranged sensibly as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to DDD&lt;/li&gt;
&lt;li&gt;Strategic Patterns&lt;/li&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Tactical Patterns&lt;/li&gt;
&lt;li&gt;Application Concerns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;But what sets it apart from &lt;a href="https://dev.to/domain-driven-design-book-review/"&gt;The Blue Book&lt;/a&gt;?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📘 Differences With The Blue Book
&lt;/h2&gt;

&lt;p&gt;Although it touches on the same concepts from the original book, contrary to it, The Red Book introduces &lt;em&gt;Strategic Patterns&lt;/em&gt; before the &lt;em&gt;Tactical Patterns&lt;/em&gt;. It also delves into the concept of &lt;em&gt;Domain Events&lt;/em&gt;, which weren’t covered in The Blue Book.&lt;/p&gt;

&lt;p&gt;Throughout the book, the reader follows a fictional case study, complete with supporting code samples. This helps make the abstract ideas concrete, hence the “Implementing” part of the title.&lt;/p&gt;

&lt;p&gt;How does it all add up? Is it a valuable book to add to your collection? Let’s find out.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚖️ A Great Book, But…
&lt;/h2&gt;

&lt;p&gt;All things considered, I do think this book should be on your bookshelf, but it is not without its flaws.&lt;/p&gt;

&lt;p&gt;Aspects of the book I liked were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Case study &amp;amp; code samples&lt;/strong&gt; help you thoroughly understand DDD concepts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain events &amp;amp; event sourcing&lt;/strong&gt; are covered extensively. These architectural styles are great to have in your “toolbox” and were not covered in The Blue Book.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strategic over tactical patterns&lt;/strong&gt;. This book does a good job of prioritizing the two and emphasizes how DDD’s effectiveness is crippled without properly applying both.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things I disliked about it were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fluff&lt;/strong&gt; caused by the author taking his time to get to the point, as well as examples requiring a lot of explanation, distracting from the main point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code samples age&lt;/strong&gt; , and some examples feel outdated due to obsolete technology.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concepts (mostly) identical&lt;/strong&gt; to The Blue Book. If you read both there will be a lot of repetition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing Domain-Driven Design is a valuable book then, but who can benefit from it most?&lt;/p&gt;

&lt;h2&gt;
  
  
  🙋 Should You Read It?
&lt;/h2&gt;

&lt;p&gt;You should read Implementing Domain-Driven Design if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re new to DDD, or&lt;/li&gt;
&lt;li&gt;The concepts did not sink in after reading the Blue Book.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is this you? Look no further, Implementing Domain-Driven Design will deliver. This title is more approachable than the Domain-Driven Design book, working hard to explain the concepts in a simple, and concrete way.&lt;/p&gt;

&lt;p&gt;The adept DDD practitioner can safely skip this title, except if the chapters on &lt;em&gt;Domain Events&lt;/em&gt;, &lt;em&gt;Event Sourcing&lt;/em&gt;, or case studies are of particular interest to you.&lt;/p&gt;

&lt;p&gt;I enjoyed this book a lot. After reading the Blue Book, I had a basic understanding of the concepts but struggled with applying them in practice. This title improved my grasp of DDD considerably.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⭐ The Verdict
&lt;/h2&gt;

&lt;p&gt;Implementing Domain-Driven Design, or &lt;em&gt;The Red Book&lt;/em&gt;, is an amazing book for anyone interested in Domain-Driven Design.&lt;/p&gt;

&lt;p&gt;It has some minor flaws, but I highly recommend this book to newcomers to DDD or those who want tangible examples accompanying the abstract concepts of DDD.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Final score: 8 out of 10.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Do you have any recommended reading about Software Design? Share them with us in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>books</category>
      <category>ddd</category>
      <category>reading</category>
    </item>
    <item>
      <title>📘 Book Review: Technical Blogging</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Fri, 15 Apr 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/book-review-technical-blogging-34hb</link>
      <guid>https://forem.com/codecraftr/book-review-technical-blogging-34hb</guid>
      <description>&lt;p&gt;Are you thinking about starting a technical blog? Technical Blogging might be the book for you. Learn why in this review.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 Technical Blogging in a Nutshell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pragprog.com/titles/actb2/technical-blogging-second-edition/" rel="noopener noreferrer"&gt;Technical Blogging: Amplify Your Influence&lt;/a&gt; is best described as a one-stop-shop for all everything you need to know to get your blog started.&lt;/p&gt;

&lt;p&gt;It covers lots of topics, and loosely follows the chronological order of planning, building, promoting, benefiting from, and scaling your blog. It aims to provide you, an aspiring blogger, an A-Z on setting up, maintaining, and growing your blog. The end goal is to increase your influence as a professional or company via your blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚖️ Likes and Dislikes
&lt;/h2&gt;

&lt;p&gt;Technical Blogging is a good book and an enjoyable read. It’s &lt;strong&gt;well-structured&lt;/strong&gt; , and brimming with &lt;strong&gt;pragmatic tips&lt;/strong&gt; to improve your existing blog or get a running start with a new one.&lt;/p&gt;

&lt;p&gt;I liked the enormous &lt;strong&gt;breadth of topics&lt;/strong&gt; covered. They range from registering a domain name, writing great content, to leveraging social media to grow your audience. After reading, you will know at least the basics of a ton of aspects of blogging.&lt;/p&gt;

&lt;p&gt;This broad range of subjects means that the book only scratches the surface of many topics. If you are looking for in-depth content about specific subjects, you will not find it here.&lt;/p&gt;

&lt;p&gt;Another aspect where the book could be better would be to include data from other blogs and opinions other the authors. This would have made some arguments and claims in the book more compelling.&lt;/p&gt;

&lt;h2&gt;
  
  
  🙋 Who Should Read It?
&lt;/h2&gt;

&lt;p&gt;Starting, or aspiring technical bloggers will get the most out of Technical Blogging. It is also suited to companies who want to start a blog to grow their influence.&lt;/p&gt;

&lt;p&gt;Are you a veteran blogger? Then this book might not be worth your while as it is at an introductory to intermediate level.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⭐ The Verdict
&lt;/h2&gt;

&lt;p&gt;Are you a starting technical blogger, or thinking about becoming one? Pick up this book, it will not let you down.&lt;/p&gt;

&lt;p&gt;It’s a pleasant read, covers a lot of ground and as a starting blogger, I’ve found it incredibly helpful.&lt;/p&gt;

&lt;p&gt;Final score: 7 out of 10.&lt;/p&gt;

</description>
      <category>books</category>
      <category>reading</category>
      <category>blogging</category>
      <category>writing</category>
    </item>
    <item>
      <title>🏋️ The Might of Microtypes</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Sat, 05 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/the-might-of-microtypes-20hc</link>
      <guid>https://forem.com/codecraftr/the-might-of-microtypes-20hc</guid>
      <description>&lt;p&gt;Ints, Doubles, Strings. We work with primitives all the time, but did you know they can hurt your Software Design? Microtypes can help!&lt;/p&gt;

&lt;h2&gt;
  
  
  🚩 Primitives Turn Problematic
&lt;/h2&gt;

&lt;p&gt;Primitives are the basic building blocks of the languages we work with, and the programs we write. The truth is, we tend to rely on them too much.&lt;/p&gt;

&lt;p&gt;Overusing primitives can lead to problems. Thankfully, with a little elbow grease we can leverage primitives in a much better way, by creating so-called &lt;em&gt;Microtypes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;First, let’s see which problems might arise from fixating on primitives.&lt;/p&gt;

&lt;h2&gt;
  
  
  🦨 Overusing Primitives a Code Smell?
&lt;/h2&gt;

&lt;p&gt;Overusing primitives is a code smell, called &lt;a href="https://refactoring.guru/smells/primitive-obsession" rel="noopener noreferrer"&gt;Primitive Obsession&lt;/a&gt;. A tell for this code smell is operating upon primitives extensively, when the primitive represents a significant concept.&lt;/p&gt;

&lt;p&gt;Consequences of this code smell can be &lt;strong&gt;bugs&lt;/strong&gt; , &lt;strong&gt;duplication&lt;/strong&gt; , &lt;strong&gt;low cohesion&lt;/strong&gt; and an &lt;strong&gt;implicit model&lt;/strong&gt;. I’ll show examples of these problems later in this post.&lt;/p&gt;

&lt;p&gt;One easily overlooked way to solve this smell is by defining a &lt;em&gt;Microtype&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔬 Introducing the Microtype
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://codebox.net/pages/microtypes-in-java" rel="noopener noreferrer"&gt;Microtypes&lt;/a&gt; are custom classes which wrap a single primitive, and are therefore very small (hence the name). They are also commonly referred to as Value Classes or Value Objects.&lt;/p&gt;

&lt;p&gt;Being &lt;em&gt;&lt;a href="https://www.martinfowler.com/bliki/ValueObject.html" rel="noopener noreferrer"&gt;Value Objects&lt;/a&gt;&lt;/em&gt;, the identity of a Microtype is defined entirely by their attribute. Furthermore, Microtypes should be &lt;em&gt;immutable&lt;/em&gt; and its &lt;em&gt;equality&lt;/em&gt; should be based on it’s attribute, not its reference.&lt;/p&gt;

&lt;p&gt;Let’s set the scene before diving into some examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  ☕ Example: Coffee Roasters
&lt;/h2&gt;

&lt;p&gt;Imagine that your writing a piece of software for a coffee roaster, and the model includes &lt;code&gt;Coffee&lt;/code&gt;. It represents a bag of coffee beans that will be sold to a customer.&lt;/p&gt;

&lt;p&gt;It needs to contain information about the type of bean used, the intensity (1-5) and the weight of the bag (in grams). A first take might look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 1. First iteration for Coffee&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;This does get the job done, but reeks of Primitive Obsession. Next, we’ll look at how Microtypes help out.&lt;/p&gt;

&lt;h2&gt;
  
  
  🪲 Bug Prevention
&lt;/h2&gt;

&lt;p&gt;Using primitives all over the place can become a way for subtle, semantic bugs to creep into the code. For instance if we look at &lt;code&gt;Coffee&lt;/code&gt;, both intensity and weight are represented using an &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It’s all too easy for clients to mix up intensity and weight. The compiler won’t catch this issue because it cannot distinguish them by semantics alone.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 2. Switching intensity and weight causes a bug&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Running the code above results in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Coffee(type=ARABICA, intensity=1000, weight=2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ouch, that is some very strong coffee. Not quite what we intended!&lt;/p&gt;

&lt;p&gt;By defining a Microtype for weight, the compiler will yell at us if we mix up the concepts. How’s that for early feedback!&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Listing 3. Preventing semantic bugs with a Microtype&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📍 Combat Duplication
&lt;/h2&gt;

&lt;p&gt;There are business rules concerning the weight of coffee. For instance, it cannot be a negative number, and we need to convert the weight to kilograms in order to determine the price for the bag of coffee beans.&lt;/p&gt;

&lt;p&gt;Without a dedicated type, this logic might pop up anywhere in the code where the it is needed:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 4. Duplication because weight logic doesn’t have a “home”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When we define a Microtype for weight, it is the logical place to define this validation. The duplication is gone, and any instances of &lt;code&gt;Weight&lt;/code&gt; we use are validated. This makes the code more maintainable!&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 5. The Microtype contains the logic, removing duplication&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Improving Cohesion
&lt;/h2&gt;

&lt;p&gt;The duplication problem also closely relates to a &lt;a href="https://en.wikipedia.org/wiki/Cohesion_(computer_science)" rel="noopener noreferrer"&gt;cohesion&lt;/a&gt; problem. Without a specific type logic regarding weight can pop up all over the place.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Coffee&lt;/code&gt; class might validate that weight is not a negative number. Some service orchestrating a use case might do some conversion of weight from grams to kilograms. Logic becomes disparate, lowering cohesion in other classes… &lt;em&gt;Bad&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As we just saw, a dedicated Microtype is a natural “home” to place these business rules (and future ones, too). It itself has high cohesion, and improves cohesion of other classes by relieving them of containing weight logic.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 6. Microtype containing weight related logic&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗣️ Expressing the Domain Model
&lt;/h2&gt;

&lt;p&gt;Expressing the concepts of weight and intensity as primitives deprives our model of &lt;em&gt;depth&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;One of the tenets of Domain-Driven Design is that your code should capture and express the Ubiquitous Language. If we express these concepts as mere primitives, it can end up making the model &lt;em&gt;implicit&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We want the opposite: an &lt;em&gt;expressive&lt;/em&gt; model. Just compare the primitive (listing 7) to the Microtype versions (listing 8).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 7. Primitives might result in an implicit model&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 8. Microtypes make the model expressive and explicit&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the primitive version you’re left making assumptions on what represents weight. Is it grams? Kilograms? Pounds? With the Microtype, you instantly see that weight is measured in grams. It captures knowledge about the domain in code!&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚖️ Microtypes: a Silver Bullet?
&lt;/h2&gt;

&lt;p&gt;So, should you go and wrap every single primitive you find?&lt;/p&gt;

&lt;p&gt;That’s probably a bad idea.&lt;/p&gt;

&lt;p&gt;Primitives are &lt;strong&gt;heavily optimized&lt;/strong&gt; , and using objects everywhere might cause a serious performance hit. This is especially true with high volume use cases.&lt;/p&gt;

&lt;p&gt;Some languages (like &lt;a href="https://kotlinlang.org/docs/inline-classes.html" rel="noopener noreferrer"&gt;Kotlin&lt;/a&gt;) offer solutions to this problem in the form of a &lt;em&gt;Value Class&lt;/em&gt;. This allows you to use a custom type at &lt;em&gt;compile-time&lt;/em&gt;, and make use of the primitive at &lt;em&gt;runtime&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Another downside is that Microtypes can be &lt;strong&gt;clunky&lt;/strong&gt; to work with. They have to be constructed, and using them requires accessing their attribute, or defining custom methods (like &lt;code&gt;plus&lt;/code&gt;, &lt;code&gt;minus&lt;/code&gt;, etc).&lt;/p&gt;

&lt;p&gt;Though the extra code problem is hard to solve, some languages help make it read nicely by allowing you to define custom operators. For &lt;code&gt;Weight&lt;/code&gt; that might look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 9. Operator overloading&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Strategically using extension functions can work miracles too. For instance you could make &lt;code&gt;Weight&lt;/code&gt; construction easier with an extension on &lt;code&gt;Int&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Listing 10. Extension functions to construct Weights&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My advice is to use Microtypes &lt;em&gt;diligently&lt;/em&gt;. Use them where they make your code more &lt;strong&gt;expressive&lt;/strong&gt; and &lt;strong&gt;maintainable&lt;/strong&gt;. You get most of your money’s worth if they capture a domain concept.&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Primitives are &lt;em&gt;essential&lt;/em&gt; in creating software. Can you imagine writing programs without Ints, Strings or Booleans? They are &lt;strong&gt;generic programming constructs&lt;/strong&gt; however, and that comes with problems.&lt;/p&gt;

&lt;p&gt;A solution to those problems are Microtypes: small classes that wrap a primitive and give it &lt;strong&gt;meaning&lt;/strong&gt; and &lt;strong&gt;purpose&lt;/strong&gt; in a certain context. Though they have their own pro’s and cons, they can improve your software when used correctly.&lt;/p&gt;

&lt;p&gt;Think twice next time you express a concept with a primitive, a Microtype might serve you better!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What’s your take on Microtypes? Do you see other pro’s or cons? Share your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>oop</category>
      <category>codequality</category>
    </item>
    <item>
      <title>🔥 5 Tweaks for a Productive Terminal</title>
      <dc:creator>CodeCraftr</dc:creator>
      <pubDate>Mon, 17 Jan 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/codecraftr/5-tweaks-for-a-productive-terminal-40f5</link>
      <guid>https://forem.com/codecraftr/5-tweaks-for-a-productive-terminal-40f5</guid>
      <description>&lt;p&gt;The terminal is a developer’s best friend. I’ll introduce five ways to make it an even better companion to your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 Why Tweak Your Terminal?
&lt;/h2&gt;

&lt;p&gt;Installing software, running tests, compiling code, managing servers. You name it, the terminal can do it. The terminal is probably one of the most versatile tools in your toolbox.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think about it, how often a day do you use your terminal?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Keeping this in mind, wouldn’t it make a lot of sense to optimize that tool as much as you can? I’ll show you five tweaks to make the most out of your terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖥️ Upgrade Your Terminal Emulator
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Terminal_emulator" rel="noopener noreferrer"&gt;Terminal Emulator&lt;/a&gt; is the application you use to interact with your shell. Your OS comes with a default terminal, and they can be pretty good, but there are more powerful “aftermarket” options around.&lt;/p&gt;

&lt;p&gt;One such option is &lt;a href="https://sw.kovidgoyal.net/kitty/" rel="noopener noreferrer"&gt;Kitty&lt;/a&gt;. Kitty is an open-source terminal emulator with some standout features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPU Rendering.&lt;/strong&gt; Offloads rendering to the GPU for a smoother experience and freeing up the CPU to do its job more quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versatile Rendering.&lt;/strong&gt; Kitty supports rendering of glyphs, emoji, ligatures and has great font support out of the box. Very useful for programmers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tabs and multiplexing.&lt;/strong&gt; Multitasking is very effective with Kitty, as it supports tabs and multiple windows within tabs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard-driven.&lt;/strong&gt; As a power user, the keyboard is your friend. Kitty embraces this philosophy and is almost entirely driven by the keyboard, sporting sensible shortcuts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensible.&lt;/strong&gt; Kitty supports plugins, which it calls &lt;a href="https://sw.kovidgoyal.net/kitty/kittens_intro/?highlight=kitten#" rel="noopener noreferrer"&gt;kittens&lt;/a&gt;. It is also &lt;a href="https://sw.kovidgoyal.net/kitty/remote-control/?highlight=script" rel="noopener noreferrer"&gt;scriptable&lt;/a&gt; at its core.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configurable.&lt;/strong&gt; Don’t like a keybinding or how something works? Change it! A tool should fit your workflow, and Kitty allows you to do just that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-kitten.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-kitten.gif" alt="Kitty rendering an image" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kitty is extensible and can even render images&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The responsiveness, great rendering experience, and productivity enhancements make a great difference in my daily terminal work. Another big factor in productivity in the terminal is the shell. Let’s see how we can give that an upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐚 Supercharge Your Shell
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Shell_(computing)" rel="noopener noreferrer"&gt;shell&lt;/a&gt; is crucial to your terminal experience because it is always present. It is what you use to interact with your Operating System.&lt;/p&gt;

&lt;p&gt;You’re probably familiar with the &lt;a href="https://en.wikipedia.org/wiki/Bash_(Unix_shell)" rel="noopener noreferrer"&gt;&lt;em&gt;Bash&lt;/em&gt;&lt;/a&gt; shell which is the default in many Operating Systems. But, same as with the emulator, there are more powerful options around. I recommend the shell &lt;a href="https://fishshell.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Fish&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What makes Fish great? It offers great productivity boosters like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autocompletion.&lt;/strong&gt; Like code completion, but for terminal commands. After a while Fish becomes almost telepathic, and you hardly have to type commands at all!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manpage completion.&lt;/strong&gt; Ever wondered which flags are available for a specific CLI? Fish can show you inline hints and descriptions based on the &lt;a href="https://en.wikipedia.org/wiki/Man_page" rel="noopener noreferrer"&gt;man pages&lt;/a&gt; for the command.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Color support.&lt;/strong&gt; Fish supports 24-bit colors, which is helpful in practice. For instance Fish colors anything you type in the terminal, letting you know whether a command is valid (blue) or not (red) before you’ve even run it!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out-of-the-box experience.&lt;/strong&gt; Other shells can get some of these features working, but it requires a lot of tinkering. Fish is great out of the box and takes up minimal time to set up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plugins.&lt;/strong&gt; If you do like to tweak your shell, you can do so with Fish. The projects &lt;a href="https://github.com/jorgebucaran/fisher" rel="noopener noreferrer"&gt;Fisher&lt;/a&gt; or &lt;a href="https://github.com/oh-my-fish/oh-my-fish" rel="noopener noreferrer"&gt;Oh My Fish&lt;/a&gt; offer great plugin support. For instance, I run a plugin that gives me a lot of sane aliases for using the git CLI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-fish.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-fish.gif" alt="Fish showing of its features" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fish is a very capable shell&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fish helps you do what you need to do in the terminal in a much more efficient manner, but we can do better! Besides the shell, we can also make the prompt more useful to us.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Power up Your Prompt
&lt;/h2&gt;

&lt;p&gt;What is a &lt;a href="https://en.wikipedia.org/wiki/Command-line_interface#Command_prompt" rel="noopener noreferrer"&gt;prompt&lt;/a&gt;? It’s (usually) the &lt;code&gt;$&lt;/code&gt; sign that tells the user whether the CLI is ready to accept a new command. Doesn’t sound too spectacular, now does it? We can make it do much more by installing a prompt like &lt;a href="https://starship.rs/" rel="noopener noreferrer"&gt;Starship&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Starship transforms your prompt and makes it display relevant information based on the directory you’re in. Some of the useful things it can show are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Git status.&lt;/strong&gt; This shows the current branch and information about the status of the repository like whether it has uncommitted changes or is behind the remote.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SDK info.&lt;/strong&gt; Starship can show the current version for Node.js, Java, Python, and many more if it detects corresponding project files. Especially useful when those projects have specific SDK requirements!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud and Docker contexts.&lt;/strong&gt; Shows you all kinds of information about the current contexts of cloud technology, like the Kubernetes context or AWS region and profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit code status.&lt;/strong&gt; Clear indicators and exit codes of the previous command.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Much more…&lt;/strong&gt; Honestly, there is so much more Starship can do. You can even show things like current ram usage, or battery percentage. Configuring it is a breeze, so experiment away.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-starship.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-starship.gif" alt="Information at a glance with Starship" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Relevant information at a glance with Starship prompt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have come to rely on Starship quite a bit. It’s very neat to have so much information at your disposal in the terminal. Saves me from typing a ton of commands!&lt;/p&gt;

&lt;p&gt;Great, we’ve got a very potent terminal stack already, what else can we improve? Next up, the multitasking experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤹 Multitask with Multiplexers
&lt;/h2&gt;

&lt;p&gt;How often do you run multiple, or long-running commands in the terminal? I often run development servers, test tasks, and software installations a lot. Wouldn’t it be great if you could do all those things effectively?&lt;/p&gt;

&lt;p&gt;Multiplexers are amazing for these use cases. &lt;a href="https://en.wikipedia.org/wiki/Terminal_multiplexer" rel="noopener noreferrer"&gt;&lt;em&gt;Terminal Multiplexing&lt;/em&gt;&lt;/a&gt; is rendering multiple terminal sessions in a single window. Kitty offers this out of the box, but there are standalone options like &lt;a href="https://github.com/tmux/tmux" rel="noopener noreferrer"&gt;tmux&lt;/a&gt; dedicated to this task.&lt;/p&gt;

&lt;p&gt;They generally offer support for rendering multiple tabs and windows within tabs. On top of this, they also allow you to personalize your layouts to just the way you like them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-multiplexing.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-multiplexing.gif" alt="Multiple processes in the terminal with Kitty's multiplexing" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Multitasking is easy with multiplexing&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I use multiplexing to run commands that take a long time simultaneously without losing focus. Gone are the days where I had to open six terminal instances or tabs. Multiplexing allows me to group relevant processes in one view.&lt;/p&gt;

&lt;p&gt;Lastly, let’s have a look at optimizing one of the most common tasks in the terminal: issuing commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧙 Keyboard Wizardry with Vim Keybindings
&lt;/h2&gt;

&lt;p&gt;Don’t you hate it when you have a command in your terminal, but you need to change just a few parts of it. This tedious work usually involves pressing the arrow keys until you reach the part of a command you wish to change. Not necessary!&lt;/p&gt;

&lt;p&gt;If you are familiar with the keybindings of &lt;a href="https://github.com/vim/vim" rel="noopener noreferrer"&gt;Vim&lt;/a&gt; this might be interesting for you. With a little tweaking, you can set up Vim keybindings for your shell. In Fish, all that’s required is to add &lt;code&gt;fish_vi_key_bindings&lt;/code&gt; to your config file (usually in &lt;code&gt;~/.config/fish/config.fish&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-vim.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codecraftr.nl%2Fassets%2Fimages%2F19-vim.gif" alt="Using Vim keybindings to manipulate a previous command effectively" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Vim keybindings make editing commands easy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this allows you to do is to enter &lt;em&gt;Normal&lt;/em&gt; mode to edit the text in commands just like you’re used to in regular Vim. This is especially powerful for editing parts of a previously executed command. It also makes navigating command history more ergonomic, as you can use the &lt;code&gt;j&lt;/code&gt; and &lt;code&gt;k&lt;/code&gt; keys in normal mode to select previous or next commands. Never leave the &lt;a href="https://en.wikipedia.org/wiki/Touch_typing#Home_row" rel="noopener noreferrer"&gt;home row&lt;/a&gt; on your keyboard again!&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ Putting It All Together
&lt;/h2&gt;

&lt;p&gt;Any of these tweaks can improve your terminal workflow, but they work even better in tandem.&lt;/p&gt;

&lt;p&gt;Starship’s prompt is beautifully rendered, with colorful emoji in Kitty. Fish is blazing fast, as is Kitty. Multiplexing requires zero setup in Kitty and is extremely smooth. Lastly, both Vim and Kitty’s keybindings are ergonomic and effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Conclusion
&lt;/h2&gt;

&lt;p&gt;The terminal is one of the most commonly used tools for a developer. In this post I showed you how to make it more productive with a few minor tweaks.&lt;/p&gt;

&lt;p&gt;By installing a better &lt;strong&gt;emulator&lt;/strong&gt; you can elevate your terminal experience, and a better &lt;strong&gt;shell&lt;/strong&gt; allows you to run commands more effectively. An upgraded &lt;strong&gt;prompt&lt;/strong&gt; shows you useful information at a glance, whilst &lt;strong&gt;multiplexing&lt;/strong&gt; can make your multitasking workflow smoother. Lastly, setting up Vim &lt;strong&gt;keybindings&lt;/strong&gt; helps with the manipulation of commands.&lt;/p&gt;

&lt;p&gt;Invest a little time into your terminal setup, it will be worth it in the long run!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What is your preferred terminal workflow? Any tips for an even better setup? Share your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>terminal</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
