• Ei tuloksia

Class and object representations

In document Visual testing of software (sivua 34-37)

Technique Representation

Plottable arrays Other arrays

Arrays as lists pp pp

Arrays as tables pp ppp

Arrays as plots ppp

-Arrays as images ppp

-Table 4.3: Array representations

Figure 4.7: Example of objects in a Java program shown using DDD

CHAPTER 4. VISUALISATION 24

• Objects that take up a large amount of screen space should not be nested inside another object. Alternatively, maximum size restrictions can be imposed on objects and propagated to their subobjects as in Amethyst [39].

It should be noted that any object in memory in a C/C++ program can be referred to by a pointer, including the fields of a struct. In fact, in most implementations, every single byte of data and code in the program can be pointed to, irrespective of what it contains.

This means that not only do the same problems with nesting apply to C/C++ programs; the problems are actually worse.

Ownership-based nesting

One way of determining whether objects unambiguously belong to a single object is to calculate theownership treeof the graph (as defined in e.g. [45]) consisting of the objects and their references to each other. An objectxowns another objectyif all reference chains from the root objectr(the only object that can be accessed without references from other objects) toypass throughx. An objectxis an ancestor ofyin the ownership tree if and only ifxownsy. The parent ofyin the tree is then the object that ownsybut does not own any object that ownsy.

The ownership tree suggests a natural nesting hierarchy with an interesting property:

Lemma 1 An object y can only be referred to by objects that are owned by y’s parent p.

Proof: p ownsybut notx. Thus, a path exists from the root node toxthat does not pass throughp. Let us assumexrefers toy.ycan therefore be reached from the root node through xwithout passing throughp, contradicting p’s ownership ofy. Thus,xcannot refer toy.

If we nest objects inside the object that owns them, Lemma 1 implies that references toycan only come frompor an objectzinsidep. However,zis not necessarily contained directly inp(i.e.pneed not bez’s parent). This means that references upward in the nesting hierarchy are still possible.

Ownership-based nesting has the advantage of automatically grouping objects together in a reasonably meaningful way. However, it has the distinct disadvantage that changes in the references between the objects can cause the nesting hierarchy to change radically, which may render it confusing to use.

As a Java method can read static variables and its own local variables at any time and start traversing the object graph from there, it seems reasonable that the root object should have references to all objects that are referred to by local and static variables. This, however, means that copying an object reference into a local variable or calling an instance method automatically means that the referenced object is considered to belong to the root.

This leads to even more unintuitive changes in the nesting. Also, the ownership diagram depends on the currently active thread. In conclusion, ownership-based nesting can change suddenly in some quite common cases. It is therefore not suitable for visual testing.

Selection based on object type

Due to the problems with nesting, it seems best to default to arrows in all cases except objects that cannot contain references to other objects and other types for which the nested appearance is known to be desirable, such as arrays. It makes sense to allow the user to adapt the default settings to his own code and needs by specifying the types of object that should be shown as nested by default.

Manual selection

The user should also be able to override the automatic nesting choices (based, for example, on the class of the object) individually for every object. This is especially useful if an object that is usually shown nested is unexpectedly referred to by several different objects.

children[1]

TreeNode 57 TreeNode 63

children[0]

key 123

TreeNode 123

children

key 456

children

TreeNode 63

key 456

TreeNode 57

children

Figure 4.8: Example of labelled references

4.3.2 Static fields

In order to show the values of static fields, classes can be displayed in the same way as ob-jects. In other words, classes can be considered singleton objects, where the static methods and fields are the methods and fields of the singleton object.

4.3.3 Labelling

To help the user identify objects and their types, each object should be labelled with its type and a unique identifier (e.g. “instance of java.lang.String, id 1234”, or more briefly “java.lang.String1234”). Classes can be labelled with their name (e.g. “class java.lang.String”). The identifier for an object should be unique at least over the ob-ject’s lifetime. There is even less potential for confusion if the identifier is unique over the program’s entire lifetime.

In languages with pointer arithmetic, such as C++, pointers can be used as identifiers.

Practically all debuggers for C and C++ use pointers to refer to heap-allocated objects.

In cases where the identity and type of an object are uninteresting, the label can be left out to save space. This is useful when visualising e.g. arrays (as illustrated in Figure 4.3) or strings.

4.3.4 Methods

Methods can also be shown in objects and classes for reference and to allow convenient method invocation. In most cases, however, displaying all available methods for every ob-ject is a waste of space. For invocation purposes, putting the methods for each obob-ject or class in a pop-up menu that is accessible e.g. by right-clicking on the object or class is almost as convenient as showing the methods all the time and occupies much less screen space.

Methods can also be shown as part of the code visualisation, as described in subsec-tion 4.4.4.

4.3.5 Indicating the origin of a reference

When showing references as arrows, there are two different ways to indicate which field of an object contains the reference represented by an arrow.

One is to label the arrow with the name of the field and place the start of the arrow on the edge of the referring object, as in DDD. An example of this style is shown in Figure 4.8.

I will refer to this style aslabelled references.

CHAPTER 4. VISUALISATION 26

key 123

TreeNode 123

children

key 456

children

TreeNode 63

key 456

TreeNode 57

children

Figure 4.9: Example of nested references Technique Representation

Objects Objects without nesting pp Objects with nesting ppp

Labelled references pp

Nested references ppp

Table 4.4: Object representations

The other is to place the start of the arrow in an area reserved for the field inside the object (the proposed pointer notation for Amethyst). Essentially, instead of a value the field of the object would contain a small placeholder from which an arrow extends. A null reference can be shown e.g. as a placeholder without an arrow. An example of this style is shown in Figure 4.9. I will refer to this style asnested references.

The latter approach seems to be less prone to clutter than the former, as the field names are shown tidily next to each other instead of appearing somewhere along the arrow. There-fore it is easier for the user to visually connect the arrow with the right field. Also, the latter approach works much better with objects nested within each other, as it allows arrows to clearly originate from a nested object instead of adding a complex label to describe the relation.

Also, the former approach becomes confusing if one wishes to mix nested and non-nested child elements in the the same array. This problem can be circumvented by display-ing the labels of all the referenced objects inside the array (like DDD does) as shown in Figure 4.8 or showing indices for the objects that are shown nested inside the array.

In short, the nested reference view is simpler, clearer and more flexible than the labelled reference view.

4.3.6 Evaluation

Showing a graph of objects without nesting is acceptable in many cases, but nesting can be used to improve clarity noticeably. Similarly, labelled references between objects are often acceptable, but nested references are clearer. This evaluation is summarised in Table 4.4.

In document Visual testing of software (sivua 34-37)