During the GSAS 2022 conference organized by Apiumhub, Dr. Carola Lilienthal presented an intriguing topic she had thoroughly explored in her book, Sustainable Software Architecture, and also in a chapter in the Software Architecture Metrics book: the Modularity Maturity Index (MMI). This talk shed light on the importance of this metric in evaluating the modularity of software architecture, and its potential to improve the sustainability and maintainability of software projects.
Despite being commonly perceived as evil, legacy code can still be considered a good project if it has a long useful life, which justifies the initial investment, and if its maintenance and extension costs are kept to a minimum. In fact, a good legacy project is characterized by its ease of understanding, modification, and extension, making it a valuable asset for the organization.
How Do We Spend Our Time?
Code comprehension 70%
Writing code 10%
A considerable amount of time is dedicated to code comprehension, accounting for 70% of the total time spent on software development. This suggests that developers spend a significant amount of time reading and trying to understand the code, which may come as a surprise to some who assume that coding is all about writing the solution. In contrast, problem-solving only takes up 20% of the total time, while writing code only accounts for 10%.
Well-formed Complex Structures = Saving Time!
This highlights the importance of writing code that is easy to comprehend and maintain, as it can significantly reduce the time and effort spent on trying to understand it. Code that is well-structured, well-documented, and uses clear naming conventions can aid in code comprehension and make it easier for other developers to work with.
Our brain employs cognitive mechanisms to comprehend and manage complexity.
- chunking: involves breaking down complexity into coherent chunks that our brain can process. Research suggests that we can only hold around 7 things (+/- 2) in our working memory at a time.
- Hierarchies: which establish a clear order of importance or arrangement. This allows us to organize information in a logical and structured way, with some elements at the top and others at the bottom.
- Schemata: they are also essential in understanding and managing complexity. Without a clear understanding of the rules and concepts that underlie a system, it can be difficult to navigate or solve problems within that system. Therefore, having a clear schema or mental model of a complex system can aid in comprehension and problem-solving.
How can we use these mechanisms to improve our code?
- High Cohesion and loose Coupling
- Responsibility Driven Design
- Separation of Concerns
- Single Responsibility Principle
- Hierarchical layering
- No cycles neither on architectural level nor on class level
- When most of the classes depend on most of the other classes, we may have a huge cycle that may be really difficult to break.
- Pattern consistency
- Design patterns: they are known to everybody
- Use a pattern language
- Consistently applied patterns help us deal with the complexity of source code.
Modularity Maturity Index (MMI)
The Modularity Maturity Index determines the extent of technical debt in a legacy system. Depending on
the result in the areas of modularity, hierarchy, and pattern consistency, the need for
refactoring or a possible replacement of the system can be determined.
Using the three principles of modularity, hierarchies, and pattern consistency, the MMI is calculated.
- Modularity is the main topic with 45% of the final weight
- Domain and technical modularization (25%)
- The same module should have high cohesion among its components but a low coupling with other modules.
- Names should define the one task the program unit does
- Internal Interfaces (10%)
- Proportions (10%)
- Well-balanced proportions: It is not desirable to have one unit with the majority of lines of code while the rest of the units have only a few percent.
- Domain and technical modularization (25%)
- Hierarchy 30%
- Technical and domain layering (15%)
- Class and package cycles (15%)
- Pattern consistency 25%
The grade of each topic is determined by some Architecture analysis tools, some metric tools, and also by the reviewers (people reviewing the code and doing some hand analysis).
A system that receives a rating between 8 and 10 indicates a low level of technical debt, this is where we want our project to be.
However, if the rating falls between 4 and 8, there is a considerable amount of technical debt present. It is a moment to start doing refactorings to reduce the complexity, to improve the quality of the system. We are still on time.
If the rating falls below 4, the system can only be maintained and expanded with significant effort. Most of us may have been in this position. In such instances, it is crucial to carefully consider whether it would be worthwhile to upgrade the system through refactoring (which may be very difficult and tough to finish) or whether it should be replaced altogether.
For a more in-depth understanding, we recommend reading the corresponding chapter in the Software Metrics book on Architecture.
Conclusion: Modularity Maturity Index Talk
Dr. Lilienthal introduced a valuable metric that can provide insight into the current state of a project. The Modularity Maturity Index can serve as a useful starting point for determining whether a project requires refactoring to maintain its quality or if a complete rewrite is necessary. The use of a mathematical metric is advantageous in that it eliminates the subjectivity of expert opinions. However, calculating the Modularity Maturity Index can be challenging, as it involves evaluating certain aspects of the project that require human input. Obtaining all the necessary metrics can also be a daunting task, but it may be essential nonetheless for large projects.