<?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>DEV Community: Nemo Oudeis</title>
    <description>The latest articles on DEV Community by Nemo Oudeis (@nemooudeis).</description>
    <link>https://dev.to/nemooudeis</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%2F404280%2F682df4df-e022-4631-9413-73c345a1a492.jpeg</url>
      <title>DEV Community: Nemo Oudeis</title>
      <link>https://dev.to/nemooudeis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nemooudeis"/>
    <language>en</language>
    <item>
      <title>Make It Explicit</title>
      <dc:creator>Nemo Oudeis</dc:creator>
      <pubDate>Tue, 30 Jun 2020 12:44:33 +0000</pubDate>
      <link>https://dev.to/nemooudeis/make-it-explicit-hfn</link>
      <guid>https://dev.to/nemooudeis/make-it-explicit-hfn</guid>
      <description>&lt;p&gt;Recently I did some pair programming and code review with a developer, we added deep links into our Android application. All in all that's a pretty simple task.&lt;/p&gt;

&lt;p&gt;During the cycles of code review and pairing I realized that I first recommended to use one technique during pair programming, just to argue against it in a later on in code review. That made me think - Do I have some type of split brain thing going on here? Why do I flip flop like that? 🤔&lt;/p&gt;

&lt;p&gt;Let's look at code: The first version I saw (slightly modified) was this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;DEEPLINK_PATH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/deepLinkPath"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;DEEPLINK_SHEMA&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"deeplink-schema"&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;handleDeeplink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACTION_VIEW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DEEPLINK_SCHEMA&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DEEPLINK_PATH&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"do the thing!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Well this is overly complicated, if I would put it into plain language it would be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I look at the intent&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, if it's not null, if it has an action, if it has data, and the action is &lt;code&gt;ACTION_VIEW&lt;/code&gt; and the data has the URL schema that I expect and if it has the path that I expect, if the path is not null, then I &lt;em&gt;do the thing&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5l6wMzcb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://nemo.oudeis.fyi/wut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5l6wMzcb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://nemo.oudeis.fyi/wut.png" alt="What did you just say?!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait what? Huh?&lt;/p&gt;

&lt;p&gt;Nobody wants to hear that. If I say that to you then your ears will start bleeding.&lt;/p&gt;

&lt;p&gt;Not to speak of the indentation, it's horribly hard to read. This piece of code goes to great efforts to &lt;em&gt;conceal&lt;/em&gt; its intent!&lt;/p&gt;

&lt;p&gt;I suggested to simplify the conditionals and remove that indentation by introducing bouncer-style if checks. Moreover there's a design issue here that we conflate 2 concerns: (1) adapter code that translates between framework and our logic and (2) our own logic, which should be independent of Android specifics (like &lt;code&gt;Fragment&lt;/code&gt;s, &lt;code&gt;Activity&lt;/code&gt;s and &lt;code&gt;Intent&lt;/code&gt;s).&lt;/p&gt;

&lt;p&gt;My guy split the concerns and added the bouncer code, resulting in the below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;DEEPLINK_HOST&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"our.deeplink.host.fyi"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;DEEPLINK_SHEMA&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"deeplink-schema"&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;DEEPLINK_PATH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/deepLinkPath"&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;handleDeepLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="nc"&gt;DEEP_LINK_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Safety check for host&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="nc"&gt;DEEP_LINK_HOST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Safety check for path&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;DEEPLINK_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"do the thing!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that's a lot easier to read, the indentation is essentially flat (ignoring the bouncer &lt;code&gt;return&lt;/code&gt; statements) and we actually do a couple of more checks. Note also that the adapter code of checking if the &lt;code&gt;Intent&lt;/code&gt;'s nullability and if it has the correct action is not here (that's handled in the adapter layer as it should be).&lt;/p&gt;

&lt;p&gt;But reading this I think: isn't that a bit verbose for the simple checks we do? Can't we reduce this to just a single conditional? Wouldn't that be more explicit?&lt;/p&gt;

&lt;p&gt;So we arrive at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;handleDeepLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;DEEP_LINK_SCHEMA&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;DEEP_LINK_HOST&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;===&lt;/span&gt; &lt;span class="nc"&gt;DEEP_LINK_PATH&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"do the thing!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the final version, which is arguably &lt;strong&gt;more explicit&lt;/strong&gt; and &lt;strong&gt;less complex&lt;/strong&gt; than both previous iterations. In normal language:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the URI has our deep link schema, host and path we &lt;em&gt;do the thing&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that's a sentence! You hear it -- you get it. That's what the code should be like.&lt;/p&gt;

&lt;p&gt;But I did tell my guy to&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add bouncer code because it will make the code cleaner&lt;/li&gt;
&lt;li&gt;Remove bouncer code because it will make the code cleaner&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🤦‍♀️&lt;/p&gt;

&lt;p&gt;The poor guy must be thinking I enjoy making him jump through hoops to appease my sense of aesthetics. And I can see why he would get that idea...&lt;/p&gt;

&lt;p&gt;Underlying this is more than a pattern, a technique, a specific design or a trick: I want the code to be explicit. All code should be explicit. This is such a universal guideline for me that I think it's a ... &lt;em&gt;*drumroll*&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Software Development Principle&lt;sup id="fnref2"&gt;2&lt;/sup&gt;
&lt;/h2&gt;

&lt;p&gt;Style, taste and aesthetics are too subjective for my taste, so let's define a &lt;strong&gt;software development principle&lt;/strong&gt; that I use to guide my decision making. Rather than detailed prescriptive solutions ("use bouncer code", "use strategy pattern") is a high level rules that I instill in my development teams.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Principle&lt;/strong&gt;: a basic idea or rule that explains or controls how something happens or works&lt;/p&gt;

&lt;p&gt;-- &lt;a href="https://dictionary.cambridge.org/dictionary/english/principle"&gt;Cambridge Dictionary&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Something fancy like that ☝️.&lt;/p&gt;

&lt;p&gt;So get ready for...&lt;/p&gt;

&lt;h2&gt;
  
  
  Principle #1: Make it Explicit
&lt;/h2&gt;

&lt;p&gt;Now this may sound basic at first glance, but bear with me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any fool can write code that a computer can understand. Good programmers write code that humans can understand.&lt;/p&gt;

&lt;p&gt;-- &lt;a href="https://learning.oreilly.com/library/view/refactoring-improving-the/9780134757681/"&gt;Martin Fowler, 1999&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Programming is communication with other programers. Therefore we have to strive to explicitly communicate the intent of our software.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Code should read like a story to the (to a reasonable extent) initiated reader.&lt;/p&gt;

&lt;p&gt;Kent Beck recognizes that in his &lt;a href="https://martinfowler.com/bliki/BeckDesignRules.html"&gt;rules of simple design&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Passes the tests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reveals intention&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;No duplication&lt;/li&gt;
&lt;li&gt;Fewest elements&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;So if that's all over 20 years old, surely we all do this already, right? I wish....&lt;/p&gt;

&lt;p&gt;Let me walk you though a couple cases I encountered "in the real world"™️, examples in which the code was less than explicit about its intent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example #1: Web Frameworks
&lt;/h3&gt;

&lt;p&gt;Spring is a &lt;del&gt;decent&lt;/del&gt; web framework, it has a lot of features and many people use it. Still I dislike Spring for the single reason that they make it damn hard to know what's going on! The significant code, the one that actually implements your business logic that -- you know, makes all the money -- is buried in a pile of annotations. This is only partially spring's fault, you don't &lt;em&gt;have&lt;/em&gt; to do it way. But in reality I see code bases doing it that way. Here is an adapted example of some real java code that someone (with far more Spring experience than me) has written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@Api&lt;/span&gt;
&lt;span class="nd"&gt;@Validated&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnExampleController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;AnExampleController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AnExampleService&lt;/span&gt; &lt;span class="n"&gt;exampleService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exampleService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exampleService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@ApiOperation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Get Example"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ExampleResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nd"&gt;@ApiResponses&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="nd"&gt;@ApiResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Success"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
          &lt;span class="nd"&gt;@ApiResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bad Request"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
          &lt;span class="nd"&gt;@ApiResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;})&lt;/span&gt;
  &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt; &lt;span class="nf"&gt;getExample&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nd"&gt;@RequestHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"subject"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="nd"&gt;@RequestHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"alternativeSubject"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;alternativeSubject&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do the thing&lt;/span&gt;
    &lt;span class="n"&gt;exampleService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doTheThing&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alternativeSubject&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's 12 annotations and 23 lines of code &lt;strong&gt;before you get to the point&lt;/strong&gt;. That is not explicit, that's the opposite.&lt;/p&gt;

&lt;p&gt;Similarly the data driven test code for class (this time in Kotlin) is a mess:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SpringBootTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ExampleApplication&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nd"&gt;@WebAppConfiguration&lt;/span&gt;
&lt;span class="nd"&gt;@RunWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Parameterized&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Suppress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UNUSED_PARAMETER"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleParameterizedTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="cm"&gt;/* parameters */&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;mockMvc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MockMvc&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;wac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;WebApplicationContext&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;

    &lt;span class="nd"&gt;@MockBean&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;exampleService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ExampleService&lt;/span&gt;

    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;Rule&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;springMethodRule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringMethodRule&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@Before&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mockMvc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MockMvcBuilders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;webAppContextSetup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wac&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@Throws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@MethodSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exampleParameters"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;someTestMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Do the test&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nd"&gt;@ClassRule&lt;/span&gt;
        &lt;span class="nd"&gt;@JvmField&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;SPRING_CLASS_RULE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringClassRule&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="nd"&gt;@JvmStatic&lt;/span&gt;
        &lt;span class="nd"&gt;@Parameterized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Parameters&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;exampleParameters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* test data */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All the effort you have to put in just to write a test... and slow running complex ones at that. I don't think we have to dive into the details here.&lt;/p&gt;

&lt;p&gt;Ok so if Spring somehow makes people write hard to read code, what are some other options?&lt;/p&gt;

&lt;p&gt;🤔&lt;/p&gt;

&lt;p&gt;How about Node.js + Express? Let's look at another adapted real world example (again authored by somebody who is a more experienced express programmer than me):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/example&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./example-controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// example-controller.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./example-service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alternativeSubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alternativeSubject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Do the thing&lt;/span&gt;
    &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doTheThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;alternativeSubject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;

&lt;span class="c1"&gt;// tests/example-controller.test.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;supertest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../example-service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// the app file above&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The example controllor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="cm"&gt;/* test data */&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* parameters*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// do the test&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now this does most what the above Spring code does. In about half the amount of code. So express definitely facilitates more concise code. And I argue that just by that fact it already is more explicit that the Spring example. Nothing is buried in boilerplate here. Sure you may not know all the details of the &lt;code&gt;Router&lt;/code&gt; or of the &lt;code&gt;supertest&lt;/code&gt; package, but that is equally true for Spring's &lt;code&gt;WebApplicationContext&lt;/code&gt; or the &lt;code&gt;@Validated&lt;/code&gt; annotation. That's totally fine, explicit doesn't need to be verbose. We don't know all the things, that's why we read documentation.&lt;/p&gt;

&lt;p&gt;What I'm getting at is that the express example explicitly communicates its intent. The spring example does not.&lt;/p&gt;

&lt;p&gt;We could have done the same exercise with &lt;a href="https://ktor.io/"&gt;ktor&lt;/a&gt;, &lt;a href="http://sinatrarb.com/"&gt;sinatra&lt;/a&gt;, &lt;a href="https://github.com/pallets/flask"&gt;flask&lt;/a&gt;, &lt;a href="https://rubyonrails.org/"&gt;rails&lt;/a&gt;, etc. In this case the problem is not Java (although in many other cases it is) and even the spring project itself is trying to dig itself out of that hole with &lt;a href="https://github.com/spring-projects-experimental/spring-fu/tree/master/kofu"&gt;spring fu&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Rails advertises and delivers convention over configuration.&lt;br&gt;
As a result the average rails codebase is more readable and communicates intent better than the average spring codebase.&lt;/p&gt;

&lt;p&gt;Spring on the other hand often ends up in the "obfuscation over convention" corner.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example #2: Generic Jenkins CD Pipeline
&lt;/h3&gt;

&lt;p&gt;Here's Another real world example from a team that operates k8s clusters as a service for application teams. They have different environments (development, staging and production) and provide a Jenkins job to deploy to each of them, i.e. 3 jobs.&lt;br&gt;
They decided to use a single Jenkins pipeline for all jobs and hardcode the credentials specific for each environment in the job config, for example the job deploying to staging environment has the &lt;code&gt;env = 'stg'&lt;/code&gt; parameter hardwired in Jenkins web UI.&lt;/p&gt;

&lt;p&gt;Here's the conditional logic of that pipeline, without the actual operations in each stage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Jenkinsfile&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s1"&gt;'action'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;choices:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'deploy'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'delete'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s1"&gt;'env'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;choices:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'dev'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'stg'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'prod'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'build app'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'dev'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'deploy'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'build docker image'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'dev'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'deploy'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'select container image'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'dev'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'deploy'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'promote container image to next env'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'dev'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'deploy'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deploy to k8s'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'monitor rollout status'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'deploy'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'release notes'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'deploy'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'prod'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'notify slack'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'deploy'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'prod'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;...now: tell me what stages run for &lt;code&gt;action = deploy&lt;/code&gt; and &lt;code&gt;env = dev&lt;/code&gt;? Can you tell? I can't, not without wasting effort untangling the mess. This pipeline obfuscates intent and control flow.&lt;/p&gt;

&lt;p&gt;So my team split up the pipeline into 3, one for each environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="c1"&gt;// develop.jenkinsfile&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'build app'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'build docker image'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deploy to k8s'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'monitor rollout status'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// staging.jenkinsfile&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'select container image'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'promote container image to next env'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deploy to k8s'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'monitor rollout status'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// production.jenkinsfile&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'select container image'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'promote container image to next env'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deploy to k8s'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'monitor rollout status'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'release notes'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'notify slack'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let me ask again: which stages run when we deploy to the development environment? Pretty obvious now, because there are no more conditionals in any of the pipelines! Isn't that much more explicit?&lt;/p&gt;

&lt;p&gt;Ok, but that's maybe not perfect, there are some concerns you might raise&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;These pipelines are not equivalent to the previous above, the &lt;code&gt;action = 'delete'&lt;/code&gt; cases are missing → We never used that - but we had no idea, because that was buried in the complexity of the previous pipeline. The code did not tell us, that was its little dirty secret.&lt;/li&gt;
&lt;li&gt;There is of duplication in the pipeline we use for production &amp;amp; staging → Yes that is true. But we value explicit separation of these concerns is more over reusing code in this case. It is a trade off: simplicity vs no-duplication. Simplicity, I chose you!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See how something interesting happened there? Because we follow a this principle of "Make It Explicit!" we are empowered to violate the programmer common sense of "duplication is bad!".&lt;/p&gt;

&lt;p&gt;Similarly following the principle lead us to identify a design problem: the pipeline clearly had multiple reasons to change, in other words: multiple responsibilities. By following our plan to make the code more explicit we also applied the single responsibility principle, without even thinking about it.&lt;/p&gt;

&lt;p&gt;I have more examples of code that obfuscates intent, code that needs to be more explicit - but I think you get the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is It Good for?
&lt;/h2&gt;

&lt;p&gt;In summary: a lot of code is damn hard to read. Not because of programming languages or frameworks. Because programmers follow rules of thumb (reuse everything always, use annotations instead of code, etc.) without asking themselves: &lt;strong&gt;is this in line with my/our development principles&lt;/strong&gt;? This is the first of the principles me and my teams follow, I'll write about the other ones in following posts - here's a shortlist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make it Explicit&lt;/li&gt;
&lt;li&gt;Business Drives IT&lt;/li&gt;
&lt;li&gt;Don't build Software&lt;/li&gt;
&lt;li&gt;Trade-Offs &amp;amp; Decisions&lt;/li&gt;
&lt;li&gt;Fast Feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a work in progress, non-exhaustive and specific to my professional environment -- but it's what I've got so for 😄. Let me know how principles affect your design &amp;amp; development and about your principles - maybe I'll steal some...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="http://nemo.oudeis.fyi/posts/make-it-explicit/"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;code&gt;Intent&lt;/code&gt; is an Android framework class, you can think of it as a value object that carries the intent of a message the operating system sent to your application. For example when the application launches or when the operating system sends a broadcast to your applications with updates of the battery level. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;I went back and forth between "principle" and "directive". Directive sounds less lofty and one definition is &lt;a href="https://www.merriam-webster.com/dictionary/directive"&gt;"something that serves to direct, guide, and usually impel toward an action or goal"&lt;/a&gt;. Which is what I am talking about, kind of. But for the time being let's stick with principle. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>design</category>
    </item>
    <item>
      <title>Master Your Tools</title>
      <dc:creator>Nemo Oudeis</dc:creator>
      <pubDate>Tue, 09 Jun 2020 16:12:08 +0000</pubDate>
      <link>https://dev.to/nemooudeis/master-your-tools-2anh</link>
      <guid>https://dev.to/nemooudeis/master-your-tools-2anh</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="http://nemo.oudeis.fyi/posts/master-your-tools/"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today I found &lt;a href="https://www.aleksandra.codes/tech-content-consumer"&gt;"Most tech content is bullshit"&lt;/a&gt; by &lt;a href="https://twitter.com/aleksandrasays"&gt;Aleksandra Sikora&lt;/a&gt;. Good title, right? 😁 In a nutshell her post says: all information on the internet is written by people who don't really know. And I'd say she's right about that. Still we point to them and say "this is the authoritative source, we should follow it!". I have seen &amp;amp; heard the same hand-wavy arguments, from junior, senior, tech leads, engineering managers, architects - really any job title and level of seniority. A lot of the time it plays out like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Expert: We need to do X!&lt;/p&gt;

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

&lt;p&gt;Expert: It's an industry best practice. Google is doing it!/I read it in a book. The author is famous!/I heard it at this conference. The speaker created a framework!/There is no other option!&lt;/p&gt;

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

&lt;p&gt;Expert: Because of the above!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Leaning into the external authority somehow has massive appeal.&lt;/p&gt;

&lt;p&gt;Anyhow if you cannot formulate the problem, how your solution addresses the problem and the benefits and drawbacks of your solution then you don't know what you are talking about. At least you don't know it well enough. Unfortunately all the bullshit tech content (that Aleksandra is referring to) is the training material for the next generation of developers. It teaches them to ask: "How do I do it? And who said so?" instead of "How do I do it? Why? No I really want to understand it!".&lt;/p&gt;

&lt;h1&gt;
  
  
  Framework Induced Ignorance
&lt;/h1&gt;

&lt;p&gt;I work several development teams on a variety of technologies. An anti-pattern I have seen on several occasions is framework worship: developers religiously follow the framework gospel (documentation &amp;amp; related blog posts) and ignore what developers have learned over decades - because React is new, how could your old idea apply to React?! I call this &lt;strong&gt;Framework Induced Ignorance&lt;/strong&gt;, developers follow the $FRAMEWORK Way™️ and close their minds to other ideas. Let me give you 3 examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Android
&lt;/h2&gt;

&lt;p&gt;The last 2 generations&lt;sup id="fnref1"&gt;1&lt;/sup&gt; of Android developers have followed the &lt;a href="http://developer.android.com/"&gt;Android developer documentation&lt;/a&gt;. It taught them to....&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;... love &lt;a href="https://en.wikipedia.org/wiki/God_object"&gt;god objects&lt;/a&gt;. Put all business logic into you &lt;code&gt;Activity&lt;/code&gt; (or &lt;code&gt;Fragment&lt;/code&gt;) - UI, business logic, external adapter code, what have you. Separation of Concerns - go home, we don't need you anymore!&lt;/li&gt;
&lt;li&gt;... ignore unit testing. The testing skill in Android land is abysmal (compared to  other communities). Most code is tightly coupled to the android platform, as a result the &lt;a href="http://robolectric.org/"&gt;Robolectric&lt;/a&gt; project was born. It provides a work around to test your code, even if it's coupled to the platform - a hack to retrofit testing into a non-testable code base. (No offense to the robolectric folks, it's a great project.)&lt;/li&gt;
&lt;li&gt;...forget about threading. On Android threading is inherently necessary, the UI thread has 16ms to draw the next frame. That's no time to do heavy lifting. Still the solutions promoted by the official Android documentation were error prone, clunky and have been rightfully deprecated (farewell &lt;code&gt;Loader&lt;/code&gt; &amp;amp; &lt;code&gt;AsyncTask&lt;/code&gt;, see you never). A lot of developers adopted &lt;a href="https://github.com/ReactiveX/RxJava"&gt;reactive extensions&lt;/a&gt; just for the sake of explicit thread control. Talk about bringing a gun to a knife fight....&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  React
&lt;/h2&gt;

&lt;p&gt;Recently I reviewed React.js code and one component was growing too big, it was several hundred lines of code at the time. The component is essentially an elaborate form, with different sections, which are semi independent. I've seen similar situations on other front end frameworks/platforms before, so I asked the developer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Me: Can we split up the into smaller, self contained pieces?&lt;/p&gt;

&lt;p&gt;Expert: No that is not possible in React, we cannot share state between functional components.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An hour of experimentation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Me: How about this → &lt;em&gt;shows pull request&lt;/em&gt;. Can't we just call a function which returns JSX?&lt;/p&gt;

&lt;p&gt;Expert: How does this work? I've never seen this before? Is there a blog post or documentation about it?&lt;/p&gt;

&lt;p&gt;Me: I don't know, it's just JavaScript. A function that takes parameters and returns JSX, nothing to do with React internals really.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Later on he got really excited about this. Him sticking only to the React docs &amp;amp; related blogs closed his mind to "non React" approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spring
&lt;/h2&gt;

&lt;p&gt;A third example is Java/Kotlin Spring. Spring is a great tool -- if you know how to use it. Sadly what I've seen looks more like Spring is using developers. A co-worker of mine, with a background the .NET, had to take over such a Spring application. He summarized it as "more annotations than actual code". Yikes.&lt;/p&gt;

&lt;p&gt;I work with a Spring expert who followed exactly the same approach - he loves god objects, tightly coupled to each other and to the framework, all tied together with an overgrowth of annotations. Really very similar to the unfortunate Androids above. Now he's un-learning the anti-patterns that the spring community taught him over the years. But it's a slow process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait a minute...
&lt;/h2&gt;

&lt;p&gt;We've been here before. So much so that Uncle Bob already wrote about this in one of his books&lt;sup id="fnref2"&gt;2&lt;/sup&gt;, so I'll just steal his summary:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Frameworks can be very powerful and very useful. Framework authors often believe very deeply in their frameworks. The examples they write for how to use their frameworks are told from the point of view of a true believer. Other authors who write about the framework also tend to be disciples of the true belief. They show you the way to use the framework. Often they assume an all-encompassing, all-pervading, let-the-framework-do-everything position.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If that sounds familiar it is essentially the same bullshit content that Aleskandra was talking about.&lt;/p&gt;

&lt;p&gt;So now we're here, ankle-deep in bullshit content, how do we get out?&lt;/p&gt;

&lt;h1&gt;
  
  
  Craft beer, craft pizza, craft... software?
&lt;/h1&gt;

&lt;p&gt;Developing software is a craft.&lt;/p&gt;

&lt;p&gt;But what does that even mean?&lt;/p&gt;

&lt;p&gt;In history the trajectory of a tradesperson typically included 3 distinct stages: apprentice, journeyman and &lt;a href="https://en.wikipedia.org/wiki/Master_craftsman"&gt;master craftsperson&lt;/a&gt;&lt;sup id="fnref3"&gt;3&lt;/sup&gt;. Some of that system still remains in parts of the world, but only in traditional crafts - carpenters, electricians, butchers, etc.&lt;/p&gt;

&lt;p&gt;What all of these trades have in common is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You need knowledge of the trade&lt;/li&gt;
&lt;li&gt;You need to apply that knowledge, over and over again to master different techniques and skills.&lt;/li&gt;
&lt;li&gt;Reflect on and improve upon techniques &amp;amp; skills.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This applies to software development exactly the same way. You have to learn the basics about development and then do it a ton to become good at it. You can learn JavaScript and React basics in several weeks (step 1), but you need months to years to master JavaScript and React (step 2). What about step 3? That's how we separate wheat from chaff. If you aspire to be a software master craftsperson you have to go beyond the knowledge from framework documentation &amp;amp; blogs. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's wrong with StackOverflow?
&lt;/h2&gt;

&lt;p&gt;Well nothing really, it's a great tool, I use it a lot. But....&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy-paste error message into Google&lt;/li&gt;
&lt;li&gt;Finding a StackOverflow answer&lt;/li&gt;
&lt;li&gt;Copy-paste solution &lt;/li&gt;
&lt;li&gt;Repeat until your problem goes away&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That will achieve the immediate goal. And if you do that over and over again you arguable follow step 1 and 2: Using Google and StackOverflow is part of the developer skillset, doing it more often will make you better or faster at finding these answers. But for step 3 you need to stop and understand why that answer solves your problem. What was the root cause of the problem? How does the solution address that? 🤔&lt;/p&gt;

&lt;p&gt;If you want to escape the bullshit content you have to understand why the solution works. If you really understand the little bit of code you found that knowledge compounds. Soon enough it's time for you to write a blog post or documentation - and you sure as hell won't write bullshit content, right?! By practicing step 3, trying to understand every bit of code you write, at least a bit better that yesterday, you have a fighting chance. By mindlessly copy-pasting however...&lt;/p&gt;

&lt;h2&gt;
  
  
  Extreme Values &amp;amp; Reasonable Expectations
&lt;/h2&gt;

&lt;p&gt;Why is that thirds step, the understanding of the solution, so important? Uncle Bob formulates a "list of perfectly reasonable expectations that managers, users, and customers have of [developers]"&lt;sup id="fnref4"&gt;4&lt;/sup&gt; and among them is &lt;strong&gt;Fearless Competence&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Customers, users, and managers expect fearless competence. They expect that if you see something wrong or dirty, you will fix and clean it. They don’t expect you to allow problems to fester and grow; they expect you to stay on top of the code, keeping it as clean and clear as possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We aspire to be software master craftspeople in order to be fearlessly competent!&lt;/p&gt;

&lt;p&gt;Similarly Courage is one of the values in Extreme Programming&lt;sup id="fnref5"&gt;5&lt;/sup&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Courage is effective action in the face of fear.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We aspire to be software master craftspeople in order to be able to act with courage!&lt;/p&gt;

&lt;p&gt;Yet another way of putting it is in the &lt;a href="https://manifesto.softwarecraftsmanship.org/#/en"&gt;Manifesto for Software Craftsmanship&lt;/a&gt;, with the subtitle&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Raising the bar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We aspire to be software master craftspeople in order to raise the bar!&lt;/p&gt;

&lt;p&gt;&lt;sup id="fnref6"&gt;6&lt;/sup&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Master your Tool
&lt;/h1&gt;

&lt;p&gt;In summary&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/aleksandrasays"&gt;Aleskandra&lt;/a&gt; says "Most tech content is bullshit" - I agree&lt;/li&gt;
&lt;li&gt;Generations of developers suffer from Framework Induced Ignorance&lt;/li&gt;
&lt;li&gt;The only remedy practicing software development as a craft&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where does that leave us?&lt;/p&gt;

&lt;p&gt;For all aspiring tech leaders/experts/architects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Master you tools instead of being used and abused by it!&lt;/li&gt;
&lt;li&gt;Create content along the way. Maybe yours won't be bullshit 😉.&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;I count a framework developer generation as 5 years. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://learning.oreilly.com/library/view/clean-architecture-a/9780134494272/"&gt;Clean Architecture&lt;/a&gt;, chapter 21 ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;I prefer the term "craftsperson" to "craftsman" because there is really no reason to gender these terms. However using "journey person" instead of "journeyman" makes the writing less clear.  ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://learning.oreilly.com/library/view/clean-agile-back/9780135782002/"&gt;Clean Agile&lt;/a&gt;, chapter 2 ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://learning.oreilly.com/library/view/extreme-programming-explained/0321278658/"&gt;Extreme Programming Explained: Embrace Change&lt;/a&gt;, chapter 1.4 ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;I know we started with discounting external authority, so let me qualify: I refer to these sources for different (better) formulations. And to clarify that these ideas are not my original thinking. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>career</category>
      <category>culture</category>
      <category>codequality</category>
      <category>developer</category>
    </item>
    <item>
      <title>Better Dev CV - one step at a time</title>
      <dc:creator>Nemo Oudeis</dc:creator>
      <pubDate>Mon, 08 Jun 2020 10:39:58 +0000</pubDate>
      <link>https://dev.to/nemooudeis/better-dev-cv-one-step-at-a-time-l80</link>
      <guid>https://dev.to/nemooudeis/better-dev-cv-one-step-at-a-time-l80</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="http://nemo.oudeis.fyi/posts/cv-advice/"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  CV fresh out of &lt;code&gt;freeCodeCamp&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;I saw this &lt;a href="https://www.freecodecamp.org/forum/t/can-anyone-here-review-my-resume-i-wont-reveal-my-true-identity/344845"&gt;career advice question on &lt;code&gt;freeCodeCamp&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I’ve been applying for jobs and I am getting really frustrated since I am rejected each time I apply. Perhaps there is something wrong with my resume&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Last year I read hundreds of CVs and conducted close to a hundred technical interviews while hiring developers for my company. My key takeaway is: Hiring is tough - on both the candidate and the interviewer. So when I saw that question on the &lt;code&gt;freeCodeCamp&lt;/code&gt; forum answers started pouring out of me. Here are some ideas for preparing a CV for a technical position.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't forget the README
&lt;/h2&gt;

&lt;p&gt;If you have a project on GitHub make sure that (a) you have a &lt;code&gt;README.md&lt;/code&gt; and (b) an uninitiated reader can understand what the project is about.&lt;/p&gt;

&lt;p&gt;A good example of this is &lt;a href="https://github.com/ReKotlin/ReKotlin"&gt;ReKotlin&lt;/a&gt;, they follow a simple structure of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 1 liner describing the project&lt;/li&gt;
&lt;li&gt;"Introduction" section that describes the project at a high level&lt;/li&gt;
&lt;li&gt;"About" section that goes into detail about design &amp;amp; details, with code examples.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Avoid Copy-Paste Statements and Templates
&lt;/h2&gt;

&lt;p&gt;I see a lot of self described "motivated", "faster learning", "flexible", "innovative" applicants. If you don't provide evidence to back it up it will sound hollow - why should I believe you?. For example&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I am a &lt;strong&gt;motivated&lt;/strong&gt; self taught web developer and a &lt;strong&gt;fast learner&lt;/strong&gt; who &lt;strong&gt;can transition easily&lt;/strong&gt; into any new work environment&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This mentions 3 skills: motivation, quick learning, adaptability. Those all sound nice - but if I don't see examples of past experience or behavior to support them they are claims to me. As a reviewer that is a bad sign.&lt;/p&gt;

&lt;p&gt;If you don't have professional experience in software development you may have examples of motivation, quick learning or adaptability in other contexts. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did you run a club in school/university? &lt;/li&gt;
&lt;li&gt;Did you volunteer for something? &lt;/li&gt;
&lt;li&gt;Have you been in a challenging work situation that you had to adapt to? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Giving a concise account (2-3 sentences) of this evidence shows that you are not just making things up and it is a great entry point for conversation during an interview.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Projects to convince me
&lt;/h2&gt;

&lt;p&gt;You probably have projects or applications to show off your skill - that is great. I particularly like source code, I always review code to gain an understanding of the candidate's development style &amp;amp; practices.&lt;/p&gt;

&lt;p&gt;However if you submit source code of a study/learning project I want to see it deployed as a functional demo (e.g. on Heroku). A running application, even if it is just a prototype, is much more convincing than just code. The technical reviewer of your CV will have confidence in your skill.&lt;/p&gt;

&lt;p&gt;On the flip side if you submit a link to a huge and complex application I need more details. What did you work on? What challenges did you face/overcome? The main goal of reviewing past projects is to understand what you are capable of - if you make that really obvious you have an advantage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visual Presentation
&lt;/h2&gt;

&lt;p&gt;The visual presentation of many tech CVs is a bit bland &amp;amp; loveless (some of this is due to recruiters, who copy content into word documents 🤦‍♀️).&lt;br&gt;
This may seem a bit nit-picky but it has a big impact. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typography&lt;/strong&gt;: Don't use too many font sizes. Don't mix serif and sans serif fonts. Don't use text background (gray boxes etc.). Go easy on the bold &amp;amp; italics. I suggest you keep it simple: 1 font, 2 font sizes, use bold rarely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual noise &amp;amp; white space&lt;/strong&gt;: Many CVs are visually busy and dense. Typography helps. In addition to that using white space to visually group sections together makes your CV more readable. This is especially useful when the reader comes back to the CV to quickly find a piece of information that she vaguely remembers from the first read through (that happens 2-10 times for every CV that I read). Making the CV easy to use for the reviewer increases your chances significantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hyperlinks&lt;/strong&gt;: You are sending a digital document to apply for a position in tech. Nobody will type out the urls you put on the CV. They will click it. Therefore I suggest you put in clickable links behind descriptive titles. &lt;/p&gt;

&lt;p&gt;🚫 Don't do&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sample project https://github.com/ReKotlin/ReKotlin&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✅ Instead do&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sample project&lt;/p&gt;

&lt;p&gt;OR&lt;/p&gt;

&lt;p&gt;Sample project (GitHub, Live Demo) &lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;I hope the above tips help you to make your CV clear and easy to read. If you have any more questions head over to the &lt;a href="https://www.freecodecamp.org/forum/"&gt;&lt;code&gt;freeCodeCamp&lt;/code&gt; forum&lt;/a&gt;, I'll come find your question 😉.&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
