Aggregate and dynamic policies

I didn’t find any question related to dynamic policies and I apologies in advance for any duplication here

My service has some policies that are parametrized so the params are stored in a table ending up in a Value Object representing the policy with the param retrieved from DB

My doubt is:

  1. Should I retrieve the policies in the application layer (use-cases) and add them in the command object as a list of policies to be verified inside aggregate?
  2. Retrieve the policies inside Aggregate and use them to validate the invariants?

I am using Hexagonal architecture so along with DDD approach I tend to avoid any resource inside aggregate not related to pure business objects (services, repositories, etc)

What could be the best approach?

Hey Rogério,

The correct answer is of course “It Depends” :wink:

That said and considering you wrote

it sounds like the policies are an essential part of the Domain Model in your case.

If that is so, then IMHO

  • they should be retrieved and used inside the relevant Aggregate(s)
  • where and how exactly they are stored and retrieved is more of an infrastructural question. If that is a concern you may change the storage or introduce wrappers, caches, etc.
  • you would also need to think about who/what, how, and when can alter those and how that affects the operations in the Domain.

Finally, if those need to be shared between multiple components (Aggregates, Handlers, Projections, …) consider using Services (as described in DDD).

Hi @milendyankov tanks for your reply!

I am in doubt about to approaches:

Empower my command with a list of policies that applies to a given scenario having something more than just a straightforward command

OfferDeliveryAmenities(basketId, [freeDelivery, deliveryDiscounts])

Or invoke a PolicyService inside my aggregate to retrieve the applicable policies

I tend to think that my aggregates should have only command and eventSource handlers keeping it as pure as possible and delegating to an ApplicationService or DomainService the charge of prepare all information needed to exec the business rules as well the invariants

What looks less ugly and maintainable?

I typically try to step away from the code and look at the things that exist, where they belong, who owns them, who uses them, etc. Once you figure those out, it becomes easier to model the domain and write code. And then, you can justify a “not perfectly pure” with the actual constraints and rules that exist in the domain.

I tend to think that my aggregates should have only command and eventSource handlers keeping it as pure as possible and delegating to an ApplicationService or DomainService the charge of prepare all information needed to exec the business rules as well the invariants

If “as pure as possible” is the goal, then you are probably right. If the goal is to guard the domain boundaries and invariants, then Aggregates are meant to do exactly that. But if their behavior depends on something that “prepares all information needed to exec,” they no longer guard anything. They can only conform to whatever is presented to them by those other services.

For example, in your case, there is the question of who is “in charge” of those policies? You propose giving full power to whoever executes a command to define (and possibly abuse) policies freely. Therefore IMHO, they are no longer policies (something that imposes rules and guards invariants) but rather command execution parameters. That may be just fine, and you may have just discovered that you’ve used the wrong term.

Or those may indeed refer to strict rules that someone else controls, and thus the command sender must not or should not be able to bend them freely for its own needs. In such a case, it’s the Aggregate that should be responsible for reliably obtaining the relevant policy, checking if the given command conforms to it, and react accordingly. While modeling the “reliably obtaining” part, you would ask yourself if any other Aggregate makes use of those policies? If not, then it’s probably best to keep them within the Aggregate. Otherwise, it’s probably better to put them into a domain service.

As with all discussions about architecture and design, there is no one right way for all. I just present a line of thinking that I hope will help you make up your own mind for the particular use case.

2 Likes