10.7 Partial Complexity

10.7 Partial Complexity

Except in the most trivial case, whenever a program module executes, only a subset of execution paths from the start node of the flowgraph to the terminal node will actually execute. In the flowgraph definition in Chapter 5, essentially all of the executable source code in a program module will map to the processing nodes of the flowgraph. The instrumentation methodology described in Section 10.5.1 will allow us to determine just exactly which of these processing blocks have been touched during the execution of each functionality. Once we know which processing blocks have executed, we can then determine exactly which source code statements have executed for that functionality.

In essence, each functionality will select a particular subset of executable source code from each module in the subset of modules M(f) that implement the functionality. The functionality clearly does not execute all of the code in each module. A more accurate representation of the complexity of each module, then, would be to identify just the code that executed and then measure the code attributes of that source code subset. A program module, for example, might contain 100 executable statements. When this module is exercised by a particular functionality, say f5, only 25 of these statements will actually execute. Thus, the partial attribute complexity for Exec for functionality f5 is 25.

Consider the program example shown in Exhibit 1. This function module will take an integer (4 bytes) and return the same integer (4 bytes). The essential structure of this program is very similar to that used to interrogate the contents of status words checking for particular bit settings. This program function module has 232 or 4,294,967,296 paths. Necessarily, its path complexity is very high. From the standpoint of control flow complexity, it is a heinous module.

Exhibit 1: Function Module Return Same 4-Byte Integer

start example

   unsigned int test (unsigned int status)   {      unsigned int power;      unsigned int cum;      power = 1;      if (status & power)      cum = 1;      else      cum = 0;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power * = 2;      if (status & power)      cum + = power;      power + = 2;      if (status & power)      cum + = power;      return (cum);   } 

end example

Now let us assume that at runtime, the function module shown in Exhibit 1 is passed the value of 2 as its only argument. The actual code that will execute, in this case, is shown in Exhibit 2. There are exactly two paths through this code. It is a very simple program from the standpoint of control flow complexity.

Exhibit 2: Code Executed

start example

   unsigned int test (unsigned int status)   {      unsigned int power;      unsigned int cum;      power = 1;      if (status & power)      cum = 1;      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power * = 2;      if (status & power);      power + = 2;      if (status & power);      return (cum);   } 

end example

In one sense, the generalized FI measure is really pessimistic. A much more realistic approach would be to identify the particular subset of code that is actually used under a particular operational profile and measure just that for fault potential. This will yield a partial FI value for each program module under an operational profile o. We will explore this notion at length in Chapter 11.

The bottom line of the notion of partial complexity is that it is possible to measure the static attributes of the actual pieces of program module that were executed.

As an aside, the function module shown in Exhibit 1 is flawed. The statement following the penultimate if statement should read, power * = 2;. This means that exactly one half the integers that may be returned by this module will be wrong. Put another way, one half of the possible executions of this module will result in a failure event. It is highly unlikely, however, that a typical user will ever experience this failure. Most people do not use large integers in their daily life. Only a very small fraction of probable executions will expose this fault.



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