Basics - Architecture Analysis for TQS
System internal dependencies form the basis of this software architecture analysis. In the following, fundamental circumstances are described, which will help the reader to understand and assess their implications.
Quality and Dependencies
„Quality is terrible as a control variable. You can make very short-term gains (days or weeks) by deliberately sacrificing quality, but the cost - human, business, and technical - is enormous" Beck 1999.
„For software to be tested effectively, it must be designed from the start with that goal in mind _ Testability, like quality itself, cannot be an afterthought: it must be considered from the start _ before the first line of code is ever written" [lakos96]
Testing alone cannot create quality. By the time that thorough quality tests are possible, the actual level of quality of the software has already been established. It is unrealistic to expect that QA towards the end of the development will by some magic improve the quality properties of software.
Software is often poorly documented, difficult to understand, hard to test and unreliable. QA must therefore be an integral part of development. If high quality software is the objective, software developers and system architects must take the responsibility to build and design quality in. See also the discussion in [lakos96] on "Design for testability".
„It is the dependency architecture that is degrading, and with it the ability of the software to be maintained" [Martin00 ]}
„Cyclic physical dependencies in large, low-level subsystems have the greatest capacity to increase the overall cost of maintaining a system" [lakos96].
„Guideline: No Cycles in Packages" [Larman02 ].
„The dependencies between packages must not form cycles" [Martin00 ].
„The dependencies between packages must not form cycles." [Martin00 ].
For medium to large-scale software development projects, it is essential to define and monitor the dependencies between software units along the whole project duration. If this is neglected, an initially well-defined architecture will be watered-down and the efforts for maintenance and modification will increase. See also "Description of Symptoms" [Martin00 ]. The rating of the physical dependencies reflects to a high degree the quality of software. Desired properties like _"extendable", "serviceable",
"comprehensible"_ become possible by controlling dependencies.
„Cyclic physical dependencies among components inhibit understanding, testing and reuse ...
Guideline: Avoid physical dependencies among components ...
Every directed a-cyclic graph can be assigned unique level numbers; a graph with cycles cannot ...
A physical dependency graph that can be assigned unique level numbers is said to be levelizable ...
In most real-world situations, large designs must be levelizable if they are to be tested effectively ...
Independent testing reduces part of the risk associated with software integration ...
Major Design Rule: Avoid cyclic dependencies among packages." [lakos96]
The following example illustrates these guidelines.
Depending on the item under consideration and level of detail, the units can be considered as layer, subsystem, and package or compilation unit:

Diagram 1 shows three units (A,B,C), whose dependencies form a cycle. A uses C, C uses B and B
uses A. These dependencies form a cyclic graph (it is not possible to assign levels), which has the following implications:
- In order to understand what a unit does, all units need to be understood.
- In order to test a unit, all units need to be tested.
- Reuse is bound to a reuse of all units.
- In order to fix a defect (or modify a unit), this has to be done in the network of units. There is no integration in a classical sense.
- Impact analysis is not possible.
In contrast, diagram 2 shows three units, which form an acyclic graph (it is possible to assign levels), which implies:
- In order to understand what a unit does, there is a strict order: A,B,C.
- In order to test a unit, there is also an order. First A must be tested, then B and finally C.
- There are re-use options: A can be re-used independently, A and B together or the whole solution. A defect in A can be fixed in isolation from B and C. The test will verify the modification. The resulting A is then integrated with B and C.
- Impact analysis can be performed.
| This example demonstrates the implications of dependencies on a very small number of units. In medium to large-scale projects, a three-digit number of packages and a two digit number of subsystems can be found. For these dimensions the effects are increased. |
„Distributing system testing throughout the design hierarchy can be much more effective per testing dollar than testing at only the highest level interface" [lakos96]
Incremental and hierarchical tests can be performed if a physical hierarchy forming a directed acyclic graph (DAG) is present. In this case, functionality added or modified can be verified on each level. Units on level 1 can be tested in isolation, as they have no further dependencies. This ensures that units that form a foundation for other units work properly.
If tests are only performed on the highest level, the unit "responsible" for this behaviour must be tracked down. This is very time-consuming and usually results in a series of test-debug-fix-retest activities as retests often reveal side effects of the fix.
It is much more effective (less time-consuming and simpler) to test on each level, as the amount of functionality and code to be tested is easier to manage.
"Testing at any given scope should be preceded by integration of lower scope components ...
A key lesson learned is that incremental integration is the most effective technique: add components a few at a time and then test their interoperability. Trying to integrate most or all of the components in a system at the same time is usually problematic." [Binder00 ]
STRUCTURAL ELEMENTS OF THE ARCHITECTURE AND DEPENDENCIES
In order to describe the architecture of software, several views are required. The logical view contains the organisation, structure and interconnection of the main elements. The implementation view describes (among other things) the transformation of the logical elements to software "pieces". For a detailed description of software architecture views see [Kruchten00 ], [Larman02 ].
The composition of the architecture from elements with precise responsibilities results in dependencies. As structural elements for composition, the architect has the following elements at his/her disposal. Please note that the elements higher in the list group the elements below:
- System
- Layer
- Subsystem
- Package
- Type (Class, Interface)
A commonly used pattern fort he usage of layers and the breakdown of the system is called „Relaxed Layered Architecture" (see [Larman02 ] and [Buschmann98 ].). This pattern says that layers on a particular level are allowed to use layers on a lower level but not vice-versa.
Given the example of a simple 4-layer architecture, the dependencies of the layers may look like this:

Layers are horizontal slices of the system and the grouping is usually more of a technical nature. A more in-depth discussion about layering of applications can be found at [Larman02 ] and [Buschmann98 ].
Subsystems on the other hand are vertical slices of the software and the grouping is usually by functionality. Subsystem is a synonym for module in this context. This leads to the following diagram.

Lakos96: Large-Scale C++ Software Design, John Lakos, Addison-Wesley 1996
Larman02: Applying UML And Patterns, Craig Larman, Prentice Hall 2002
Buschmann98: Frank Buschmann et.Al., Addison-Wesley 1998
Martin00: Testing Object-Oriented Systems, Robert V. Binder, Addison-Wesley, 2000
Kruchten00: The Rational Unified Process An Introduction, Philippe Kruchten, Addison-Wesley 2000
Binder00: Testing Object-Oriented Systems, Robert V. Binder, Addison-Wesley, 2000