Thursday 26 April 2018

Structuring Rest Based Project

Here we're taking java as example language with maven as build tool; however with any language, structure still remains the same.
Following is the recommended structure (3 Maven modules):
  1. 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
  2. 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
  3. 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.