Want to see the full-length video right now for free?
In this episode, Chris is joined by thoughtbot CTO Joe Ferris.
With the magic of live-coding, Joe demonstrates how a simple Extract Class refactoring can lead to a host of code improvements.
You can see the full changes in this commit commit to the Namely Connect repo.
Joe decides to extract a class when he notices that the Normalizer
class
refers to a payload
object repeatedly (and passes it among nearly all its
methods).
A common reaction to detecting this code smell is to extract a class to hold (and operate on) this data. This provides some noise reduction (since you no longer have to pass the data around) but also readability improvements and lower coupling.
Joe begins by creating a private class inside the Normalizer
class and moving
appropriate methods inside it. This is a good first step that can later be
promoted to a public class if desired.
Joe gets bitten by a classic Ruby gotcha: referencing an instance variable that
doesn't exist returns nil
. You can hear Joe discuss why returning nil
is
developer-hostile in another Weekly Iteration episode, Nil is Unfriendly.
After a series of small changes and fixes, Joe's test are green again.
Take note of how Joe works in small steps and constantly re-runs his tests. A good TDD workflow allows you to run tests quickly from your editor. For more on that, see Speedy Tests.
So far, the improvement from the extracted class is minimal. However, the
newly-extracted Payload
class makes it easy to make a few additional
improvements.
First, Joe moves the payload
data into instance state. This allows Joe to
remove the argument from many methods inside the new class, which provides the
promised noise-reduction and lower coupling.
While refactoring, it's a great idea to make small commits along the way. It's easy to do and can be extremely useful for restoring your code to a known-good state.
Payload
's instance data allows Joe to delete a whole host of parameters.
However, when attempting to remove it from the custom_fields
method, Joe
discovers that the parameter is poorly-named. While called payload
, it
actually can be one of several objects. Rather than living with this duplicity,
Joe renames the parameter on the spot. This is a nice example of constantly
tidying a codebase.
Joe continues to make small improvements in his new class: removing parameters, renaming methods, and a textbook Extract Temp to Query refactoring.
Before undertaking a refactoring, it can be hard to predict how much better the code will become. However, once the inital refactoring is complete the opportunity for additional cleanup often becomes apparent. Because of this phenomenon, it's a good idea to make any positive changes you can clearly see, since it may make several others obvious afterwards.