14

Having a bit of a debate about the starting project structure (using Maven/Eclipse) for a big Java application.

Option 1:

entities (i.e. the whole database using Hibernate classes-first)
services (i.e. sets of read/write operations on the entities)
app (perhaps split up more further down the line)

Option 2:

area1-entities
area1-services
area1-app
area2-entities
area2-services
area2-app
...
(where area1, area2 etc. are functional areas of the system)

Option 2 will clearly result in a great deal more Maven projects/modules and means the classes that would generate the database are distributed amongst multiple projects. Could anyone advise pros/cons of each approach?

migrated from stackoverflow.com Oct 6 '14 at 13:47

This question came from our site for professional and enthusiast programmers.

  • 3
    Neither. IMHO (here we go) we should quit with seperating on technical layers that simply leads to a big ball of mud. Instead package functionally. Just area1/area2 which should contain the core of your application (entities, services (split in public interface and package private implemenation), repositories (if needed). Now you should connect your web/ws/messaging layer to that core. You might want to take a look here and here – M. Deinum Sep 4 '14 at 9:24
  • It still is opiniated :). But I'll do some polishing to put it in an answer. – M. Deinum Sep 4 '14 at 9:35
  • You might want to check out stackoverflow.com/questions/11733267/… – geoand Sep 4 '14 at 9:48
  • Thanks but this question is about project structure rather than package structure – Steve Chambers Sep 4 '14 at 9:54
26

I would suggest doing neither.

Trying to enforce a technical layering with a package structure leads to a lot of entanglement in your application. Not to mention the fact that we try so hard to hide everything behind a service interface and the first thing we do (mostly due to packaging) is make everything a public class. This becomes painful when there is a technical separation between a x.y.z.service and x.y.z.repository package, now everything can access the repository. Boom there goes your encapsulation inside the service layer.

Instead you should follow a more functional and onion based approach (clean architecture, hexagonal architecture). This is also nicely in line with the Single Responsibility Principle (when applied to a package) and also in accordance with the packaging principles

  1. Things that change together are packaged together
  2. Things that are used together are packaged together

Oliver Gierke has written a nice post on packaging components together in Java. Simon Brown has written a more general story on the subject.

I would strive for a core package structure like the following to hold the core of your application:

x.y.z.area1
x.y.z.area2

Now if you have a web interface you add, for instance, a web subpackage, for webservice a ws or rest package to hold only that. It basically connects to the core.

x.y.z.area1.web
x.y.z.area1.ws
x.y.z.area2.rest

Now you could consider reusing the objects from inside your core into the other layers, but IMHO it is better to use a specific domain for that layer. As, just as with Object to SQL mapping there is (often) a mismatch in what we want show on the screen or use as XML in the webservice and how the business logic is implemented. Depending on the complexity of the business and web domains you could consider them as seperate problem domains to solve which need to be connected, basically 2 different bounded contexts.

To use a quote from a CQRS resource

It is not possible to create an optimal solution for searching, reporting, and processing transactions utilizing a single model.

Don't try to put everything into a single (domain) model, separate the responsibilities. You probably end up with more (smaller) classes but a cleaner separation between the layers of your application.

Final Note

Remember creating a architecture is deciding on the trade-offs of one solution to the other. It depends highly on the complexity of the domain and should mainly be driven by the functional requirements of your application. However it is influenced by the non-functional (performance, security) and environmental constraints (language to use, platform, experience). And architecture, like coding, is never finished each new requirement can (and maybe should?) lead to a redesign of the application.

Disclaimer

Yes I also tried to put everything in a single model, and yes I also tried to use a technical separation in my applications. However after a couple of years of experience in creating entangled application layering (at first it seems a good idea, then the application starts to grow...) I figured there must be another way.

Links

  1. Clean Architecture, Uncle Bob Martin
  2. Hexagonal Architecture (aka Ports and Adapters), Alistair Cockburn
  3. Whoops where did my architecture go, Oliver Gierke
  4. Principles of OOD, Uncle Bob Martin
  5. Mistakes when applying DDD, Udi Dahan
  6. Bounded Contexts, Martin Fowler
  7. Architecturally Evident Coding Style, Simon Brown

Books

  1. Growing Object-Oriented Software, Guided by Tests
  2. Java Application Architecture: Modularity Patterns with Examples Using OSGi (Robert C. Martin Series)
  3. Domain-Driven Design: Tackling Complexity in the Heart of Software
  4. Software Architecture for Developers
  5. Implementing Domain Driven Design

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.