Java Champion / JavaOne Rockstar Adam Bien (adam-bien.com) is a self-employed consultant, lecturer, software architect, developer, and author in the enterprise Java sector. He is also the author of several books and articles on Java and Java EE technology, as well as distributed Java programming. adam has posted 59 posts at DZone. View Full User Profile

Modules, Cycles, Unwanted Friends - The Modularity Challenges In Enterprise Projects

03.12.2010
| 3345 views |
  • submit to reddit

Building modules and components is not that hard. You "only" have to encapsulate the internal component implementation and expose a clean and easy to use interface. ...at least on paper. In practice you will be confronted with the following challenges in the early iterations:

  1. The external interface is too coarse and far less interesting for internal reuse, than you had thought.
  2. The interesting things are residing inside the component. They are, however, well encapsulated and not accessible from the outside.
Example: you have two independent components; customermgmt and address / geo-location service. The module customermgmt exposes CRUD services and the address component extensive search capabilities. So far the world is perfect.
Now: a customer has an address - how to model that? The external, customer contract will have to reference the address somehow. That is often modeled as a direct relation between DTOs (just a getter). The external view of the customer component is now dependent on the address component. The implementation is still independent. The relation between the customer and the address has to be persisted somehow. And now the trouble starts. Now the implementation of the customer component is dependent on the address component - because of direct (JPA) link between both modules. Now the internal implementation *and* the component contract are dependent on each other. You are using JPA 1.0 - and your database experts just don't want to introduce an additional mapping table between the customer and the address. So you have to model a bi-directional relation between the customer entity and the address (introducing a back-link with a mappedBy attribute). Now you get a bidirectional dependency between the implementation of your component - the external dependency of the customer can remain unidirectionally dependent on the address. This is only true if you are using DTOs. So you get two components which should be independent of each others, but are actually tightly coupled. Your modules have to expose everything - if you are using Java EE 6 - the DTOs and JPA-entities are dependent of each other - probably only the very thin boundary may remain independent. In practice you will get e.g. an invoice module in addition, which will be dependent on both the customer and the address.... You can do the following to "improve" the situation:
  1. Factor out all entities into a common package. Often called "domain", "model" or even "common". Such a common package is not cohesive (it contains multiple business concepts) and also not very good to maintain (the generic names have nothing to do with the actual business). This approach looks great ...on paper.
  2. Drop JPA-relations and introduce proxy-objects, which contain the ID and can be resolved on demand. This will significantly increase the amount of code and will hit your performance. You will be not able to use joins...
  3. Allow bidirectional friend-dependencies between modules. In that case it will be hard to introduce a framework like OSGi, jigsaw or something else. But you can still put all "business components" into few modules. Then the real benefit of OSGi, Jigsaw etc is questionable.
  4. Remove OR-mappers and go with "plain" JDBC. Let the DB handle the dependencies for you. In most cases this is not really a maintainable option.

Dependencies between persistent objects from different modules are practically not existing in other domains like IDEs, servers or plugins, but are the standard case in enterprise projects.
So, you shouldn't kill any OSGi project - you should implement some typical use cases (PoCs) with modularity solution of your choice before the project really starts. This is actually independent of any framework like OSGi, jigsaw or EMS (esoteric module system) :-).

From http://www.adam-bien.com

Published at DZone with permission of its author, adam bien.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Scott Ferguson replied on Fri, 2010/03/12 - 1:09pm

This example sounds like it's relying on an over-constrained module system or rather attempting to use too fine-grained modules when the natural module for this problem is larger. Modules are not packages.

 If the database implementation itself has a codependency, that's an indication both entities belong in the same module, though not necessarily the same package. A module is really all about providing a unified concept, not necessarily a single component.

That's why the Java module language features being implemented by Jigsaw are so exciting. Finally, we have a way to express modularity in our code and have it be validated by the JDK runtime. The archive/repository management stuff in jigsaw and osgi are nice, but not nearly as critical to good design as the language support.

 

 

adam bien replied on Mon, 2010/03/15 - 3:04am in response to: Scott Ferguson

If the database implementation itself has a codependency, that's an indication both entities belong in the same module, though not necessarily the same package.
Exactly - thats the challenge. You will end up with 1-3 (OSGi) plugins. The question to ask then - are 1-3 plugins still beneficial? Packages / namespaces are crucial for maintenance - full agreement. Even so you will get bidirectional references between packages...

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.