In DDD, business logic should not be completely contained in domain types?
Yes. And, in Ddds, Services are in fact domain objects.
In DDD, Services are not a layer but a kind of business object.
What these domain services really are and how we can identify them?
The way to identify them is in your quote, but I would write differently:
In Ddds, Services are objects that contain business logic that does not naturally belong to any Entity.
The difference between my statement and your quote is that I took the comma and the "but". There is no "but/however/however/however" in the definition of Services. They are simply what they are. I also took the "business logic that does not belong to Valuables" because Valuables never have a business rule.
How to choose where a business logic should reside
Visualize a business rule and identify which entity it belongs to. The question to ask is: "which entity should have this behaviour?" If you cannot determine and the design is ok, then this business rule belongs to a Service and not to an Entity.
Eventually a business rule appears to belong to an Entity, but will affect several entities of that type and not just a single instance - in this case the business logic also belongs to a service.
Entity Behaviors
See this business rule:
- Download a receivable that was paid today.
If you have an entity Contareceber, this business logic belongs to this entity. You obtain the meaning of this entity and invoke its behavior download:
ContaReceber contaReceber = contaReceberRepo.get(contaId);
contaReceber.baixaPorQuitacao(dataReferencia);
contaReceberRepo.persist(contaReceber);
Behaviors of Services
Look at this other business rule:
- Expunging irrecoverable receivables.
A receivable has no way of knowing that it is uncollectible. To know which accounts are uncollectible, you need to get the parameters from somewhere. These parameters will, for example, be accounts that have been overdue for more than five years without any interest from the client in trading. The knowledge contained in several other entities is required to find out which payables meet this criterion.
This business rule naturally does not belong to any Entity, so it belongs to a service, which would be, for example:
ServicoBaixaAutomatica servicoBaixaAutomatica = BaixaAutomaticaService.get();
servicoBaixaAutomatica.expurgarIncobraveis(dataReferencia)
Complementing
Business or domain objects, in DDD, do not constitute layers; on the contrary, they all reside in the same layer, the business layer (of course), usually called Domain.
The DDD layers are:
- Interfaces: is the interface of the system to the outside world. It can be for example a graphical user interface or a service facade.
- Application: contains the mechanics of the application, directs to business objects the interactions of the user or other systems.
- Domain: layer where the business objects reside (Entities, Value Objects, Aggregations, Services, Factories, Repositories).
- Infrastructure: supports the other layers, for example by providing mapping between business objects and databases and access services to these databases.
Thank you for the reply @Caffé. Just one question: the interface of a service is part of the domain, but can the implementation of the service depend on the infrastructure? For example, can a domain service depend on a class of infrastructure responsible for sending emails or communicating with a database? I saw something like this in an example a few days ago and I was in doubt. Thank you again!
– SomeDeveloper
@Leonardo That, the service interface is always part of the domain and its implementation or part of its implementation can be provided by the infra layer. The code in the domain layer can explicitly consume an infrared class but the coolest design is when the domain code completely ignores the infras and consumes only interfaces, and then the infras implementations are injected.
– Caffé
@Leonardo Thus, the service would not consume the database but rather a repository (which is a domain object) and the implementation of access to the database would be abstracted by Hibernate, for example. And in the case of email, the service code, implemented in the domain layer, would consume a domain interface as well, e.g.:
@Inject IEnvioEmail email; email.enviar(..., ...);
and the object of infrastructure that actually sends the email would be injected by the dependency injection framework.– Caffé
@Caffé, fantastic his answer, answered assiduously my doubt. Grateful.
– G. M4rc14L