The beauty of refactoring
What is refactoring and why should you do it?
Please make me a cup of tea... (messy kitchen)
You know you need to refactor when your programmers struggle to fix bugs and deliver new functionality in what seems like a reasonable time.

Recently, I have been refactoring the software I developed to publish this blog, which led me to realise something: Refactoring brings many benefits and, if you don't do it, your applications will soon become "legacy" and will ultimately be retired or replaced.

Refactoring is the process of restructuring and rewriting an application's code, whilst not changing the application’s functionality, to make the application more secure, reliable, maintainable and performant.

The challenge is that refactoring is often a complex, time consuming and risk-laden task. Undertaking it can be an expensive exercise that, furthermore, brings an abrupt halt to the delivery of new functionality. And, finally, it can be difficult to define exactly what the benefits are.

Basically, refactoring is reviewing old code (logic) that already works, to rewrite it and retest it from scratch, without changing the functionality.

So what are the benefits? “Well, the application will be better.” The code will be better understood, easier to update, less bug-prone and likely more secure.

And how long will it take? “Well, …”

Now, that is a hard sell!

How do you know that you need to refactor?

You know you need to refactor when your programmers struggle to fix bugs and deliver new functionality in what seems like a reasonable time.

You may also notice that programmers respond to requests with heads down, sheepish looks and sighs. This can be a sign that they are grappling with the code. Remember, it is often their own code that needs refactoring. This can be rather embarrassing for them.

Who wrote this garbage??? Oh, wait… I did.

How to sell the need to refactor?

In order to sell the need for refactoring, you might consider the following benefits:

Security

In this new brave world of hyper-connectivity, basically all applications are increasingly vulnerable to attack, whether it is a customer-facing web app or the software that runs the windscreen wipers on your car.

Even if you are not in the habit of doing vulnerability testing to find and fix potential security exploits, all applications these days are built on libraries which are constantly being updated for known bugs and security flaws as they are discovered and fixed. In order to keep your applications secure, it is necessary to keep the libraries used up-to-date.

Whilst many libraries used in your application can be updated without breaking your applications, some include changes that require you to refactor your application to use the updated libraries.

Thus refactoring is often critical to maintaining security against known vulnerabilities that can easily be found and exploited in your applications.

BTW, vulnerability testing is a good idea! You should at least be using linting software to do static code analysis. I will write separately on vulnerability testing soon.

Reliability and maintainability

Programming is complex. Like writing a complicated essay, there are many ways to go about things. Finding the right way often takes time (often time that the programmer doesn’t have).

Things can be said in a thousand words, but it is arguably better for everybody if the same thing can be said in a few sentences.

Code is always written better the second time.

When code is well written, it is easy to reliably add functionality. When code is a mess, there is typically a lot of confusing redundant code, which encourages bugs, more redundant code and inconsistent behaviours. Refactoring is largely a process of rationalising and reducing code - reuse and reduction.

Smaller code-bases will give you more consistent behaviour and be much easier to leverage for the delivery of new functionality.

A key sign that we are in need of a refactor is when the programmer is struggling to fix an issue because the code is just not right.

Modern digital infrastructure

source: https://xkcd.com

Performance and productivity

Application performance has a massive impact on user experience. Consider your own experiences of waiting for applications to load. Even just a few seconds can be mightily annoying.

This waiting experience also has an enormous impact on programmer productivity. A lot of time and focus is typically lost waiting for applications to load, compile and run.

Even without targeting application performance in the process of refactoring, reducing code will likely result in reduced load, compile and application execution time. Targeting performance as an objective of refactoring will ensure that both user experience and programmer productivity are optimised.

Another side benefit can also be a reduction in infrastructure costs due to the reduction of storage, network and CPU utilisation!

Why does the code need refactoring

Why do programmers write code that needs refactoring, in the first place?

There are a number of reasons that you will always need to refactor. They include:

Evolving tools and techniques

Programmers are constantly learning new ways of doing things and trying them out to best deliver business outcomes. There is no alternative to this. Like the heart surgeon - there always has to be a first patient - otherwise we wouldn’t have heart surgeons!

And, invariably, their first attempt may not be their best!

More than most other industries, the software industry is evolving constantly at a phenomenal rate. There are constantly new and better tools and techniques - and to stay competitive you must embrace them. And yet each will all ultimately be superseded (some faster than others)!

So programmers must learn and evaluate new tools and techniques, decide which to try and apply them. Chances that they get everything right the first time are negligible. And even if they excel, the techniques will be outdated sooner rather than later.

Evolving requirements

“That’s a great solution! Can I also have that here too?” Well, yes, but it hasn’t been built to be reused. Do I copy it or will you then want to use it in many places - in which case I should make a reusable component?

What the programmer may do is copy the code into two places for now (hopefully with a comment explaining this) and refactor later to use a reusable component when it starts getting out of hand.

This is a simple example to demonstrate that the most reliable, maintainable, performant solution can vary as the requirements evolve. And requirements should evolve. The best software is agile - constantly responding to the discoveries made from using the last version.

So, to have a suitably reliable, maintainable and performant solution for a given version of an application, there will often be the need to refactor.

How to facilitate refactoring

Refactoring can be classified as “technical debt”, which includes other non-functional deliverables that are often left behind, such as test scripts and documentation.

The resolution of technical debt should be built into your delivery roadmap with importance equivalent to delivering new functionality. Depending on the nature of your projects, maybe everything 5th sprint should be dedicated to technical debt. For this sprint, refactoring will be prioritised alongside the other technical debt candidates.

If you have multiple platforms, refactoring can be staggered across the platforms so that some business functionality is still delivered every sprint. Various metrics can also be used to demonstrate the value delivered by the technical debt sprints.

Conclusion

The need to refactor is inevitable. If it isn’t done, the application will become a legacy that will ultimately be retired or replaced.

Refactoring should be built into your delivery roadmap as "technical debt".

The challenges include knowing what and when to refactor. Only those people intimate with the code can evaluate when refactoring is a valuable exercise, but there are telltale signs when it is likely required.

The best way to explain to interested stakeholders will typically be to use metrics - such as reported code smells / vulnerability, build-time and performance.