6

DDD noob here. Say we have a domain aggregate for Orders (e.g. MS DDD Article). Using this example, we want to query all orders that contain a particular item. Further, we are not really interested in all that is in the order or item. Just the orderId, date, and item name suffice for displaying back to user/responding to API. Struggling with the following:

  • Does the repository (which returns domain objects) return full (i.e all properties) matching orders and all their items and then subsequently a domain object/service has to filter for non-interested items? Seems very inefficient and not taking advantage of our persistence (SQL) engine capabilities to narrow a search. Also this subsequent filtering will change the behavior of the domain object (e.g. state of the order and its total) which may cause side effects if this order's data/behavior is used by the caller.
  • Or does the repository return a DTO of sorts that only has the data properties we need for the caller? This seems efficient, except over time this list of DTOs can grow to be hundreds of classes that satisfy some niche requirement in the system. Seems ugly.

Are these concerns valid and/or is there a better way ?

Heems
  • 142
  • 1
  • 9
  • Possible duplicate of [Can repository pattern be used for loading of "partial entities"](https://stackoverflow.com/questions/24898053/can-repository-pattern-be-used-for-loading-of-partial-entities) – guillaume31 Nov 29 '18 at 10:30

1 Answers1

12

The repository pattern comes from the original Domain Driven Development book, by Eric Evans. In chapter six, he discusses the advantages of having a clear separation between your application logic and the storage concerns. The concept of a repository was that you would have an interface that supported the illusion that all of your domain "aggregate" objects were reachable via an in memory collection somewhere.

The aggregate object would encapsulate all of the state associated with a particular identifier. In theory, that would mean that you would answer queries by first fetching a collection of aggregates from the repository, and then enumerating those objects to compose the response.

Seems very inefficient and not taking advantage of our persistence (SQL) engine capabilities to narrow a search.

Yup. Some implementors experimented with the idea of having repositories that would accept query objects as arguments, to try to work around that.

Another approach, that got more traction, was to build more sophisticated queries into the repository interfaces. That is, instead of trying to create a single uniform repository interface, to instead create interfaces that were fit for purpose -- you could look at the repository contract, and start to understand what kinds of constraints your data store needed to satisfy.

But the big unlocking piece is -- the realization that if you are in a read use case, you don't actually need the data model as such, you just need to make an immutable copy of some data. So skip the model altogether, and just use a repository that returns an immutable DTO representation rather than an "aggregate root".

This seems efficient, except over time this list of DTOs can grow to be hundreds of classes that satisfy some niche requirement in the system. Seems ugly.

  • It works
  • It's simple
  • It surfaces the real costs of supporting each niche requirement.
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • Do you have an example of a repository that returns immutable DTOs? That sounds like a good idea but I haven't seen it or mentioned it somewhere else so far. – siva Feb 22 '23 at 17:51