9.7 Measuring Software Design Alternatives

9.7 Measuring Software Design Alternatives

From a statistical perspective there are at least three degrees of freedom in the design process. One degree of freedom is attributable to the manner in which the several program modules will be executed. We could, for example, design a program in which all of the functionality is implemented in a small number of the total program modules. On the other hand, we might choose to distribute the functionality across a large number of program modules. The entropy of the design will measure this.

The second degree of freedom in design relates to the complexity of the program modules. We might be able to choose from a series of design alternatives that express the complexity of the set of functionalities in different ways in differing modular structures. This will be measured by the modular complexity of the design. We can think of the design process as one of parsing the functional complexity of our design to particular program modules.

The third degree of freedom is related to the choice of functional alternatives for the high-level design. The interesting thing about the design problem is that there are many different ways to implement a set of operational specifications from a functional viewpoint. The important thing, from a user's perspective, is that all of the different functional approaches create exactly the same operational metaphor. Some of the functional solutions will result in very complex functional metaphors. These complex metaphors will, in turn, create very complex modular structures. A good functional design is one that minimizes the complexity of the functional metaphor or the design functional complexity.

9.7.1 Design Module Complexity

There are many design trade-offs. We can, for example, choose to write a small number of program modules. This will make each module relatively large and very complex. The total module coupling complexity will be very small in this case. At the other extreme, we can decompose our task into lots of very small program modules. In this case, the complexity of each module will tend to be very low. The total system coupling complexity will, however, be astonishingly large. This type of design alternative is one that very naturally emerges in the object-oriented design metaphor.

Unfortunately, we do not know the consequences of the various design alternatives. We do not know, for example, whether low coupling complexity and high module complexity is to be preferred over high coupling complexity and low module complexity. The science simply has not been done. If we are to make sound engineering decisions about our design alternatives, then we must first do the necessary science to evaluate the various alternatives.

9.7.2 Design Functional Complexity

As previously indicated, there are a number of metrics that we can gather from the low-level modular design of a system. We can begin to measure some very important properties of control flow complexity, coupling complexity, and data structures complexity. More often than not, it is not entirely apparent to us, when we are at the early stage of design, which of the many functional design alternatives are most suitable for our operational metaphor. If we choose the wrong (inappropriate) functional metaphor during the design stage, we can potentially pay a very high price for this choice over the life of the software product we are developing.

We now have at our disposal a means of measuring the complexity of a design specifically in terms of the potential total fault burden of that design. The fault index (FI) presented in Chapter 5 is a criterion measure that we can use in this regard.

As per the earlier discussion of FI, it can be seen that it is possible to characterize a program module by a single value such as FI. Many of the metrics we will use to form FI are, in fact, available to us when we have finished our specification of the low-level design at the module specification stage. We can begin our measurement process at this stage, in advance of actually creating the code. The preliminary FI measure p of a module is a leading indicator. When a program is executing, not every one of its modules will receive the same level of exposure. This is evident in the concept of execution profile. Some executions might result in very complex program modules being executed. Other program input stimuli may cause the program to execute only its least complex modules.

There is, then, a dynamic aspect to program complexity that is related to its entropy under a particular test scenario. The design functional complexity φq, of a system with a known functional profile is then:

where pj is the fault index of the jth program module and qj is the execution probability of this module under a given functional profile. This is simply the expected value of the fault index under a particular execution profile.

The execution profile for a program can be expected to change across the set of program functionalities. That is, for each functionality, fi, there is an execution profile represented by the probabilities . As a consequence, there will be a functional complexity φi for each function fi execution, where:

This is distinctly the case during the test phase when the program is subjected to numerous test suites to exercise differing aspects of its functionality. The functional complexity of a system will vary greatly as a result of the execution of these different test suites.

Given the relationship between complexity and embedded faults, we would expect the failure intensity to rise as the functional complexity increases. If an application is chosen in such a manner that there are high execution probabilities for the complex modules, then the functional complexity will be large and the likelihood of a failure event during this interval will be relatively high. In Exhibit 20, the operation of a hypothetical software system executing various functionalities across time is presented. From this exhibit we would expect the software failures to be directly related to those periods when the functional complexity is high.

There are two degrees of freedom in the determination of system functional complexity. First, the functional complexity will vary in accordance with the functionality being executed. It will also vary as a function of the reconstitution of the software over builds. Thus, the functional complexity for function fi, at the jth build represented by vj will be:

where Nj represents the cardinality of vj and is the kth element of this vector.

It is possible to simulate the functional complexity for various execution profiles for different design alternatives and thus measure their likely failure intensity. To model correctly the reliability of a software system we will necessarily have determined the functionality of the program and how these functions will interact as the program executes. The latter information not only directs the formation of test suites but also provides the information necessary to formulate execution profiles. The functionalities that imply execution profiles which cause the functional complexity to increase merit our attention because these are the conditions that will increase failure rates for a given design.

9.7.3 Testability

Testability is a term that has been much used and little defined in the software testing community. We can now begin to define and quantify this term in terms of our understanding of the distribution of functionality to program modules. If we were to write a system that always exercised all of its modules, it would be a relatively simple matter to test all of the modules in the system. On the other hand, if we were to build a system that seldom or occasionally used some of the constituent program modules, then it would be pretty difficult to test this system because the circumstances that would cause our shy modules to execute might be obscure or ill defined.

Remember that the cardinality of the set of potentially invoked modules for a functionality fi was denoted by . Then, for a system of k functionalities, we can find the set Mp of all modules that are potentially invoked by at least one functionality; that is, by

We can also identify the set of those modules Mi that are indispensable to at least one functionality; that is, by

Now we wish to identify the set of modules that are also not in the set of indispensable modules for at least one functionality. There is a set of modules Ma that are in the intersection set Ma = Mp Mi. If we remove this intersection set Ma from the set of modules Mp, we are left with the set to wit: . The cardinality of the set is .

The cardinality l of , in relation to the total number of program modules n, is certainly one attribute dimension of the concept of testability. We could formalize this as τ =l /n. A system where τ is relatively small will have a relatively high testability attribute, testability being inversely related to the cardinality of the set of modules .

The concept of testability is a multidimensional problem. There are many attributes for testability. One attribute dimension certainly relates to poor design choices that create large sets of modules . As we progress in our understanding of measurement, other aspects of program testability will become clear.



Software Engineering Measurement
Software Engineering Measurement
ISBN: 0849315034
EAN: 2147483647
Year: 2003
Pages: 139

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net