avatarNicklas Millard

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

4029

Abstract

       </div>
        </div>
      </a>
    </div><h2 id="f0a0">1 Improving readability by turning IFs into maps</h2><p id="38c8">It usually takes a few iterations to refactor a messy class. First, we’re improving the readability. It’s difficult to achieve a highly maintainable and flexible class if it’s unreadable.</p><p id="be3b">Entirely getting rid of <code>if-else</code> is a great first step.</p><figure id="c318"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*jsFYU2idfwg3WEoCTMHLZQ.png"><figcaption>Refactored into an incredibly readable class</figcaption></figure><p id="77e0">The <code>ProcessOrder(Order)</code> method just got immensely easier to read, and is now doing only one, single job.</p><p id="856e">If you’re not familiar with <code>Action&lt;T&gt;</code>, it’s just a lambda taking an argument, or, anonymous function if you’d like.</p><p id="4ce1">We’ve taken the nasty <code>if-else</code> and made it into a dictionary instead.</p><p id="055c">Also, notice the added benefit in regards to the property <code>OrderTypes</code>. If a new order type comes along, we don’t need to manually add it in two places.</p><h2 id="da17">2 Creating separate classes improves maintainability</h2><p id="1662">We could easily stop at this point and call it a day. You’ve already made the class so much simpler. But you haven’t exactly reached ‘stupid simple’ yet. That’s our end goal.</p><p id="94fb">Currently, with our first refactoring iteration, our class still knows too much about how each type is processed.</p><p id="bf13">In this case, achieving maintainability is about refactoring the action implementations out of the processor class and into their own classes.</p><figure id="5c7a"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*nG6kXkq0TlB3nogtj_XHnQ.png"><figcaption>How the actions are split into separate classes</figcaption></figure><p id="4e3a">In code, this looks like the following — notice the new <code>IOrderProcessing</code> interface. Each lambda action from the dictionary is now its own, separate class.</p><figure id="7aa1"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*QjSIbjY96xQOqI6FtZb3ZA.png"><figcaption>Interface and separate processing classes</figcaption></figure><p id="0994">This incredibly simple refactoring allows us to granularly test each processing. We no longer need to ‘new’ up the whole <code>OrderProcessor</code> just to see if e.g. a virtual order is processed correctly.</p><p id="62d9">Your order processor is starting to look really stupid. Just how we like it.</p><figure id="22f8"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*a2cAvH5s5AKs9akBVJ329g.png"><figcaption>Refactoring to a highly maintainable class</figcaption></figure><h2 id="916c">3 One final refactoring for maximum flexibility</h2><p id="8fbd">Sure, unit testing is easy at this point. But, you’d still be required to test the <code>ProcessOrder(Order)</code> method three times, just to make sure it’s working properly. Even worse, this is not obvious. You’d need to be aware of the inner workings to know this.</p><p id="7ec3">For every new order type, you’d need to test the same method with an additional case. This is surely a code smell.</p><p id="ddf0">Your last refactoring is going to make the processor class amazingly simple. You simply turn the dictionary instantiation into an explicit dependency.</p><figure id="d554"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*pu6mQtqWtjc9TO0F7yCysw.png"><figcaption>Refactoring to a very simple class</figcaption></figure><p id="43c7">So light. So easy. So simple to test.</p><p id="1b39">When your code suddenly becomes stupidly simple, you know you’ve hit the right level of abstraction. This is one of those times. Congrats.</p><h2 id="d288">Refactoring to more classes</h2><p id="45cf">Computer science majors may shriek in horror as each new class is added, calling out potential performance issues (which never manifests)

Options

.</p><p id="fa60">Well, there’s a trade-off to everything. Nicely composed code requires more components as opposed to an entangled, unreadable, lightning-fast mess. Pick your poison.</p><p id="9cbf">But, again, for good measure, I did a simple performance test. 1 million iterations of instantiating the non-refactored class vs the flexible class, calling the process order method for each order type.</p><figure id="47a0"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ZOAee-eKM6UuFmdA1qcmgg.png"><figcaption>Performance table of doing 1 million instantiations and method class</figcaption></figure><p id="402f">You decide yourself how terrible those numbers are.</p><div id="a386"><pre><span class="hljs-section">Resources for the curious -------------------------</span></pre></div><div id="25e8"><pre><span class="hljs-attribute">Making</span> Your C<span class="hljs-comment"># Code More Object Oriented by Zoran Horvat</span></pre></div><div id="578c"><pre><span class="hljs-built_in">Clean</span> <span class="hljs-built_in">Code</span> Principles in C# by Cory House</pre></div><div id="2176"><pre><span class="hljs-attribute">Code</span> Complete <span class="hljs-number">2</span> by Steve McConnell</pre></div><figure id="dd2d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*wwX3odMdAFlYWUCQ.png"><figcaption></figcaption></figure><p id="cc49"><b>Nicklas Millard</b> is a software development engineer in one of the fastest-growing banks, building mission-critical financial services infrastructure.</p><p id="7bfa">Previously, he was a Big4 Senior Tech Consultant developing software for commercial clients and government institutions.</p><blockquote id="71d7"><p><a href="https://www.youtube.com/channel/UCaUy83EAkVdXsZjF3xGSvMw">New YouTube Channel (@Nicklas Millard)</a></p></blockquote><blockquote id="4349"><p><i>Connect on <a href="https://www.linkedin.com/in/nicklasmillard/">LinkedIn</a></i></p></blockquote><figure id="6f7f"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*z1n_Sp6dgXbCYSIY.png"><figcaption></figcaption></figure><div id="3293" class="link-block"> <a href="https://readmedium.com/factory-pattern-without-switch-this-is-how-it-should-be-done-cd895e356f44"> <div> <div> <h2>Factory Pattern Without Switch, This Is How It Should Be Done</h2> <div><h3>My approach to creating easily extensible factory classes without logical statements such as switch and if-else</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*a1kITu1qyNi9sF19GFqCsA.png)"></div> </div> </div> </a> </div><div id="32e4" class="link-block"> <a href="https://readmedium.com/refactoring-from-trash-to-solid-74b10005ccd3"> <div> <div> <h2>Refactoring From Trash to SOLID</h2> <div><h3>Amp up your code quality, the easy way.</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*EsrElEhlwbNxiCdpRmiubg.png)"></div> </div> </div> </a> </div><div id="415e" class="link-block"> <a href="https://readmedium.com/5-ways-to-replace-if-else-statements-857c0ff19357"> <div> <div> <h2>Better Software Without If-Else</h2> <div><h3>5 Ways to Replace If-Else. Beginner to advanced examples</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*3Ju0VYbFi0w0rVYt9RT_vw.png)"></div> </div> </div> </a> </div></article></body>

REFACTORING MESSY CODE

Creating Highly Configurable Code in Three Simple Steps

Hard-coded, unconfigurable code is headache-inducing

It’s honestly not very difficult to write great, configurable classes. But, it might be if you’ve grown used to doing things in certain ways.

From my experience, the best way to turn an existing class into a configurable one is first to move logic into separate classes and then the moving hardcoded part into constructor or method arguments.

It’s that easy. Let me show you how.

But first, what’s so great about a configurable class?

Before you spend any time refactoring your existing classes into configurable ones, I’ll let you know why it’s so great.

A configurable class is damn easy to use. It’s extensible. It doesn’t do too much. It’s stupid simple, which is awesome.

The biggest selling point, it’s easy to test.

Meet the classes

For good measure, here’s a quick overview of the classes you’re dealing with.

You have an OrderProcessor class with a single method ProcessOrder(Order).

Next, there’s a base class Order and three subclasses VirtualOrder, ServiceOrder, ShippingOrder.

Understanding the Order classes is completely irrelevant. Don’t get distracted by thinking of how they’re implemented. If you really must know, they just have two properties, ‘Name’ and ‘Price’… Okay, let’s carry on.

You’ve implemented the order processor the following way.

Messy if-else based method

It took 1 minute to implement. It works. You’re happy. Your manager is happy. Your customer is happy.

But it’s a mess.

This could be a switch. But if that’s your first thought, you’re focusing on entirely irrelevant aspects of software development.

Let me show you how to make this better

Better is of course subjective. If you’re certain (you’re not) this class will never change (it will), this might be a great implementation (it’s not).

You and I are refactoring this hot mess into a sensible, configurable class — without much effort whatsoever.

We’ll make this class better regarding three internal software qualities.

Readability. Currently, this class’ method reads terribly. I got an easy fix up my sleeve for this.

Maintainability. If you need to modify the processing of a ‘ServiceOrder’, you’ll do so at a place surrounded by unrelated code. Also, if other developers are working on the same class, you probably get merge conflicts. Annoying and potentially introducing unexpected bugs.

Flexibility. Adding a new order? You’ll have to add an extra else-if. I’m sure you already know that’s bad, and a clear violation of Open/Closed.

1 Improving readability by turning IFs into maps

It usually takes a few iterations to refactor a messy class. First, we’re improving the readability. It’s difficult to achieve a highly maintainable and flexible class if it’s unreadable.

Entirely getting rid of if-else is a great first step.

Refactored into an incredibly readable class

The ProcessOrder(Order) method just got immensely easier to read, and is now doing only one, single job.

If you’re not familiar with Action<T>, it’s just a lambda taking an argument, or, anonymous function if you’d like.

We’ve taken the nasty if-else and made it into a dictionary instead.

Also, notice the added benefit in regards to the property OrderTypes. If a new order type comes along, we don’t need to manually add it in two places.

2 Creating separate classes improves maintainability

We could easily stop at this point and call it a day. You’ve already made the class so much simpler. But you haven’t exactly reached ‘stupid simple’ yet. That’s our end goal.

Currently, with our first refactoring iteration, our class still knows too much about how each type is processed.

In this case, achieving maintainability is about refactoring the action implementations out of the processor class and into their own classes.

How the actions are split into separate classes

In code, this looks like the following — notice the new IOrderProcessing interface. Each lambda action from the dictionary is now its own, separate class.

Interface and separate processing classes

This incredibly simple refactoring allows us to granularly test each processing. We no longer need to ‘new’ up the whole OrderProcessor just to see if e.g. a virtual order is processed correctly.

Your order processor is starting to look really stupid. Just how we like it.

Refactoring to a highly maintainable class

3 One final refactoring for maximum flexibility

Sure, unit testing is easy at this point. But, you’d still be required to test the ProcessOrder(Order) method three times, just to make sure it’s working properly. Even worse, this is not obvious. You’d need to be aware of the inner workings to know this.

For every new order type, you’d need to test the same method with an additional case. This is surely a code smell.

Your last refactoring is going to make the processor class amazingly simple. You simply turn the dictionary instantiation into an explicit dependency.

Refactoring to a very simple class

So light. So easy. So simple to test.

When your code suddenly becomes stupidly simple, you know you’ve hit the right level of abstraction. This is one of those times. Congrats.

Refactoring to more classes

Computer science majors may shriek in horror as each new class is added, calling out potential performance issues (which never manifests).

Well, there’s a trade-off to everything. Nicely composed code requires more components as opposed to an entangled, unreadable, lightning-fast mess. Pick your poison.

But, again, for good measure, I did a simple performance test. 1 million iterations of instantiating the non-refactored class vs the flexible class, calling the process order method for each order type.

Performance table of doing 1 million instantiations and method class

You decide yourself how terrible those numbers are.

Resources for the curious
-------------------------
Making Your C# Code More Object Oriented by Zoran Horvat
Clean Code Principles in C# by Cory House
Code Complete 2 by Steve McConnell

Nicklas Millard is a software development engineer in one of the fastest-growing banks, building mission-critical financial services infrastructure.

Previously, he was a Big4 Senior Tech Consultant developing software for commercial clients and government institutions.

New YouTube Channel (@Nicklas Millard)

Connect on LinkedIn

Technology
Software Development
Software Engineering
Programming
100daysofcode
Recommended from ReadMedium