[Top] [Prev] [Next] [Index] [TOC]

Chapter 12

Vue: A Tool for Effective Software Maintenance

Maintenance and modification of legacy software systems are the most costly activities in the life cycle of a long-lived system. Central to this activity are techniques for effectively finding and modifying code which implements features. The tool, Vue, is tailored to this need and has a state of the art graphical user interface to allow the maintainer or programmer to quickly locate code that is associated with features of the system.


12.1 Background

Ideally, in a well-designed software system each program feature would be implemented in a single identifiable module; in practice, though, this is never the case. In the early development stage of a system, programmers may follow certain standards to ensure a clear mapping between each feature and its corresponding code segments. However, as development continues, it is likely that such traceability will often become the first casualty of the pressure to keep a system operational. As a result, program features are implemented over several non-adjacent subroutines which makes the features more difficult to locate and understand. Such delocalized programs can lead to serious maintenance errors.

In general, the first step towards software maintenance is to locate the code relevant to a particular feature. There are two methods of achieving this. First, a systematic approach can be followed which requires a complete understanding of the program behavior before any code modification. Second, an as-needed approach can be adopted, which requires only a partial understanding of the program so as to locate, as quickly as possible, certain code segments that need to be changed for the desired debugging/enhancement. The systematic approach provides a good understanding of the existing interactions among program features, but is often impractical in a real work environment due to the pressures of time and cost when working with large complicated software systems. On the other hand, the as- needed approach, although less expensive, may ignore some non-local interactions among the features and cause a program modification to result in disastrous side-effects. Thus, a need arises to identify those parts of the system that are crucial for the maintainer to understand. A possible solution is to read the documentation; however, in many cases, this may not be effective. The documentation may not exist; or even if it exists it may be incomplete, difficult to comprehend or not updated. Also, programmers/maintainers may be reluctant to read it. Perhaps a faster and a more efficient way of identifying the important segments of the code is to let the system speak for itself. It is this issue that the tool, Vue, attempts to address.

The execution slice-based technique is a solution which helps programmers and maintainers locate the implementation of different features in a software system. To find, for example, where the call forwarding feature is implemented in a telephone switching system, one would run a small, carefully selected, set of tests -- some that invoke the call forwarding feature and others that do not. Such tests are classified as invoking tests and excluding tests, respectively. Traces of program execution are analyzed to look for code components that were executed in the invoking tests but not in the excluding tests. Although this technique may not find all relevant code that makes up the call forwarding feature, it does identify a small number of program components that are unique to this feature. The identified code can then be used as a starting point for studying this feature. This is especially useful for those features that are implemented in many different modules in a large, complicated and poorly documented system.

It is important to note that code segments so identified rely heavily on the test cases used. Different sets of code may be identified by different sets of invoking and excluding tests. This implies poorly selected tests will lead to inaccurate identification by either including components that are not unique to the feature or excluding the ones that should not be excluded.

There are many ways in which execution traces of invoking and excluding tests may be compared to identify pieces of code that are related to a given feature, say f. One approach is to identify code that is executed by any invoking test case but not executed by any excluding test case. Another approach is to identify program components that are executed by every invoking test case but not executed by any excluding test case. The latter approach identifies only those program components that are always executed when feature f is exhibited but not otherwise. Another, simpler, approach is to compare the execution trace of just one invoking test with that of one excluding test. To minimize the amount of relevant code identified, the invoking test selected may be the one with the smallest execution trace and the excluding test selected may be the one with the largest execution trace. Depending on how features are implemented in the program, programmers/maintainers may have to try all these approaches, or construct their own approaches, in order to find the best set of code related to a given feature.

Ideally, the excluding tests used should be as similar as possible to the invoking tests in order to filter out as much common code as possible. To illustrate how to select the invoking and excluding tests, consider the example code in Figure 12-1. Suppose we want to find the code that is uniquely used to identify an equilateral triangle. We first construct an invoking test t1 that exhibits this feature and two excluding tests t2 and t3 which assign isosceles and rectangle, respectively, to class. Clearly, t1 is closer to t2 than t3. The difference between the execution traces of t1 and t2 shows that only statements s10 and s13 are unique to this feature, whereas additional code such as the statements s3- s7 would also be identified should t3 be used in place of t2 as the excluding test. Furthermore, this example also indicates we do not even need to use the feature that identifies a rectangle to find code that is unique to equilateral triangle. The ability to identify program components unique to a feature without even knowing all the program's features greatly enhances the feasibility of using the execution slice technique to quickly highlight a small number of program components.

 s1:    scanf ("%c", &type);
 s2:    if (type == triangle) {
 s3:        scanf ("%d %d %d", &a, &b, &c);
 s4:        class = scalene;
 s5:        if ((a == b) || (b == c))
 s6:            class = isosceles;
 s7:        if (a*a == (b*b + c*c))
 s8:            class = right;
 s9:        if ((a == b) && (b == c))
s10:            class = equilateral;
s11:        switch (class) {
s12:            case right       : area = b * c / 2.0; break;
s13:            case equilateral : area = a * a * sqrt(3.0) / 4.0; break;
s14:            default          : s = (a + b + c) / 2.0;
s15:                               area = sqrt (s * (s-a) * (s-b) * (s-c)); break;
s16:        }
s17:   } else {
s18:        scanf ("%d %d", &w, &h);
s19:        if (w == h) 
s20:            class = square;
s21:        else
s22:            class = rectangle;
s23:        area = w * h;
s24:   }
s25:   output (class, area);
Figure 12-1 A simple example

12.2 A Tutorial

The use of Vue is most easily understood by an example. In this chapter we use the same wordcount program as used in the previous chapters to illustrate how the basic features of Vue can be used in identifying functional features. To copy these files, create a new directory, cd to it, and copy the contents of the directory in which the tutorial files are installed into the new directory.

For the illustrations in this chapter, we will use (1) two .c files: main.c and wc.c, (2) three data files: input1, input2, and input3, and (3) the Makefile. Now you are ready to compile the wordcount program, with atac, by entering the appropriate make command, as specified in Appendix A, Platform Specific Information.

After the compilation, two .atac files (main.atac for main.c and wc.atac for wc.c) and the executable wordcount(.exe) are created. Note one .atac file is created for each instrumented .c file, i.e., the .c files compiled with atac cc.

Invoke the graphical interface of the Toolsuite by:

	prompt:> xsuds *.atac
Then, pull down the ``Tool'' menu and select the ``xvue'' option. Figure 12-2 shows the initial main window of Vue.

Figure 12-2 The initial display of the main Vue window
Let us run the following tests:
 	prompt:> wordcount -x input1     (wordcount.1)
	prompt:> wordcount -wlc input1   (wordcount.2)
	prompt:> wordcount -wl input1    (wordcount.3)
	prompt:> wordcount -w input1     (wordcount.4)
	prompt:> wordcount nosuchfile    (wordcount.5)

The file input1 contains the following line:

		test input file 1
After the execution, a trace file wordcount.trace is created containing the execution information used in feature analysis.

To tell Vue to incorporate the dynamic information from this trace file into its display, click with the left mouse button on the ``File'' button in the top button bar. This will cause the ``file'' menu to pop-up. Click on the ``open trace file...'' entry in the menu. This will open a dialog box as shown in Figure 12-3. (The Windows dialog box looks slightly different.) Select wordcount.trace and click on the ``Open'' button. This will cause Vue to read in the trace file.

Figure 12-3 The trace file dialog box for UNIX
To verify this, you can click the left mouse button on the ``TestCases'' button in the top button bar. A block coverage summary by test case over all files will be displayed as shown in Figure 12-4.

Figure 12-4 The coverage summary by test case
Run wordcount again using input2 and input3 with option -c and -l, respectively, by entering:
        prompt:> wordcount -c < input2   (wordcount.6)
        prompt:> wordcount -l input3     (wordcount.7)

Running these two additional tests causes their dynamic information to be added to the trace file. Note that Vue has highlighted the ``Update'' button in the top button bar, as shown in Figure 12-5, to alert you to this fact. Vue continuously monitors the specified trace files to see if any new information has been added to them. If so, it highlights the ``Update'' button to indicate this to you. You may choose to click on this button now to update the display with the information from the test case you have just run, or you may choose to wait until you have run several test cases.

Figure 12-5 The Update button
Click on the ``Update'' button to tell Vue to incorporate the information from wordcount.6 and wordcount.7 into its display. Figure 12-6 shows the updated display.

Figure 12-6 The updated coverage summary by test case
Now it's time to specify a feature. Click on the ``Features'' button in the top button bar to switch back to the main window of Vue. Click on the ``add'' button in the middle button bar to have a feature editing window pop up as shown in Figure 12-7. By default, all seven tests appear in the dont_know category, which means the user has not yet categorized them.

Figure 12-7 The initial display of the feature editing window
Suppose the feature we have in mind is wordcount's character counting feature (i.e., the -c option). Then we enter the name of the feature, character_counting, in the rectangle next to Feature Name. Enter the corresponding description, the -c option, in the rectangle next to Description. Since wordcount.2 and wordcount.6 exhibit the feature, they should be categorized as invoking tests. To achieve this categorization, select wordcount.2 by clicking on it with the left mouse button, and then click the left arrow button between invoking_tests and dont_know. Apply the same procedure on wordcount.6. This will move wordcount.2 and wordcount.6 from the dont_know category to the invoking_tests category.

Tests wordcount.3, 4 and 7 do not involve this feature. Thus, they should be categorized as excluding tests. To achieve this categorization, select wordcount.3 by clicking on it with the left mouse button and then with the right arrow button between excluding_tests and dont_know. Apply the same procedure on wordcount.4 and wordcount.7. This will move wordcount.3, 4 and 7 from the dont_know category to the excluding_tests category. For tests wordcount.1 and wordcount.5, suppose we don't care. Hence, they remain in the dont_know category. Figure 12-8 shows the resulting display. If all the information is correct, click on the ``ok'' button to close this editing window. This will update the main Vue window as shown in Figure 12-9.

Figure 12-8 The final display of the feature editing window
Figure 12-9 The updated display of the main Vue window
If you make any mistake assigning a feature, you can select the feature to be modified (character_counting in our case) by first clicking on it and then on the ``edit'' button in the middle button bar. An editing window will be displayed (that is the same as Figure 12-8 in our case) for your editing. You may now move tests from one category to another using the techniques described earlier. After you are done, click on the ``ok'' button, thereby closing the editing window and automatically updating the main Vue window to reflect the latest modification. Since there is no mistake involved in our case, instead of clicking on ``ok'', you can click on the ``cancel'' button which closes the editing window without changing the display of the main Vue window.

You can save the present feature description in a file by clicking on the ``save_as'' button in the middle button bar. This will cause a dialog box to appear as shown in Figure 12-10. (The dialog box on Windows looks slightly different.) Enter wc as the name of the file in the rectangle next to the label File name and click on the ``Save'' button. A file named wc.features is created in your working directory containing all the feature descriptions you have entered. (The file extension .features is appended automatically by Vue.) Once you have saved your feature description in a file, you can update it by simply clicking on the ``save'' button in the middle button bar. Vue will reuse the last selected file name and overwrite it with the latest feature descriptions.

Figure 12-10 The save_as dialog box for UNIX

To delete a feature, select it by clicking on it, (character_counting in our case) and click on the ``delete'' button in the middle button bar. A dialog box as shown in Figure 12-11 will appear. If you wanted to confirm the deletion, you would click on the ``yes'' button. This would cause the selected feature to be deleted and the main Vue window to be updated accordingly. Since we do not want to delete the feature, click on the ``cancel'' button to close the dialog box and return to the main window of Vue as displayed in Figure 12-9.

Figure 12-11 The feature deletion dialog box

To use features that were previously saved in another feature file, click on the ``open'' button in the middle button bar. This will cause a dialog box to pop up as shown in Figure 12-12. (The dialog box for Windows looks slightly different.) You would select the file which contains the feature(s) to be imported and then click on the ``Open'' button to have them displayed in the main window of Vue. In our case, there is no need to do so because the feature (character_counting) is already displayed. So, click on the ``Cancel'' button to close the dialog box and return to the main window of Vue as displayed in Figure 12-9.

Figure 12-12 The feature open dialog box for UNIX

The next step is to answer the question: ``Where in wordcount is feature character_counting (i.e., the -c option) implemented?'' To look for program components that are uniquely related to character counting, first select this feature by clicking on character_counting under the ``Feature Name'' button and click on the ``heuristics'' button in the middle button bar. This will cause a heuristics window to appear as shown in Figure 12-13.

Figure 12-13 Heuristics window with heuristic A selected
Vue provides three heuristics. By default, heuristic A is selected. With this heuristic (see Figure 12-13) program components that are executed by any invoking test (wordcount.2 and wordcount.6 in our case), but not executed by any excluding test (wordcount.3, wordcount.4 and wordcount.7 in our case), are identified. In other words, program components that are in the union of wordcount.2 and 6, but not in the union of wordcount3, 4 and 7, are identified.

You can switch to heuristic B or heuristic C as shown in Figure 12-14, by clicking on the corresponding button with the left mouse button. With heuristic B, program components that are commonly executed by all invoking tests (wordcount.2 and wordcount.6 in our case), but not any excluding test (wordcount.3, wordcount.4 and wordcount.7 in our case), are identified. In other words, program components that are in the intersection of wordcount.2 and 6, but not in the union of wordcount.3, 4 and 7, are identified. With heuristic C, program components that are executed by the smallest invoking test (wordcount.6 in our case), but not by the largest excluding test (wordcount.3 in our case), are identified.

Figure 12-14 Heuristics window with heuristic B selected
Instead of using the default heuristic, let us use heuristic B for the purposes of this tutorial. Click on the ``heuristic B'' button. Click on the ``find_code'' button towards the bottom of the heuristics window to close it and have a summary by file displayed in the main Vue window as shown in Figure 12-15. You can have the summary displayed in other formats by clicking on the ``by-type'' or the ``by-function'' button in the middle button bar. To see the source display of the corresponding file, click on a file name in this summary window. In our case, we can only select main.c since wc.c does not have blocks that ``seem to be unique'' to the character_counting feature, the feature for which we are looking.

Figure 12-15 A summary by-file over all selected test cases

The source code of main.c is displayed in Figure 12-16. The scroll bar is a thumbnail sketch of the entire file indicating there are two red spots. Clicking with the left mouse button at any spot in the scroll bar brings the corresponding region of the file into the source window. You can use the arrows at the top or the bottom of the scroll bar to scroll up or down the source file a few lines at a time. You can also drag the mouse up or down the scroll bar with the left mouse button pressed to rapidly scroll up or down the file. In addition, Vue also provides keyboard shortcuts. Pressing the Up or Down arrow key will move the file up or down one line at a time. The PageUp and PageDown keys scroll up and down the file one page at a time, respectively. The Home key scrolls to the beginning of the file, whereas the End key goes to the end of the file.

Figure 12-16 Blocks in main.c that are unique to character_counting

The display in Figure 12-16 shows the resulting code after the first red spot is selected. Analysis of the code reveals that all the highlighted blocks are indeed ``unique'' to the character_counting feature (the -c option).

Similarly, you can view the feature at the decision, c-use or p-use level by selecting the corresponding criterion from the ``Options'' menu as shown in Figure 12-17. For example, the decisions in main.c that are unique to character_counting are shown in Figure 12-18. For each highlight, Vue can further indicate which branch of it is uniquely related to a given feature. In our case it is the true but not the false branch of dochar that is unique to character_counting.

Figure 12-17 The Options menu
Figure 12-18 Decisions in main.c that are unique to character_counting

You can make your own customized heuristic by moving tests around as shown in Figure 12-19. In this case, program components that are executed by wordcount.2 but not wordcount.3 are identified. Recall that test wordcount.2 is:

	prompt:> wordcount -wlc input1   (an invoking test)
and test wordcount.3 is
	prompt:> wordcount -wl input1    (an excluding test)
Figure 12-19 Heuristics window with a custom heuristic selected
This heuristic follows the strategy discussed in Section 12.1, Background by selecting an invoking test (wordcount.2) and an excluding test (wordcount.3) which have very similar execution traces. In fact, the only difference between these two tests is that one executes the -c option and the other does not. Unique code so selected is the same as that selected by heuristic B.

In some situations, the highlighted code may be a super set of the unique code with respect to a certain feature. Nevertheless, code so selected provides a good starting point for mapping features to program components at different levels of granularity.

To quit Vue, click on the ``File'' button in the top button bar, then click on the ``exit'' entry of the menu that pops up.

Since you have already run several tests and saved the information in wordcount.trace and wordcount.features, the next time you invoke Vue you can use the command:

	prompt:> xsuds *.atac *trace *features
to import them directly as command line arguments instead of loading them interactively through the graphical interface.



[Top] [Prev] [Next] [Index] [TOC]