One of my personal bugaboos relates to the whole topic of package dependencies and dependency management. It’s a topic that people don’t need think about very much when they’re dealing with small projects (say, 10,000 to 20,000 lines/statements of Java code), but as the size of the application grows, proper packaging is crucial to being able to evolve the an application gracefully.
We have an application that’s moderately big: it’s currently somewhere in the neighbourhood of 200,000 statements and maybe another 100,000 statements of test code. And it is very easy to feel the effect of poor package structure on that kind of project.
I’ve really only ever read one book that covered the significance of package dependencies: Large Scale C++ Software Design by John Lakos. Although he talks about C++ (which doesn’t have a formal notion of packages), a lot of his insights about package structure directly translate to Java.
There are two neat tools that I often find myself using to analyze package structure. The first one is Mike Clark’s JDepend tool. It was the first tool I ever encountered that tried to analyze package dependencies. It’s a nice tool, but it’s made even easier to use by an Eclipse plugin.
Another tool, which really shines, is made by Compuware. The tool used to be called “Pasta” or the “package structure analysis tool”, but is now called OptimalAdvisor. The appeal of OptimalAdvisor is based on two things:
- Pictures! OptimalAdvisor renders your package structure as a big picture, showing which packages are related to other packages.
- Layering. OptimalAdvisor nicely articulates the concept of package layering over here.
OptimalAdvisor is a really nice tool, and my only beef with it is that it uses a notion of packages that is automatically hierarchical. I can’t see a picture of my whole application — it wants to assume that each qualifier in my hierarchy is meaningful.
If you use any number of open source components in your code (like Log4J or Struts, or something like that), you’ll quickly find the limitations of the hierarchical model of packages. For example, at the highest level, OptimalAdvisor would tell me that the “ca” (the first part of “ca.intelliware.example”) level depends on “org” (the first part of “org.apache.struts”). That’s the only extent to which you can visualize how your code depends on Struts, and that’s not terribly useful.