What is the point of using UnitOfWork along with DDD principles? - domain-driven-design

Namely, if aggregate root is the transactional boundary and if each AR has its repository, what would be the point of using UnitOfWork and group different repositories operations into a single transaction?
Doesn't that actually stand against the fundamentals of DDD where an AR is a transaction boundary?
I just can't reconcile those two.

The "change one aggregate at a time" is a suggestion to follow closely, but it's not a strict rule that can't never be broken. There may be situations where it just make sense to break it, depends on what's your domain.
But keep in mind, you don't need an UoW in those scenario either. It's infrastructure, an implementation details. Can use or not use it, it will not have an impact on the DDD design you apply, nor will invalidate it.
Also, UoW aren't useful only for having to manage more than one AR at the same time. You can use them to create repository that behave like in-memory
persistent collections. (i.e, repository that have an add, remove, find methods, but don't need a save or persist). The UoW can keep track of the changes, and flush the transaction later on.

Related

Does repository pattern really repository plus unit of work? Or not always repository pattern need unit of work?

I have found some old questions, but I doesn't really answer or clear my doubts.
Repository Pattern + Unit Of Work: it is from 2012, and they tell that really to the repository pattern is not needed nowdays. Really I would like to know if repository pattern implies always unit of work and another aspects. Anyway, it would be to know another opiniones more recents if really repository pattern is useful or not today.
DDD - the rule that Entities can't access Repositories directly: this is a good post, but it desn't talk about unit of work.
Also I have asked another questions that are not answered in this posts. So I open a new one.
I am reading some examples how to implement repository pattern, thinking in a DDD architecture.
The pattern is called repository pattern, but many of the examples that I have seen implement the both and it seems that it is a unit, it has no sense or it is not good to implement only repository pattern, that it is needed the unit of work too.
Here are some examples, that they have small difference but it is the same one to do:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
https://www.youtube.com/watch?v=rtXpYpZdOzM
In this examples, they use the repositories through the unit of work, so they don't use directly the repository to say in some way (really the repositories are uses because they are properties in the unit of work).
So my questions are various:
1.- When it is talked about pattern repository, really it means repository and unit of work or there is in some cases where it could be implemented only the repository?
2.- If it is implemented the unit of work, is it recommended to access the repositories only throuth it? Because in this examples, it is posible, in the consumer, instantiate the repositories and the unit of work. Wouldn't it be better to avoid the consumer to can use repositories and only create the unit of work?
3.- In the second link that I put, in the video, it is said that the repositories shouldn't have methods like update, that this is not the responsability of the repository, but in most cases of another examples, I always see the update method. So is it really a bad practice to have an update method in the repository? In this case, if I don't have this method and call the complete() method of the unit of work, it will work because behind the interface, the implementation uses an OR/M, but if another implementation doesn't use it, I have to notify in some way that the entity was changed. I guess an update method is the most easy to do it.
Well, in summary, I would like to know if really means to have the unit of work too or not.
Thanks.
When it is talked about pattern repository, really it means repository and unit of work or there is in some cases where it could be implemented only the repository?
From Evans, 2004
Leave transaction control to the client. Although the REPOSITORY will insert into and delete from the database, it will ordinarily not commit anything.... the client presumably has the context to correctly initiate units of work.
So Evans considers them to be separable ideas.
Implicit in Evans's writing is the idea that the information of the domain model is stored in a single relational database; which means that transactions spanning multiple aggregates are fine, because the database ensures that information is persisted atomically. But when you start looking at alternatives to a monolithic SQL database, robust persistence is... tricky.
A lot of modern writing eases some of this by adding a constraint that aggregate boundaries and transaction boundaries are aligned. In this kind of a design, you might reasonably factor the transaction management into the repository facade.
As a reader, we have to be really careful that we understand the implicit constraints of the author's context.
it is said that the repositories shouldn't have methods like update, that this is not the responsibility of the repository, but in most cases of another examples, I always see the update method
Evans again:
The ideal is to hide all of the inner workings from the client (although not the developer of the client) so that the client code will be the same whether the data is stored in an object database, stored in a relational database, or simply held in memory.
There are a couple problems with this ideal
Collections simply held in memory don't have distributed failure modes like the other candidate implementations
When is the change I made visible to others is an important design consideration
So you end up with people choosing different repository interfaces depending on how/if they decide to address these issues.
The important idea to recognize here is that REPOSITORY is a pattern; something we expect to have different expressions depending on the system of forces at play.
Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice. -- Christopher Alexander, A Pattern Language (emphasis added)

Why should repository methods accept domain entity as parameter?

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.

Do we need another repo for each entity?

For example take an order entity. It's obvious that order lines don't exist without order. So we have to get them with the help of OrderRepository(throw an order entity). Ok. But what about other things that are loosely coupled with order? Should the customer info be available only from CustomerRepo and bank requisites of the seller available from BankRequisitesRepo, etc.? If it is correct, we should pass all these repositories to our Create Factory method I think.
Yes. In general, each major entity (aggregate root in domain driven design terminology) should have their own repositories. Child entities *like order lines) will generally not need one.
And yes. Define each repository as a service then inject them where needed.
You can even design things such that there is no direct coupling between Order and Customer in terms of an actual database link. This in turn allows customers and orders to live in completely independent databases. Which may or may not be useful for your applications.
You correctly understood that aggregate roots's (AR) child entities shall not have their own repository, unless they are themselves AR's. Having repositories for non-ARs would leave your invariants unprotected.
However you must also understand that entities should usually not be clustered together for convenience or just because the business states that some entity has one or many some other entity.
I strongly recommend that you read Effective Aggregate Design by Vaughn Vernon and this other blog post that Vaughn kindly wrote for a question I asked.
One of the aggregate design rule of thumb stated in Effective Aggregate Design is that you should usually reference other aggregates by identity only.
Therefore, you greatly reduce the number of AR instances needed in other AR's creationnal process since new Order(customer, ...) could become new Order(customerId, ...).
If you still find the need to query other AR's in one AR's creationnal process, then there's nothing wrong in injecting repositories as dependencies, but you should not depend on more than you need (e.g. let the client resolve the real dependencies and pass them directly rather than passing in a strategy allowing to resolve a dependency).

Aggregate roots depend on the use case so does that mean that we might end up with really a lots of repositories?

Ive heard a lots that aggregate roots depend on the use case. But what does that mean in coding context ?
You have a service class which offcourse hold methods (use cases) that gonna accomplish something in a repository. Great, so you use a repository which is equal to an aggregate root to perform your querying.
Now you need to perform some other kind of operation which use totally different use case than the first service class but use the same entities.
Here the representation :
Entities: Customer, Orders, LineOrder
Service 1: Add new customers, Delete some customers, retrieve customer orders
Here the aggregate root seem to be Customer because you need this repository to perform thoses use cases.
Service 2: Retrieve customer from an actual order
Here the aggregate root seem to be Order because you need this repository to perform this use case.
If i am wrong please correct me. Now that mean you have 2 aggregates roots.
Now my question is, since aggregate roots depend on the use case does that mean that we might end up with really a lots of repositories if you end up having lots of use cases ?
The above example was probably not the best example... so lets say we have a Journal which hold JournalEntries which each entries hold Tasks, Problems and Notes. (This is in the context of telling to a system what have been done to a project)
Does that mean that im gonna end up with 2 repository ? (Journal, JournalEntry)
In the use cases where i need to add new tasks, problems and notes from an journal entry ?
(Can be seen as a service)
Or might end up with 4 repository. (Journal, Task, Problems, Notes)
In the use cases where i need to access directment task, problems and notes ?
(Can be seen as another service)
But that would mean if i need both of theses services (that actually hold the use cases) that i actually need 5 repository to be able to perform use cases in both of them ?
Thanks.
Hi I saw your post and thought I may give you my opion. First I must say I've been doing DDD in project for three years now, so I'm not an expert. But I'm currently working in a project as an architect an coaching developers in DDD, and I must say it isn't a walk in the park... I don't know how many times I've refactored the model and Entity relationships.
But my experience is that you endup with some repositories (more than few but not many). My Aggregates usually contains a few classes and the Aggregate object graph isn't that deep (if you know what I mean).
But I try to be concrete:
1) Aggregate roots are defined by your needs. I mean if you feel that you need that Tasks object through Journal to often, then maybe thats a sign for it to be upgraded as a aggregate root.
2) But everything cannot be aggregate roots, so try to capsulate object that are tight related. Notes seems like a candidate for being own by a root object. You'd probably always relate Notes to the root or it loses its context. Notes cannot live by itself.
3) Remember that Aggregates are used for splitting up large complex domains into smaller "islands" that take care of thier inhabbitants. Its important to not make your domain more complex than it is.
4) You don't know how your model look likes before you've reached far into the project implementation phase. If you realize that some repositories aren't used that much, they may be candidates for merging into other root object (if they have that kind of relationship). You can break out objects that are used so much through root object without its context. I mean for example if Journal are aggregate root and contains Notes and Tasks. After a while you model grows and maybe Tasks
have assoications to Action and ActionHistory and User and Rule and Permission. Now I just throw out a bunch om common objects in a rule/action/user permission functionality. Maybe this result in usecases that approach Tasks from another angle, "View all Tasks performed by this User" etc. Tasks get more involved in some kind of State/Workflow engine and therefor candidates for being an aggregate root itself.
Okey. Not the best example but it maybe gives you the idea. A root object can contain children where some of its children can also be root object because we need it in another context (than journal).
But I have myself banged my head against the wall everytime you startup with a fresh model. Just go with the flow and let the model evolve itself through its clients/subsribers. You refine the model through its usage. The Services (application services and not domain services) are of course extended with methods that respond to UI and usecases (often one-to-one).
I hope I helped you in someway...or not :D
Yes, you would most likely end up with 5 repositories (Journal, JournalEntry, Task, Problems, Notes). Your services would then use these repositories to perform CRUD for each type of entity.
Your reaction of "wow so many repositories" is not uncommon for developers new to DDD.
However, your repositories are usually light weight assuming your model and DB schema are fairly evenly matched which is often the case. If you use an ORM such as nHibernate or a tool such as codesmith generator then it gets even easier to create your repositories.
At first you need to define what is aggregate. I don't know about use case aggregates.
I know about aggregates following...
Aggregates are union of several entities. One of the entities is the aggregate root, the rest entities (or value types) have sense only in selected aggregate root context. For example you can define Order and OrderLine as an aggregate if you don't need to do any independent actions with OrderLine entities. It means that OrderLine makes sense in Order context only.
Why to define aggregates at all? It is required to reduce references between objects. That will simplify you domain model.
And of course you don't need to have OrderLineRepository if OrderLine is a part of Order aggregate.
Here is a link with more information. You can read Eric Evans DDD book. He explains aggregates very well.

data access in DDD?

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.

Resources