On “Refactoring – Improving the Design of Existing Code”, Martin Fowler wrote “Code refactoring is the process of restructuring existing computer code without changing its external behavior.” . Along with the “recipes” for safe refactoring, the term code smells was introduced. Code smells refer to certain structures in code that present potential design and implementation problems, also called anti-patterns.
The idea is “if it stinks, change it”: when the anti-pattern is getting too much in the way, you should do something about it. “Getting too much in the way” is very opinion based. Is this method too long? Is this class doing too little? If you ask different people, you’ll probably get different answers.
When are we are over refactoring it or not doing enough? What are the consequences of both extremes? Most importantly, what impacts our decisions to when refactor and how much?
Too little means hammer another nail in the code and it’s done. It is the fastest and simplest thing to do, until it’s not. One of the ideas behind Waterfall software development was to get it right the first time, thus change would not be need. We all know how it turned out.
If you have been long enough in Software Development, you know everything is constantly changing. It is the reason behind Iterative approaches and at the core of every Agile methodology. We usually don’t get it right at first, because we are just humans. Even if we could, no one knows the future. Developing Software is to continuously try to hit a moving target.
Changing code is an unavoidable activity. Doing the least possible effort will result in increasing technical debt, unhealthy code base and ultimately a Legacy System : every little change is a headache, the odds of introducing new bugs tremendous. No one likes to work on a Legacy system. Productivity is close to none.
On the other extreme, we could rewrite the whole application every time we wanted to make a change. Just start all over again, from scratch. We developers would love that: always a greenfield project. It seems totally crazy, but it happened quite often. Remember Microsoft releasing a whole new Windows version every couple of years?
Rewriting the whole thing is a common practice, when too little was made to avoid a Legacy System. Too little refactoring resulted in too much refactoring, as technical debt didn’t disappear by itself.
Too much refactoring in smaller scale it is also very dangerous. Nothing is never perfect. Perfect is spelled PARALYSIS . A variable could always be renamed, some other pattern could be used… Hours, days, weeks, months pass by and nothing is completely finished, nothing is fully working.
The line between over refactoring and improving code is very blurry. It is very subjective and opinion based. To make matters worst, non Software Developers usually don’t understand the need to redo something. It is counter-intuitive: when a house is being built, a wall is not demolished to build another one in it’s place.
As much as we would love to refactor ad libitum, it is not feasible. It will end up creating friction with the management. Worst of all, they would be right.
How much is enough?
If you were hoping for a recipe on how much refactoring is enough, I have bad news: I don’t know. Instead let’s look at what influences our decision on wether to refactor and how much.
Imagine a scale with two plates. More weight on the left means less refactoring, down to none at all. More weight on the right means more refactoring, on bigger extent, up to rewriting the whole thing.
On our everyday, we mentally place weights on those plates. Some weights can go on either sides. Some weights can change their relative weight to others over time and on different situations. The scale will determine how much refactoring is enough.
As explain before, code smells are anti-patterns in the code. These anti-pattens cause pain understanding and changing code. Code smells can only go on the right. Its weight can change with the area you are working on and will continuously increase over time, if nothing is done to prevent it. The weight can become so heavy, it will push the scale all the way up to “rewrite the whole thing”.
Yeah, you with your knowledge! You, as developer, have specific factors that can weight considerably on both sides of the scale:
- Your knowledge of the code base – the more you know the codebase, the more you are confident to change it. You will refactor proportionately to your knowledge. Knowledge of the codebase is about knowing how the application works, understand its design and implementation decisions.
- Your business logic knowledge – Business logic is completely different from code base knowledge. A product manager has profound business knowledge, but usually no understanding of the codebase. You might know a lot about the codebase, but not understand the reasons behind certain implementations. The more you know about business logic, the more you will refactor.
- Your technical knowledge – I have been working in Java for 20 years now. Every time I start a new job, even if all codebase is in Java, I have no knowledge of the business logic nor of the codebase. Having more technical expertise makes me confident to refactor more.
The scope of what your team has control over. If your team owns the codebase, you can even rewrite it all. Outside of your team ownership it’s a different story. On service-based architectures, for example, the contract between the different services are hard to change, specially if owned by different teams. Sometimes it is no worth refactor, because the smell is bigger than the team scope and little can be done about it.
Team and company culture. To achieve objectives you have to be a team player. You are being payed to do a job and the results need to justify the investment.
Refactoring is all about taking risks and making investments. It has immediate negative impact on productivity. If something goes wrong, it is easy to know what caused it. On the other hand, the return of investment takes much longer and is very hard to measure.
The amount of refactoring will be directly linked to how much the company and team is willing to risk and invest.
You might not have much power over how much you can refactor, but you will always have some. Put the weights on the scale, look to where it points and use your judgment. Too much or too little is never good.
My advise to you is Refactor as if there is no tomorrow. Don’t think on what the future can bring, most likely you will get it wrong. Don’t save for tomorrow what you can refactor today, or you will payed it with interests.
 “Refactoring: Improving the design of existing code”, Martin Fowler, 1999, Addison Wesley
 “Nothing prevails but perfection,” may be spelled PARALYSIS. – Winston Churchill quote
 “Big ball of mud”, Brian Foote and Joseph Yoder