Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Springer Science - 2005 - Reverse Engineering of Object Orie.pdf
Скачиваний:
17
Добавлен:
15.08.2013
Размер:
6.11 Mб
Скачать

5.2 Interaction Diagram Recovery

91

Reverse engineering of the interaction diagrams from the code can be conducted either dynamically or statically. Dynamic extraction of the interactions among objects requires the availability of a full, executable system, which is run with some predefined input data. The statements issuing calls to methods are traced during the execution, with information for the unique identification of the source and target objects. The main disadvantages of this approach are that it does not apply to incomplete systems, but only to whole, executable ones, and that the resulting diagrams describe the system for a single execution with given input values. A static, conservative analysis of the code for the reverse engineering of the interaction diagrams addresses both problems. However, it may overestimate the set of admissible behaviors. This is why these two kinds of diagrams complement each other and it is desirable to have both of them during reverse engineering of a given Object Oriented system.

5.2 Interaction Diagram Recovery

The static recovery of the interactions among objects is done in two steps: first, the objects created by the program and accessible through program variables are inferred from the code. Then, each call to a method is resolved in terms of the possible source and target objects involved in the message exchange.

Fig. 5.1. Flow propagation specialization to determine the set of objects allocated in the program that are (possibly) referenced by each program location.

A static approximation of the objects created by a program and of their mutual relationships can be obtained by performing a flow propagation inside the OFG, as described in more detail in Chapter 4. For the reader’s convenience, the rules for the generation of the related flow information are reported also in Fig. 5.1. Each object allocation point in the program gives rise to an object identifier where is the object’s class name. Propagation of such object identifiers along the program’s data flows (i.e., in the OFG)

92 5 Interaction Diagrams

allows associating each variable with the set of statically determined objects

it may reference.

 

The set of objects

extracted from a program approximates the set of

objects the program may create at run time. The main source of approximation consists of their multiplicity: since it is impossible to determine statically the number of times a statement is executed, the actual multiplicity of each object is unknown.

During interaction diagram construction, source and target of method invocations are resolved into a set of statically determined objects An alternative would be associating them with the respective classes, instead of their instances. However, the first choice provides a better approximation than just using the class of the objects that are invocation sources or targets. In fact, in the resulting interaction diagrams, objects of a same class allocated at different program points are distinguished in the first case, while they are represented as a single element in the second case. Moreover, objects belonging to a subclass of the declared class are assigned the exact type, as obtained from the allocation statement, while the analysis of method invocations at the class level does not allow distinguishing instances of the given class from instances of the subclasses.

Fig. 5.2. Algorithm for the static resolution of a method call.

Once the objects referenced by program locations are obtained by the flow analysis on the OFG, method calls can be resolved by means of the algorithm shown in Fig. 5.2. Given a statement containing a call expression of the form p.g()inside a method f of class A, the source objects and the target objects of the call are respectively those referenced by the this pointer of the current method (out[A.f.this]) and by the location p (out[A.f.p] or out[A.p] in case p is a class attribute).

More complex Java expressions involving method calls can be easily reduced to the case reported in Fig. 5.2. For example, if a chain of attribute accesses precedes the method call, as in p.q.g(), the invocation targets are obtained from the last involved attribute: out[B.q], where B is the class of the attribute q accessed through p. When another method call precedes the one

5.2 Interaction Diagram Recovery

93

to be solved, as in p.f().g(), the related return location can be used to determine the targets of the call: out[B.f .return], where B is the class of the method f accessed through p.

The procedure resolveCall given in Fig. 5.2 returns a pair of sets, sources and targets, containing the object identifiers that are statically determined as respectively possible source or target objects of the given invocation. The source and target objects returned by the procedure resolveCall will be connected by a call relationship in the interaction diagrams.

eLib example

Let us consider the method addLoan from class Library (line 40). It contains four method calls (lines 42, 43, 45, 46) that must be resolved before constructing the interaction diagrams.

Fig. 5.3. Portion of OFG used for call resolution.

Fig. 5.3 shows the portion of OFG that contains the information required for the resolution of the four calls inside method addLoan. The object Library1, allocated at line 348 and assigned to the static attribute lib of class Main, is the object referenced by this inside addLoan. The object Loan1, allocated inside borrowDocument at line 60, is passed as the parameter loan to addLoan. The attribute user of class Loan is returned by the method getuser of class Loan and is assigned to the variable user (line 42), a local variable of method addLoan. The set of objects possibly referenced by the attribute user of class Loan was determined in the previous chapter (see

94 5 Interaction Diagrams

Fig. 4.9). In Fig. 5.3 it is represented as the out set of node Loan.user. By propagating such values in the OFG, the out set of Library . addLoan. user is computed. Similarly, the OFG edges that lead to Library.addLoan.doc (the local variable doc inside method addLoan) indicate that it references the objects stored inside the attribute document of class Loan. These were also determined in the previous chapter (see Fig. 4.9) and are reported as the out set of node Loan.document in Fig. 5.3.

The out sets reported in Fig. 5.3 can be used to resolve method calls, according to the algorithm in Fig. 5.2. The resulting sets of source and target objects are shown in Table 5.1. The source of the calls is the set of objects possibly referenced by this in method addLoan, that is, the set out[Loan.addLoan.this] in Fig, 5.3. Targets are obtained similarly, as the out sets of the locations involved in the four calls (resp. loan, loan, user, doc inside method addLoan). The content of these sets, shown in Fig. 5.3, is reported in Table 5.1 under the heading “Targets”.

Given the resolved method calls (sources and targets), it is straightforward to either build the sequence or the collaboration diagram. Figure 5.4 depicts both of them. The first call issued inside method addLoan is a call to method getUser and is made on the object Loan1 (allocated at line 60). The second call (getDocument) also has Loan1 as its target. Then, method addLoan is invoked either on the object User1, an object of class User allocated at line 382, or on object InternalUser1, an object of class InternalUser allocated at line 390. The last call (still addLoan) has three possible target objects: Book1, TechnicalReport1, Journal1 (resp. allocated at lines 406, 414, 422). The source object of all these calls is Library1.

In Fig. 5.4, the associations between objects shown in the collaboration diagram at the bottom are those recovered during reverse engineering of the object diagram, as described in Chapter 4.