Here we're taking java as example language with maven as build tool; however with any language, structure still remains the same.
In general:
Following is the recommended structure (3 Maven modules):
- Core
- Contains "entity" POJOs, "DAO" classes, "Service" classes (aka "Processor" classes or "Actor" classes) which contain (caller-agnostic) business logic, "Helper" classes (aka "Utility" classes)
- Classes to be annotated with javax.* annotations where applicable (e.g. javax.inject.* for dependency injection, javax.persistence.* for modelling database entities etc.)
- This Maven module must not have dependency on Hadoop or Guice or Jackson or Dropwizard or Dropwizard's underlying libraries (that is, anything library specific to caller)
- May depend on Hibernate
- Web Service
- Contains Resource classes, Guice module classes
- This Maven module typically depends on Dropwizard, Guice, Jackson etc
- This layer should be as light as possible with minimal logic (e.g. translating data from Core layer to DTOs). This layer must not contain business logic
- Job
- Typically contains Hadoop-related classes (e.g. Mapper classes, Reducer classes, Driver classes etc) and Azkaban entry-point classes.
- This Maven module typically has dependency on Guice, Hadoop etc.
If you want to standardise API contracts with your clients (which is a good thing btw), following needs to be done:
- Break your Web Service module into two modules:
- DTO
- To contain POJOs that represent either of below:
- API request or response classes
- Message payload structure in queues or topics
- Must depend on jackson-annotations only (that is, this maven module must not depend on jackson-core or jackson-databind)
- If Lombok is added as a dependency, the scope of the dependency should be "provided".
- Web Service
- (as explained above)
- Publish DTO module to Flipkart's artifactory.
- Any change in contract (howsoever minimal) must create a new version of artifact
In general:
- Maintain clear separation of concerns between the layers
- Decouple your domain objects from your data transfer objects
- Do not create maven modules unnecessarily. This creates unnecessary inter-module dependency and increases chances of jar hell.
- Follow Single Responsibility Principle. Also, don't make mutually exclusive code interact with same database objects.