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.
Related
Lets assume we have separate read models so that we use repositories only on write side, not on read side. (and this question is all about write side)
Also, lets assume one of our goals is to have full Aggregate/Entity encapsulation in a way that they expose only behaviour and not state. (meaning, no getters/setters)
Next, lets assume we dont want to use ORMs nor reflection for getting aggregate internals from within repository.
Obviously, one of the solutions left is that aggregate itself exposes its full state as a VO/poco and hand it over to repository. Repository would then know how to map it to DAO and save it.
Now, on many places i read that repositories should accept aggregates themselves.
Question is: why? What is wrong with aggregate expose VO of its state, hand it to repository and let repo do the save based on it?
Benefit is full & clear aggregate encapsulation.
What is wrong with aggregate expose VO of its state, hand it to repository and let repo do the save based on it?
That approach violates some of the other assumptions of the domain modeling idea.
One of those assumptions is that the key business logic and the "plumbing" should be separate. The fact that you need to get a serializable representation of the aggregate is an accident of the fact that you are trying to write state into a stable storage (that step would be completely unnecessary if you were keeping the aggregate cached in memory).
A second assumption is that using "objects" to model the domain is a good idea. If you were using a functional approach, then of course you would be saving values, rather than objects.
It helps, I think, to keep in mind that the context of the solutions we write has changed a lot in the last 15-20 years. Patterns that make sense for a localized application with long sessions that include many interactions don't necessarily make sense for distributed stateless applications, and vice versa.
that pattern cause you to sacrifice aggregate encapsulation
No, it doesn't - asking an object for a copy of some information in a previously agreed upon representation doesn't violate encapsulation. See Kevlin Henney, for example.
What it does do, however, is require interfaces suitable for two different collaborators: your applications, that care about the business rules, and your repository, that cares about persistence of representations.
I am trying to learn about details of domain driven design and i came to this question.
I found many examples with:
Defining repository interface within the domain
Defining repository implementation somewhere else
Inject repository interface into aggregate root
On the other hand, there are examples that strictly go against it and do all repository related stuff from service.
I cannot find authoritive answer and explanation: is it considered a bad practice and if so - why?
I cannot find authoritive answer and explanation: is it considered a bad practice and if so - why?
Yes, mostly because a number of different concerns get confused.
Aggregates define a consistency boundary; any change of state should be restricted to a collection of related entities that are all part of the same aggregate. So once you have looked up the first one (the "root" entity), you should be able to achieve the change without needing to examine any data other than this graph of domain entities and the arguments that you have been passed.
Put another way, Repository is a plumbing concern, not a domain concern. Your domain entities are responsible for expressing your domain, without infrastructure concerns getting mixed in.
To have, for example, Aggregate.Save() method that would inside use IRepository interface to save.
Aggregate.Save() definitely indicates a problem. Well, two problems, to be precise: Save probably isn't part of your ubiquitous language, and for that matter its likely that Aggregate isn't either.
Save isn't a domain concern, it's a persistence concern - it just copies data from your in memory representation (volatile storage) to a durable representation (stable storage). Your domain model shouldn't need to know anything about that.
One of the reasons you found "many examples with" is that getting these concerns separated correctly is hard; meaning you really need to think deeply about the problem to tease them apart. Most examples don't, because teasing things apart isn't critical when you always deploy everything together.
I'm breaking my system into (at least) two bounded-contexts: study-design and survey-planning.
There's a concept named "subject" (potential subject for interviewing) in the study-design context. We also maintain associations between subjects and populations in that domain.
Now, in the survey-planning, we also need (some) information about the subject (for example: for planning a visit, or even for anticipated selection of questionnaire, in case the population the subject belongs to is known beforehand).
So, I need that "subject" in both contexts.
What approach should I pick? Having a shared kernel, as explained in Eric Evans DDD book? I don't mind (at least for now) having the two contexts sharing the same database.
Or... should I go pure microservice? Meaning: those two can't / shouldn't share database..., and in that case I might have to go the mirroring / duplicating route through event passing: https://www.infoq.com/news/2014/11/sharing-data-bounded-contexts
Any thoughts on which one is better, for the above situation?
Thanks!
The context for microservices is distributed systems. In any other situation it would probably be overkill. Shared kernel will eventually split. That is usually the case. You may start from it. Nothing wrong with that. However, it will not stay there.
I recommend that you choose a event-driven solution, but not necessarily to use microservices. You could build an event-driven monolith in order to spend much less time on synchronizing the two models. When the application grows too big then you split the monolith into microservices. You could use CQRS to split event more the models into write and read. If you use event-sourcing things get even more interesting.
In my experience, with shared kernel, the models become god objects, one-size-fits-all kind of objects.
In my opinion, you have three entities:
study
survey
person
It is pretty intuitive to see that each of these is its own aggregate root. So then we are talking about inter-root relationships. In my experience, those are meaningful entities on their own, and cleanest and most future proof by far is to treat those relationships as independent aggregate roots.
The relationship between a study and a person is perhaps called TestSubject, and the relationship between a person and a survey could be called Interviewee or something similar. In another context, the person could be an employee for a company, and then the Employee would be its own aggregate root. Information that only relates to the relationship and not to the person or the study say, should be limited to this relationship specific aggregate root. This could for instance be the start date at which the subject started to take part in the test, and the end date (when he dropped out, if he or she dropped out prematurely, etc.)
As for storage, all aggregate roots should define their own separate repositories as interfaces and know only those interfaces, but the implementation of those interfaces is free to choose to use the same database or different ones, or even different kinds, local or distributed, etc. So this holds for these 'relational' aggregate roots as well. But you should almost force yourself to use different databases and preferably even different technologies (e.g. one EntityFramework, the other MongoDb) when you start with this, to force yourself to make sure your interfaces are properly defined and independent of implementation.
And yes, big fan of CQRS as well here, and Event/Command Sourcing as well. There are many light-weight implementations possible that allow you to upscale, but are very easy to get into and afford you almost completely linear (=predictable) complexity.
You can start with microservices that share a monolithic data source, but only use partial domain entities and value objects
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'm facing several problems trying to apply DDD with EF4 (in ASP MVC2 context). Your advaice would be greatly appreciated.
First of all, I started to use POCO because the dependacy on ObjectContext was not very comfortable in many situations.
Going to POCO solved some problems but the experience is not what I was used to with NHibernate.
I would like to know if it's possible to use designer and to generate not only entities but also a Value Objects (ComplexType?). If I mean Value Object is a class with one ctor without any set properties (T4 modification needed ?).
The only way I found to add behavior to anemic entities is to create partial classes that extends those generated by edmx. I'm not satisfied with this approach.
I don't know how to create several repositories with one edmx. For now I'm using a partial classes to group methods for each aggregate. Each group is a repository in fact.
The last question is about IQueryable. Should it be exposed outside the repository ? If I refer to the ble book, the repository should be a unit of execution and shouldn't expose something like IQueryable. What do you think ?
Thanks for your help.
Thomas
It's fine to use POCOs, but note that EntityObject doesn't require an ObjectContext.
Yes, Complex Types are value objects and yes, you can generate them in the designer. Select several properties of an entity, right click, and choose refactor into complex type.
I strongly recommend putting business methods in their own types, not on entities. "Anemic" types can be a problem if you must maintain them, but when they're codegened they're hardly a maintenance problem. Making business logic separate from entity types allows your business rules and your data model to evolve independently. Yes, you must use partial classes if you must mix these concerns, but I don't believe that separating your model and your rules is a bad thing.
I think that repositories should expose IQueryable, but you can make a good case that domain services should not. People often try to build their repositories into domain services, but remember that the repository exists only to abstract away persistence. Concerns like security should be in domain services, and you can make the case that having IQueryable there gives too much power to the consumer.
I think it's OK to expose IQueryable outside of the repository, only because not doing so could be unnecessarily restrictive. If you only expose data via methods like GetPeopleByBirthday and GetPeopleByLastName, what happens when somebody goes to search for a person by last name and birthday? Do you pull in all the people with the last name "Smith" and do a linear search for the birthday you want, or do you create a new method GetPeopleByBirthdayAndLastName? What about the poor hapless fellow who has to implement a QBE form?
Back when the only way to make ad hoc queries against the domain was to generate SQL, the only way to keep yourself safe was to offer just specific methods to retrieve and change data. Now that we have LINQ, though, there's no reason to keep the handcuffs on. Anybody can submit a query and you can execute it safely without concern.
Of course, you could be concerned that a user might be able to view another's data, but that's easy to mitigate because you can restrict what data you give out. For example:
public IQueryable<Content> Content
{
get { return Content.Where(c => c.UserId == this.UserId); }
}
This will make sure that the only Content rows that the user can get are those that have his UserId.
If your concern is the load on the database, you could do things like examine query expressions for table scans (accessing tables without Where clauses or with no indexed columns in the Where clause). Granted, that's non-trivial, and I wouldn't recommend it.
It's been some time since I asked that question and had a chance to do it on my own.
I don't think it's a good practice to expose IQueryable at all outside the DAL layer. It brings more problems that it solves. I'm talking about large MVC applications. First of all the refactorings is harder, many developers user IQueryable instances from the views and after struggle with the fact that when resolving IQueryable the connection was already disposed. Performance problems because all the database is often queried for a given set of resultats and so on.
I rather expose Ienumerable from my repositories and believe me, it saves me many troubles.