19

After doing some research, I got confirmation that folder-by-feature structure is superior to folder-by-layer structure in the majority of cases. To get some arguments we can read, among others, the following articles or even this answer.

Package by features, not layers
Feature folders vs Tech folders
Package by feature, not layer
Package by Layer for Spring Projects Is Obsolete

However, all the DDD project examples that I found are made with package-by-layer, most of the time following a structure like:

├── application
├── config
├── domain
├── infrastructure
└── interfaces

So my question is: why the DDD community does not follow package-by-feature even if it’s apparently superior in the majority of cases?

Should we use package-by-feature with DDD? If so, how to do it?

I mention that I’m not talking about the particular case of micro-service architecture where obviously package-by-layer is more relevant.

Kwadz
  • 2,206
  • 2
  • 24
  • 45

3 Answers3

16

My understanding and my vision of this subject is as follows:

Package by feature is about vertical slicing (structuring the source code according to domain concepts) instead of by horizontal layering (structuring according to technical concepts).

But saying "instead of" isn't completely true, since there's a moment when you have to distinguish between those technical concepts. It would be better to say package by feature first, and then package by layer inside each feature.

In strategic DDD, each Bounded Context (BC) is a vertical slice (a whole application, full stack... with UI, application, domain model and infraestructure layers).

Then, inside a BC, tactical DDD promotes packaging the domain model code by business concepts first, and then by technical concepts (tactical patterns). So you have modules (groups of aggregates that are tightly cohesive and loosely coupled), and inside each aggregate you have entities, value objects, factories, repository. The other layers (UI, application, infra) can be structured by modules as well.

So as a summary DDD does follow a mixed approach:

  • Packaging by business concepts with different levels of granularity: BCs, modules, aggregates.

  • Package by layer inside a BC: UI, application, domain, infraestructure.

PD: this subject (source code structure) is explained in Chapter 9 (Modules) of Vaughn Vernon's book "Implementing DDD".

choquero70
  • 4,470
  • 2
  • 28
  • 48
  • 1
    Many "package by feature" promoters seems to be advocating that package by feature as a top-level structure is better (within a BC), but I'm not sure `someAr/application/UserApplicationService` is any better than `application/someAr/UserApplicationService`. – plalx Mar 21 '19 at 14:28
  • 1
    @plax in my response I meant your 2nd option: inside a BC , structure each layer into modules. I think that your 1st option is another possibility Vernon mention in his book too, which is applied when in our whole domain isn't very clear the partitioning (linguistic) into BC. It is called «Module before BC» (page 344 of the book). – choquero70 Mar 21 '19 at 17:27
  • I'll go over that chapter again, it's been a while. Thanks for the reference. – plalx Mar 21 '19 at 17:34
  • @plalx you are wellcome.You know more than me about DDD.Re-reading now that chapter section(since it's been long time for me too), I think that it is not what you meant.What "module before BC" says is that if we are not sure enough about the thick linguistic division of one domain model into two models,or it isnt clear,we shouldn't create 2 BCs(one for each model), but create 2 modules keeping just one model. I think that this a case where the subdomain:BC relationship isnt 1:1, but 2:1 since we are implementing 2 ("fuzzy") subdomains with just one BC (model), each subdomain would be a module. – choquero70 Mar 21 '19 at 19:22
7

DDD is about domain, so group everything in entity folders. But at the very high-level preserve 4 Hexagonal architecture layers. This could be packages for simplicity or best separate modules with strict mutual dependencies (as in Android Instant Apps).

src/main/java
├── Domain
│   ├── Entity1
│   │   └── ... (entity & DTO files)
│   └── Entity2
│       └── ... (entity & DTO files)
├── Service
│   ├── Entity1
│   │   └── ... (port interfaces, application service files)
│   └── Entity2
│       └── ... (port interfaces, application service files)
├── UserInterface
│   ├── Entity1
│   │   └── ... (controllers, routers, MQ-consumers, other adapters files)
│   └── Entity2
│       └── ... (controllers, routers, MQ-consumers, other adapters files)
└── Infrastructure
    ├── Entity1
    │   └── ... (repositories, 3-rd party server clients, MQ-publishers files)
    └── Entity2
        └── ... (repositories, 3-rd party server clients, MQ-publishers files)

Here is a a good article wtih clean explanation.

Zon
  • 18,610
  • 7
  • 91
  • 99
3

why the DDD community does not follow package-by-feature

I think you'll find that the good projects do follow package-by-feature.

In examples, you may find that it isn't being followed. The generous interpretation is that the authors are trying to make it easier to recognize the separation of concerns and the directions of the dependency arrows.

Less generously? the authors aren't paying attention, or don't know better.

Should we use package-by-feature with DDD? If so, how to do it?

Yes, and pretty much the same way you would do package-by-feature if you weren't doing DDD. They are orthogonal concerns.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • Thanks! Would you have a link to a good DDD project that follows _package-by-feature_? Even [this example](https://github.com/citerus/dddsample-core) based on the cargo example used in [Eric Evans' book](https://books.google.com/books/about/Domain_driven_Design.html?id=7dlaMs0SECsC&redir_esc=y), [this one](https://github.com/mploed/ddd-with-spring) with Spring or [this one](https://github.com/jorge07/symfony-4-es-cqrs-boilerplate) with Symfony do not follow it. – Kwadz Mar 19 '19 at 19:09
  • 1
    I really don't see how you could have a clean domain segregation without a package as a boundary. Are you suggesting that `application` and `domain` packages shouldn't exist and you should have domain classes mixed up with application services? To me, it seems that by layer and then by feature seems to be the most logical approach. You could as well do by feature and then by layer, but it seems quite important to be able to have a clean separation of domain classes with the rest of the application or to be able to clearly identify application entry points (application services). – plalx Mar 20 '19 at 16:05
  • I would consider doing it the other way around, package by feature then by layer. This way if you need to break some functionality out into it's own service it'll be pretty much packaged in a way that you can just move it. – mal Feb 01 '23 at 16:10