Uncle Bob has a passage early in his book where he criticizes the function below, calling it “too long” and “missing context”. I agree that it’s cluttered and hard to read, but his representative solution is, frankly, absurd. He turns this into a C++ class with static methods for providing the modifiers to the text, all the while ignoring the huge elephant in the code: it does two things.

<code class="sourceCode cpp"><a title="1" class="sourceLine" id="cb1-1"><span class="kw">private</span> <span class="dt">void</span> printGuessStatistics(<span class="dt">char</span> candidate, <span class="dt">int</span> count) {</a>
<a title="2" class="sourceLine" id="cb1-2">  String number;</a>
<a title="3" class="sourceLine" id="cb1-3">  String verb;</a>
<a title="4" class="sourceLine" id="cb1-4">  String pluralModifier;</a>
<a title="5" class="sourceLine" id="cb1-5">  <span class="cf">if</span> (count == <span class="dv">0</span>) {</a>
<a title="6" class="sourceLine" id="cb1-6">    number = <span class="st">"no"</span>;</a>
<a title="7" class="sourceLine" id="cb1-7">    verb = <span class="st">"are"</span>;</a>
<a title="8" class="sourceLine" id="cb1-8">    pluralModifier = <span class="st">"s"</span>;</a>
<a title="9" class="sourceLine" id="cb1-9">  } <span class="cf">else</span> <span class="cf">if</span> (count == <span class="dv">1</span>) {</a>
<a title="10" class="sourceLine" id="cb1-10">    number = <span class="st">"1"</span>;</a>
<a title="11" class="sourceLine" id="cb1-11">    verb = <span class="st">"is"</span>;</a>
<a title="12" class="sourceLine" id="cb1-12">    pluralModifier = <span class="st">""</span>;</a>
<a title="13" class="sourceLine" id="cb1-13">  } <span class="cf">else</span> {</a>
<a title="14" class="sourceLine" id="cb1-14">    number = Integer.toString(count);</a>
<a title="15" class="sourceLine" id="cb1-15">    verb = <span class="st">"are"</span>;</a>
<a title="16" class="sourceLine" id="cb1-16">    pluralModifier = <span class="st">"s"</span>;</a>
<a title="17" class="sourceLine" id="cb1-17">  }</a>
<a title="18" class="sourceLine" id="cb1-18">  String guessMessage = String.format(</a>
<a title="19" class="sourceLine" id="cb1-19">    <span class="st">"There </span><span class="sc">%s</span><span class="st"> </span><span class="sc">%s</span><span class="st"> </span><span class="sc">%s%s</span><span class="st">"</span>, verb, number, candidate, pluralModifier);</a>
<a title="20" class="sourceLine" id="cb1-20">  print(guessMessage);</a>
<a title="21" class="sourceLine" id="cb1-21">}</a></code>

Here’s how you should write this code:

<code class="sourceCode rust"><a title="1" class="sourceLine" id="cb2-1"><span class="kw">pub</span> <span class="kw">fn</span> formatGuessStatistics(candidate: <span class="dt">char</span>, count: <span class="dt">usize</span>) -> <span class="dt">String</span> <span class="op">{</span></a>
<a title="2" class="sourceLine" id="cb2-2">    <span class="kw">let</span> (pluralModifier, message) = <span class="kw">match</span> count <span class="op">{</span></a>
<a title="3" class="sourceLine" id="cb2-3">        <span class="dv">0</span> => (<span class="st">"s"</span>, <span class="st">"are no"</span>.to_string()),</a>
<a title="4" class="sourceLine" id="cb2-4">        <span class="dv">1</span> => (<span class="st">""</span>, <span class="st">"is 1"</span>.to_string()),</a>
<a title="5" class="sourceLine" id="cb2-5">        _ => (<span class="st">"s"</span>, <span class="pp">format!</span>(<span class="st">"are {}"</span>, count)),</a>
<a title="6" class="sourceLine" id="cb2-6">    <span class="op">}</span>;</a>
<a title="7" class="sourceLine" id="cb2-7">    <span class="pp">format!</span>(<span class="st">"There {} {}{}"</span>, message, candidate, pluralModifier)</a>
<a title="8" class="sourceLine" id="cb2-8"><span class="op">}</span></a>
<a title="9" class="sourceLine" id="cb2-9"></a>
<a title="10" class="sourceLine" id="cb2-10"><span class="kw">pub</span> <span class="kw">fn</span> printGuessStatistics(candidate: <span class="dt">char</span>, count: <span class="dt">usize</span>) <span class="op">{</span></a>
<a title="11" class="sourceLine" id="cb2-11">    <span class="pp">print!</span>(<span class="st">"{}"</span>, formatGuessStatistics(candidate, count));</a>
<a title="12" class="sourceLine" id="cb2-12"><span class="op">}</span></a></code>

This is a look-up table. That’s all it is; using an algorithmic guide, you’re looking something up, translating one thing into another. Formatted this way, this is shorter, more readable, and more extensible. This version is a little performance and memory-wonky, using the format() macro twice and string-ifying statics, but worrying about that is a premature optimization waiting to take root; as it is, this function pair is literally an ideal until profiling tells you otherwise.

And while I’m being snarky about using a grown-up language, there’s nothing in C++ that says you couldn’t achieve the same results. Rust’s match is nothing more than a switch statement turned into an expression and using the move-semantic to avoid memory leaks. C++ has both lambda expressions and move semantics. Java, as of Java 9, has tuples and lambdas and garbage collection. Go is, well, Go; you get what you pay for.

I’m not asking for much. I just want you to stop writing code like it’s 1998.. I was there. It wasn’t fun. Writing code isn’t a privilege, and lots of extra lines isn’t extra value, it’s extra liability.

Oh, notice something else? My version separates the formatting from the printing: it can be tested. Write the tests first.