VIDEO: Principles of Refactoring

Chapter 2 of “Refactoring, Improving the Design of Existing Code” by Martin Fowler, titled “Principles of Refactoring,” continues to set the stage for the rest of the “recipe book” of refactorings by explaining some of the basics of refactoring, including:

  1. Why you should refactor your code
  2. When you should refactor your code, and
  3. Problems that could arise when refactoring your code

Here’s my perspective on the chapter:

Video Transcription:

Hey what’s up everybody, I’m Andy, the Clean Swifter. Welcome back to the second video episode from my blog, where I share tips, tricks, articles, and commentary on how to write cleaner Swift code. In this video, I’ll be providing some commentary on chapter two of Martin Fowler’s book, “Refactoring, Improving the design of existing code.” The second chapter is titled “Principles of Refactoring.” You can buy the book through my Amazon affiliate link in the description for this video. In this chapter, Fowler covers three important topics, first: why you should refactor your code. Second, when you should refactor your code. And third, potential problems to be aware of when refactoring your code.

Before we jump in, let’s just recap as to the definition of refactoring. Paraphrasing how Fowler puts it at the beginning of this chapter, refactoring is the process of improving code while making no observable changes in behavior. In other words, improving your code, while not changing how it behaves to the end user. You can actually use the word refactor as both a noun and a verb, for example “That refactoring really improved my design” or “let’s go refactor that method to clean it up.”

Now that we’re clear on the definition, let’s dig into the first topic, why you should refactor your code. I know to some people this may be kind of obvious, but let’s talk about it just to be clear. You should refactor your code because it helps you improve its design. By helping improve its design, it will become easier to understand, bugs will be easier to find, and you’ll ultimately be able to add functionality faster. All of these reasons relate to eachother. Messy code will have more bugs. Additionally, because it’s messy, you’ll spend more time trying to find and fix the bugs, and thus spend less time adding end user features. If code is hard to understand, you’ll be slow to enhance it, and when you do, chances are you’ll be adding bugs because you don’t know the true impact of your change. Refactoring aims to solve each of these problems.

Let’s move on to the second important topic, when you should refactor your code. Fowler sums it up simply as “the rule of three.” The first time you do something, you just do it. The second time you do something similuar, you duplicate the first time while wincing. The third time you do something similar, you refactor and remove all the duplication. Think of it as: three strikes and you refactor. I think this is a nice metaphor, but I don’t think I’d live with the first duplication. Any duplication smells to me, I’d probably refactor at that point. When else might you refactor, well any other time that you’re modifying code such as when you’re adding funcitonality, or fixing a bug. Both of those are great times when you can get in and improve the internal structure of your code, while also adding or fixing something in the meantime. Fowler goes on to advocate refactoring during code review. I’m not such a big fan of that, and I think this is another area where the book is showing its age. Today, in a world of github pull requests, code reviews are very common, and I put it on the original author to ensure that the code is in good shape prior creating a pull request for it to be merged into the main code base. In my software collaboration, I’ll usually have worked out the design ahead of time so there aren’t any surprises or really opportunity for further improvement when code review happens.

Finally, the third important topic in the chapter 2 of Fowler’s “Refactoring, Improving the design of existing code” is recognition of some problems that can occur when refactoring. One common thing I run into all the time is a constraint put onto my apps by the backend API. Fowler makes the comparison with a “database” but I’ll move the analogy into something a little more real for apps. As app developers, we need a really solid layer of abstraction between our apps and the backends that you may use, and in my case this is commonly remote web APIs. Otherwise, any refactoring you encounter is going to be constrained by that API and potentially limit what you can do. Similarly, another thing you can run into is if the code you are refactoring is part of a library consumed by others, like a cocoapod, you need to be really careful when performing refactorings that will change that public interface. Doing so will impact any consumers of your API. You need a good migration strategy for them. And another case where you simply shouldn’t refactor, is if the code starts off in a bad or buggy state. If this is your starting point, you should correct any errors first, and then once you have passing tests that cover the error cases, move on to your refactoring.

Those were my big takeaways from chapter two, “principles of refactoring.” Depending on where you are with your refactoring adoption, over time and with practice, it will soon become second nature to constantly be looking for places to improve the structure of your code while ensuring that how it behaves doesn’t change. You’ll even start to integrating refactorings into your thought process while designing your code, before you even write a single line.

Looking ahead to chapter 3, it’s title is “bad smells in code.” Fowler puts some definition around things to look for in code that should be refactored. I hope you enjoyed this video from until next time, happy cleaning.

“Refactoring, Improving the Design of Existing Code” Chapter 1 Highlights

I’m really excited to announce the online book club! Participate by reading, or just follow along as I go through the best books in programming, chapter by chapter, week by week. Each Monday, I’ll post a video recap of the latest chapter. The video will include both my personal commentary, as well as live coding examples. For the first book, I’ll be re-reading “Refactoring, Improving the Design of Existing Code” by Martin Fowler. Here’s episode one!

Video Transcription:

Hey, what’s up everybody, I’m Andy, the Clean Swifter. If you haven’t seen it yet, check out my blog at where I share tips, tricks, articles, and commentary on how to write cleaner Swift code.

Today I’m really excited to kick something new for, videos! Specifically, I’m starting an online book club with you, where each week, I’ll read a chapter in a book, and then post a video demonstrating important topics from the chapter. If you want to read along with me, great, if not, no worries. We can still have a great conversation about the book and the topics regardless.

For the first book, I’m going to be covering “Refactoring, Improving the Design of Existing Code” by Martin Fowler. You can buy it on Amazon, just use the link in the description for this video. I actually read this book years ago in a different world when I was writing server side Java code for a giant web application. I love this book, aside from it being a kind of recipe book for refactorings, it comes with this really cool ribbon that you can use as a bookmark. I have no idea why more books don’t have these ribbons.

I just finished reading Chapter 1, and like most programming books, it doesn’t really teach anything yet, as much as it sets the stage for the rest of the book. One thing I want to get out the way right off the bat is recognition that this book is OLD! It was published in 1999, and now going back to re-read it, certain things in the book are showing their age, not including the technical information. For example, in Chapter 1 Fowler sets up a problem domain where you are building a system for use in a movie rental store. I don’t about you, but I can’t even remember the last time I was in an actual movie rental store. Additionally, at one point, he also mentions “limitations of Java 1.1.” Umm, I think Java is on version 8 now. Regardless, this book is about the patterns and recipes, not the technology used for implementation. Keep that in mind as we go through the book because what’s taught in it, absolutely applies to the Swift code you are writing for your iOS apps.

Another thing that Fowler comes right out and recognizes in chapter 1, is the difficulty in choosing a sample project to use for a refactoring book. Often, refactoring is most important in large, complex systems. Unfortunately, using a project of such magnitude in a book isn’t feasible. You would spend the majority of the time just describing the project itself. On the other end of the spectrum, with simplistic code bases, refactoring seems trivial and pointless. One thing that Fowler asks the reader to keep in mind, and I’m going to ask you to as well, is to imagine the examples we go through as part of a larger and more complicated system.

Throughout chapter one, Fowler goes through a whirlwind tour of several refactorings to improve an initial structure of the video rental system. Since the book will later go through these refactorings in detail, I’m don’t think it’s worth mentioning at this point.

As Fowler sets up the rest of the book, four important points about software design stuck with me: what Fowler calls: “the first step in refactoring,” the need to rename variables and methods as refactoring progresses, how refactoring can actually increase the size of your code base, and finally the need to force yourself not to abort a refactoring because you are prematurely optimizing your code.

Diving into the what Fowler calls “the first step in refactoring.” If you’ve been following me at you could probably guess what this is: writing tests. Just like anytime that you are setting out to write or change code, the first thing you need to do is write a test. This follows two categories: tests for the existing code, and writing a test for the expected result of the change. Now when refactoring, you often aren’t changing behavior, so an existing test base can be sufficient, as long as you’re confident that it’s comprehensive. And then, as you move forward with each small change in your refactoring, absolutely run your test suite with each code change to make sure you didn’t break anything, as well as figure out if there’s additional tests you can write for further verification.

The second thing that Fowler mentions in chapter 1 that resonated with me, was the need to rename variables and methods as you move forward with your refactoring. Specifically, he says, “Code that communictes its purpose is very important.” I absolutely agree with this. Please don’t use a variable named “i” – it gives no indication what it does. Additionally, name your tests well. My proposed format for test names captures: what is being tested, what is the expected outcome, and under what conditions. For example, “testViewDidLoad_SetsNameLabel_WhenNameProvided.” And just as good clean code communicates its purpose well, good clean tests do the same. Tests serve as functional documentation.

The third topic Fowler identifies in chapter 1 that I like is how one of his refactorings actually increased the number of lines of code in the project. This is totally valid, and something I’ve seen time and time again. Sometimes you start out with a 1000 line UIViewController, and after a number of refactorings, you get that view controller down to 250 lines of code, but created an additional 1000 new lines in addition to the other 750 lines that also got moved. This is a good thing. The goal isn’t to write less code, it’s to write clean code. I’ve seen single lines of Perl code that do more things than you can imagine, but it’s entirely complicated and difficult to mentally parse.

Finally, the fourth thing that jumps out at me as chapter 1 sets the stage for the rest of the book, is recognition of the urge to prematurely optimize your code. In one example, Fowler refactors a method with a single loop. The new implementation results with two additional while loops. As important as it is to recognize the POTENTIAL performance impact this could have, it’s also just as important to understand that it is only a POTENTIAL performance impact, and that when refactoring, don’t necessarily let a potential performance impact stop you from the refactoring. If anything, move forward with the incremental step towards code cleanliness while following it up with actual performance testing to quanitify its impact on speed.

In closing chapter 1, Fowler recaps that refactoring leads to “better distributed responsibilities and easier to maintain code.” Me, I just call this, “clean code.” One other thing I wanted to call out, a lot of these refactorings are done in light of object oriented design. Keep in mind, these all apply to your Swift iOS code. Just because Swift can support functional language paradigms, doesn’t mean that that’s the only way to write it. These are are all just tools in our toolbox to writing cleaner swift.

Looking ahead to Chapter 2, it’s title is “Principles of Refactoring” and moves towards establishing some common language and rationale for refactoring. I hope you enjoyed this video, the VERY first one from Until next time, happy cleaning.