How to organise aggregates of inheriting objects in DDD? - domain-driven-design

Let's say you're constructing a domain model and you have the following requirements:
There will be visitors who can read the data
There will be publishers that can read and write the data
There will be moderators that can read, write and delete the data
From an OOP perspective, you would create a base class that has everything common to each of the "actors" above. Then, I would create subclasses to represent each of the concrete types.
My question is this, in DDD world, how should I arrange my aggregates?
Thanks!

I wouldn't use inheritance for that. Your requirements just need some user rights support. It's not even a DDD issue and what you're suggesting are not aggregates, but at most entities.
Anyway, the point is you'd have rights and groups (roles) which have specific rights. When you need to do something, you just check the current user's rights then proceed or forbid.
I'd use the same approach, no matter if I'd use DDD/OOP or not.

Related

Domain model defining relationships

Assuming everyone has the rights to do the CRUD operations (everyone is an admin type user). I have displayed CRUD operations the user can perform in the Domain diagram however, it's become quite messy. I am curious if it's acceptable to do the alternative approach shown in the images below instead since the multiplicative relationships remain the same for each action (create,edit,delete)
Seperated CRUD
Alternative approach? (create, edit, delete)
In short
If it becomes messy, it probably lacks of separation of concerns, or represents associations that are not really needed.
More explanations
Are the associations needed?
An association between User and Xxx implies a semantic relationship between the two classes. This means that instances of the classes are linked and not just for the time of an operations. So x would be able to find the User(s) that updated it, and u would know the Xxx instances that it updated. This kind of association can make sense if you want some audit trails, but this seems not to be your purpose here.
In other words, the fact that a User may perform some operations that CRUD instances of Xxx is not sufficient for justifying an association.
If they are needed, do they represent what you think?
Now it appears that your associations are can ..., i.e. some kind of authorisation scheme. Your diagram tells that each user would need to know in advance all the Xxx that it could update. This is a heavy burden. It would also imply that a user needs to know all the Xxx it can create; before they are even created? This looks somewhat inconsistent.
Modeling an authorisation scheme
If you'd wand to design an authorisation system, you'd probably not link users directly to the object, but use some intermediary mechanisms:
To express that a user can create new projects, you'd probably have some authorisation object that tells the caracteristics of projects that can be created.
To express that a user can edit, update, delete projcts, you could have a direct association like you envisaged, if some admin would maintain such authorisations.
But probably you would have some authorisation object that would tell what a user can do (e.g. a user "role"/"profile") and what category of projects.
Equally probable is that there are some rules that govern CRUD authorisations (e.g. a user having the role "edit" can edit the project he/she is assigned to, but not the others). Making use of such rules instead of explicitly designing (redundant) authorisations could then save you a lot of unnecessary extra associations (and extra constraints to keep the authorisations consistent with the rules).
Separation of concerns
And to keep things continue to be messy, you should consider:
having a separate diagram in your model for the authorisation concept
use some common CRUD interface: the users would then be associated with the CRUD interface without having to replicate everything for every possible class.
The main issue with both of your class models is a confusion between the type/instance levels. Your "can create/edit/delete" authorization relationships do not hold between a specific user and a specific object (an instance of Company, Project or Ticket), but rather between a specific user and a sepcific object type (Company, Project or Ticket), so it's not an ordinary association between two ordinary object types.
If you want to describe/define such authorization relationships with a class model, you would need to define a meta-class like ObjectType and express that your object types (Company, Project or Ticket) are instances of it.

Relationships between multiple aggregate roots

In many applications, I deal with users and finance companies (as an example) and I have long been struggling to model the relationship between the two according to Domain Driven Design principles.
In my system I can do the following:
Add a user to an existing finance company.
Add a finance company to an existing user.
I believe both are aggregate roots... Finance Company and User.
How do I model the relationship between the 2? Is it FinanceCompany.Users? or User.FinanceCompanies? Is it neither? Or am I missing knowledge of some key DDD concept(s)? The problem is if I choose one way over the other, the code is more understandable / clear from one aggregate root entry point, but not the other. Sometimes there are cases where it makes more sense to navigate to a Finance Company and add users to it, and other times there are cases where it makes more sense to navigate to a specific user and add finance companies to the user.
Is there some better way to approach this, maybe through repository methods? Is there some key concept I am not getting or understanding here? It doesn't feel right to assume the relationship between Finance Company and User belongs under either of the 2 ARs. When I store the relationship I have to store it in a table named FinanceCompanyUsers or UserFinanceCompanies, but it still doesn't seem clear.
Would I have code such as FinanceCompany.AddUser() and User.AddFinanceCompany()? or is there some completely different approach for relationships such as this?
You have already determined that both User and FinanceCompany are aggregates so each has its own life-cycle.
The problem with many domains is that we don't have a complete understanding of the relationships. As another example we can take an Order and a Product. Both are aggregates but would we have Order.AddProduct() or Product.AddOrder()? In this case it seems pretty obvious in that an Order contains a limited subset of Product entries whereas a Product may very well contain many orders and we are not really too interested in that relationship since it is a rather weak relationship. A Product can exist and be valid without any orders attached but an Order is pretty useless without at least one product entry. This means that the Order has an invariant imposed in terms of its OrderItem entries. In addition to this we have enough knowledge about this hackneyed example that we know we are going to need an associative entity (in relational theory speak) since we need additional information regarding the relationship and entering the fray would be our OrderItem table. Curiously I have not seen it called OrderProduct.
The guidance I would suggest is to pick the most appropriate side.
However, if no side is a true winner and both aggregates can exist without a relationship to the other in terms of an invariant perhaps the relationship itself is an aggregate as you have certainly alluded to. Perhaps it isn't only a UserFinanceCompany aggregate but perhaps there is a concept that is missing from the ubiquitous language that the domain experts refer to. Perhaps something like Auditor or some such that represents that relationship. This is akin to the OrderItem or OrderLine concept as opposed to OrderProduct.

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

DDD Repository and Entity

I have some big Entity. Entity has propertis "Id", "Status" and others.
I have Repository for this Entity.
I want to change status in one entity.
Should I get whole Entity, change property Status and use save method in Repository or should I use method ChangeStatus(id, newStatus) in Repository?
Probably you don't need a domain model. You could try a transaction script that directly use SQL to update the database.
You need a domain model if and only if you need to hire an expert to understand the business.
Otherwise, it's just expensive buzzwords driven development.
And btw, if you have big entity classes containing data that you don't need during most of operations, then you know that you haven't properly defined context boundaries.
The best definition of bounded context is the one of Evans:
The delimited applicability of a particular model. BOUNDING CONTEXTS gives team members a clear and shared understanding of what has to be consistent and what can develop independently.
That is: you have to split the domain expert knowledge in contexts where each term has an unambiguous meaning and a restricted set of responsibility. If you do so, you'll obtain small types and modules with high cohesion an

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