Sponsored Link •
Can you divide your logical layers into separate deployable units without changing a single line of code? You should be able to!
Recently I suggested that we should be separating layers into separate deployable units. Not everyone agreed with this physical separation, but I do think we can all agree that applications should be layered. So what exactly does it mean for an application to be layered? Does it mean we only layer our classes? How about our packages? Maybe something more?
To help answer these questions, let's look at some of the reasons why we layer an application. We'll assume three principle layers - user interface, domain logic, and data source. Here are some of the benefits of layering an application.
I suppose we could pretty easily come up with other advantages, and maybe even some disadvantages, but that's not the point here. Instead, let's consider for a moment that we at least separate layers based on class responsibility. That's a start, but I suspect it will become a maintenance burden since it's difficult to distinguish layers within a package unless we come up with a class naming convention.
So minimally, we want to separate layers at the package level, which brings a bit more distinction to the various layers. Now we can begin to think about enforcing the layering scheme. JDepend allows us to create test cases that enforce package dependencies. If we violate these dependencies, the tests fail. And to a certain extent, we've achieved some of the advantages cited above. But how are we going to reuse layers in different contexts if all layers are bundled into the same deployable unit? How easy is it going to be to swap layers with new implementations? And if everything is bundled into the same deployable unit, are we ever really certain that the test suite is sufficient enough to verify all layer dependencies? Even one violation in the dependency graph between layers means we really don't have a layered application.
Nonetheless, separating layers by package is the most common approach. We take all that good design stuff we've done to help us realize the benefits listed above, and then bundle it into deployable unit(s) that give no attention to layer boundaries. We say we have a layered application, but in reality, do we?
Alas, we can prove we have a layered application that achieves the benefits listed above. By performing a levelized build, where each layer is compiled with only the desirable dependencies in the build classpath, we can verify the application layers. We should be able to do this without changing a single line of code. Instead, we should only need to change the build script. Any violations among the various layers results in a failed build. Even if we don't presently divide layers into separate deployable units, if we have a layered application, we should be able to do so. I challenge you to try it.
|Kirk Knoernschild is a hands-on software consultant with over ten years of industry experience, and is passionate about using leading best practices to build better software. Kirk is the author Java Design: Objects, UML, and Process, published in 2002 by Addison-Wesley. He frequently contributes to various technical publications, and actively updates his personal website, www.kirkk.com, with new articles and whitepapers on a variety of software development topics. He is also the founder of www.extensiblejava.com, a growing resource of design pattern heuristics in Java.|