I think I've read 16,154 questions, blog posts, tweets, etc about DDD and best practices. Apologies for yet another question of that type. Let's say I have three tables in my database, User, Department, and UserDepartment. All very simple. I need to build a hierarchy showing what departments a user has access to. The issue is that I also need to show the parent departments of those that they have access to.
Is it best to have a GetDepartments() method on my user class? Right now I have a user service with GetDepartments(string userName), but I don't feel like that is the optimal solution. If user.GetDepartments() is preferred then how do I get access the repository to get the parent departments for those that the user has access to?
Don't think it matters, but I'm using the Entity Framework.
public class User
{
[Key]
public int UserId { get; private set; }
[Display(Name = "User Name")]
public string UserName { get; private set; }
[Display(Name = "Email")]
public string Email { get; private set; }
[Display(Name = "UserDepartments")]
public virtual ICollection<UserDepartment> UserDepartments { get; private set; }
public List<Department> GetDepartments()
{
// Should this be here? and if so, what's the preferred method for accessing the repository?
}
}
DDD is more about the behavior, which also mean it is TDA (tell, don't ask) oriented.
Normally you structure your aggregates in a way that you tell them what to do, not ask for information.
Even more, if some extra information is required by the aggregate in order to perform its behavior, it is typically not their job to figure out where to get this information from.
Now, when you are saying that your User aggregate has GetDepartments method, it raises a bell. Does the aggregate need this information in order to perform any kind of behavior? I don't think so, it is just you wanting some data to display.
So what I see here is that you are trying to structure your aggregates against your data tables, not against the behavior.
This is actually #2 error when applying DDD (#1 is not thinking about bounded contexts).
Again, aggregates represent business logic and behavior of your system. Which means that you don't have to read from aggregates. Your read side can be done much easier - just make a damn query to the DB.
But once you need to ask your system to do something - now you do it through aggregates: AppService would load one from the repository and call its behavior method.
That's why normally you don't have properties in your aggregates, just methods that represent behavior.
Also, you don't want your aggregates to be mapped to the data tables anyhow, it is not their job, but the job of repositories. Actually, you don't want your domain to have dependencies on anything, especially infrastructure.
So if you want to go for DDD direction then consider the following:
Structure your aggregates to encapsulate behaviors, not represent data tables
Don't make your domain dependant on infrastructure, etc.
Make repositories to be responsible to load/save aggregates. Aggregates themselves should know nothing about persistence, data structure, etc.
You don't have to read data through aggregates.
Think of #4 as your system has two sides: the "read" side when you just read the data and show them in the UI, and the "command" side when you perform actions.
The first one (read) is very simple: stupid queries to read the data in a way you want it. It doesn't affect anything because it is just reading, no side effects here.
The second one is when you make changes and that is going through your domain.
Again, remember the first rule of DDD: if you don't have business logic and behavior to model then don't do DDD.
Related
I am wondering whether it is good (and possible practice) to split one piece of data (property?) into two aggregates. Let's consider the following example:
There are Debt, Description and Tag properties.
There are 2 business requirements that if Debt value is bigger than 50.0 you cannot change Tag or Description anymore
The very first solution that comes to my mind is to create an aggregate like this along with Optimistic locking
public class Aggregate {
decimal Debt { get; private set; }
string Description { get; private set; }
string Tag { get; private set; }
int ConcurrencyToken { get; private set; }
void IncreaseDebt(decimal value) {
Debt += value;
ConcurrencyToken++;
}
void ChangeDescription(string description) {
Description = description;
ConcurrencyToken++;
}
void ChangeTag(string tag) {
Tag = tag;
ConcurrencyToken++;
}
}
Consistency of business rule is achieved, however modifying Tag and Description at the same time would cause ConcurrentAccessException. From business perspective user should be allowed to modify two of them at the same time.
The only solution that I see is to perform automatic retry on the client's side whenever changing Tag or Description and ConcurrentAccessException occurs. How to approach such problems?
The way I see it, using an optimistic concurrency check is the right approach, but if modifying Tag and Description can be done concurrently, then you can implement the retries at the server level, not the client. So, if you have two requests coming in exactly at the same time, the behaviour from the client's point of view will be the same as if they came one after the other.
One consideration you have to make though is the experience from the user's point of view. A user makes the decision to modify the information based on the information that was presented on the screen. But when they submit the changes, someone has changed that information. For example, user A fixes a typo in the description and before submitting user B adds a full paragraph. If you just implement automatic retries (either at the client or the server) the description will be overridden. In these scenarios, you can use the Concurrency Token to detect the change (even before executing the business operation and attempting to save the aggregate) and show the user the updated information.
That said, I don't understand what you mean in the title of the question, because these two properties belong to a single aggregate and this type of solution will only work this way. In fact, that is the main point of the aggregates: maintaining data consistency based on the business rules. Data in multiple aggregates can only be eventually consistent.
What would be a rule of thumb when designing an aggregate in DDD?
According to Martin Fowler, aggregate is a cluster of domain objects that can be treated as a single unit. An aggregate will have one of its component objects be the aggregate root.
https://martinfowler.com/bliki/DDD_Aggregate.html
After designing aproximatelly 20 DDD projects I am still confused about the rule of thumb when choosing domain objects that would create an aggregate.
Martin Fowler uses order and line-items analogy and I don't think it is a good example, because order+line-items are really tightly bounded objects. Not much to think about in that example.
Lets try with car analogy where CarContent is a subdomain of a car dealer domain.
CarContent would consist of at least one or more aggregate/s.
For example we have this AggregateRoot (i am keeping it as simple as possible)
class CarStructureAggregate
{
public int Id {get; private set;}
public ModelType ModelType {get; private set;}
public int Year {get; private set;}
public List<EquipmentType> {get; private set;}
}
Alternative could be this (example B)
class CarStructureAggregate
{
public int Id {get; private set;}
public ModelType ModelType {get; private set;}
public int Year {get; private set;}
}
class CarEquipmentAggregate
{
public int Id {get; private set;}
public List<EquipmentType> {get; private set;}
}
Car can be created without equipment but it cannot be activated/published without the equipment (ie. this can be populated over two different transactions)
Equipment can be referenced trough CarStructureAggregate in example A or using CarEquipmentAggregate in example B.
EquipmentType could be an enum, or could be a complex class with many more classes, properties.
What is a rule of thumb when choosing between examples A and B?
Now imagine that car could have more information such as
photos
description
maybe more data about the engine
and CarStructureAggregate could be an extremely large class
So what is it that makes us split Aggregate into new Aggregates? Size? Atomicity of a transaction (although that would not be an issue since usually aggregates of a same sub domain are usually located on the same server)
Be careful about having too strong OO mindset. The blue book and Martin Fowler post are a little bit old and the vision it provides is too narrow.
An aggregate does not need to be a class. It does not need to be persisted. Theese are implementation details. Even, sometimes, the aggregate do things that does not implies a change, just implies a "OK this action may be done".
iTollu post give you a good start: What matters is transactional boundary. The job of an aggregate is just one. Ensure invariants and domain rules in an action that, in most of the cases (remember that not always), change data that must be persisted. The transactional boundary means that once the aggregate says that something may, and has, be done; nothing in the world should contradict it because, if contradiction occurs, your aggregate is badly designed and the rule that contradict the aggregate should be part of aggregate.
So, to design aggregates, I usualy start very simple and keep evolving. Think in a static function that recives all the VO's, entities and command data (almost DTO all of them except the unique ID of the entities) needed to check domain rules for the action and returns a domain event saying that something has be done. The data of the event must contain all data that your system needs to persist the changes, if needed, and to act in consequence when the event reach to other aggregates (in the same or different bounded context).
Now start to refactoring and OO designing. Supress primitive obsession antipattern. Add constraints to avoid incorrect states of entities and VO's. That piece of code to check or calculate someting related to a entity better goes into the entity. Put your events in a diet. Put static functions that need almost the same VO's and entities to check domain rules together creating a class as aggregate root. Use repositories to create the aggregates in an always valid state. And a long etc. You know; just good OOP design, going towards no DTO's, "tell, don't ask" premise, responsibility segregation and so on.
When you finish all that work you will find your aggregates, VO's and entities perfectly designed from a domain (bounded context related) and technical view.
Something to keep in mind when designing aggregates is that the same entity can be an aggregate in one use case and a normal entity in another. So you can have a CarStructureAggregate that owns a list of EquipmentTypes, but you can also have an EquipmentTypeAggregate that owns other things and has its own business rules.
Remember, though, that aggregates can update their own properties but not update the properties of owned objects. For example if your CarStructureAggregate owns the list of EquipmentType, you cannot change properties of one of the equipment types in the context of updating the CarStructureAggregate. You must query the EquipmentType in its aggregate role to make changes to it. CarStructureAggregate can only add EquipmentTypes to its internal list or remove them.
Another rule of thumb is only populate aggregates one level deep unless there is an overriding reason to go deeper. In your example you would instantiate the CarStructureAggregate and fill the list of EquipmentTypes, but you would not populate any lists that each EquipmentType might own.
I believe, what matters here is transactional boundary.
On one hand, you can't establish it more narrow than it is sufficient for preserving an aggregate's consistency.
On the other hand, you don't want to make it so large to lock your users from concurrent modifications.
In your example, if users should be able to modify CarStructure and CarEquipment concurrently - then I'd stick to implementation B. If not - it would be simpler to use A.
in a very simple sentence, I can say:
basically, a business use case that aims to change and consists of one or more relevant entities, value objects, and invariants based on the business in domain-driven design is aggregate. being a model command is important because if you only need to read, you don’t need an aggregate.
Could my domain model reference my repository interfaces? or better yet, containing my repositories definitions?
I ask because I was thinking about what I read on the limbo of internet that says that a model shouldn't know about its persistence, but I think if the repository exists due the model, I mean, to handle specific needs of its model, why not the model project define it?
Is it a problem/ bad design if I do the following?
public interface ISomethingThatNeedToBeAprovedRepository
{
void Save(SomethingThatNeedToBeAproved somethingThatNeedToBeAproved);
}
public class SomethingThatNeedToBeAproved
{
public int Status {get;set;}
public string Reason {get;set;}
public ISomethingThatNeedToBeAprovedRepository Repository{ get; set;}
public void Aprove(status, reason)
{
DoSomeAsserts();
Status = status;
Reason = reason;
Repository.save(this);
}
}
Yes, it can!
At given point you need to persist your aggregate so a repository is needed. I use to take IRepository inside my domain model, while infratructure details of Repository in another project.
No, it will be a bad design.
The domain model (this domain layer) should totally be independent of any other layer.
The repository interface and implementation should refer to the domain model to save and perform storage operations.
The answer is really it depends.
As #marianoc84 said, at some point, the application would really need to concern about persistence. The question here, is the particular domain model needs a concern about data persistence?
If it does, then it is make sense to put a repository inside the model.
On other side, having the repository inside 'may' makes unit test more challenging, and just be aware that generally speaking, the domain model could be distributed anywhere to pretty much up to application layer.
However, if the model does not really need to concern about persistence, then you don't really need a repository inside. The persistence could be done on other places such as having an 'ApprovalServices' which in this case, there could be several A, B, C, D and E that could be approved and have this to be persisted.
As per the title, I have the following classes:
public class Company : AggregateRoot {
public AddressBook AddressBook { get; set; }
}
public class AddressBook {
public List<Address> Addresses { get; set; }
public Address GetPrimaryAddress() {
return Addresses.FirstOrDefault();
}
}
Is it acceptable for me to call:
company.AddressBook.GetPrimaryAddress();
Or should I expose a GetPrimaryAddress() method on Company that in turn calls the AddressBook method?
I know I shouldn't have references to entities within an AggregateRoot but I wasn't sure what the rulings are on calling operations.
Update
For what it's worth, below is a diagram (click here for full size) of my actual model. ContactList contains rules for how all types of contact (Person/Business Location) should be managed, such as what happens when a primary contact is removed. It also works around some caveats of how RavenDB stores nested entities (essentially we need to provide our own Id strategy - hence the LastContactId property).
First of all, it's all depending on the context and I assume that Company really is the AR for that specific context. The same Company can be a simple object in other contexts. Now, I'm not a fan of dogmatic use of rules and patterns so it is not important what the 'rule' says.
In this case I won't expose the Address as it seems to be an internal of the Company. As a coosnumer of the Company, I want its primary address, I don't care you're using the AddresBook to organize them.
To give a not so common example: the AR Human has two Eye objects. Will you ask the Person to give one of his eyes so you can check their color or you ask the Person directly what color his eyes are?
According to the Aggregate pattern:
Transient references to the internal members can be passed out for use within a single operation only.
Meaning - a Company can pass a reference to its Address object to other objects outside the aggregate, but Address cannot be a member of any other object outside the aggregate.
For example, an object User can ask a reference to an Address from a Company, but User cannot have Address as one of its members.
And why is that so important?
Because the root controls access, it cannot be blindsided by changes to the internals.
If an object User would have Address as one of its members, it might pull it out of the database without its Company and thus, Company would be blindsided by changes to its internals.
Please see a post I've wrote in which i demonstrate why is this principle so important.
Good question, this is one of the things I've always found hard to get right in DDD - do you always access entities through their aggregate root and probably violate the Law of Demeter at some point (AggregateRoot.EntityX.EntityY.DoStuff()) ? Do you short-circuit the aggregate root ? Do you add at the aggregate root level one direct accessor for each sub-sub-entity you want to access, muddling the aggregate root ?
One way to solve that could be : try to make every object talk only to its immediate or nearby neighbors and not to some distant stranger. Use multiple objects that each know a small part of the path from the aggregate root to the final entity you want to access.
The first object knows only the aggregate root,
It injects AggregateRoot.SubEntity1 into a second object,
Second object in turn injects SubEntity1.SubEntity2 into a third object
and so on.
Interestingly enough, one thing this reveals is the (ir)relevance of some of your domain entities. In the Address example, ask yourself if it feels right for every object that wants to access the primary Address of a Company to be injected an AddressBook. If it seems too convoluted, maybe you should not have an AddressBook in the first place. Maybe it isn't such a strong notion that it deserves to be part of the ubiquitous language after all.
Or, maybe you'll find out an AddressBook is precisely the right object to be used by your client object, and that this client object tries to do too many things at a time in manipulating both a Company and an Address.
I currently create a Repository for each database table and a corresponding data class for the column values (object to pass around data).
I recently started using some 1 to 1 relationships and I'm not sure what would be the best way to implement them.
For example
If I have a User table and a UserSettings Table in a 1:1 relationship.
// Data classes (Holds all the field value for the table)
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
}
public class UserSettings
{
public int UserId { get; set; }
public bool SomeSetting { get; set; }
}
Questions:
Should I always go through the User object to manipulate the UserSettings object, or should I be able to manipulate them
independently?
Should I include the primary key field in the UserSettings object?
Should I store a reference to the USerSettings object in the User object?
Do I make two repo's one for User and one UserSettings, or do I handle everything in the Users Repo.
The only time I've ever found a 1:1 relationship between aggregate roots to be useful is when the aggregate roots on either side of the relationship are managed by different domains. They must share the same primary key, and therefore if they are both managed by the same domain then they are by definition parts of the same aggregate root. I think you need to approach this question from a different angle:
Is the User object only going to exist for this application?
Do you expect that to always be the case?
If the User is a concept that resides entirely inside of this domain, then there's no reason to have a UserSettings aggretate root that has a 1:1 relationship with a User; you simply make User.Settings a way to retrieve the UserSettings for that User. (And of course that obviates the need for a repository - it becomes the responsibility of the UserRepository to hydrate the UserSettings when it hydrates everything else on the User.)
But, if the User will eventually inform sessions for multiple domains, then User needs to represent its own domain, the services of which your application will consume. Then, you gain a very real need to separate the UserSettings of this application from those of a different application. The User is not specific to this application, but the UserSettings for that User is.
NOTE - In the interest of not refactoring your project at this point, if the answer to either question 1 or 2 above is "no", then you should make UserSettings a separate aggregate root within the same domain, in order to create a seamless transition when you eventually do move User into its own domain.
What exactly do you mean by 'going through the user object' ?
IMHO, no.
You can, but I do not think you should. Is there any reason why you'd want to know to which User the settings belong to ? The only time you'd want to know that -imho- is when you persist it. In your database, you need to know to which User, the UserSettings belong to. In your model, I think you can suffice by a uni-directional relationship
You should only create a repository per aggregate root, in your case 'User' can be an aggregate root. UserSettings is -imho- not even an entity but a value object.
I currently create a Repository for each database table
...
// Data classes (Holds all the field value for the table)
It seems you're adopting a bottom-up (database first/database centric) approach which is uncommon in DDD. As the name Domain Driven Design implies, you usually rather start by modelling your domain, fleshing out your Aggregates, Aggregate Roots and Entities.
Aggregate roots usually have their own Repository while regular entities most often don't. To know whether an entity should be an Aggregate root, you have to ask yourself if that object is going to be one of the main entry points in the application, with a group of related objects gravitating around it and only obtainable through traversal of it.
User is an obvious candidate for an Aggregate root. User Settings in contrast isn't IMO a root, it belongs in the sphere of influence of a User. I'd make it a part of the User Aggregate and only obtainable through traversal of a User. It means having a reference to UserSettings in User but not necessarily the other way around.
I would ask yourself if a UserSettings can exist with out an associated user, and/or does a User always have an associated UserSettings. If so then the UserSettings could easily be made part of the User aggregate rather then being a separate aggregate itself. Yes in the database they will most likely be in different tables with 1:1 relationship between them, but this is a specific concern of the implementation of the repository. Your domain model could consider the UserSettings part of the user.