Refactoring. Some developers dread it, others live by it. If you’re a beginner developer and have never heard the term before, Refactoring in the context of programming is the process of restructuring the existing code of an application without affecting any actual behaviour.
I consider it to be the equivalent of doing regular check-ups on your vehicle. Similar to a car, you need to worry about your system’s internals and avoid neglect in order to prevent future headaches.
Why do we Refactor?
Theres some mixed feelings on refactoring. Some developers claim you should write your code right in the first place. Ha ha ha. The truth of the matter is that often our greatest learnings come after the code base is written. Unfortunate, I know, but understanding comes through experience, and while we are developing a new system, we quickly find out what works and doesnt work, or what should have been done differently.
I think its worth discussing here some key benefits I have personally experienced from refactoring. These are observations I’ve made from working for over 8 years in tech as a software engineer.
#1 – Maintain and Improve Clarity
The quality of your code base and pleasure that comes from working with it is largely a function of how easy it is to understand. Often in many companies, developers get pressurized to developing features in a sub-optimal way. To meet deadlines and achieve quick speed to market, we make small sacrifices and annotate them with notes like this:
//TODO - This is a temporary feature, revisit this project.
Improving clarity, but I would say it also includes general code cleanup including shorter functions, organizing class structures, removing redundant classes, migrating to a new JDK, etc.
#2 – Domain Enrichment
Other times, your team may make a sudden revelation in how to model a particular concept, and realize that we should modelling our system in a different context. These assessments are usually pretty rare and take an experienced developer to discover. Prioritizing these discoveries is essential to maintaining the O of the SOLID principles (in case you forgot the O in solid stands for Open Closed Principle).
By the way, if you’re interested in Domain Modeling and domain enrichment in general, you should check out my book review post on Domain Driven Design by Eric Evans.
#3 – Revisit Crippling Legacy Systems
Some systems are old and complicated. In fact, did you know that many banking systems core transactional systems are running on mainframes written in COBOL?
Unfortunately, sometimes we inherit legacy systems that are an actual mess. In order to add new features, or address existing bugs, it is impossible to begin working on a code base unless developing a solid understand of how it currently works.
Often these systems require quite a bit of refactoring when initially being pawned off. There’s usually a reason ownership is being transferred.
Because of this, my strategy when inheriting a system is to dive through the code and make notes on where certain areas can be improved. You’re going to be reading through it anyways trying to figure out how it works from the logic perspective, so you might as well knock out two birds with one stone and assess where some refactoring could be productive.
Afterwards, take comprehensive notes on where a factor is required and why it is useful. If you have time to address the problem right away, just do it right way. Otherwise, prioritize the changes and add them to your upcoming Sprints so they are addressed promptly.
#4 – Address Technical Debt
The concept of technical debt may be foreign to some. Its the idea that as developers, we sometimes make decisions that are sub-optimal from a technical perspective, but the only or best decision to make at the time for the business.
I don’t mean sub-optimal in the sense of using a Dictionary instead of a List, I’m mean taking a deliberate shortcut to move faster. These changes produce a shortcut that requires effort to fix at some point in the future. The time that is required to address these changes is called technical debt. Like all debt, it must be repayed, and it gets increasingly crippling as we acquire more.
In short, code quality tends to degrade over time, and business priorities or domain discoveries can cause model representations to become outdated. Either way, we need to devote time to Refactoring in order to ensure our codebase stays healthy and maintains to the SOLID principles.
Personally, I tend to prioritize refactoring towards the slow season of your company. Often I find managers are willing to dedicate resources to code improvement when they aren’t under the gun of deliverables.