Question

I thought domain services should only represent domain concepts, but it seems we should also use them to control the granularity of domain layer interfaces ( which also prevents domain knowledge leaking into application layer ) and to decouple clients from entities and value object:

Eric Evan's DDD book, pg. 108:

Although this pattern discussion has emphasized the expressiveness of modeling a concept as a Service, the pattern is also valuable as a means of controlling granularity in the interfaces of the domain layer, as well as decoupling clients from the Entities and Value Objects.

Medium-grained, stateless Services can be easier to reuse in large systems because they encapsulate significant functionality behind a simple interface. Fine-grained domain objects can contribute to knowledge leaks from the domain into the application layer, where the domain object's behavior is coordinated.

a) If we also introduce domain services that don't represent domain concepts, but instead only control the granularity, don't we introduce non-domain concept into domain? If so, doesn't that hurt domain model?

b) Should most of communication with upper layers be done through medium-grained domain objects? Thus, for every use-case where communication happens through fine-grained domain objects we should introduce medium-grained domain service(s)?

c) Eric Evan's DDD book, pg. 108:

Coding conventions can make it clear that these objects are just delivery mechanisms for SERVICE interfaces and not meaningful domain objects.

What coding conventions is he referring to?

UPDATE:

I think you're saying that the quote is describing Application Services and not Domain services?

I'm aware of Application Services and of their purpose, but I think author is describing Domain Services, since he warns that knowledge leaks into application layer can happen due to fine-grained domain objects:

... as well as decoupling clients from the Entities and Value Objects. Medium-grained, stateless Services can be easier to reuse in large systems because they encapsulate significant functionality behind a simple interface. Fine-grained domain objects can contribute to knowledge leaks from the domain into the application layer, where the domain object's behavior is coordinated.

And if we want to prevent knowledge leaks from domain layer into application layer, then shouldn't ( by my logic at least ) a "barrier" ( ie. a medium-grained service ) be built within domain layer?

SECOND UPDATE:

a)

With regards to granularity, a domain service serves a similar role to an application service.

What kind of domain service are you talking about? One created only for the purpose of controlling the granularity or...?

b)

IMO, it is a matter of preference whether the application service exists in a separate application layer project or together with other domain objects.

You're calling a service ( the purpose of which is only to control the granularity ) an Application service even if it exists within a Domain layer?

c)

The application service does a fine job of preventing knowledge leaks and in some sense, that is its central job.

But since a "barrier" ( ie. a medium-grained service ) exists within an Application layer, doesn't this mean that domain knowledge does leak into an Application layer ( but no further thanks to Application services )?

d) We could say that Application layer is a client of Domain layer and author does warn throughout the book that no domain knowledge must leaks into a client. Why is Application layer ( ie Application services ) an exception to this rule?

Thanks

Was it helpful?

Solution

a) If we also introduce domain services that don't represent domain concepts, but instead only control the granularity, don't we introduce non-domain concept into domain? If so, doesn't that hurt domain model?

While the services don't introduce any new behavior into the domain, they don't introduce non-domain concepts either. I view these services, application services specifically, as providing an encapsulating role for the domain - a facade. Each method on the service represents a domain use case and it delegates directly to domain objects. This makes it much easier for clients of the domain layer, since they don't need to worry about coordinating repositories and calling suitable behavioral methods on aggregates. Instead, they invoke a method on the application service.

b) Should most of communication with upper layers be done through medium-grained domain objects? Thus, for every use-case where communication happens through fine-grained domain objects we should introduce medium-grained domain service(s)?

Outer layers should call application services, which in turn delegate to aggregates or domain services. Note, application services are different from domain services. An application service can fully encapsulate the domain such that no domain objects are exposed by its interface, instead relying on DTOs to pass messages between outer layers and the application service. In addition to protecting the domain, this provides an opportunity to utilize something other than a domain model to implement use cases, such as a transaction script.

What coding conventions is he referring to?

One convention can be the presence of Application in service name, such as CargoApplicationService. Another convention is to place application services, which BTW can also be implemented as command handlers, into an Application module within the project.

EDIT

Take a look the this project on GitHub which implements the domain discussed in the book in a modern C# style.

UPDATE

With regards to granularity, a domain service serves a similar role to an application service. IMO, it is a matter of preference whether the application service exists in a separate application layer project or together with other domain objects. Creating an additional barrier between an application service and domain objects can become a needless abstraction. The application service does a fine job of preventing knowledge leaks and in some sense, that is its central job.

UPDATE 2

a) I was talking about domain services in general, because they all tend to increase granularity beyond entities and VOs.

b) Yes, because it still captures a domain concepts, namely use cases which are less granular then the domain objects used to implement them. Sure the application service has concerns largely orthogonal to the domain, but there isn't always a reason to put them into different layers.

c) Yes, but you can't get around leaking domain knowledge all together. If you have a database table with a name Customers which corresponds to the Customer entity, you have domain knowledge leaked into database. The point isn't to prevent all leaks, but to instead create boundaries around areas of cohesion, such that when making changes, they can be isolated to a specific layer.

d) Application service creates a facade around domain objects, effectively establishing a barrier so that clients of the domain, other than app service, have a clean interface to work with. In this way, app service is an "exception", because it sits between domain objects and outer layers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top