A Dependency Structure Matrix or Design Structure Matrix (DSM) is a simple, compact, and visual representation of a system, software application or project in the form of a square matrix. The DSM representation was invented more than 30 years ago. Since then, the use of DSMs has advanced by ongoing work at MIT, Harvard, University of Illinois and a number of other organizations where DSMs have been applied to the analysis of complex systems. Lattix is the first company to apply DSMs to software architecture. The process of representing software architecture typically consists of simple matrix transformations which are guided by the dependencies between the subsystems.
The figure below illustrates a DSM for a system that has been decomposed into 4 subsystems: Module A, Module B, Module C, and Module D. The x-axis and the y-axis of the matrix represent the same subsystem which are numbered sequentially.
The dependencies for each subsystem are read down a column. Reading column 1, we see that Module A depends on Module C with a dependency strength of ‘7’. We also note that Module A does not depend on Module B and Module D as those cells are empty. The dependencies indicated in the DSM shown below are as follows:
- Module A depends on Module C
- Module B does not depend on other modules
- Module C depends on Module A and B
- Module C depends on Module A and C
We will now reorder the subsystems in the DSM through a process called partitioning. Though Lattix supports a large number of partitioning algorithms, the algorithm that we describe here is called component partitioning and is well suited for software systems.
Partitioning yields a block triangular matrix. The overall goal of this algorithm is to order a system starting with the subsystems that use the most of other subsystems and ending with the subsystems that provide the most to other subsystems, while grouping systems that have interdependencies (cycles) together in the ordering. Partitioning algorithms yield a “block triangular” form the matrix. In a “block triangular” matrix all cells outside of the blocks and above the identity diagonal are empty. Furthermore, those blocks which contain dependencies above the identity diagonal are guaranteed to have cyclic dependencies. This partitioning gives us three blocks. Module A and C have been grouped into one block because they are coupled to each other. Partitioning helps us determine the layering that is typical in most medium to large scale software systems.
We can combine Module A and C into a compound Module A-C which contains Module A and Module C.
Lattix’s innovative use of DSM in representing hierarchies is the key to representing and managing large scale architectures. Note that we have called “Module” is simply an abstraction – it can be a small abstraction representing a single class or a large abstraction representing an entire subsystem containing thousands of classes.
We can now collapse Module A-C so that we don’t see Module A and C.
The dependency that Module D has on Module A-C is an aggregation of the dependencies that Module D had on Module A and Module C. By default, the aggregation is a simple summation although other approached to aggregation can also be configured in Lattix Architect.
To summarize: we performed a series of simple matrix transformations. In these transformations we were guided by the dependencies between the subsystems. We started with a system that consisted of 4 modules: Modules A, B, C, and D. Through a sequence of transformations, we ended up with a system that consists of 3 modules: Module D, Module A-C and Module B. Module A-C in turn consists of Modules A and C. Furthermore, we ordered the modules in a particular way so as to get a layered representation of the system with the lowest layer being Module B. Module A-C is layered on top of Module B and Module D in turn layered on top of Module A-C.
The DSM representation is a blueprint of a software system’s architecture; each cell of the DSM represents design intent. Design rules are simply a way of specifying allowed and disallowed dependencies.
With the context of a map of the existing subsystems, their current decomposition, and the existing dependencies between subsystems, this framework is ready for codifying the architect’s intent through a set of formal design rules. Typically, a design rule is applied to a subsystem and is then inherited by every subsystem contained within it. This allows a widely pervasive rule to be applied simply by clicking on a single cell of the DSM. The Lattix Architect solution can then inform or enforce when developers inadvertently create architectural violations.
The matrix representation itself provides a powerful way to specify and visualize design rules
Rules can also be specified to standardize external libraries that can be used so that redundancy is minimized, architectural integrity is maintained and licensing issues are managed.
Some of the things that you can do with Design Rules include:
- Specify and Enforce Layering
- Maintain Hidden Subsystems
- Keep Components Independent
- Manage External Library Usage
The Lattix Whitepaper on Design Rules describes in detail how design rules are specified and applied.