Refactoring Day 18 : Replace exception with conditional


Today’s refactoring doesn’t come from any place specifically, just something I’ve picked up over time that I find myself using often. Any variations/comments would be appreciated to this approach. I think there’s some other good refactorings around these type of problems.

A common code smell that I come across from time to time is using exceptions to control program flow. You may see something to this effect:

   1: public class Microwave
<pre><span class="lnum">   2:</span> {</pre>

<pre><span class="lnum">   3:</span>     <span class="kwrd">private</span> IMicrowaveMotor Motor { get; set;}</pre>

<pre><span class="lnum">   4:</span>&nbsp; </pre>

<pre><span class="lnum">   5:</span>     <span class="kwrd">public</span> <span class="kwrd">bool</span> Start(<span class="kwrd">object</span> food)</pre>

<pre><span class="lnum">   6:</span>     {</pre>

<pre><span class="lnum">   7:</span>         <span class="kwrd">bool</span> foodCooked = <span class="kwrd">false</span>;</pre>

<pre><span class="lnum">   8:</span>         <span class="kwrd">try</span></pre>

<pre><span class="lnum">   9:</span>         {</pre>

<pre><span class="lnum">  10:</span>             Motor.Cook(food);</pre>

<pre><span class="lnum">  11:</span>             foodCooked = <span class="kwrd">true</span>;</pre>

<pre><span class="lnum">  12:</span>         }</pre>

<pre><span class="lnum">  13:</span>         <span class="kwrd">catch</span>(InUseException)</pre>

<pre><span class="lnum">  14:</span>         {</pre>

<pre><span class="lnum">  15:</span>             foodcooked = <span class="kwrd">false</span>;</pre>

<pre><span class="lnum">  16:</span>         }</pre>

<pre><span class="lnum">  17:</span>&nbsp; </pre>

<pre><span class="lnum">  18:</span>         <span class="kwrd">return</span> foodCooked;</pre>

<pre><span class="lnum">  19:</span>     }</pre>

<pre><span class="lnum">  20:</span> }</pre>

Exceptions should only be there to do exactly what they are for, handle exceptional behavior. Most of the time you can replace this type of code with a proper conditional and handle it properly. This is called design by contract in the after example because we are ensuring a specific state of the Motor class before performing the necessary work instead of letting an exception handle it.

   1: public class Microwave
<pre><span class="lnum">   2:</span> {</pre>

<pre><span class="lnum">   3:</span>     <span class="kwrd">private</span> IMicrowaveMotor Motor { get; set; }</pre>

<pre><span class="lnum">   4:</span>&nbsp; </pre>

<pre><span class="lnum">   5:</span>     <span class="kwrd">public</span> <span class="kwrd">bool</span> Start(<span class="kwrd">object</span> food)</pre>

<pre><span class="lnum">   6:</span>     {</pre>

<pre><span class="lnum">   7:</span>         <span class="kwrd">if</span> (Motor.IsInUse)</pre>

<pre><span class="lnum">   8:</span>             <span class="kwrd">return</span> <span class="kwrd">false</span>;</pre>

<pre><span class="lnum">   9:</span>&nbsp; </pre>

<pre><span class="lnum">  10:</span>         Motor.Cook(food);</pre>

<pre><span class="lnum">  11:</span>&nbsp; </pre>

<pre><span class="lnum">  12:</span>         <span class="kwrd">return</span> <span class="kwrd">true</span>;</pre>

<pre><span class="lnum">  13:</span>     }</pre>

<pre><span class="lnum">  14:</span> }</pre>

This is part of the 31 Days of Refactoring series. For a full list of Refactorings please see the original introductory post.

← Refactoring Day 17 : Extract Superclass
Refactoring Day 19 : Extract Factory Class →