Practice what you preach – a code refactor kata

Hello everyone,

 

Recently I came across an article on Michael Feathers’ blog entitled Testing Yourself – Growing Through Refactoring. The article reminded me of a kata that I had put together a while ago that includes various code refactors that I regularly use to prime my brain before I get started on my daily duties as a software developer. After reading Michael’s article, I felt inspired to share this kata with the community.

 

“What is a kata?” you may ask. Well, in karate a kata is an exercise where one repeats a form many, many times, making improvements in each iteration. In software development, the term is applied in the same sense.

 

This particular kata helps me practice various code refactors, as well as a few useful shortcuts in my IDE (Integrated Developer Environment). The starting point is a simple project called EmployeeDemo written in Objective-C, with an Employee class and an associated unit test suite, which can be downloaded from GitHub.

 

The idea behind the kata is I start off with the Employee class that exposes a single method, payAmount, and then proceed to refactor the Employee class so that adding a new employee type (a Developer in this instance), will not violate the Open / Closed principle, and enable me to add any additional employee types later without opening up the Employee class for modification again. The Open / Closed Principle forms part of the SOLID engineering principles described in my previous blog.

 

The employee types are defined according to an enum called EmployeeTypes, and initially contain three types: Engineer, Salesman, and Manager. Each employee type returns its own pay amount as per the associated unit tests.

 


I will transform the Employee class from


 

Employee before


To


 

Employee after

Notice how the ugly switch statement has disappeared from the Employee class in the latter image? This is what will make it possible to add the Developer type without opening up the Employee class again :)

 

I came across the various refactorings in Martin Fowler’s excellent book, Refactoring: Improving the Design of Existing Code. The code samples in his book are written in Java, but I have adapted them to Objective-C for my code kata. A version of this kata written in Swift will be made available soon.

 

As mentioned earlier, I have made the kata available for download on GitHub. The repository has two branches: Master is the vanilla implementation of the Employee class and its test suite, with the tests asserting the employee pay amounts are as expected. The second branch, Refactor-Kata, shows each refactor as a separate commit, each with passing unit tests. You should be able to follow the refacotrings by navigating through the individual commits on the Refactor-Kata branch.

 

What follows is an overview of each step along the refactor process.

Self Encapsulate Field

The first step is to apply the Self Encapsulate Field refactor to the type field. I am accessing the field directly in the original version of the Employee class, but the coupling to the field will become awkward when I want to introduce a separate class to handle the employee types. Getting and Setting methods are added for the field, and only those are used to access the field

 

Self-encapsulate field

Replace Type Code with State/Strategy

Next the Employee class is refactored by applying the Replace Type Code with State/Strategy. The EmployeeType class has been added as a State class that will handle the various employee type codes

 

Replace Type Code with State

 

Yes, another ugly switch statement has been introduced here, but as I will show later, there will be only one at the end, and it is only used at creation.

 

To clean up the Employee class, I next use the Factory Pattern to extract the creation of the EmployeeType derivates from the Employee class to the EmployeeType state class

 

EmployeeType Factory Pattern

 

Then I extract the payAmount logic from the Employee class to the EmployeeType state class

 

Extract payAmount - Employee

 

Extract payAmount - EmployeeType

Replace conditional with polymorphism

Now for the cool part – I get to use polymorphism :) This is the final refactor I have to do before adding the Developer type.

One by one, I comment out each leg of the switch statement in the payAmount method, which causes the tests to fail, until I override the payAmount method in the required EmployeeType derivative, and all that’s left in the payAmount method is a @throw statement. The payAmount method now uses polymorphic dispatch to determine the correct employee pay amount

 

Replace conditional with polymorphism

 

Replace conditional with polymorphism - Engineer

 

Replace conditional with polymorphism - Manager

 

Replace conditional with polymorphism - Salesman

 

Alright. Now I can do the Developer stuff. First, add the Developer type to the EmployeeTypes enum

 

Add Developer to EmployeeTypes

 

Add the test for the Developer’s pay amount

 

Add Developer test

 

Initially the new test won’t pass, but that’s fine – it’s called TDD (Test-Driven Development). We write a failing test first, then we write enough production code to make it pass.

 

To make the test pass, I need to add a new case to the EmployeeType’s factory method for the Developer type

 

Add Developer to factory

 

And add the new Developer class as a EmployeeType derivative, and override the payAmount method

 

Developer with payAmount override

 

And I’m done! All the tests pass, and I have achieved my goal of making the Employee class open for extension, but closed for modification.

 

I find this kata very useful to show how one could use polymorphism to replace an if…else or switch statement (otherwise known as a conditional), and fix an Open/Closed Principle violation.