Perpetual Testing Logo

Complex design-code mappings

"As-built" organizations of software are not a simple elaboration of architectural designs. The mapping from logical components in an architectural design to implementation modules need not be 1:1 nor even 1:n; in practice one often finds that a single implementation component corresponds to facets of multiple components in the architectural design, so that the mapping between design and implementation structures is many-to-many. Moreover, the grouping of components in the as-built structure may be different.

 

Should we require that implementation structures more closely mirror architectural designs? In many cases, we cannot. The implementation structure reflects concerns of physical platform (distribution, etc.) and performance that are properly suppressed in the highest levels of architectural design. If we forced a simple relation between logical architecture and implementation structure, we would have to either accept poor implementation structures or pollute logical designs with lower-level implementation considerations. It is better to accept the complex relationship, and accomodate it in our approaches to quality assurance.

 

The hierarchical static analysis techniques that can provide strong assurances of critical properties of multi-threaded systems scale to large systems only when they can exploit the modular organization of the design to "divide and conquer" the overall analysis task. Unfortunately, the "as built" structures are seldom amenable to hierarchical analysis, so we can obtain strong assurances of critical properties only with respect to the logical, architectural design. In the case of legacy systems without suitable architectural design representations, we can build restructured design representations and reconstruct the mapping between design and implementation. Regardless of whether we establish the relation between logical architecture and implementation structure through forward engineering or restructuring legacy software, this complex relation can be interpreted as a set of analysis obligations: In addition to verifying properties of interest with respect to the architectural design, we must validate the correspondence between "as-designed" and "as-built" components through some combination of static and dynamic analysis.

 

While it may often be impractical to apply state-space analysis techniques directly to implementations, models constructed in the course of analysis of the architectural model can be used as test oracles for dynamic testing to establish the conformance of an implementation to a design. Conformance testing can be more sensitive than directly testing an implementation against specified properties, particularly in the case of subtle, timing-dependent errors. For example, conformance testing can detect the possibility of a race condition without observing an actual occurence of the race. This "two-phase" combination of analysis and testing is strictly more powerful than direct testing of implementations, in the sense that it is guaranteed to detect an error whenever direct testing would detect the same error, but and can additionally detect potential errors that escape detection by direct testing.


Contact: Michal Young