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> </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> </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> </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> </pre>
<pre><span class="lnum"> 10:</span> Motor.Cook(food);</pre>
<pre><span class="lnum"> 11:</span> </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.
