In “Refactoring, Improving the Design of Existing Code” by Martin Fowler, he presents the Extract Method refactoring. It is one of the best refactorings out there. It’s one of the most common ones that I use.
Here’s a video walkthrough of the Extract Method refactoring and its benefits:
Hey, what’s up everybody, it’s Andy from cleanswifter.com, and I’m back this week to actually continue our series on reading “Refactoring, Improving the Design of Existing Code” by Martin Fowler. This week for the first time, we’re going to look at an actual refactoring in code. The refactoring we’re going to look at is called “Extract Method.” Extract Method is actually a really easy refactoring, it’s often supported by IDEs and the benefit of it is that it increases the opportunity for code reuse, you’ll have less duplication of your code, it enables smaller units of code, so it helps you get rid of those really long methods. And it also reduces the semantic distance between the method name and method purpose. I really like that wording that Fowler actually used in the book. That means your method names will be very clear and close to what the method actually does. As a result, for that to happen, your method needs to be succinct and cohesive. Extract method refactoring enables this. Let’s take a look at it.
Here’s a class,
AccountViewController that subclasses
UIViewController. Right here in
viewDidLoad() is some simple code that creates two
UILabels. Three properties are set on each label: the text color, the text alignment, and the number of lines. There are actually two different labels on which these properties are being set. But what’s in common between these two pieces of code, is that, the three properties are being set on the label are exactly the same. This is a prime opportunity to leverage the Extract Method refactoring. For Extract Method, all we’re going to do is create a new method called
setUpLabel. In there, I’ll add a parameter that is the label to be set, and on that label, I’ll take this code, remove it from
viewDidLoad() and add it to this new method that we’re extracting, and then down in
viewDidLoad(), call the new method by providing the label. Down where the second label is setup, I can also then delete this code and call that same method with the
addressLabel. Now you can see we’ve removed the redundant code that is setting up the label, and now we have a dedicated method that is named very clearly for what it does: sets up a label. The redundant code for
addressLabel has also been consolidated.
Let’s make the example a little more complicated. In this example we see the similar three lines of code setting up the label that configure the text color, the text alignment, and the number of lines. To make it a little more complicated, we’re actually going to set the text on the two labels as well.
nameLabel will be set to “Andy” and
addressLabel will be set to “Philadelphia.” Now we want to perform a refactoring that removes redundancy while also preserving the ability to set the test on the labels. We’ll start off in the same way as before, creating the new method
setUpLabel. Move forward with the refactoring to get to the same point we were at in the last example. Now that a baseline for
setUpLabel is extracted, we need to update it to be able to accept a
String such that the text on the label may be set, and the redundant use of temporary variables in
viewDidLoad() can be removed. Add a parameter to
setUpLabel of type
text. Set the text on the
text. Update the method call to
viewDidLoad to actually pass in the text to be set. Do the same thing for
addressLabel. At this point, we’ve removed redundancy and consolidated the code which includes setting the label’s text based on a provided parameter. There’s one more level of complication that we can add while leveraging the Extract Method refactoring.
Increasing the complexity of the example towards something even more real-life is to add properties on the view controller for each label so the values that are created are stored. After
setUpLabel is called, we’re now storing the label in the property on the class. To further reduce the redundant code, I’m going to extract the label creation into
setUpLabel. That will cause me to return the created label so that it can be set on the property. The goal of what I want to do here, is delete the creation of the
viewDidLoad() and move it to
setUpLabel(). I will no longer need to pass the created label in to
setUpLabel(). Instead, I will create a new
UILabel each time
setUpLabel is called. Then using that new label, set it’s properties, and return it. Now you can see the final result of the refactoring where all the redundant code has been consolidated into one place, a method dedicated to setting up labels.
viewDidLoad() now reads very clearly.
You just saw an example of the Extract Method refactoring. Just to recap it’s benefits: it increases the opportunity for code reuse by reducing duplication, it enables smaller pieces of code (as you saw
setUpLabel become small). And finally, decreases the semantic distance between the method name and method purpose – which means you can create a nice small method with a nice clear name that reflects what the method does.
I hope you liked this screencast on the Extract Method refactoring from “Refactoring, Improving the Design of Existing Code” by Martin Fowler.