The refactoring vs development scale
In many conversations with developers I hear them complain about the bad state of their code and how difficult it is to deliver new functionality. Often we’re looking for improvements, but it often happens that, when I make a suggestion for a small refactoring, their response is something like: “I can’t do this right now, because they give me no time for that. My deadlines are very tight.” That’s a sad conclusion, because it makes it impossible to get ever out of this situation. I’m also convinced that improvements are still possible, and that they even deliver extra time. Wouldn’t it be nice to get your software delivered in time, and also be able to clean up the mess? This is definitely possible.
The improvement problem
When talking about improving the software design or architecture, I often get the feeling that people implicitly treat each improvement as a a thing that must be done either completely or not at all. Improvements are so big that you need separate budget and management consent before you can to start working on it. I think that is a misconception.
Let’s see what happens when such a request is made by a developer. Management is thinking in business terms like cost, risk and yield. So first, they will be asking questions like these:
- How much will it cost? (And they know you’re going over budget every time, so they increase that number by 2.5 or so.)
- What will it deliver? (So you have to make a clear estimate how many hours it will save on development and maintenance. This is almost impossible for something intangible like this.)
They will also weigh that up against the fact that, during the time you’re working on the improvement, you’re not delivering value for the business. And there are always business opportunities. Especially the latter fact tells management that some improvements might be useful, but only if they cost little time.
Now we’re talking about business and management, perhaps we should think some more about their side of the coin. For any company that has a software department, that department is there only because it adds value to the company. Therefore, adding business value is crucial for any software department and recursively for any developer working within such a department. Or put it differently: the software department exists to provide its services to the business, and failing to do so threatens the department’s right to exist.
Weigh that against any plan that implies the department to go largely ‘out of business’ for a few months, and you can imagine that any manager will be (and should be) very hesitant to such a proposal.
A better approach
What then? Should we just continue to muddle and apply fix to fix instead of solving the underlying problems? I think not. Perhaps we should first fix the problem with our mindset: implementing large improvements in this way is risky, and especially in a tangled code base you don’t want to introduce risks. A much better approach is to apply improvements while reduce risks instead. How would you do this?
First of all, develop a general idea where the code should be going. This is not a big document, but just an idea or concept. The concept should be clear, but not all details are needed. You treat this idea as a vision that you work towards. It is your ‘dot on the horizon’. A concept can be to use a specific design pattern, or to separate off functionality into packages. It can also be to introduce some abstraction.
Now, once you have this concept, you get an idea which code needs to be changed and how. While in your daily work, you’ll come across places in the code that need to be changed. Now, based on your conceptual idea, you can take the chance and improve on the design one step at a time. Each decision you make should be in the direction of your concept. You’re not changing to make it look nice, but you’re changing it with a clear goal in mind. Do remember however to make small changes.
Advantages of taking small steps
In my experience, this will yield some big advantages:
- Refactorings are kept small and hence carry little risk. Even more, you needed to work on that code anyway, so it needs to be tested anyway.
- By doing a refactoring first, you make it much easier to add the feature. It may turn out that the refactoring even saves time because the feature could be implemented so quickly.
- If you are working towards the right concepts, you’ll quickly experience that stability improves. New features will have fewer defects, and you can add features in less time.
- You’ll also see that the right concepts introduce additional flexibility. This is very important for the business since you can deliver much more added value with less effort.
It may happen that you overlooked something and did not choose the right concepts exactly. Since you’re making changes towards these ideas, you’ll run into difficulties. But since you make small changes, you can spot them early on and work out a better direction instead. This means that you make improvements, but on a small scale during daily work.
Extract a function so you can reuse it. Split classes so you can combine them in new ways. Add unit tests for that piece of code that fails often. Would you need management consent for that? You’re just doing your job, even in a better way than before. If that would need management consent, then you would also need consent to do your regular work. That would be rather counterproductive.
Refactoring is a scale
This article started with the idea of people of doing large improvements instead of adding functionality. I showed that this needs not be the case, many improvements can better be done in small steps. But how small would those steps be? At least small enough to make it safe to do it. You can also add multiple small improvements when implementing a feature, thus working faster towards your vision.
The amount of refactoring you do can be seen as a scale: depending on the context, you can choose anywhere between 100% refactoring and 100% new features. As clear as it is that 0% refactoring is not going to work long term, it is also clear that 100% refactoring is a waste of time. But you always need to do some refactoring when adding features, otherwise the code rots under your hands.
How much refactoring is enough? This is a trade-off between short term and long term added value, and it depends on the business demands. After all, you’re hired to make the business more profitable.