After reading Vaughn Vernon's book I looked for an even more tactical book to demonstrate these patterns. A good friend of mine recommended N-Layered Domain-Oriented Architecture Guide and I was lucky enough to take his advice. This book really takes you step by step on how to structure your source code up to the smallest details.
Data Transfer Objects and DDD
When it comes to the application layer, one of it's key roles is the generation and handling of DTOs.
Domain Oriented N-Layered Architecture |
The adapters component is usually used by the application services to generate the DTOs after they were fetched using the domain layer repositories or when a response from a domain service is received.
DTOs are usually used for minimizing remote calls overhead (as described in the great Patterns of Enterprise Application Architecture) or to customize the returned data to clients, but on one of my latest projects I also used them for another use case, which IMHO, expanded the combination of DTOs and N-Layered pattern a little bit.
When we built a RESTful API on the distributed interface layer we ran into a resource that has two use cases when GETing it. The first is a request with an authenticated credentials which should get the whole entity as it is (there is still an adapter that transforms the domain model entity to the sent DTO - but the mapping is almost one-to-one). The second is a case where it is a public GET request - which implies all you will get in response is just the public version of the resource (basically, some of the fields are left out and not filled).
The out of the box solution will be to have the Application service call the Domain Entity repository for the full version and according to the authentication level fill the required fields of the returned DTO at the relevant adapter.
But, we chose a different path. We decided to treat the public resource as a whole new resource - an application layer "entity" with it's own route on the API level. One could suggest to use the the value type pattern and basically place the public entity on the domain level, but IMHO, public/private and authentication is not a concern of the domain model and it is a pure application layer matter.
Eventually, This implied having an application layer repository for this new entity (which is still obviously implemented in the infrastructure layer).
The great benefit here was both simplicity on the API level, where there is a one-to-one mapping and expectation between the request and response (which added type safety and clarity as one doesn't need to guess what fields are filled and what aren't) but furthermore - this new repository only fetches the relevant public data from the persistence store, which is more secure, more efficient and a much cleaner design.