• No results found

Packages and Dependencies

not represent a subsystem: it is merely a container for the two components X and Y. The example shows that the responsibility of deciding whether a view is relevant or not is carried by the reverse engineer. During the navigation process, he has to analyze each view and decide whether all the modules in the view are at the right abstraction level or not. After each exploration operation, the reverse engineer has to address the following questions for each of the modules in the view:

1. Is the module at a higher abstraction level than needed? Then expand it. 2. Is the module at the right abstraction level? Then do not expand it. 3. Is the module at a lower abstraction level than needed? Then collapse it. 4. Is the module not relevant for the current architectural view? Then filter it out.

5. Is there a set of modules that need to be grouped into a single component? Then merge them together.

The challenge that results from here is providing a way to automate the module characteri- zation process such that the user does not have to analyze every module in the working set after every exploration operation.

Our solution to this problem is based on a classification of modules based on their relation with the other modules in the system and on their internal structure. The result of the classi- fication is a set of module patterns that have associated exploration operations that need to be performed once the modules appear in a view. The solution that we present in the remainder of this chapter assumes that the following constraints are respected:

• The system is written in an object-oriented language.

• The system is decomposed in a rich hierarchy of modules and submodules. This is usually the case in large software systems.

• The architectural components are found at diverse depth levels in the module hierarchy.

6.3

Packages and Dependencies

In the remainder of this chapter we use examples of modules from several Java case studies, and we consider the system decomposition to be represented by the package hierarchy.

Packages are the main mechanism for the decomposition and modularization of a system written in Java, and they are essential for the understanding and maintenance of non-trivial programs. The Java language specification defines packages as scoping mechanism. In practice the programmers use packages also as a mechanism for the hierarchical organization of the source code. The semantics of a package then become ambiguous since it might refer to the entire hierarchy under it or simply to the classes in the scope of the package.

To avoid confusion we introduce two terms for the two concepts. We call a restricted package the root of the package hierarchy, or the package seen as a scoping mechanism, and an extended

package the package as a module, which is organized hierarchically [LLG06]. When we talk

112 6.3 Packages and Dependencies containers for classes: the restricted packages contains only the classes in its own scope while the extended package contains all the classes in its scope together with all the classes in the extended packages it may contain.

Dependencies between packages

Some languages support explicit relationships between modules. This is the case with import statements in Java or the prerequisite relationships between packages in Visual Works Smalltalk. However there are two problems with these explicit relationships:

1. They are not universal. Software systems written in the C programming language do not have the concept of a module as an explicit entity. Modules are implicitly inferred from the directory structure of the project. Since there is no concept of a module, there will not be a concept of an explicit inter-module dependency.

2. They are insufficient for some types of analysis. For some understanding tasks, the depen- dency relations need to be aggregated from lower level packages to higher level ones and from the classes to the packages. Sometimes even the number of the dependencies be- tween two packages is important for the understanding of the relationship between them. To address these two problems we lift relationships between the low-level entities such as classes and methods to the package level. The relationships between the low-level entities are explicit in the source code and they can be extracted from the code. Dependencies can be either invocations between methods of a class, inheritance relations between classes or access relations between classes. These types of relations are defined by the FAMIX language-independent meta- model that describes the static structure of object oriented software systems1.

Based on the two perspectives on a package that we have presented earlier, there are two types of package dependencies:

A B C1 C D C2 Restricted dependency Invocation Extended dependency C4 C3 C5

Figure 6.3. The two types of dependencies between packages

• A Restricted Dependency is the dependency between two restricted packages. It represents the set of all the low-level, explicit dependencies between the elements contained in the two restricted packages. In Figure6.3the dependency between the restricted packages B and D consists of the invocation between C1 and C2. There is no dependency between the restricted packages A and C.

113 6.4 Vertical Package Slices