So far we have learned, that business logic is shared between Entities and ValueObjects. Together they form an Aggregate which manages a whole collection and guards them from being corrupted. But what if we need some more sophisticated validation or another Aggregate must be compared to current one? There is a solution for that, and it’s called Domain Service (DS).
Characteristics
First and foremost, DS is a “service” object, just like Repository. It means that Domain Service must be stateless, highly specialized class which deals greatly with one thing only. Services may rely on one another, there might case when Repository will be used inside a Domain Service. And last but least, Domain Services may publish Domain Events.
Complex Business Rules
SHELF bookstore has this fancy business rule, that every third Order will have a free delivery, if two previous ones had had price bigger than 100 Money and at least one of them contained “The Book Of The Month”. As you can see it’s quite compound. Let’s try to code it.
Domain Service called EveryThirdOrderFreeDelivery handles some complex business rules that could not be implemented on shoulders of Entities and ValueObjects. In this case, when we need to look back at some previous Orders, there is a need for Repository to provide us with two last Orders. On the fetched collection we need to check if every Order has some particular item and if its price was at least 100.
Summary
Don’t hesitate to tackle your complex business rules with Domain Services. As you can see, this is a great way to encapsulate some complicated calculations which require additional data or some other steps to be validated.