Analyzing Alternative Class Encapsulations in C++ and Java

Encapsulation is the major means of achieving cohesion in an object oriented program. Suboptimal encapsulation, such as too many objects within a class, unrelated objects within a class, or tightly related objects spread across too many classes, can lead to problems in the extensibility, testability and reuse of the software.

Imagix 4D's class level metrics, particularly the Chidamber and Kemerer metrics, provide insight into the overall quality of a system's object oriented design. They also highlight specific areas where coupling and cohesion are a problem. You can then use Imagix 4D source code analysis and visualization features to study the specifics of your code's fundamental design and implementation.

The particular focus of this app note is how, working with existing source code, you can experiment with alternative encapsulation strategies and study the impact they would have on your code's architecture.
One of Imagix 4D's built in abstraction features is that symbol level relationships are abstracted to the symbols' containers. So if classA::methodA calls classB::methodB, classA is considered to call classB. The same is true for files. This is the basis of Imagix 4D's Class Calls and File Calls views.

In this Class Calls view, you can quickly see the classes calling into and called from CFolderScanItem.

To view these classes and their calling relationships in more context, you can switch to the Subsystem Architecture Diagram. Here, you can see where the classes exist within the directory and file hierarchy. You also gain an understanding of where the classes fit within the overall subsystem layering.

The layout of the diagram reveals the layering of subsystems. At each level of subsystem detail, subsystems are placed so that any function calls they make are downwards or sideways but never upwards. For example, the layout of classes within queue.h is consistent with what was displayed in the Class Calls view.

By switching to the UML Class Diagram, you can see the specific function calls being abstracted in the earlier views. You're able to get a sense of how many calls are being made and which specific functions are involved.

These relationships contribute to the coupling between classes. By examining the specifics, you're able to understand the implementation details suggested by the metrics, look for patterns in the inter-class coupling, and identify candidate classes for restructuring.

The UML Class Diagrams include controls over which types of members and inter-class relationships are displayed. When switching from a Class Calls view, the diagram automatically focuses on those specific member functions involved in function calls with members of other classes. (Full Size)

Depending on the number and inter-relatedness of the classes being examined, the UML Class Diagram can become fairly dense. Once you've got some initial ideas about encapsulation changes, you might want to examine the specific classes in more detail. You can examine the detailed relationships between pairs of classes to understand the particular functions (methods) and variables (attributes) that are involved.

Through Imagix 4D's Analyze feature, you can examine the inter-class associations in detail. Here, the calls between CQueueView members and CFolderScanItem members are displayed.

Imagix 4D's Subsystem Architecture Diagram allows you to edit as well as examine an architecture. You're able to create, delete and move subsystems (classes). And you can easily drag and drop members (functions and variables) from one subsystem (class) to another.

In this way, you can experiment with different encapsulation strategies quickly and easily, before you change a single line of code. You're able to graphically analyze what would happen to the coupling and cohesion if you were to change your class partitioning. You can even run subsystem metrics to measure the impacts of the potential changes.

By moving members between subsystems, and even splitting or merging subsystems, you can experiment with different encapsulation strategies. Here, the impact of splitting CFolderScanItem into two classes is seen.

Optimizing Coupling and
Cohesion in C++ and Java