Domain-Driven Design, part 8 — Services and Factories

Domain-driven design is about the domain. Domain services and domain factories do not exist in the domain. In general we shouldn’t use them.

They are artificial constructions and this causes a lot of problems with code understanding, maintainability and also divergence between the domain, the model and the code.

Domain Service

It may happen that use case doesn’t naturally belong to any aggregate. And it is awkward when one aggregate contains the domain logic of another aggregate.

A domain service is a stateless service object. It encapsulates a single use case that involves more aggregates.

Cart and Order Example

The complicated use case is to order the cart. This use case involves at least two aggregates — cart and order. It doesn’t belong to the cart — the cart is a shopping box not responsible for the order. It doesn’t belong to the order — order doesn’t care about source of its items. But conversion is still a single use case.

The solution is a domain service that does exactly this complicated use case.

Don’t use Domain Services

Application Service

I think that common confusion comes from the fact that both types work with domain objects.

Remember that domain service has no state; it doesn’t contain any private property. Domain services are rare and contain complicated cross-aggregate domain logic.

Domain Factory

Factory is an object that produces complicated aggregates or sometimes also entities and value objects. It can be used in several scenarios.

If the object construction is complicated, it is fine to move the construction process into a separated factory instead of using complicated constructor.

If we have a custom repository, we can delegate the object reconstruction responsibility into the factory. We get JSON data from an API for example, we pass them into a factory and it returns a domain object.

Sometimes the object construction needs some information that we do not have, like the information from an external system. The factory can be responsible for getting the needed information and constructing the object. In the following example, we get the order number from an external sequence.

Don’t use Domain Factories

Factory Pattern

But this is not true in the domain layer. In the domain layer we know exactly what implementation we are using, it is the domain object. Not any abstract object, the exact domain object. And the only reason for changing the domain object is a domain change. But if the domain changes, no factory can help us, we have to refactor the code.




Developer interested in Domain-Driven Design & Modeling

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store