I've recently watched a few Pluralshigh courses on DDD by Vladimir Khorikov. He was encouraging to create a rich instead of anemic domain models. It all looked very nice in a small test-project, however I still have no idea how to put extensive business logic inside rich domain model.
In rich domain model we are supposed to put domain logic into entities. So let's say we want to model an Employer
who pays the salary the their Employees
. I see Employer as the aggregate root here.
So we add a Employer.PayTo(someEmployeeIdentificator)
method. Business rules for calculating the salary could be very elaborate and depend on things like:
- Employer and Employees countries
- Employment form
- Employee taxation form
- How much did an Employee work last month
- and so much more, you get the point
Potentially, there could be a few dozens of algorithms. Some might even require communication with external services. A perfect case for strategy pattern, but:
- The logic was supposed to be implemented inside the entities
Employees
are hidden inside theEmployer
aggregate root- I cannot use
IOC
to inject stuff into my entities (they are usually created by some ORM). And providing the dependency trees is no fun. - Injecting the some implementations of SalaryCalculator to the
Employer
entity might be a bad idea, as the calculators might not be 'pure'. They might have references to some external resources (e.g. issue tracker)
How would you model it?
Best Answer
Yes, although it's usually more specific than that - the logic that computes the new state of an entity is supposed to be "inside" the entity.
That may not be an effective model to use for this kind of problem; it might make more sense to focus on the transactions (exchanges of money), or the ledgers, rather than on the people.
I find it helpful to remember that aggregates are digital things; they are (parts of) documents that describe something, not the thing itself.
Remember, inversion of control "is really just a pretentious way of saying taking an argument." We don't usually inject stuff into entities, that's true. Instead, we pass stuff to the entities as arguments (domain services).
The early discussions of domain model (Evans in the blue book, Fowler in Patterns of Enterprise Application Architecture) don't call for it to be pure. It's objects calling other objects, with the expectation of side effects.
As best I can tell, you really have two options - you can make the orchestration among objects part of the domain model, or you can treat the model itself as just a single collaborator, and manage the orchestration elsewhere.
"It depends". I'd probably begin by separating out different processes
Additionally, pay close attention to correctly modeling subtle distinctions; if salaried compensation, hourly compensation, and commissioned sales exist in your domain, then they should be separately identifiable in your model. "Almost the same" is just a wishy-washy way of spelling different.