The Smell of Rotting Software

Jack Reeve introduced the concept that source code is the design and programming is about designing software.1 As software grows, the design, or architecture, tends to grow large and complex. This is because software architecture is constantly evolving, making software maintenance difficult and error-prone. In this article, we will talk about symptoms of bad architecture and how to fix them.

Poor Software Architecture

According to Robert Martin2, there are seven symptoms of poor architecture.

  1. Rigidity: this means the system is hard to change. Every change forces other changes to be made. The more modules that must be changed, the more rigid the architecture. This slows down development as changes take longer than expected because the impact of a change can not be forecast (impact analysis can help). System stability and average impact are good architecture metrics to monitor for rigidity. System stability measures the percentage of elements (on the average) that would not be affected by a change to an element. Average impact for an element is calculated as the total number of elements that could be affected if a change is made to this element (or the transitive closure of all elements that could be affected).
  2. Fragility: when a change is made to the system, bugs appear in places that have no relationship to the part that was changed. This leads to modules that get worse the more you try to fix them. In this case, these modules need to be redesigned or refactored. Cyclicality metrics can help find fragile modules. Cyclicality is useful in determining how many elements of a system are in cycles. See our blog post “Cyclicality and Bugs” for more information.
  3. Immobility: this is when a component cannot be easily extracted from a system, making it unable to be reused in other systems. If a module is found that would be useful in other systems, it cannot be used because the effort and risk are too great. This is becoming a significant problem as companies move to microservices and cloud-ready applications. A metric that is useful in this case is called coupling. Coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are and the strength of the relationship between modules.
  4. Viscosity: this is when the architecture of the software is hard to preserve. Doing the right thing is harder than doing the wrong thing (breaking the architecture). The software architecture should be created so it is easy to preserve the design.
  5. Needless complexity: the architecture contains infrastructure that adds no direct benefit. It is tempting to try to prepare for any contingency, but preparing for too many contingencies makes the software more complex and harder to understand. Architectures shouldn’t contain elements that aren’t currently useful. Cyclomatic complexity metrics can help diagnose this problem.
  6. Needless repetition: this is when an architecture contains code structures that are repeated, usually by cut and paste, that instead should be unified under a single abstraction. When there is redundant code in software, the job of changing the software becomes complex. If a defect is found in code that has been repeated, the fix has to be implemented in every repetition. However, each repetition might be slightly different.
  7. Opacity: this is when the source code is hard to read and understand. If source code is the design, this is source code that does not express its intent very well. In this case, a concerted effort to refactor code must be made so that future readers can understand it. Code reviews can help in this situation.

Summary

While source code may be the design, trying to figure out the architecture from the source code can be a daunting experience. Using architectural analysis tools like Lattix Architect can help by visualizing the dependencies. This allows you to refactor the architecture, prevent future architectural erosion, and provide metrics like system stability, average impact, cyclicality, coupling, and cyclomatic complexity.

1. C++ Journal, “What is Software Design?”
2. Agile Software Development, Principles, Patterns, and Practices, Robert Martin