DDD – Rich Domain Model vs Strategy Pattern

Architecturedesign-patternsdomain-driven-designstrategy

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 the Employer 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

The logic was supposed to be implemented inside the entities

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.

Employees are hidden inside the Employer aggregate root

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.

I cannot use IOC to inject stuff into my entities

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

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)

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.

How would you model it?

"It depends". I'd probably begin by separating out different processes

  • Calculating how much compensation has accrued during some pay period
  • Calculating the dispersal of some amount of compensation
  • Tracking and confirming the asset transfers

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.