Jekyll2016-11-18T11:27:30+00:00https://mateuszrasinski.github.io//SoftwArt BlogBlog about Software Development by Mateusz RasińskiMateusz RasińskiDo not create public static methods2016-11-12T00:00:00+00:002016-11-12T00:00:00+00:00https://mateuszrasinski.github.io/do-not-create-public-static-methods<p>The usage of <strong>public static</strong> methods of <em>~Utils</em> classes is very popular. Those methods are great if being a part of the library. Therefore, you shouldn’t create them unless you’re <a href="http://http://eclipsesource.com/blogs/2013/11/06/get-rid-of-your-stringutils/">developing another StringUtils class</a> or something similar.</p>
<h2 id="why-the-temptation-is-so-strong">Why the temptation is so strong?</h2>
<p>You could be convinced you need to use the <strong>public static</strong> method, because:</p>
<ul>
<li>your method doesn’t operate on any of the instance variables (remember <a href="https://books.google.pl/books?id=_i6bDeoCQzsC&lpg=PP1&pg=PA140">cohesion</a>?);</li>
<li>your method is a <em>util</em> - you will use it in many places to do a simple thing;</li>
<li>you have a method that doesn’t fit in well into a single Entity nor a Value Object.</li>
</ul>
<p>But you really shouldn’t create a <strong>public static</strong> method to do it. Why?</p>
<h2 id="example">Example</h2>
<p>Imagine that you’re developing a price calculator. There are two use cases to implement.</p>
<h3 id="use-case-1-multiplication">Use Case 1: Multiplication</h3>
<p><em>As a client (<code class="language-java highlighter-rouge"><span class="n">PriceFacade</span></code>), I want to have <code class="language-java highlighter-rouge"><span class="n">PriceCalculatingService</span></code> being able to multiply list of prices, so I can display it.</em></p>
<p>The multiplication of prices is a feature tied directly to the prices itself. It is easily implemented in the class wrapping the collection of prices.</p>
<div class="title">PriceFacade.java - client code</div>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceFacade</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">PriceCalculatingService</span> <span class="n">priceCalculatingService</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">PriceFacade</span><span class="o">(</span><span class="n">PriceCalculatingService</span> <span class="n">priceCalculatingService</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">priceCalculatingService</span> <span class="o">=</span> <span class="n">priceCalculatingService</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">multiply</span><span class="o">(</span><span class="n">Prices</span> <span class="n">prices</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">priceCalculatingService</span><span class="o">.</span><span class="na">multiply</span><span class="o">(</span><span class="n">prices</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p><code class="language-java highlighter-rouge"><span class="n">PriceCalculatingService</span></code> is delegating the multiplication logic to the <code class="language-java highlighter-rouge"><span class="n">Prices</span></code>, which do the math:</p>
<div class="title">PriceCalculatingService.java - application service</div>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceCalculatingService</span> <span class="o">{</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">multiply</span><span class="o">(</span><span class="n">Prices</span> <span class="n">prices</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">prices</span><span class="o">.</span><span class="na">multiplyAll</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<div class="title">Prices.java - prices' collection wrapper</div>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Prices</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">Collection</span><span class="o"><</span><span class="n">Price</span><span class="o">></span> <span class="n">prices</span><span class="o">;</span>
<span class="c1">// constructor, etc.</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">multiplyAll</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">prices</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
<span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="nl">Price:</span><span class="o">:</span><span class="n">multiply</span><span class="o">)</span>
<span class="o">.</span><span class="na">get</span><span class="o">();</span>
<span class="o">}</span>
</code></pre>
</div>
<h3 id="use-case-2-rounding">Use Case 2: Rounding</h3>
<p><em>As a client (<code class="language-java highlighter-rouge"><span class="n">PriceFacade</span></code>), I want to have <code class="language-java highlighter-rouge"><span class="n">PriceCalculatingService</span></code> being able to <strong>properly round</strong> multiplied list of prices, so I can display it better.</em></p>
<p>That’s the tricky part. Obviously, <code class="language-java highlighter-rouge"><span class="n">Price</span></code> should be able to round itself, just as it can multiply itself. However, what does <em>properly</em> mean? Should <code class="language-java highlighter-rouge"><span class="n">Price</span></code> know what are the proper rounding settings in the current context? I don’t suppose so. We have to come up with another class to hold that information.</p>
<h2 id="static-method-solution">Static method solution</h2>
<p>We create a <code class="language-java highlighter-rouge"><span class="n">PriceRoundingService</span></code> - a <em>util</em> class, that contains a single <strong>public static</strong> method:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceRoundingService</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="n">Price</span> <span class="nf">round</span><span class="o">(</span><span class="n">Price</span> <span class="n">price</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">price</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>and use it in <code class="language-java highlighter-rouge"><span class="n">PriceCalculatingService</span></code> by importing it:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">com.github.mateuszrasinski.blog.staticmethod.service.PriceRoundingService</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceCalculatingService</span> <span class="o">{</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">multiply</span><span class="o">(</span><span class="n">Prices</span> <span class="n">prices</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Price</span> <span class="n">product</span> <span class="o">=</span> <span class="n">prices</span><span class="o">.</span><span class="na">multiplyAll</span><span class="o">();</span>
<span class="k">return</span> <span class="n">PriceRoundingService</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="n">product</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>The code works. What’s wrong then?</p>
<h3 id="testing">Testing</h3>
<p>You can’t (or shouldn’t have to) mock static method calls. From now on, every time you would like to test any code that uses <code class="language-java highlighter-rouge"><span class="n">PriceRoundingService</span></code> you have to rely on its implementation and either <em>know</em> what it does or <em>use</em> it in the assertion section of the test.</p>
<div class="language-groovy highlighter-rouge"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">PriceCalculatingServiceTest</span> <span class="kd">extends</span> <span class="n">Specification</span> <span class="o">{</span>
<span class="kd">private</span> <span class="n">PriceCalculatingService</span> <span class="n">priceCalculatingService</span> <span class="o">=</span> <span class="k">new</span> <span class="n">PriceCalculatingService</span><span class="o">()</span>
<span class="kt">def</span> <span class="s1">'should multiply two prices'</span><span class="o">()</span> <span class="o">{</span>
<span class="nl">given:</span>
<span class="n">Price</span> <span class="n">price1</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Price</span><span class="o">(</span><span class="mf">1.50</span><span class="o">,</span> <span class="n">Currency</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s1">'PLN'</span><span class="o">))</span>
<span class="n">Price</span> <span class="n">price2</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Price</span><span class="o">(</span><span class="mf">1.75</span><span class="o">,</span> <span class="n">Currency</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s1">'PLN'</span><span class="o">))</span>
<span class="n">Prices</span> <span class="n">prices</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Prices</span><span class="o">([</span><span class="n">price1</span><span class="o">,</span> <span class="n">price2</span><span class="o">])</span>
<span class="nl">when:</span>
<span class="n">Price</span> <span class="n">product</span> <span class="o">=</span> <span class="n">priceCalculatingService</span><span class="o">.</span><span class="na">multiply</span><span class="o">(</span><span class="n">prices</span><span class="o">)</span>
<span class="nl">then:</span>
<span class="n">product</span><span class="o">.</span><span class="na">value</span> <span class="o">==</span> <span class="o">(</span><span class="n">price1</span><span class="o">.</span><span class="na">value</span> <span class="o">*</span> <span class="n">price2</span><span class="o">.</span><span class="na">value</span><span class="o">).</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">)</span> <span class="c1">// <1> </span>
<span class="n">product</span> <span class="o">==</span> <span class="n">PriceRoundingService</span><span class="o">.</span><span class="na">round</span><span class="o">(</span>
<span class="k">new</span> <span class="nf">Price</span><span class="o">((</span><span class="n">price1</span><span class="o">.</span><span class="na">value</span> <span class="o">*</span> <span class="n">price2</span><span class="o">.</span><span class="na">value</span><span class="o">),</span> <span class="n">price1</span><span class="o">.</span><span class="na">getCurrency</span><span class="o">())</span>
<span class="o">)</span> <span class="c1">// <2></span>
<span class="o">}</span>
<span class="c1">// <1> Repeated implementantion</span>
<span class="c1">// <2> Static method used in the assertion section</span>
<span class="o">}</span>
</code></pre>
</div>
<h3 id="changes">Changes</h3>
<p>Let’s assume, that you need to dynamically change the scale of the price’s rounding. With <strong>static</strong> method you can’t use any instance variable (you can’t inject dependency), nor you can extend it. All you can do, is to introduce a new parameter to the method.</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceRoundingService</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="n">Price</span> <span class="nf">round</span><span class="o">(</span><span class="n">Price</span> <span class="n">price</span><span class="o">,</span> <span class="n">RoundingSettings</span> <span class="n">roundingSettings</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">price</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="n">roundingSettings</span><span class="o">.</span><span class="na">getScale</span><span class="o">(),</span> <span class="n">roundingSettings</span><span class="o">.</span><span class="na">getMode</span><span class="o">());</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>That makes your client code has to provide the information about rounding. The problem how to <em>properly</em> round the price is now also the client’s responsibility. Not nice.</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceCalculatingService</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">RoundingSettings</span> <span class="n">roundingSettings</span><span class="o">;</span>
<span class="c1">// how to initialize roundingSettings? maybe statically, again...</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">multiply</span><span class="o">(</span><span class="n">Prices</span> <span class="n">prices</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Price</span> <span class="n">product</span> <span class="o">=</span> <span class="n">prices</span><span class="o">.</span><span class="na">multiplyAll</span><span class="o">();</span>
<span class="k">return</span> <span class="n">PriceRoundingService</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="n">product</span><span class="o">,</span> <span class="n">roundingSettings</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>As if that weren’t bad enough, the new parameter has also broken the tests that were using the static method. The following line is not compiling anymore:</p>
<div class="language-groovy highlighter-rouge"><pre class="highlight"><code><span class="n">product</span> <span class="o">==</span> <span class="n">PriceRoundingService</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="k">new</span> <span class="n">Price</span><span class="o">((</span><span class="n">price1</span><span class="o">.</span><span class="na">value</span> <span class="o">*</span> <span class="n">price2</span><span class="o">.</span><span class="na">value</span><span class="o">),</span> <span class="n">price1</span><span class="o">.</span><span class="na">getCurrency</span><span class="o">()))</span>
</code></pre>
</div>
<p>We would have to pass a <code class="language-java highlighter-rouge"><span class="n">RoundingSettings</span></code> instance as the second argument of the <code class="language-java highlighter-rouge"><span class="n">PriceRoundingService</span><span class="o">.</span><span class="na">round</span><span class="o">()</span></code> method. We’d just have to <em>know</em> how to use it. Again…</p>
<h2 id="object-oriented-solution">Object-oriented solution</h2>
<p>We create nearly the same <code class="language-java highlighter-rouge"><span class="n">PriceRoundingService</span></code>. The only change is that <code class="language-java highlighter-rouge"><span class="n">round</span><span class="o">(</span><span class="n">Price</span><span class="o">)</span></code> is <strong>not</strong> static:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceRoundingService</span> <span class="o">{</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">round</span><span class="o">(</span><span class="n">Price</span> <span class="n">price</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">price</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>The usage is more demanding to initialize, but it states the needed dependency clearly in the constructor:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceCalculatingService</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">PriceRoundingService</span> <span class="n">priceRoundingService</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">PriceCalculatingService</span><span class="o">(</span><span class="n">PriceRoundingService</span> <span class="n">priceRoundingService</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Assert</span><span class="o">.</span><span class="na">notNull</span><span class="o">(</span><span class="n">priceRoundingService</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">priceRoundingService</span> <span class="o">=</span> <span class="n">priceRoundingService</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">multiply</span><span class="o">(</span><span class="n">Prices</span> <span class="n">prices</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Price</span> <span class="n">product</span> <span class="o">=</span> <span class="n">prices</span><span class="o">.</span><span class="na">multiplyAll</span><span class="o">();</span>
<span class="k">return</span> <span class="n">priceRoundingService</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="n">product</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>The code works, too. It has even lines. What’s so great about it, then?</p>
<h3 id="testing-1">Testing</h3>
<p>We can stub the call to the external service easily, so we can focus on the single responsibility of the class. Each class can be tested independently. Additionally, if there is a need to test the interactions with the external class, it can be mocked.</p>
<div class="language-groovy highlighter-rouge"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">PriceCalculatingServiceTest</span> <span class="kd">extends</span> <span class="n">Specification</span> <span class="o">{</span>
<span class="kd">private</span> <span class="n">PriceCalculatingService</span> <span class="n">priceCalculatingService</span>
<span class="kt">void</span> <span class="nf">setup</span><span class="o">()</span> <span class="o">{</span>
<span class="n">PriceRoundingService</span> <span class="n">priceRoundingServiceMock</span> <span class="o">=</span> <span class="n">Stub</span><span class="o">(</span><span class="n">PriceRoundingService</span><span class="o">)</span> <span class="o">{</span>
<span class="n">round</span><span class="o">(</span><span class="n">_</span> <span class="k">as</span> <span class="n">Price</span><span class="o">)</span> <span class="o">>></span> <span class="o">{</span> <span class="n">Price</span> <span class="n">price</span> <span class="o">-></span> <span class="k">return</span> <span class="n">price</span> <span class="o">}</span>
<span class="o">}</span>
<span class="n">priceCalculatingService</span> <span class="o">=</span> <span class="k">new</span> <span class="n">PriceCalculatingService</span><span class="o">(</span><span class="n">priceRoundingServiceMock</span><span class="o">)</span>
<span class="o">}</span>
<span class="kt">def</span> <span class="s1">'should multiply two prices'</span><span class="o">()</span> <span class="o">{</span>
<span class="nl">given:</span>
<span class="n">Price</span> <span class="n">price1</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Price</span><span class="o">(</span><span class="mf">1.50</span><span class="o">,</span> <span class="n">Currency</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s1">'PLN'</span><span class="o">))</span>
<span class="n">Price</span> <span class="n">price2</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Price</span><span class="o">(</span><span class="mf">1.75</span><span class="o">,</span> <span class="n">Currency</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s1">'PLN'</span><span class="o">))</span>
<span class="n">Prices</span> <span class="n">prices</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Prices</span><span class="o">([</span><span class="n">price1</span><span class="o">,</span> <span class="n">price2</span><span class="o">])</span>
<span class="nl">when:</span>
<span class="n">Price</span> <span class="n">product</span> <span class="o">=</span> <span class="n">priceCalculatingService</span><span class="o">.</span><span class="na">multiply</span><span class="o">(</span><span class="n">prices</span><span class="o">)</span>
<span class="nl">then:</span>
<span class="n">product</span><span class="o">.</span><span class="na">value</span> <span class="o">==</span> <span class="n">price1</span><span class="o">.</span><span class="na">value</span> <span class="o">*</span> <span class="n">price2</span><span class="o">.</span><span class="na">value</span>
<span class="o">}</span>
<span class="c1">// ...</span>
<span class="o">}</span>
</code></pre>
</div>
<h3 id="changes-1">Changes</h3>
<p>With OO design we can simply implement changes to the service, as we did in the client code - by injecting the dependency:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PriceRoundingService</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">RoundingSettings</span> <span class="n">roundingSettings</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">PriceRoundingService</span><span class="o">(</span><span class="n">RoundingSettings</span> <span class="n">roundingSettings</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">roundingSettings</span> <span class="o">=</span> <span class="n">roundingSettings</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="n">Price</span> <span class="nf">round</span><span class="o">(</span><span class="n">Price</span> <span class="n">price</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">price</span><span class="o">.</span><span class="na">round</span><span class="o">(</span><span class="n">roundingSettings</span><span class="o">.</span><span class="na">getScale</span><span class="o">(),</span> <span class="n">roundingSettings</span><span class="o">.</span><span class="na">getMode</span><span class="o">());</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>And that’s it. We don’t have to change the client code, because the contract of the <code class="language-java highlighter-rouge"><span class="n">round</span><span class="o">(</span><span class="n">Price</span><span class="o">)</span></code> method hasn’t changed and we don’t have to change the tests - because we’ve stubbed the service call. One reason to change made us change one class’s code. That’s how it supposed to be.</p>
<h2 id="summary">Summary</h2>
<p><em>-Helper</em> or <em>-Utils</em> classes are perfectly fine to patch a common class’s bad design or lack of features. Good examples are: StringUtils (from Apache or Spring) or <del>DateUtils</del> (use <code class="language-java highlighter-rouge"><span class="n">java</span><span class="o">.</span><span class="na">time</span></code> package!). The <code class="language-java highlighter-rouge"><span class="n">String</span></code> class is heavily used in different ways and it’s missing a lot of features. You can’t just add a feature to the <code class="language-java highlighter-rouge"><span class="n">String</span></code>, so in order to do something more with it, public static methods from the <code class="language-java highlighter-rouge"><span class="n">StringUtils</span></code> are used. That’s fine.</p>
<p>What is definitely not fine is creating <em>-Utils</em> class in your own project to use with your own classes. Instead of fixing the bad design - it would worsen it. There are better ways to write reusable code, but they may need a little more effort upfront.</p>Mateusz RasińskiThe usage of public static methods of ~Utils classes is very popular. Those methods are great if being a part of the library. Therefore, you shouldn’t create them unless you’re developing another StringUtils class or something similar.