On September 3, 1967, Sweden made a switch from “left-hand traffic” system to “right-hand traffic” system. Sweden relied primarily on American made cars with left-side drive. Further, other Scandinavian countries (Norway and Finland) used right-side driving. These mismatches led to accidents. Hence Sweden decided to move to “right-hand side driving”.
In software terms, you can consider this change in driving directions as refactoring – a structural change for improving quality characteristics. The change was done for the sake of consistency and for safety. Such a refactoring is an “architecture refactoring” because it is a major change that involves buy-in from relevant stakeholders, careful planning, and flawless execution.
Agile methods have given central focus to (code) refactoring. Other kinds of refactoring such as design and architecture refactoring are in fact more important than code refactoring. This statement may be controversial, so let me elaborate.
The classic description of code refactoring comes from Martin Fowler – it is “a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behaviour”. ‘Bad smells’ in code are candidates for refactoring. To apply refactoring in practice, we can adopt Robert C. Martin’s approach – “The Boy Scouts of America have a simple rule that we can apply to our profession: Leave the campground cleaner than you found it. If we all checked-in our code cleaner than we checked it out, the code simply could not rot”.
Code refactoring is a key software engineering practice and it is important to practice is regularly. An analogy is from writing – keep polishing the draft to evolve it to a gem.
“Given the success of code refactoring, it’s surprising that architectural refactoring hasn’t taken off yet.” – Olaf Zimmermann
However, no amount of code-level improvements can replace huge benefits that can derive from making major structural clean-up or changes. Existing code may have the GUI and application-specific code all mixed together, and the refactoring may be to cleanly separate them. The software may have accumulated references to unnecessary dependencies to third-party libraries that we can get rid of now. Or we may want to move from Service Oriented Architecture (SOA) to Microservices-based style. Paraphrasing George Fairbanks, such sweeping architectural changes can be referred to as architecture refactoring. When we perform such changes, the risk of breaking the working software is very high, but the benefits are also significantly high (which makes it worthwhile to take the risk).
“All repairs tend to destroy structure, to increase the entropy and disorder of a system. Less and less effort is spent on fixing original design flaws; more and more is spent on fixing flaws introduced by earlier fixes. As time passes, the system becomes less and less well-ordered. Sooner or later the fixing ceases to gain any ground. Each forward step is matched by a backward one. Although in principle usable forever, the system has worn out as a base for progress.” – Fred Brooks (in ‘Mythical Man Month’)
Architecture refactoring is inevitable for any long-lived software. Consider the Windows OS for example. Over the past 25+ years, Windows code base has grown to more than 50 Million LOC. Hence, it is completely understandable that its structure deteriorates over time. Refactoring was performed on its kernel from “Windows Vista” to “Windows 7” to address “layering violations” and “improve dependency structures”.
Periodic refactoring is also absolutely necessary in any long-lived software. For example, as Benjamin Peterson observes in case of of PyPy project, “it was originally envisioned that the C backend for the translator would be able to work off the high-level flow graphs! It took several iterations for the current multi-phase translation process to be born.”
However, performing architecture refactoring is a risky and expensive process, and hence we need all the help and guidance that we can get. There are many articles, research papers, blog posts, tutorials, and book chapters on architecture refactoring, but they are certainly not enough. As George Fairbanks rightly observes, “… little published guidance exists, architectural refactoring is generally performed ad hoc”.
“From my viewpoint, we have just started to understand and apply refactorings in a more holistic context. As the old saying goes, we have just seen the tip of the iceberg. Architecture refactorings will guide architects to identify potential problems in a software architecture and also provide them with refactorings to solve those issues.” – Michael Stal
When I analyzed existing literature on architecture smells and refactoring, I could identify a few major gaps:
- A cohesive view of architectural smells and refactoring is missing from existing smell catalogs.
- Architecture refactoring is typically performed manually, without adequate tool support.
- Though there are numerous case studies on architecture smells and refactoring, there is a clear lack of empirical studies on architectural smells and refactoring.
I sincerely hope that software engineering community starts to focus more on architecture refactoring given the tremendous benefits it can bring to software projects. If you are a researcher, tool developer, or architect, you can contribute by addressing these gaps.