I'm learning DDD and have some troubles.
I've created rich domain model with value objects and some functions for manipulating model properties.
Currently i'm using in memory DB and my domain models are persisted as is.
All is good.
But now i want to separate domain model from DB model.
Scenario for creating (lets say "concert"):
User sends command.
Application service gets domain model
Then application service calls repository to persists that model
Repository (infrastrucure layer) translates that domain model to his DB model and write to DB
Second scenario (I want to update "concert")
User send command to update concert
Application service calls repository to get "concert" to update (first question what repository should return here, doest it need to return domain model or something else)
Now (if I have domain model) I can call method concert.sellTickets(3);
Then app service calls repository to update that concert
Does my thinking is good?
Does repository need to reconstruct DB model to Domain model and return to caller?
I hope you understand what I'm asking.
Above scenarios with some sample code:
Creating concert (application layer)
// application service
var concert = Concert.Create(); // creating rich domain model or concert
_repository.Add(concert);
Update concert (sell tickets) - application layer
var concert = _repository.Get(//by id); // this is rich domain model
concert.SellTickets(//some number); // calling "smart" method
_repository.Update(concert); // persisting to DB with new value
repository side (writing) (infrastructure layer)
var concert = Adapter.Map(domain_model); // converting rich domain model to plain class for pesisting
_db.Add(concert);
_db.SaveChanges();
repository side (reading) - infrastructure layer
var concert = _db.Find(); // read concert from db
var rich_domain_model = Adapter.Map(concert) // convert it to rich domain model
return rich_domain_model;
I know that ORM's using their mappers,
but let's say I'm using,for now, in memory DB. So i need to do some conversions.
These two use-cases you are presenting are pretty standard in the context of DDD world. Also, they reflect a valid separation between domain model (domain layer) and database model (infrastructure layer).
Application service gets domain model
What do you mean by "gets"? A command object received by user is a flat object, containing no value objects; it is not (and should not be) a domain model. It is possible to delegate command-to-domain translation to application service, however some would prefer to apply such translation inside API layer (it is a matter of taste).
User send command to update concert
There are probably more than one command that "update" a concert (e.g. assign musicians, order hall, selling tickets). This is why we should be careful when defining a single update operation in the context of DDD: sending a command with many properties not necessarily relating to each other is a symptom of an anemic model.
first question what repository should return here, does it need to return domain model or something else
A repository should translate database objects into a domain entity, and return the latter. In DDD all layers "know" the domain.
One last point:
A rich domain is more than entities with value objects and methods that manipulate properties; the richness should be expressed by "smart" methods, that is methods that perform appropriate validations to prevent the entity from entering an inconsistent state. If you want to project a domain model as is into database, there is no point for smart entities because running plain validations would be sufficient. But if your application is not purely CRUD, providing rich flows and structured as many user commands mutating business entities, that's where DDD shines.
Related
I have two questions related to CQRS and Domain Driven Design (DDD).
As far as I understand the segregation idea behind CQRS, one would have two separate models, a read model and a write model. Only the write model would have access to and use the business domain model by means of commands. The read model, however, directly translates database content to DTOs by means of queries and has no access to the business domain at all.
For context: I am writing a web application back-end that provides calculation services for particle physics. Now my questions:
1.) My business domain logic contains some functions that calculate mathematical values as output from given measurement system configurations as input. So, technically, these are read-only queries that calculate the values on-the-fly and do not change any state in any model. Thus, they should be part of the read model. However, because the functions are heavily domain related, they have to be part of the domain model which again is part of the write model.
How should I make these calculation functions available for the front-end via my API when the read model, that should contain all the queries, does not have any access to the domain model?
Do I really have to trigger a command to save all the calculations to the database such that the read model can access the calculation results? These "throw-away" calculations will only be used short-term by the front-end and nobody will ever have to access the persistent calculation results later on.
It's the measurement configuration that has to be persistent, not the calculation results. Those will be re-calculated many times, whenever the user hits the "calculate" button on the front-end.
2.) I also feel like I duplicate quite a bit of data validation code, because both read model and write model have to deserialize and validate the same or very similar request parameters in the process chain http request body -> json -> unvalidated DTO -> validated value -> command/query.
How should I deal with that? Can I share validation code between read model and write model? This seems to dissolve the segregation.
Thanks in advance for all your help and ideas.
I think that what do you have is a set of domain services that with a given input they return an output.
As you said, this services are located in the domain. But, nothing denies you to use them in the read model. As long as you don't change the domain inside the functions, you can use them in any layer above the domain.
If, for any reason, this solution is not viable, because for example the services require domain objects that you cannot/don't want to build in the query side, you can always wrap the domain services inside application services. There you take in input a base object, you do all the transformations to the domain one, you call the domain service and you return the resulting value.
For the second question, you can build a validation service in the domain layer, as a set of services or simple functions. Again, nothing denies you to use them in the validation steps.
I've done the same in my last web app: the validation step of the form data calls a set of domain services, that are used also when I build the domain objects during the handling of a command. Changing the validation in the domain has as effect that also the Web related validation changes. You validate two times (before building the command and during the building of the domain object), but it's ok.
Take a look at the ports/adapters or the onion architecture: it helps a lot understanding what should stay inside a layer and what can be used by an overlapping layer.
Just to add my two pence worth.
We have microservices that use mongo as a backend. We use NET Core using mediatr (https://github.com/jbogard/MediatR) to implement a CQRS pattern in the MSs. We have .Query and .Command features.
Now in our world we never went to Event Sourcing. So, at the mongo level, our read and write models (entities) are the same. So what worked best for us was to have a single entity model which could be transformed into different models (if needed ) via each command/query handler(s).
If you are doing pure CQRS via event sourcing (so different read and write models) or something else then please ignore me! But this worked best for us.
Are services part of domain model according to DDD? If we google for "ddd onion architecture", we can mostly see that the most inner layer is called something like "Domain Model Layer" and the second is "Domain Services", for example, [dead link, NSFW anymore] . But in https://en.wikipedia.org/wiki/Domain-driven_design and DDD book we see that that entities, value objects and services all express the model and are model elements. If entities, value objects and services are all part of domain model, how should we call those two layers of onion: model (entities + value objects) and services (as I sometimes do)? But if all are part of domain model, this naming does not seem accurate.
Are domain services part of domain model?
Yes, but also no.
In the blue book, domain services are described in chapter five; immediately after entities and value types. Evans writes
In some cases, the clearest and most pragmatic design includes operations that do not conceptually belong to any object. Rather than force the issue, we can follow the natural contours of the problem space and include SERVICES explicitly in the model....
A service is an operation offered as an interface that stands alone in the model, without encapsulating any state....
The interface is defined in terms of other elements of the domain model.
But it will not always be the case that the implementation of the domain service lives within the domain model itself.
In some cases, the domain service is really acting as a service provider, which needs to be wired to the infrastructure to perform its role (for example, sending messages to another process). So the domain model defines the provider interface, an implementation of that interface is passed to it (for example, as an argument to a method on an aggregate root), and then the model decides if/when to invoke the methods on that interface.
can entities and value objects have a compile time dependency on interfaces of domain services? Are they (entities, value objects and interfaces of the domain service) in the same layer of the domain model?
Yes, and yes. For example, here's an online sample of the shipping application from chapter 7.
public interface RoutingService {
List<Itinerary> fetchRoutesForSpecification(RouteSpecification routeSpecification);
}
Now, this particular demonstration happens to keep the domain services in a different namespace than the model, and uses an application service to bridge the two.
return routingService.fetchRoutesForSpecification(cargo.routeSpecification());
But it would be equally correct to make this part of the responsibility of the model
return cargo.fetchRoutes(routingService);
Queries give you a bit of room to play, because you don't have to worry about allowing the model to protect its own invariant. With commands, the latter approach provides better encapsulation
order.updateSalesTax(taxCalculatorService);
Are services part of domain model according to DDD?
It is part of the domain layer. Domain services encapsulates domain logic that cannot be naturally modeled as value objects or entities.
In the onion architecture, all dependencies face inward. Value object and entities should not have any dependencies on domain services. Domain services depends on entities and value object. At the heart of the architecture is the domain layer (value+entities+services). This is DDD which is an abstract view of the business/problem domain. This layer does not depend on anything like database, web services calls, smtp and other infrastructure related services.
One layer above is the application layer which depends on the domain layer. Application layer consists of application services that contain application logic to orchestrate business use cases.
Next layer is the infrastructural layer which can responsible for technical implementation of storing information, logging,security, notification and integration with other bounded contexts. This layer also enables the application layer to be consumed via web services or message endpoints.
To avoid tight coupling between these layers, the higher layer must adapt to the message types of the lower layer. Between these layers, you may use data transfer objects(DTO) so you don't pass domain objects(entities) across boundaries. Also to avoid tight coupling to specific technology(eg. database), layers communicate via interfaces.
I am trying to follow DDD in the following pattern.
Controller-----DataContract----> Domain Layer (DDD)
Controller-----Domain Object---> Repository---Entity--->EntityFramework
As you see in the above diagram, the domain layer is independent to make business decisions, but in my case, most of the business decisions are taken on the fly. For example,
if(Account Number Associated?)
Load CustomerDetails //A database call is needed
....
.....
if(Has customer another loan)
.....
.....
Load other loan details //A database call is needed
.....
.....
if(Was that repaid?)
....
....
Load collateral details //A database call is needed
.....
.....
Calculate collateral details and return.
else
Load other data //A database call is needed
else
Load other data //A database call is needed
else
Load other data //A database call is needed
As you see the above example, the application is making a lot of business decisions on the fly by making database calls. Since Domain Layer should not depend on the Repository Layer, I don't know how to proceed.
I may use Application service for database calls, but then Domain Layer wouldn't have any logic in it. All the logic would go into the Application Service.
Please help me in this.
-Pandian
There are at least three possible ways out
1) Design your repository to load the entire aggregate at once. This approach gives the domain model all of the state that it may need right away, rather than trying to load the state on demand.
2) Run the queries in the app service, and pass the data to the domain model. Ideally, you do this in advance (so that you are making a single call into the domain model), but when that doesn't make sense you have the domain model tell the app service what data is needed, and the app service finds that data and returns it.
3) Pass a repository into the domain model that allows it to read the data that it needs. This is essentially the "domain service" pattern, but used to access a data store.
In this design, the domain model is defining the repository interface, and the application provides the implementation. In other words, we're using the service provider pattern to keep the dependency arrows pointing the correct direction.
#Pandiarajan Domain layer can contain domain models(entities, value objects), domain services and domain events.
From your code above, you can create a domain service that encapsulates all these domain logic and concepts that are not naturally modeled as value objects or entities. These domain service can take a repository that handles all the database calls.
Note also that if the data you need to return are for read-only or reporting purpose, you may want to look for CQRS as alternative. In CQRS, all these read-queries can bypass your domain layer in presenting data. CQRS will eliminate the need of transforming your data to a domain model.
I am learning about DDD so apologies if my question is naive. I think I need to use Local Data Transfer Object in order to display data to the users as a lot of properties are not part of any of Entity / Value Objects.
However, I am not sure where this DTO should be implemented - in a Domain Layer or in an Application Service Layer. The DTO implementation seems part of the Domain, but it means that when I create a collection of DTOs in the Service Layer and pass it to a Presentation Layer, I have to reference Domain Layer in Presentation Layer, which seems wrong.
What is the correct way to implement DTO using DDD principles?
Define the DTO to the layer where the source of the values comes from.
Relative to OP's question: place the DTO in the Application Service Layer. DTO is an output of that layer, it makes sense if you define it there. Don't put your DTO in the Domain Layer. The Domain Layer does not care about mapping things to serve external layers (the domain does not know there is a world outside of its own).
Presentation Layer (closes to consumers)
This could be your API
Has Models or Dto definitions of its own with attributes relative to its layer. If this is an API then Models/DTO have attributes for formatting or data type validations
This is the "Application Root" (meaning that it must reference both Domain Service layer, Data/Infrastructure Layer to be able to inject services)
Maps data between ApplicationService.Dto and Presentation.Dto
Application Service Layer
Has Dto definitions of its own to be able to return data without exposing the domain entities.
Bridge between Presentation Layer and Domain Layer.
Contains Application Services. See answer https://stackoverflow.com/a/3840552/1027250 for detailed definition of Application Services.
Domain Layer
Domain entities
May contain Interfaces bridging the infrastructure layer, defined in words that can be understood by the business, free from technical terms (IE: IExcelReport, IGoogleSheetReport, IRepository)
May contain "Domain Services"
Data / Infrastructure Layer (closest to your database or external services)
Database infrastructure (mapping).
Excel libraries if you define this layer as infrastructure code.
Mail or notification services.
PDF output files
Such DTOs that are exposed to the outside world become part of a contract. Depending on their form, a good place for them is either the Application Layer or the Presentation Layer.
If the DTOs are only for presentation purposes, then the Presentation Layer is a good choice.
If they are part of an API, be it for input or output, that is an Application Layer concern. The Application Layer is what connects your domain model to the outside world.
As an interesting observation, it follows that the Presentation Layer should access the domain model only through the Application Layer. Otherwise, we lose our single point of access - we'd have multiple layers invoking the domain model. The Application Layer exposes all of our use cases. Whether they are invoked by a call from another service or by the Presentation Layer makes little difference.
Sources
The core of these concepts I learned from The Red Book by Vaughn Vernon. (I would quote from it, but I don't have it handy.) The chapters about the Application Layer and the Presentation Layer are relevant.
Primarily, my conclusions come from being strict with the concepts as presented by Eric Evans and Vaughn Vernon, and prioritizing freedom in the domain model, as this is Domain-Driven Design:
The domain model should be easy to change. That means not exposing domain objects externally, as having external dependants would make them hard to change (without breaking things).
The Application Layer is the external point of access. It is what defines the use cases on the domain model. That means not operating on the domain model from elsewhere. The Presentation Layer can only go through the Application Layer. Nobody likes having to deal with many different points of access!
Yorro is right about where to place DTO but I encourage you to avoid "DTO mindset". This way of thinking collides with DDD way of thinking.
Thinking about "I need a DTO here" is thinking about technical representation (as plalx says); it is a level of abstraction too low. Try a higer level of abtraction and think about your domain, user's tasks and your UI.
Do you need get view data to the user? Bring it to UI through a View Service that return a specific YourViewInfo class.
Do you need to send data to some Service to perform a task? Send it a specific TaskMessageInfo class or a specific Command class.
When you begin to modeling the internals of these classes is when you should start to thinking about its technical representation; then you could reach to the conclusion that could be, i.e., DTO classes for convenience.
Thinking this way helps you to model the system and doesn't trigger questions like
Where to put or belongs this thing?
DTO and Domain are different layers.
So it requires mapping from one to another and usually it is done in what is called Application Services layer.
Take a look at the following articles to go deeper with DTO and layering:
Is Layering Worth the Mapping? by Mark Seemann
DTO vs Value Object vs POCO: definitions
Hexagonal (Ports/Adapters) Architecture
What has to be mentioned here is so-called Hexagonal (Ports/Adapters) Architecture [Vernon, the red book p. 125]. It is very convenient to place objects that represent data for the external (outside the domain & the application) comsumers. The architecture is the great addition to Layered Architecture generally implied by DDD.
Here is the example.
Along with ports/adapters for a DBs, email services etc.
We may define a ports/adapters/http/ui/myestore/ShoppingCartResponse.valueobject.ext (assume we use some imaginary programming language EXT) that contains the data your UI application MyEStore will use to show the end user his shopping cart state.
ShoppingCartResponse.valueobject.ext is created by ports/adapters/http/ui/myestore/EStoreHTTP.adapter.ext (for brevity it could be a synonim for a very slim HTTP REST API controller from REST world in our example).
The adapter asks the domain service ShoppingCart.service.ext for aggregates, entities, other value objects. Then it creates the desired ShoppingCartResponse.valueobject.ext from them (by itself or with creators - factories, builders etc.). Then sends the value object as an HTTP response to the consumer.
DTO or Value Object?
Whether ShoppingCartResponse would be a value object or a DTO (.dto.ext) you should decide based on
The particular structure of your Ports/Adapters object hierarchy;
If it is justified to have another type of object, a DTO, in the system, or it is better to keep only value objects only;
A semantic meaning of DTO vs value objects in object hierarchy;
The responsibilities differentiation between them: say your value object would do some invariants logic-keeping, whereas DTO could be just a dumb object with no logic.
I would prefer starting with the simplest approach, allowing only for value objects, and add DTOs only as the clear architectural need in them appears.
This approach gives much flexibilty yet it keeps code design clean and simple. Ports/Adapters section accommodates objects that belong together (the adapter, VO or DTO, their creators) and keeps Application Layer clean keeping the space for more relevant application layer objects.
Assume you have entities, a service layer, and repositories (with an ORM like NHibernate). The UIs interact with the service layer.
What types of code are appropriate for the service layer?
Repository Coordination?
It looks like entities should not reference the repository so should calls for loading/saving/evicting entities exist in the service layer?
Business Logic that Involves Repositories?
If the above is true, should something like checking if a username is distinct go in the service layer (i.e. call GetUsersByUsername and check the results)? Before suggesting that the DB should handle distinct, what about verifying that a password hasn't been used in 90 days?
Business Logic that Involves Multiple Entities?
I'm not sure about this one, but say you have the need to apply an operation against a collection of entities that may or may not be related and is not really applicable to a single entity. Should entities be capable of operating on these collections or does this sort of thing belong in the service layer?
Mapping?
Whether you use DTOs or send your entities to/from your service layer, you will likely end up mapping (preferably with AutoMapper). Does this belong in the service layer?
I'm looking for confirmation (or rejection) of the ideas listed above as well as any other thoughts about the responsibilities of a service layer when working with entities/repositories.
Repository Coordination?
Aggregate roots should draw transactional boundaries. Therefore - multiple repositories should rarely be involved. If they are - that usually happens when You are creating new aggregate root (as opposed to modifying its state).
Business Logic that Involves Repositories?
Yes, checking if username is distinct might live in service layer. Because User usually is an aggregate root and aggregate roots live in global context (there is nothing that "holds" them). I personally put that kind of logic in repository or just check directly through ORM.
As for checking password usage - that's a concern of user itself and should live underneath User object. Something like this:
class User{
void Login(){
LoggedOn=DateTime.Now;
...
}
bool HasLoggedInLast90Days(){
return (DateTime.Now-LoggedOn).Days<=90;
}
}
Business Logic that Involves Multiple Entities?
Aggregate root should manage their entity collections.
class Customer{
void OrderProduct(Product product){
Orders.Add(new Order(product)); //<--
}
}
But remember that aggregate root should not micro-control its entities.
E.g. this is bad:
class Customer{
void IsOrderOverdue(Order order){
return Orders.First(o=>o==order)....==...;
}
}
Instead use:
class Order{
void IsOverdue(){
return ...;
}
}
Mapping?
I suppose mapping to dto`s live in service layer. My mapping classes lives next to view model classes in web project.