In my recent workshop on software architecture, I was discussing architecture refactoring. After the workshop, an architect made an important observation: “You have given many case studies and examples on architecture refactoring. But you clearly did not explain the difference between code refactoring and architecture refactoring. Developers are familiar with code refactoring, but architecture refactoring is a whole new ball game – so you should bring this out first”. And yes, I completely agree with his observation. With that, I am writing this article explaining how architecture refactoring is a totally different ballgame when compared to code refactoring.
Let us consider a real-world analogy in “refactoring” cities. If a road is accident prone because of sharp turns, poor lighting, etc, we can introduce barricades, speed bumps and warning signs, and also put more streetlights to improve the situation. In this case, we are performing micro-level structural improvements. The changes have localized impact and can be made with reasonably less effort; however, the benefits are also limited. On the other hand, if we were to build flyovers or underpasses to get rid of sharp turns altogether, such structural changes are harder to perform. Why? Building flyovers or underpasses require budget, getting necessary approvals, and planning. However, with the greater amount of risk and effort, the benefits are also substantial. Code refactoring is like making localized changes such as introducing a speed bump; architecture refactoring is like introducing a flyover.
Consider that a developer wants to add support for generating PDF report in addition to generating reports in plain text and HTML. When analyzing the code before adding the feature, she finds that code is duplicated for generating plain text and HTML reports. Instead of copying and pasting the code segments, she does the right thing: she removes the duplicate code segments and creates a class that abstracts the report generation functionality. With this refactoring in place, adding support for PDF reports becomes easier. Here the smell is duplicated code and the refactoring is abstracting the common code into a class.
When performing this refactoring to extract classes, the same developer found that there are different kinds of logging mechanisms used in the code base: log4j, java.util.logging, custom log library, and SOPs (System.out.printlns). This made her task of tracing the logs difficult. When she analyzed the root cause, she found that the software has acquired components from different business units and these components used different logging mechanisms. Refactoring the code base to use uniform logging approach or even using something like Simple Logging Facade for Java (SLF4J) will require months of effort and time. When bought to notice, the architect made a proposal to the management to perform architecture refactoring for using unified logging approach. The question from the management was simple: “What is the ROI (Return On Investment) on spending 4 months of the team’s effort?” Though the architect argued that the time for debugging and tracking/tracking defects through log files will improve turn around time for fixing defects, the benefits were difficult to quantify. So the architecture refactoring for this smell was not taken up.
[Note: In this specific case, architecture refactoring is hard to justify in business terms and illustrates the need for management buy-in. However, in general, benefits of architecture refactoring are typically clear from business perspective.]
This example clearly illustrates the difference between code and architecture refactoring. Code refactoring can be often performed by a developer (or two), typically in a few hours. Most smells and their refactoring are are well-known. The impact is localized and management approval or buy-in is not typically necessary.
However, architecture refactoring requires team effort, and hence it requires more planning and coordination efforts. Architecture refactoring will consist of reasoning about the changes required and getting buy-in from stakeholders if necessary. It will also involve changing architecture description and documentation to reflect the changes. Architecture smells and the corresponding refactoring are more of folklore knowledge and is not really codified well in the form of catalogues.
Code refactoring is well-known and is popular because of the key role it plays in Agile methods. Code refactoring consists of improving the internal structure of the code. Code refactoring can be thought of as making micro-level (tactical) changes to improve the internal quality of the software. However, architecture refactoring is relatively less known and is of much higher importance (given the benefits it could have). Architecture refactoring can be thought of as making system-wide (strategic) changes to improve the internal quality of the software. In short, architecture refactoring is an entirely different ballgame when compared to code refactoring.