Reputation: 5020
I'm starting with DDD and trying to apply in my current project, but as you can suppose I have thousand of questions.
Here I present a sample domain so I can make different question and serves as an exercise on which you can explain me how things can be made.
Our hypothetical system must take control of companies and what persons works on each one.
A person can only work on a company and a company can have many employees working on it.
The system must allow to add a new employee to a company. For this it receives the company id
and the name, surname, age
of the new employee. There are some restriction to satisfy:
name, surname and age
in the company.I have a mess in my mind :)
To implement the operation I'm thinking on:
CompanyRepository->findCompanyById
to retrieve the company instance.company->addEmployee
to attach the employee to the company.company->AddEmployee
check the new employee satisfies the conditions (specifications).CompanyRepository->save(company)
to persist the company in addition to the employee.Because company+employee
is managed as a cluster (aggregate) I'm considering the company the aggregate root.
company+employee
an aggregate, in the same way I described to save the cluster company+employe
, must I retrieve all the related employees too when I retrieve the company instance from repository ?CustomerRepository->findEmployeeByName(idCompany, nameEmployee)
or better create a specific EmployeeRepository
.Upvotes: 3
Views: 900
Reputation: 64933
What is good or bad is just an opinion. DDD shouldn't be a dogma and you can take the best of it and your own additions to build good software architectures.
No, company can either lazily-load employees (i.e. when runtime access the Employee
property the first time after the company has been retrieved) or company can implement a Load
method which also supports pagination to load only required employees.
You should implement this at repository level (for example ICompanyRepository.ContainsEmployee(Employee)
) and use the underlying data mapper to perform this heavy operation.
Also, I tend to call specifications as pre-/post-conditions in repositories, because it's the only way to be sure that they will be fulfilled in all cases.
I would avoid it, but if you want to ensure a lot of domain rules, you'll need to use them in specifications. BTW, I wouldn't use repositories but I would use services instead.
The right place depends on the requirement. If you want to perform checks to be sure that domain objects are being stored in the repository in a valid state, I find no issue if you want to call an specification from within ICompanyRepository.Add
or ICompanyRepository.Update
, or ICompanyRepository.AddOrUpdate
. The point here is you shouldn't verify object states both when they're stored in the repository and when they're retrievied. If your specifications and your code is reliable, if the repository has filtered domain objects and it has stored them in the underlying data store, you can be sure than read operations will get valid domain objects.
Side note: While you shouldn't model your domain based on the underlying data store (either relational, NoSQL, file system...), again, you shouldn't apply DDD like a dogma. If the underlying data store provides a better approach to define data constraints, I would try to use them instead of implementing complex specifications which might need to access the data anyway.
Your solution should be a balance of an optimal software architecture and runtime performance.
Upvotes: 3