Core Java

Analyze package dependencies with structure101

One key to a stable application is a well-structured codebase. We know that we should build as many black boxes as possible, because as soon as one black box is finished, we no longer have to think about its interior. You just use the code you or another team member has written through a well-defined interface. This gives you the possibility to concentrate on the next feature you want to add.

When we think about black boxes we often have classes or whole jar packages in mind. Classes should of course be black boxes, no discussion about that. The same is true for jar packages. But in-between classes and jar packages there is another level of structure, which is often not seen this directly as a black box: packages.

Packages are often second class citizens and their interrelationship is not analyzed this thoroughly. But there is a great tool for such analysis: Structure101. It in general helps you to monitor and verify the dependency structures and complexity of your project by the means of well-organized diagrams.

So let’s start with a sample project. I have taken one of my own projects for this: japicmp is a tool to compute the differences between the API of two jar archives in means of what methods and classes have changed. structure101 has a great composition view, which shows you the dependencies between the packages of a project. This is how it looks for the current version of japicmp:

structure101_before

Cleary we can see for example that the cli package, which is responsible for the command-line parsing, uses the exception as well as the config package and is used itself by the main package, where the main() method resides. With the cli package everything seems to be OK. But what about the three packages cmp, util and model. The difference computation between the classes and methods, i.e. the business logic, resides in the package cmp. Hence it should use the model as well as the util package. But these two packages should not have any backward dependencies. This problem is also shown in the matrix view:

structure101_before0_matrix

When we take a closer look at the tangle between these three packages, we see that the class AccessModifier, which is located in the cmp package, is used from the util package:

structure101_before2

Beyond that, this class is also used in the model. This clearly indicates that the class should rather stay in the model package as in the cmp package. This seems to make sense, as the access modifiers of a class or method are part of the model of a jar archive and do not belong into the business logic. If we move this class to the model package, we get the following result:

structure101_after

This looks much better. We do not have any tangles within the package structure. The nice layout also shows clearly that the whole application depends on the model, as the package is located at the bottom of the diagram. The business logic, which resides within cmp, is called from the main package and uses util, config and the model, as it should be. The same is true for the output package, where the implementations for the cli and xml output reside. This package uses the config as well as the model, once it is computed.

Conclusion

Packages should not be second class citizens but help you to structure your application such that it is easy to overview the code and separate functionality. Tools like structure101 help you to analyze the dependencies between packages and therefore let packages be an important level between the jar on the one side and the class on the other side.
 

Martin Mois

Martin is a Java EE enthusiast and works for an international operating company. He is interested in clean code and the software craftsmanship approach. He also strongly believes in automated testing and continuous integration.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button