acanimal
acanimal

Reputation: 5020

Understanding DDD (services, aggregate, entities, repositories and specifications)

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.

Domain.

A person can only work on a company and a company can have many employees working on it.

Operations

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:


Questions

I have a mess in my mind :)

To implement the operation I'm thinking on:

Because company+employee is managed as a cluster (aggregate) I'm considering the company the aggregate root.

  1. Is this a good implementation?
  2. If I consider 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 ?
  3. Respect specifications I can understand easily how to check, for example, if a employee name has more than 10 chars, but: how to check if the employee exists in the same company if the company has thousands of employees?
  4. Can a specification call repository operations? and if yes, and the fact that considering company+employee a cluster is right, what would be the right place? CustomerRepository->findEmployeeByName(idCompany, nameEmployee) or better create a specific EmployeeRepository.

Upvotes: 3

Views: 900

Answers (1)

Matías Fidemraizer
Matías Fidemraizer

Reputation: 64933

1

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.

2

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.

3

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.

4

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

Related Questions