How does DDD play nice with dynamic business rules?

DDD was chosen as an architectural pattern to tame a wild database model, as well as ubiquitous language. However, there is a sticky part of our model — many of the rules are dynamic, and I don’t know how to reconcile them with what I understand of DDD.

class Account {
    private Mailing[] mailings;

    void SubscribeToMailing(Mailing m) {
        if (/* this is allowed */) {

The problem I am encountering is that the “this is allowed” check must be determined at runtime. There are conditional rules the system can be configured for. It makes sense to me to check these in a service, because the service can get a rule check injected into it. But, to do that would drive me towards an anemic domain model, which I’ve been led to believe Is A Bad Thing.

Where should these runtime checks happen?

edit for more clarification:

The product is multi-tenant, so “one size fits all” does not necessarily apply. The tenants are across multiple industries, so industry-specific rulesets cannot even be baked in there. There are known hooks in the system that configuration can happen, and that is the language we are trying to capture.

Rulesets could be something like “this product costs $5.35 each, unless the account is in this role, in which case the product costs $5.15 each”. The roles are created by the tenants, the product pricing is created by the tenant, and even the decision to apply different pricing at all is created by the tenant.


Where should these runtime checks happen?

If it is domain logic, then the checks should happen inside the domain model. If it is application logic, then the checks should happen in the application code.

If it is domain logic, and the configured information isn’t copied into the data structure of the domain entity, then that configuration information would be passed to the domain model as an argument.


How did you end up solving it, @bryan-boettcher?

I’m facing the same problem (including “multi-tenant with different roles and rulesets”).

Here’s what I’m considering (applying to your specific use case)

Application layer:

class SubscribeToMailingCommandHandler: ICommandHandler<SubscribeToMailingCommand> {
    Handle(SubscribeToMailingCommand command) {
        var mailing = _mailingRepo.GetById(command.mailingId);
        var account = _accountRepo.GetById(command.accountId);
        var tenant = _tenantRepo.GetById(account.tenantId);
        IRule[] rules = tenant.GetRulesForMailingSubscription();

        account.SubscribeToMailing(mailing, new MailingRulesetValidator(rules));

Domain layer:

   interface IRule {
       bool IsBroken();
   //domain service
   class MailingRulesetValidator {
       private IRule[] _rules;
       MailingRulesetValidator(IRule[] rules) {
          _rules = rules;
       //returns broken rules
       public IRule[] Validate() {
           return rules.Where(r => r.IsBroken()).ToArray();
       public bool IsAllowed() {
           return Validate().Length == 0;

   //domain entity
   class Account: Entity {
      void SubscribeToMailing(Mailing m, MailingRulesetValidator validator) {
         if (validator.IsAllowed()) {

this way, it’s tenants responsibility to give me the rules. I have some of them static but some are just feature flags that can be turned on/off at runtime. Not sure if the MailingRulesetValidator is a Specification pattern or Strategy pattern but I saw in Evan’s DDD book that he passes a BalanceCalculator into an Entity method in one of his examples so I guess that’s “allowed”…


DDD as practiced today by most, and described by most resources online and offline is about anemic models. The most I’ve seen people do is to have some trivial methods which work in complete isolation in the “domain objects” themselves, but that is basically it. For anything more there are “Services”.

Just to be clear, there is a spectrum from anemic to rich objects. The more “Services” you have the more anemic your objects become, since you are taking behavior away from your model. In a completely “rich” object model there are no services whatsoever, and in a completely anemic model there are no methods in the “model” other than setters/getters.

So in short, if you want to have “rich” objects (i.e. with real behavior) you can not have DDD, or have to significantly re-interpret what DDD is.


Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *