I have a web application with news posts. Those news posts should be searchable. In context of DDD what kind of buililng block are search query and search result?
These are my thoughts
They both don't have identity, therefore they are not Entities. But the absence of identity doesn't imply they are Value Object. As Eric Evans states:
However, if we think of this category of object as just the absence of identity, we haven't added much to our toolbox or vocabulary. In fact, these objects have characteristics of their own and their own significance to the model. These are the objects that describe things.
I would like to say that both are value objects, but I'm not sure. What confuses me are examples that I've found on Internet. Usualy value object are part of other entities, they are not "standalone". Martin Fowler gives for example Money or date range object. Adam Bien event compares them to enums.
If search result would be considered value object, that would be value object that consists of entities. I'm not sure that's completely alright.
I don't think they are DataTransferObject. Because we are not current concerned with transferring data between layers, but we are concerned with their meaning for the model in absence of layer.
I don't think search query is command. Because it's not a request for change.
As stated on CQRS
People request changes to the domain by sending commands.
I'm trying to use and learn DDD, can someone clarify this problem to me? Where did I go wrong with reasoning?
The simple answer is that querying is probably not part of your domain. The domain model is not there to serve queries, it is there to enforce invariants in your domain. Since by nature queries are read-only, there are no invariants to enforce, so why complicate things? I think where people usually go wrong with DDD is that they assume since they are "doing DDD" every aspect of the system must be handled by a domain model. DDD is there to help with the complex business rules and should only be applied when/where you actually have them. Also, you can and probably should have many models to support each bounded context. But that's another discussion.
It's interesting that you mention CQRS because what does that stand for? Command query responsibility segregation. So if commands use the domain model, and query responsibility is segregated from that, what does that tell you to do? The answer is, do whatever is easiest to query and display that data. If select * from news table filled to dataset works, go with that. If you prefer entity framework, go with that. There is no need to get the domain model involved for queries.
One last point I'd like to make is I think a lot of people struggle with DDD by applying it to situations where there aren't many business invariants to enforce and the domain model ends up looking a lot like the database. Be sure you are using the right tool for the job and not over complicating things. Also, you should only apply DDD in the areas of your system where these invariants exist. It's not an all or nothing scenario.
Related
I am studying hard DDD now. After months of studying, I found a contradiction between modeling and coding. As you know, DDD has the principle of "Domain 1st, Tech 2nd". However, there are "definite" constraints when moving the actual model into the implementation, for example:
Original model:
With the domain concept, posts are associated with multiple comments, and comments are an ordinary model that depends on the post. Moving this into code ...
class Post{
Integer postId;
String title;
String content;
String writer;
Collection<Comment> comments;
}
class Comment{
String content;
}
Like this... But if there are hundreds of millions of comments, there will be performance problems. According to the solution I have investigated, finally I change the original model as follows....
Revised model:
Also the code will change...
class Post{
Integer postId;
String title;
String content;
String writer;
}
class Comment{
Integer postId;
String content;
}
This revised model works well for me and I am satisfied with the solution. But I feel something inconsistent. It seems that the model is distorting due to technical constraints. If we show the first and second models to the domain experts and talk about the diagram, he or she will better understand the first model.
Am I misunderstanding about DDD concept? If so, give me some advice. Thank you.
One of the changes in mindset that come with Domain Driven Design is that your domain will constantly evolve with changes to your understanding of the domain. It is not just that the domain will evolve, but your understanding and perception about it will evolve, as well.
What you are running into right now, in my opinion, is trying to rationalize the design based on the loading of one or more entities into an aggregate by looking at it from how it is persisted. This common parent and child relationship feels natural, because it is the way that most of us have done things in the past. Even from a DDD perspective, it is easy to get caught up in the "Comments can't exist without Posts" paradigm.
This comes down to the fact that you are modelling based upon data inside of the domain, instead of use cases. Look at it this way... Posts are not simply a collection of Comments. Instead, a Comment refers to a specific Post. The nuance sounds minor, but it has broad-reaching consequences. When modeled in this fashion, it matches your revised model - and it is completely and totally fine. The only thing you need to change is your mindset, being that Comment can be considered an Aggregate, just as a Post is. They both are going to have use cases where the other one must exist, but at the same time, you need to see that you are unlikely to do something where both are impacted as part of the same use case (outside of deletion of the Post).
To illustrate, consider this use case:
As a Writer, I want to be able to edit the Content of my Post.
Your new model actually effectively supports that. Instead of looking at the relationship, you are looking at how the domain is used. Should you load Comments for a Writer to edit? Without knowing your domain, I would still assume that you would not want to do so. There are use cases that will likely involve both Posts and Comments, and that is also fine. Since you have two Aggregates inside of a single Bounded Context, you will be able to support use cases that are solely based on Posts, solely based on Comments, or a combination of both.
In terms of the technical concerns, you mention "hundreds of millions of comments". I assume that you mean system-wide, and not for a single Post? Assume that you have an active post, and that it sees 20k comments in its lifetime. For a properly designed and optimized database, this should still not be an issue. When it becomes an issue, if it ever does, it can be further addressed by additional changes to the technology used, as opposed to changing the domain. You can look at things like caching strategies (outside of the domain, since that is an application concern and not a domain concern), external indexes, eventual consistency, etc.
Highly recommend taking a read through Vaughn Vernon's "Effective Aggregate Design" series of articles, if you have not already:
Effective Aggregate Design
Additionally, his excellent book "Implementing Domain-Driven Design", is a must-read, in my opinion. While the Evans material is essential, it is more like the theoretical concepts; whereas the Vernon material talks about how to put the concepts into practice and what the implications of those decisions are.
As an addendum, like plalx points out in the comments below. None of this is meant to be a generalization about Posts and Comments in general, but explicitly how they apply to your domain, as it has been described to us and what could be inferred from your models. Posts and Comments will likely behave differently for others, because others will have distinct use cases. Even within your own domain, should Posts and/or Comments exist in a different context, they could behave differently. Above all else, try and make sure that everything you add to your domain model (in general) is added because of a specific and direct use case. It is tempting to simply start data modeling, but you will start to find yourself trying to force use cases into the domain model. Domain modeling should not be a finite process, or a single step in the process. Be willing and able to adapt to changes in understanding or changes to the way that the business changes its overall operational strategies over time.
One pitfall I notice about people entering the DDD world is that they visualize their ARs as source of READ operations as well. So, many times they tend to "model" the ARs and its entities/value objects in a way that "appeals" a DTO that is meant to hydrate the UI.
In your case, I would make Post an AR and Comments another AR. Adding a comment shouldn't require to instantiate Post at all. Editing a Post shouldn't require to 'load' the comments at all.
Use an independent mechanism to project your post/comments into a POCO/DTO class that may make sense to have a collection of comments in your post.
Does it make sense?
Somewhere far, far away in a domain galaxy there is mention of
'Measurement values' and 'Places'
Each 'Measurement value' comes from/belongs to a specific 'Place'
Each 'Measurement value' is registered on a given date & time and of a given, specific type (eg. waterflow, wind, etc)
Each 'Place' has a name and a collection of 'Measurement Values' that gets registered
Given my current model where 'Places' are the aggregate root that holds 'Measurement values' I have a dilemma:
Users wishes to view one type of measurement values at a time and there are quite a lot of measurement values.
To load all measurement values when only some of them are needed seems unneccessary..
Eg. Im stuck on how to organize/model the need "Show me waterflows (measurement values) in River X (Place) between time A and B"
Is it allowed to instantiate River X aggregate root only partially loaded with the type of measurement values concerned in a given use case?
Are there other ways of modelling measurement values and their origin?
Please let med know your thoughts...
I think that your aggregate is consistent as it is. Your dilemma as nothing to do with domain model but rather than with a presentation model.
I will consider the possibility to deserialize each measurement in a NoSQL instance, in this way your presenteation layer could filter and make any query without affecting the consistency of domain layer.
Correct me if I'm wrong but it sounds very much like the data model and storage are impacting the design of your system? If this is so it may be the cause of your dilemma. A key part of the benefit modeling using aggregates is it is free of dependencies. Dependencies such as databases and data models. There is no direct 'view' of an aggregate, so it's not shaped by the view. This makes aggregates much easier to design. They are much more focused on solving the problem. And are therefore great candidates for doing complex stuff.
If it turns out you don't need aggregates to model your domain. You can then just focus on an efficient storage and retrieval mechanism.
In other words...
Don't tie yourself up in knots doing DDD if you don't need to.
If it helps I created an infographic on common DDD mistakes. You may find it helpful. You can find it here.
By the way, I think DDD is a great way to go, but only if your domain warrants it. Appologies if I have misunderstood you.
I fail to see the real problem. You said that each Measurement is tied to a specific Place, then you don't have to load all Measurements.
Using correct data layer configuration, you can load the required Measurement by selecting/loading/instantiating only it's parent (Place).
I've got a question on my mind that has been stirring for months as I've read about DDD, patterns and many other topics of application architecture. I'm going to frame this in terms of an MVC web application but the question is, I'm sure, much broader. and it is this: Does the adherence to domain entities create rigidity and inefficiency in an application?
The DDD approach makes complete sense for managing the business logic of an application and as a way of working with stakeholders. But to me it falls apart in the context of a multi-tiered application. Namely there are very few scenarios when a view needs all the data of an entity or when even two repositories have it all. In and of itself that's not bad but it means I make multiple queries returning a bunch of properties I don't need to get a few that I do. And once that is done the extraneous information either gets passed to the view or there is the overhead of discarding, merging and mapping data to a DTO or view model. I have need to generate a lot of reports and the problem seems magnified there. Each requires a unique slicing or aggregating of information that SQL can do well but repositories can't as they're expected to return full entities. It seems wasteful, honestly, and I don't want to pound a database and generate unneeded network traffic on a matter of principle. From questions like this Should the repository layer return data-transfer-objects (DTO)? it seems I'm not the only one to struggle with this question. So what's the answer to the limitations it seems to impose?
Thanks from a new and confounded DDD-er.
What's the real problem here? Processing business rules and querying for data are 2 very different concerns. That realization leads us to CQRS - Command-Query Responsibility Segregation. What's that? You just don't use the same model for both tasks: Domain Model is about behavior, performing business processes, handling command. And there is a separate Reporting Model used for display. In general, it can contain a table per view. These tables contains only relevant information so you can get rid of DTO, AutoMapper, etc.
How these two models synchronize? It can be done in many ways:
Reporting model can be built just on top of database views
Database replication
Domain model can issue events containing information about each change and they can be handled by denormalizers updating proper tables in Reporting Model
as I've read about DDD, patterns and many other topics of application architecture
Domain driven design is not about patterns and architecture but about designing your code according to business domain. Instead of thinking about repositories and layers, think about problem you are trying to solve. Simplest way to "start rehabilitation" would be to rename ProductRepository to just Products.
Does the adherence to domain entities create rigidity and inefficiency in an application?
Inefficiency comes from bad modeling. [citation needed]
The DDD approach makes complete sense for managing the business logic of an application and as a way of working with stakeholders. But to me it falls apart in the context of a multi-tiered application.
Tiers aren't layers
Namely there are very few scenarios when a view needs all the data of an entity or when even two repositories have it all. In and of itself that's not bad but it means I make multiple queries returning a bunch of properties I don't need to get a few that I do.
Query that data as you wish. Do not try to box your problems into some "ready-made solutions". Instead - learn from them and apply only what's necessary to solve them.
Each requires a unique slicing or aggregating of information that SQL can do well but repositories can't as they're expected to return full entities.
http://ayende.com/blog/3955/repository-is-the-new-singleton
So what's the answer to the limitations it seems to impose?
"seems"
Btw, internet is full of things like this (I mean that sample app).
To understand what DDD is, read blue book slowly and carefully. Twice.
If you think that fully fledged DDD is too much effort for your scenario then maybe you need to take a step down and look at something closer to Active Record.
I use DDD but in my scenario I have to support multiple front-ends; a couple web sites and a WinForms app, as well as a set of services that allow interaction with other automated processes. In this case, the extra complexity is worth it. I use DTO's to transfer a representation of my data to the various presentation layers. The CPU overhead in mapping domain entities to DTO's is small - a rounding error when compared to net work calls and database calls. There is also the overhead in managing this complexity. I have mitigated this to some extent by using AutoMapper. My Repositories return fully populated domain objects. My service layer will map to/from DTO's. Here we can flatten out the domain objects, combine domain objects, etc. to produce a more tabulated representation of the data.
Dino Esposito wrote an MSDN Magazine article on this subject here - you may find this interesting.
So, I guess to answer your "Why" question - as usual, it depends on your context. DDD maybe too much effort. In which case do something simpler.
Each requires a unique slicing or aggregating of information that SQL can do well but repositories can't as they're expected to return full entities.
Add methods to your repository to return ONLY what you want e.g. IOrderRepository.GetByCustomer
It's completely OK in DDD.
You may also use Query object pattern or Specification to make your repositories more generic; only remember not to use anything which is ORM-specific in interfaces of the repositories(e.g. ICriteria of NHibernate)
I read this article today and am trying to clarify some things. Does this article mean that model objects should contain business logic?
For example let us say that there is a Student object that we retrieve form the database via Hibernate. Does this article say that the Student object should contain business logic as well rather than having only getters and setters?
Disregard the date, what Martin Fowler states is as relevant today as it was eight years ago. Fowler does not state that you should mix persistence into the domain objects, quite the contrary:
"It's also worth emphasizing that putting behavior into the domain objects should not contradict the solid approach of using layering to separate domain logic from such things as persistence and presentation responsibilities."
You should read the article again, because the article describes this anti-pattern extermely well, but I shall try to summarize it for you in the context of what you are asking:
If you are to create a domain model, yes your domain objects should contain business logic as well as state, and changes to the state of your domain entities should be done through methods which convey business meaning. The anemic domain model is an anti-pattern because you incur the cost of an extra layer of classes but you are not reaping the benefits. Why bother with a domain layer which you have to map against the database when it convey exactly the same intent as you get from using an active record style approach (dataset, etc)? So the article does not say that you should have a "student-object", but it states that if you do, you should definitively add state to that class.
The point in the article about not having a set of objects to represent your model if you don't also model your domain can be a bit confusing due to the technologies available today. There are great tools out there which can effortlessly move data between a set of POCOs and the database (Nhibernate, EF, Simple Data, Massive, Dapper, etc) so in that retrospectiv I would say that you would probably end up with a set of "entities" in most solutions today, the real difference being whether this is just a database model or a real domain model.
I'll close up by showing you an example of the interaction between a domain entry point (command handler) and a domain model. The method shown below lives in a command handler which consumes a request to change something in the domain. Notice that the layer-ontop-of-your-domain-code simply gets the domain entity and calls one method on the domain? Thats an important point because the workflow we are modelling is fully encapsulated in the domain, not in the layer-ontop-of-your-domain-code or anywhere else:
public void Handle(AddEmailAddressForAlerts command)
{
var agent = _repository.GetAgent(command.AgentKey.AgentId);
agent.AddEmailAddressForAlerts(new EmailAddress(command.EmailAddress));
}
Notice the date - the citation is over eight years old.
Martin Fowler is obviously a very smart guy, and I like the article's point, but take it with a grain of salt. Encapsulating state and behavior together is a good thing in general, but it should be balanced against layering considerations. Persistence isn't the same thing as business logic. I'd still have a separate persistence tier; I wouldn't put persistence in a model object.
Dogma should be challenged in all its forms. Be aware of other people's ideas, but think for yourself.
After reading Evan's and Nilsson's books I am still not sure how to manage Data access in a domain driven project. Should the CRUD methods be part of the repositories, i.e. OrderRepository.GetOrdersByCustomer(customer) or should they be part of the entities: Customer.GetOrders(). The latter approach seems more OO, but it will distribute Data Access for a single entity type among multiple objects, i.e. Customer.GetOrders(), Invoice.GetOrders(), ShipmentBatch.GetOrders() ,etc. What about Inserting and updating?
CRUD-ish methods should be part of the Repository...ish. But I think you should ask why you have a bunch of CRUD methods. What do they really do? What are they really for? If you actually call out the data access patterns your application uses I think it makes the repository a lot more useful and keeps you from having to do shotgun surgery when certain types of changes happen to your domain.
CustomerRepo.GetThoseWhoHaventPaidTheirBill()
// or
GetCustomer(new HaventPaidBillSpecification())
// is better than
foreach (var customer in GetCustomer()) {
/* logic leaking all over the floor */
}
"Save" type methods should also be part of the repository.
If you have aggregate roots, this keeps you from having a Repository explosion, or having logic spread out all over: You don't have 4 x # of entities data access patterns, just the ones you actually use on the aggregate roots.
That's my $.02.
DDD usually prefers the repository pattern over the active record pattern you hint at with Customer.Save.
One downside in the Active Record model is that it pretty much presumes a single persistence model, barring some particularly intrusive code (in most languages).
The repository interface is defined in the domain layer, but doesn't know whether your data is stored in a database or not. With the repository pattern, I can create an InMemoryRepository so that I can test domain logic in isolation, and use dependency injection in the application to have the service layer instantiate a SqlRepository, for example.
To many people, having a special repository just for testing sounds goofy, but if you use the repository model, you may find that you don't really need a database for your particular application; sometimes a simple FileRepository will do the trick. Wedding to yourself to a database before you know you need it is potentially limiting. Even if a database is necessary, it's a lot faster to run tests against an InMemoryRepository.
If you don't have much in the way of domain logic, you probably don't need DDD. ActiveRecord is quite suitable for a lot of problems, especially if you have mostly data and just a little bit of logic.
Let's step back for a second. Evans recommends that repositories return aggregate roots and not just entities. So assuming that your Customer is an aggregate root that includes Orders, then when you fetched the customer from its repository, the orders came along with it. You would access the orders by navigating the relationship from Customer to Orders.
customer.Orders;
So to answer your question, CRUD operations are present on aggregate root repositories.
CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);
I've done it both ways you are talking about, My preferred approach now is the persistent ignorant (or PONO -- Plain Ole' .Net Object) method where your domain classes are only worried about being domain classes. They do not know anything about how they are persisted or even if they are persisted. Of course you have to be pragmatic about this at times and allow for things such as an Id (but even then I just use a layer super type which has the Id so I can have a single point where things like default value live)
The main reason for this is that I strive to follow the principle of Single Responsibility. By following this principle I've found my code much more testable and maintainable. It's also much easier to make changes when they are needed since I only have one thing to think about.
One thing to be watchful of is the method bloat that repositories can suffer from. GetOrderbyCustomer.. GetAllOrders.. GetOrders30DaysOld.. etc etc. One good solution to this problem is to look at the Query Object pattern. And then your repositories can just take in a query object to execute.
I'd also strongly recommend looking into something like NHibernate. It includes a lot of the concepts that make Repositories so useful (Identity Map, Cache, Query objects..)
Even in a DDD, I would keep Data Access classes and routines separate from Entities.
Reasons are,
Testability improves
Separation of concerns and Modular design
More maintainable in the long run, as you add entities, routines
I am no expert, just my opinion.
The annoying thing with Nilsson's Applying DDD&P is that he always starts with "I wouldn't do that in a real-world-application but..." and then his example follows. Back to the topic: I think OrderRepository.GetOrdersByCustomer(customer) is the way to go, but there is also a discussion on the ALT.Net Mailing list (http://tech.groups.yahoo.com/group/altdotnet/) about DDD.