How should I structure my repository classes? - domain-driven-design

I am new to DDD. In my mini-project, I have a structure that looks like this (different from the actual names):
EntryClassificationGroup
EntryClassification
Entry
EntryType
Should I have just one repository class for all these 4 entities, since they are all related? Or should I have individual repositories for each one?

The question is can you add/delete/update EntryClassification or EntryClassificationGroup independently from your Entry and is it possible for them to exisit independently form your entries? If so it might be good idea have separate repository for it.
You might be concerned about querying data from your repositories here but Query object pattern allows you to query by different fields in the repository for Entry, let say by EntryType. So you may overcome this issue.

Related

Repository within domain objects

I have seen lot of discussions regarding this topic but i couldn't get a convincing answer. The general advice is not to have repository inside a domain object. What about an aggregate root? Isnt it right to give the root the responsibility to manipulate the composed objects?
For example, i have a microservice which takes care of invoices. Invoice is an aggregate root which has the different products. There is no requirement for this service to give details about individual products. I have 2 tables, one to store invoice details and other to store products of those invoices. I have two repositories corresponding to the tables. I have injected product repository inside the invoice domain object. Is it wrong to do so?
I see some mistakes according to DDD principles in your question. Let me try to clarify some concepts to give you hand.
First, you mentioned you have an Aggregate Root which is Invoice, and then two different repositories. Having an Aggregate Root means that any change on the Entities that the Aggregate consists of should be performed via the Aggregate Root. Why? That's because you need to satisfy some business rule (invariant) that applies on the relation of those Entities. For instance, given the next business rule:
Winning auction bids must always be placed before the auction ends. If a winning bid is placed after an auction ends, the domain is in an invalid state because an invariant has been broken and the model has failed to correctly apply domain rules.
Here there is an aggregate consisting of Auction and Bids where the Auction is the Aggregate Root.
If you have a BidsRepository, you could easily do:
var newBid = new Bid(money);
BidsRepository->save(newBid);
And you were saving a Bid without passing the defined business rule. However, having the repository just for the Aggregate Root you are enforcing your design because you need to do something like:
var newBid = new Bid(money);
auction.placeBid(newBid);
auctionRepository.save(auction);
Therefore, you can check your invariant within the method placeBid and nobody can skip it if they want to place a new Bid. Afterwards you can save the info into as many tables as you want, that is an implementation detail.
Second, you said if it's wrong injecting the repository into a Domain class. Here a quick explanation:
The repository should depend on the object it returns, not the other way around. The reason for this is that your "domain object" (more on that later) can exist (and should be testable) without being loaded or saved (that is, having a dependency on a repository).
Basically your design says that in order to have an invoice, you need to provide a MySQL/Mongo/XXX instance connection which is an infrastructure detail. Your domain should not know anything about how it is persisted. Your domain knows about the behavior like in the scenario of the Auction and Bids.
These concepts just help you to create code easier to maintain as well as help you to apply best practices such as SRP (Single Responsibility Principle).
Yes, I think it is wrong.
Domain should match real business model and should not care how data is persisted. Even if data internally are stored in multiple tables, this should not affect domain objects in any way.
When you are loading aggregate root, you should load related entities as well in one go. For example, this can easily be achieved with Include keyword in Entity Framework if you are on .NET. By loading all the data you ensure that you have full representation of business entity at any given time and you don't have to query database anymore.
Any changes in related entities should be persisted together with aggregate root in one atomic operation (usually using transactions).

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).

PHP How should Repositories handle adding/removing/saving/deleting entities?

I am having a bit of trouble implementing the Repository pattern, due to some confusion.
As far as I can tell now, a Repository should behave like an in-memory collection of objects, so if I do say:
$users = new UserRepository(new UserMapper);
$users->findAll();
The Users repository will load and return an array of User entities. Now I can either use them for just reading data, or can update the data on any particular entity, and invoke a save() method on the Repository that will utilize the Mapper to save the loaded entities back to the data source, with the updates that have been applied.
What I am wondering is if that is a correct understanding.
Should the add() method add an entity directly to the data source, or only to the collection within the Repository?
Likewise for remove(); should this method remove an entity from the data source, or only from the Repository.
The confusion stems from the fact that some implementations I have seen in tutorials have both add()/remove() methods, alongside save()/delete() methods. Is that the correct approach?
I've been developing using DDD techniques for around 6 months now and always use the save and delete methods, the save should persist the data to your persistence layer, the delete should remove from your persistence layer.
Saying the above, there is no reason why it shouldnt add to your collection.
p.s check out the dddinphp Google Group, theres an active community purely for these questions

How do read-only database views fit into the repository pattern?

Example: Your database has a SQL view named "CustomerOrdersOnHold". This view returns a filtered mix of specific customer and order data fields. You need to fetch data from this view in your application. How does access to such a view fit into the repository pattern? Would you create a "CustomerOrdersOnHoldRepository"? Is a read-only view such as this considered an aggregate root?
I would prefer separating the read repository, preferably even change its name to Finder or Reader, the repository is meant for Domain usage not for querying read-only data, you can refer to this article and this which explains the usage of Finder separated form repository.
I would recommend also the separating of read model from write model architecture CQRS and there
This architecture allows you to separate the read model from write model even in terms of data storage and the use of event sourcing.
For a middle solution you can utilize some CQRS concepts without the complexity of separating database by just separating repository from finders, read this post
for a sample of this type of solution (use the same database but separating finders form repositories) check this sample
Your read-only data would be considered Value Objects in the DDD world.
I typically place access methods for value objects in existing repositories until such time that it makes sense to create a separate repository. It's similar to a method that might return a static list of states to be used on an address form:
IAddressRepository
{
Address GetAddress(string addressID);
List<string> GetStates(string country);
}
I think that it is fine to have a separate repository like "CustomerOrdersOnHoldRepository". The interface of the repository will reflect the fact that the objects are readonly (by not defining Save/Add/MakePersistent method).
From How to write a repository:
... But there is another strategy that I quite like: multiple
Repositories. In our ordering example there is no reason we can have
two Repositories: AllOrders and SurchargedOrders. AllOrders represent
a list containing every single order in the system, SurchargedOrders
represents a subset of it.
I would not call returned object an Aggrgate Root. Aggregates are for consistency, data exchange and life cycles. Your objects don't have any of these. It seems that they also can not be classified as Value Objects ('characteristic or attribute'). They are just standalone classes.

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.

Resources