I recently became aware of a great technique for beating procrastination called the “2-minute rule”. It works like this: if you see something that needs to be done, and it will take you less than 2 minutes to do it, go ahead and do it, don’t put it off until later. It helps to get you motivated by getting you started, and helps to stop the habit of putting things off. After learning about this technique and implementing it in my own life, I found that I was more productive, less overwhelmed about my to-do list, and most things I put off took less time than I thought. The biggest change, however, is how many more things I got done. By doing small two minute tasks throughout the day, I could get large amounts of tasks completed and it never felt overwhelming.
Interestingly enough, this “2-minute rule” can also help us create better code. In the apprenticeship program here at Greater Sum, one of the videos we watch is “Practical Refactoring” by Woody Zuil and Llewellyn Falco. One of the key aspects they talk about in the video is that we always need to be 2 minutes from checking in our code. Don’t make lengthy complicated changes. Don’t try to redesign everything in one go. Making small incremental changes will get us to better code faster than rewriting everything. It also helps if we are working on one project and need to suddenly be pulled away to work on something else. You don’t want to be knee deep in implementing a code overhaul. You want to be 2 minutes away from a stopping point and be able to revisit it later.
How do we implement this technique when dealing with messy and difficult to read legacy code? First, I want to emphasize that we must have tests around any code that we are changing. If we are refactoring code without tests, we are flying blind. Tests help us to be sure that, when we make changes to the structure of our code, we are not changing any of the functionality.
Tests help us to be sure that, when we make changes to the structure of our code, we are not changing any of the functionality.
Approval tests are great for this kind of testing. Approval tests can help us establish what the code is doing and then, make sure that it keeps doing that while we make changes. After we have 100% test coverage, we focus on the three simple rules: remove clutter, remove complexity, and remove cleverness. With these three strategies, we can take the overwhelming task of working with unruly code and create small steps that require almost no brain power at all. Because we are breaking things down into small increments, the task at hand becomes less staggering and we can get more work done. Sound familiar?
Let’s start with the first task, removing clutter. What is clutter in your code? According to Woody and Llewellyn, clutter includes comments, dead code, unformatted code, and unnecessary code. Llewellyn recalls an experience where he deleted 47 thousand lines of code in one week just by removing clutter. This created an enormous impact on his workload going forward. Originally the code base was 80 thousand lines of code. When we are trying to read and understand a piece of legacy code with 47K lines of clutter, it’s going to take us that much longer to figure out what is clutter and what is really working code. If we can eliminate this clutter, the result is cleaner code that is easier to read and understand. (Read our blog post on comments to better understand why we think comments are unnecessary clutter in your code)
The second task at hand is to remove complexity. Some examples of complexity in our code include bad names, long methods, deep conditionals, magic numbers, improper variable scoping, missing encapsulation, and obscure code blocks. When we are removing complexity in our code, it’s important to remember we are not trying to “understand the code”. We are making small changes. Trying to understand the code is ineffective when you’re refactoring.
it’s important to remember we are not trying to “understand the code”. We are making small changes. Trying to understand the code is ineffective when you’re refactoring.
It takes too much time. if you make these small changes, eventually you’ll get to a point where you can just read it, and you will understand it much more easily.
The last step is to remove cleverness. Sometimes we think cleverness is a good thing. After all, a three line solution is better than a 15 line solution, right? Often the problem with this type of thinking is that if your three line solution is so clever that it’s impossible for the next developer to tell what is going on, (or worse, if you have to write a comment to explain how it works) then it is not well-written code. Clean code is easy to read and understand. As developers, we spend a lot of time reading and trying to understand code. We should write code that is easy to read and understand and cleverness undermines that, so removing cleverness is important. Some examples of cleverness in our code might be cryptic code, abbreviated code, or hijacking a method.
After we’ve completed all three of these steps, our code should be in a much better state than when we found it. It will be much easier to understand and hopefully easier to make changes to. I hope you can find some value in this technique as I have. If you’d like to practice some of these refactoring techniques check out the links I’ve listed to some coding Katas. Have fun and happy coding!