DDD and package name improvements

Layers within microservice:

  1. Presentation layer
    1. Application (package: org.openlmis.fulfillment.service):
      1. Should not contain any business logic.
      2. Services are responsible for coordinate the usage of domain objects (repository, aggregate roots) and for being domain event listeners.
      3. All services could go to one package
      4. Every Excepion threw by services that are not used by domain should go here
      5. This is right layer for for security handling.
      6. This is right place for localization handling
    1. Web (package: org.openlmis.fulfillment.web):
      1. Conrollers, DTO builders and DTOs should go here.
      2. Only responsibility should be to transform DTO to domain objects / vice versa and call Application services 
      3. Package structure should refer API structure. So for shipment resource we have one package with: ShipmentController, ShipmentDto, ShipmentLineItemDto, ShipmentDtoBuilder)
      4. This is right place for error handling as this layer is above all other layers.
  2. Domain layer (package: org.openlmis.fulfillment.domain):
    1. Apart from what currently is in domain layer (Entities, Value Objects) we can move here repository interfaces so application layer is not dependent on our custom repository classes.
    2. Domain model classes for entities from other bounded contexts with fields needed in my bounded context only
    3. Other building blocks worth introduce: Aggregates, Aggregate Roots, Factories, Domain Services, Domain Events (POJO will work here: https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2, we only need to figure out how these event can be sent from domain layer), Repositories (interfaces for hibernate repositories and communication services).
    4. Every Aggregate (so Entities, Factories, Repositories) should go to its own package. Value objects and Domain Events can have separate package.
    5. Every Excepion threw by domain object should go here. Message keys can be here too.
    6. Business logic validation should go here.
  3. Repository layer (package: org.openlmis.fulfillment.repository):
    1. Place for custom repository implementations, communication service implementations (like GeographicZoneReferenceDataService that search geographic zones in referencedata using rest template to http communication)
    2. We can have two packages within this layer: repository/persistence, communiationservice OR have similar structure to Domain layer (same package sub-name for implementations of domain repositories)

Util package

This package should be removed All classes that currently are part of util/utils package can find its place in proper layer described above e.g. 

  • AuthenticationHelper goes to Application layer since only this layer should be responsible for security handling, 
  • MoneySerializer/MoneyDeserializer goes to Web layer as this layer is responsible for user interface, so for de/serialization from/to JSON)
  • RequisitionHelper code should be refactored and find its place in DDD building blocks in Domain layer (some code goes to Entity, some to ValueObjects) 

Exception package

This pakage should be removed. We should follow our style guide: Exception classes should go with the classes that throw the exception. If more than one layer use Exception it should be placed with given order: 1. domain; 2: service; 3: web

Validate package

Eventually, we want to get rid of this package. Business logic validations should find place in domain layer, constraint validations should be at database level, all others in application layer.


Open questions:


I modified structure aboce 

  • Use of package private scope of Java  - we could use a more concrete plan to see if we're taking advantage of this

I created simple UML to show how it will look

  • Should database repositories and repositories that are backed by a different service use the same interface? Consider potential differences in error handling.

No, different interface for database repositories and repositories that are backed by a different service

  • Is the repository name overused when used for both database backed and service backed? 

I don't think so. Domain layer shouldn't really care if some data come from database or other service. Domain layer should be free from technical complexity. I would even say that currently 'service' name is overused currently, in DDD repository has simple definition: retrieve and persist domain objects from bounded contexts. On the other hand, in Repository layer-package we will easily distinguish type of repository by prefixes like: Jpa*, Rest*, e.g. JpaRequisitionRepository


OpenLMIS: the global initiative for powerful LMIS software