Search code examples
dependenciesdomain-driven-designproject

DDD driven solution structure


I am creating a project based on DDD principles. I came up with the following while reading the resources on the internet, does that make sense? In particular, parts like:

  • Having Shared.Core project that is shared between bounded contexts
  • Having separate .Data projects for each bounded context
  • Having Rest.API that depends on Shared.Core and FeatureX.Core projects.

The following table shows the projects I have created and their dependencies, -> denotes 'depends on'.

Rest.API -> Feature1.Core -> Feature1.Data
                          -> Shared.Core
         -> Feature2.Core -> Feature2.Data
                          -> Shared.Core
         -> Shared.Core

Solution

  • You can name the folders whatever you want but it is recommended that:

    • you have a module/namespace/package/directory that has no dependencies to any infrastructure or technology (like REST, SQL, NOSQL, MONGO etc) where only your business logic should stay; here live the Aggregates, Value objects, Domain services, Sagas etc. At least one for each Bounded context; let's name it the Domain layer. It may not depend on other Domain layers. It should be side-effects free, easy testable.

    • you may use inside the domain layer shared components but only if they are stateless and general purpose like datetime manipulation libraries, lists, stacks etc.

    • anti-corruption layers that convert from remote models to local models. Most probable they depend on multiple Domain layers.

    • other presentation, infrastructure and technology specific libraries and frameworks, IO adapters and ports should be clearly separated from other layers. May depend on the Domain layer.

    So, to map to you already have:

    Rest.API -> Feature1.Domain -> Shared.Lib
             -> Feature1.Infrastructure
             -> Feature1.ACL -> Feature1.Infrastructure
             -> Feature2.Domain -> Shared.Lib
             -> Feature2.Infrastructure
             -> Shared.Lib
    

    With the following comments:

    • Shared.Lib should contain only technology-agnostic, side-effects-free libraries, language constructs, utility functions etc
    • Feature1.Domain should not contain logic from more than one Domain/Bounded context
    • Feature1.ACL (Anti-corruption layer) can depends on the infrastructure (i.e. to store/fetch from a database or a cache) but should not contain business logic, only mapping logic, from remote objects/concepts to local objects/concepts.