A Common Structure of a Well-modularized System
Baldwin and Clark’s design rule theory [1] explains how modularity adds value to a system in the form of options. Their theory suggests that independent modules are decoupled within a system by the creation of Design Rules (DRs). A highly modularized system should have the following features:
(1) Having clearly defined design rules (DRs). In a software system, DR may be realized as key header files, interface files, abstract classes, API, key data structures, etc. These files should have the following characteristics:
- They should decouple other files into independent modules so that they don't have to depend on each other. Most key interfaces in design patterns are designed for the purpose of decoupling.
- They should not depend on other concrete classes or files, following the Dependency Inversion Principle [14].
- The more dependents a DR file has, the more stable it should be (see Assessing Modular Structure Based on Evolution History).
(2) Having independent modules. An independent module has the following characteristics:
- It should only depend on DRs, not on other modules, following the Dependency Inversion Principle [14].
- As long as the DRs remain stable, a module can be improved or even replaced without affecting other parts of the system, and this property can be measured by analyzing a system’s evolution history (see Assessing Modular Structure Based on Evolution History).
- Based on the Single Responsibility Principle [14], each module should only have one reason to change.
- A high-quality, independent module should not be too large or too small.
(3) If a file depends on many other files, such as an “entry point” file, it shouldn't have many dependents, following the low-coupling, high-cohesion principle.
Using DV8, the user can conduct an evaluation of the existence and quality of DRs and modules using Design Rule Hierarchy (DRH) clustering (menu "Tree->Cluster as DRH").
Following is a DRH-clustered DSM derived from the source code of a system implementing a simple maze game. This system applies the abstract factory pattern, an example used in the GOF book [3]. This DSM shows that:
(1) The system's design rules include the key abstract factory interface, MazeFactory.java, all the base classes, and the MapSite.java abstract class.
(2) These design Rules decouple the system into independent modules: a blue maze factory with 3 files, a red maze factory module with 4 files, and a module containing just the entry file.
From the DSM, it is clear that these two concrete factory modules only depend on the design rules but not on each other. This is a well-modularized system.
If the system evolves, that is, as more concrete factories are added, the DSM would show this expansion by including additional concrete factory modules. For example, if an “enchanted” maze game and a “bombed” maze game are added, two additional modules will be added as follows. This simple example demonstrates that the design follows the Open-Closed Principle [14].
Research has shown that well-modularized systems all have similar structures: independent modules decoupled by well-defined, stable design rules. In particular, most design patterns feature one or two key interfaces that decouple other files into independent modules.
However, in a complex system these rules may not be as readily apparent. There could be multiple patterns, features, or concerns in a complex system, and the above modular structure may not as clear because multiple aspects may overlap and influence each other. In the next section, we illustrate how to examine a complex system through the lens of Design Rule Spaces [13].