10

I have read Eric Evans book. I was under the impression that a Domain Model should not have dependencies injected (even repositories).

This statement is supported by questions like this: https://stackoverflow.com/questions/20035810/should-domain-objects-have-dependencies-injected-into-them, where the answerer says that "Domain Objects shouldn't depend on anything else". However, I then see this: http://www.zankavtaskin.com/2013/11/applied-domain-driven-design-ddd-part-4.html i.e. a domain service in the domain model that depends on the repository.

Should a Domain service have dependencies? I realise that application services have repositories injected.

My use case is a domain model that figures out what offers a customer is entitled to based on their preferences. There is a table in the database called offers, which contains the offer expiry date etc. Does the domain model:

1) Tell the application service that the customer is entitled to offer a, b and c. Then the application service goes to the database and gets the offers

or

2) The domain model (domain service?) goes to the database and gets details of the offers and returns them to the application service as a list of DTOs.

7
  • 1
    Do you have a specific use case in mind that you can describe in your question for illustration purposes? Otherwise, this is a rather hypothetical exercise. Commented Jun 29, 2017 at 20:46
  • @Rovert Harvey, I have added more content. Does that help?
    – w0051977
    Commented Jun 29, 2017 at 20:53
  • Which option requires the dependency injection we are discussing here? Commented Jun 29, 2017 at 20:58
  • @Robert Harvey, option two i.e. the repository is injected into the domain service so that the domain service can go to the database to get a list of offers to return to the application service.
    – w0051977
    Commented Jun 29, 2017 at 21:00
  • What does your "domain service" do, other than to serve as an object-oriented interface to the database tables? Commented Jun 29, 2017 at 21:01

4 Answers 4

9

I was under the impression that a Domain Model should not have dependencies injected (even repositories).

Yes, that's right.

Should a Domain service have dependencies? I realise that application services have repositories injected.

Here's what Evans wrote

A good SERVICE has three characteristics

  • The operation relates to a domain concept that is not a natural part of an entity or value object
  • The interface is defined in terms of other elements of the domain model
  • The operation is stateless

Statelessness here means that any client can use any instance of a particular SERVICE without regard to the instance's individual history. The execution of a service will use information that is accessible globally, and may even change global information (that is, it may have side effects).

Further along, he addresses your question, although somewhat obliquely

But we are still left with calls to SERVICES in the interbank networks. What's more, in most development systems, it is awkward to make a direct interface between a domain object and external resources. _We can dress up such external SERVICES with a FACADE that takes inputs in terms of the model....

The domain service (facade) would have a dependency on the external service.

That said; looking back 10 years later, I'm not sure that he got the details of this one right. When you interact with state that is distributed somewhere else, that somewhere else may not be available. Distributed communication fails, and if that's not part of your domain, the logic for handling those failures starts to get in the way.

Gary Bernhardt and Cory Benfield both have given very interesting talks about separating side effect concerns from those of the model.

A model that transforms inputs into outputs is simple to reason about; a model that transforms inputs into outputs plus side effects, that's not simple any more.

1
  • How about domain service depending on other domain service on the same module? Would that be allowed? Commented Jun 28 at 7:55
1

We need to clarify some important concepts from DDD. So:

Every DDD application can be logically split into two parts:

  1. The write/command part, where you do the modifications to your persisted objects. Here live the Aggregates and all they need to do their job, i.e. all their Value objects. This is referenced in the literature as "the domain model".

  2. The read/query side where you show the persisted objects or some projection of them. Here stay the domain services and the Repository interfaces.

There are also the Sagas/Process managers that bridge the two parts.

I have read Eric Evans book. I was under the impression that a Domain Model should not have dependencies injected (even repositories).

Yes, I agree. This refers to the Write part of your application (i.e. the Aggregates).

Should a Domain service have dependencies? I realise that application services have repositories injected.

Yes, they may have.

1) The domain model tell the application service that the customer is entitled to offer a, b and c. Then the application service goes to the database and gets the offers

Not the domain model but a domain service. This is strictly a read side concern (if you use this information to display it to the user or in a Saga).

2) The domain model (domain service?) goes to the database and gets details of the offers and returns them to the application service as a list of DTOs.

The domain service and not the model, as I wrote in the previous paragraph. This really depends on how much you want to optimize the speed of the persistence retrieval as you can make use of the persistence optimisation and not fetch the entire documents/rows but only the data needed. Being on the read side you are "permitted" to do all kinds of optimisations.

In any case, the logic about the selection of those offers should stay in the domain layer.

P.s. there is the CQRS architecture/pattern that is based on this separation of read and write.

11
  • You seem to be suggesting that the "write/command part" should not have dependencies injected. Therefore you appear to be advocating tightly coupling that part to the persistence mechanism. This is bad design, regardless of what Eric Evans or any other DDD fan might say on the matter.
    – David Arno
    Commented Jun 30, 2017 at 12:31
  • @DavidArno no, no dependencies at all, neither injected nor newed Commented Jun 30, 2017 at 12:35
  • Clearly it does have dependencies since you say its purpose is "where you do the modifications to your persisted objects", thus it has a dependency on those persisted objects, which are either globally accessible or are injected via eg a method's parameters. But I take it you mean that it doesn't do the persistence itself, it just modifies objects that are then persisted by another aspect of the code?
    – David Arno
    Commented Jun 30, 2017 at 12:40
  • @DavidArno yes, the write part does not care or know about persistence. The Application layer/services/command-handlers do the persistence/repository load and save operations. Commented Jun 30, 2017 at 12:58
  • @DavidArno I used "persisted objects" only to identify what objects live there and nothing about the actual persisting operations Commented Jun 30, 2017 at 13:00
0

If the domain service is an intermediary between Customers and Offers, like a func returning the eligible offers, maybe the application service would use the domain service to select from the repository?

The interface for the repository can/should live in the Domain layer, so the implementation for the repository could be injected into the domain service.

0

A domain model and let's extend that to any model in general, should not have injectable dependencies.

A domain service (factory) is built inside the domain and is going to have constructor injection in any non-trivial software implementation. The minimum to inject typically is the infrastructure service (EF, Dapper, ADO? (your DTO's typically live here). The maximum? Anything and everything the domain has access to (facades, stand alone projects, other factories / domain services, etc...).

You can then throw an interface on the factory, wire it up in DI, and inject it that way abstracting out it's (many?) dependencies, until you have an intricate web of inter-dependencies that you'll find in most enterprise architecture.

Not the answer you're looking for? Browse other questions tagged or ask your own question.