90

Where do we draw the line between delegation and encapsulation of business logic? It seems to me that the more we delegate, the more anemic we become. However, delegation also promotes reuse and the DRY principal. So what is appropriate to delegate and what should remain in our domain models?

Take the following concerns as examples:

Authorization. Should the domain object be responsible for maintaining its access control rules (such as a CanEdit property) or should that be delegated to another component/service solely responsible for managing access, e.g. IAuthorizationService.CanEdit(object)? Or should it be a combination of the two? Perhaps the domain object has a CanEdit property which delegates to an internal IAuthorizationService to perform the actual work?

Validation. The same discussion as above relates to validation. Who maintains the rules and who is responsible for evaluating them? On the one hand, the state of the object should belong to that object and validity is a state but we don't want to rewrite the code used to evaluate rules for every domain object. We could use inheritance in this case...

Object Creation. Factory class versus factory methods versus 'newing' up an instance. If we use a separate factory class, we are able to isolate and encapsulate creation logic but at the expense of opening our object's state to the factory. This can be managed if our domain layer is in a separate assembly by exposing an internal constructor used by the factory but this becomes a problem if there are multiple creation patterns. And, if all the factory is doing is calling the right constructor, what's the point of having the factory?

Factory methods on the class eliminate the issue with opening up the object's internal state but since they are static, we aren't able to break dependencies through injection of a factory interface like we can with a separate factory class.

Persistence. One could argue that if our domain object is going to expose CanEdit while delegating the responsibility to perform the authorization check to another party (IAuthorizationService) why not have a Save method on our domain object that does the same thing? This would allow us to evaluate the internal state of the object to determine if the operation can be performed without breaking encapsulation. Of course it requires that that we inject the repository instance into our domain object, which smells a bit to me, so do we raise a domain event instead and allow a handler to perform the persistance operation?

See where I'm going with this?

Rockford Lhotka has a great discussion about his reasons for going the Class-in-Charge route for his CSLA framework and I have a bit of history with that framework and can see his idea of business objects paralleling domain objects in many ways. But trying to become more adherent to good DDD ideals, I'm wondering when collaboration becomes too much.

If I end up with an IAuthorizationService, IValidator, IFactory and IRepository for my aggregate root, what's left? Is having a Publish method that changes the state of the object from Draft to Published enough to consider the class a non-anemic domain object?

Your thoughts?

  • Great question. I don't have an answer for you since I almost always end up completely anemic in design for the exact same reason -- using/consuming/exposing services from/to many different contexts or different applications. – hromanko Apr 27 '11 at 17:58
  • Great question, would love to see unclebob, martinfowler, ericevans et al to chime in on this. Now for me to go away and have a long think – Martijn Verburg Apr 27 '11 at 18:40
  • I find myself evolving to an anemic model all the time; and so I'm struggling with this exact same thing. Great question! – L-Four Sep 20 '11 at 9:38
  • This has been my experience with DDD as well. We're doing it where I work, and we always end up anemic. I previously (and still do actually) use Csla. Our architect doesn't like that we're anemic, but hasn't been able to give me a good answer to what the object should do if all the stuff you point out can't be done within the object. At the end of the day, trying to be purist DDD seems to create more work than its worth. I personally think Csla and DDD get along (they seem identical in principals), if you're willing to leave the DDD dogma behind. – Andy Oct 22 '11 at 1:49
  • Here is an example of some techniques used when modeling domain from behavioral (non-data-centric) perspective: medium.com/@wrong.about/… – Zapadlo Nov 2 '17 at 6:59
66

Most of the confusion seems to be around functionality that should not exist in the domain model at all:

  • Persistence should never be in the domain model. Never ever. That's the reason you rely on abstract types such as IRepository if part of the model ever needs to do something like retrieve a different part of the model, and use dependency injection or some similar technique to wire up the implementation. So strike that from the record.

  • Authorization is not generally part of your domain model, unless it is actually part of the domain, e.g. if you're writing security software. The mechanics of who is allowed to perform what in an application are normally handled at the "edge" of the business/domain tier, the public parts that the UI and Integration pieces are actually allowed to talk to - the Controller in MVC, the Services or the messaging system itself in an SOA... you get the picture.

  • Factories (and I assume you mean abstract factories here) aren't exactly bad to have in a domain model but they are almost always unnecessary. Normally you only have a factory when the inner mechanics of object creation might change. But you only have one implementation of the domain model, which means that there will only ever be one kind of factory which always invokes the same constructors and other initialization code.

    You can have "convenience" factories if you want - classes that encapsulate common combinations of constructor parameters and so on - but honestly, generally speaking, if you've got a lot of factories sitting in your domain model then you're just wasting lines of code.

So once you turf all of those, that just leaves validation. That's the only one that's kind of tricky.

Validation is part of your domain model but it is also a part of every other component of the application. Your UI and database will have their own, similar yet different validation rules, based on a similar yet different conceptual model. It's not really specified whether or not objects need to have a Validate method but even if they do, they'll usually delegate it to a validator class (not interface - validation is not abstract in the domain model, it is fundamental).

Keep in mind that the validator is still technically part of the model; it doesn't need to be attached to an aggregate root because it doesn't contain any data or state. Domain models are conceptual things, usually physically translating to an assembly or a collection of assemblies. Don't stress out over the "anemic" issue if your delegation code resides in very close proximity to the object model; it still counts.

What this all really comes down to is that if you're going to do DDD, you have to understand what the domain is. If you're still talking about things like persistence and authorization then you're on the wrong track. The domain represents the running state of a system - the physical and conceptual objects and attributes. Anything that is not directly relevant to the objects and relationships themselves does not belong in the domain model, period.

As a rule of thumb, when considering whether or not something belongs in the domain model, ask yourself the following question:

"Can this functionality ever change for purely technical reasons?" In other words, not due to any observable change to the real-world business or domain?

If the answer is "yes", then it doesn't belong in the domain model. It's not part of the domain.

There's a very good chance that, someday, you'll change your persistence and authorization infrastructures. Therefore, they aren't part of the domain, they're part of the application. This also applies to algorithms, like sorting and searching; you shouldn't go and shove a binary search code implementation into your domain model, because your domain is only concerned with the abstract concept of a search, not how it works.

If, after you've stripped away all the stuff that doesn't matter, you find that the domain model is truly anemic, then that should serve as a pretty good indication that DDD is simply the wrong paradigm for your project.

Some domains really are anemic. Social bookmarking apps don't really have much of a "domain" to speak of; all your objects are basically just data with no functionality. A Sales and CRM system, on the other hand, has a pretty heavy domain; when you load up a Rate entity then there is a reasonable expectation that you can actually do stuff with that rate, such as apply it to an order quantity and have it figure out the volume discounts and promo codes and all that fun stuff.

Domain objects that just hold data usually do mean that you have an anemic domain model, but that doesn't necessarily mean that you've created a bad design - it might just mean that the domain itself is anemic and that you should be using a different methodology.

  • 2
    In addition, @SonOfPirate, it's not entirely unlikely that you'd want to change your entire security model sometime; role-based security is often obsoleted in favour of claims- or rights-based security or maybe you even want field-level security. Imagine trying to rework your entire domain model if this happened. – Aaronaught Apr 28 '11 at 14:18
  • 1
    @SonOfPirate: It almost sounds like you're still a little stuck on the old "business tier" model wherein there was a "middle tier" that was basically a thin veneer over the data layer, implementing various business rules and also usually security rules. That is not what the domain layer is. The domain is what everything else depends on, it represents the real-world objects and relationships that the system is meant to manage. – Aaronaught Apr 30 '11 at 15:40
  • 1
    @LaurentBourgault-Roy: Sorry, I don't believe you. Every company could say that about every application; after all, changing a database is hard. That doesn't make it part of your domain, and business logic that is coupled to the persistence layer just means poor abstraction. A domain model is focused on behaviour, which is exactly what persistence isn't. This isn't a subject on which people can invent their own definitions; it's pretty clearly spelled out in DDD. You often don't need a domain model for CRUD or reporting apps, but you also shouldn't claim that you have one when you don't. – Aaronaught Jan 23 '14 at 1:49
  • 1
    Authorization absolutely belongs in the domain layer. Who decides what permissions exist? The business does. Who decides who can do what? The business does. We just had a feature request a few weeks ago to change the authorization needed to edit a particular object in our system. If a template was based on a master template, then higher privileges were needed to edit (override the values from the master) the template than you'd normally need. Where does that logic belong if not in the domain? – Andy Jul 15 '17 at 18:09
  • 1
    Another kind of authorization could be a customers account limit. Normal customer service people can raise it to a certain point, but maybe higher limits need management approval. That's authorization logic. – Andy Jul 15 '17 at 18:10
6

Authorization. Should the domain object be responsible for maintaining its access control rules

No. Authorization is a concern unto itself. Commands that wouldn't be valid due to a lack of permissions should be rejected before the domain, as early as possible - which means often we will even want to check authorization of a potential command in order to build the UI (so as to not even show the user the option of editing).

Sharing authorization strategies across layers (in the UI and further up in a service or command handler) is easier when authorization is componentized separate from the domain model.

One tricky part that can be encountered is contextual authorization, where a command may or may not be allowed not only based on user roles but also business data/rules.

Validation. The same discussion as above relates to validation.

I would also say no, not in the domain (mostly). Validation occurs in different contexts, and the validations rules often differ between contexts. There is rarely an simple, absolute sense of valid or not valid when considering the data encapsulated by an aggregate.

Also, like authorization, we utilize validation logic across layers - in the UI, in the service or command handler, etc. Again, it is easier to employ DRY with validation if it is a separate component. From a practical point, validation (particularly when using frameworks) requires exposing data that otherwise should be encapsulated and it often requires custom attributes to be attached to fields and properties. I much prefer these to be on other classes than my domain models.

I would rather duplicate some properties in a couple similar classes than try to force the requirements for a validation framework into my entities. That inevitably ends up making a mess of the entity classes.

Object Creation. Factory class versus factory methods versus 'newing' up an instance.

I use one layer of indirection. In my more recent projects, this is a command + handler for creating something, i.e. CreateNewAccountCommand. An alternatives could be to always use a factory (although that can be awkward if the rest of an entities operation are exposed by a service class that is separate from the factory class).

In general, though, I try to be more flexible with design choices for object creation. new is easy and familiar but not always sufficient. I think using judgement here and allowing different parts of a system to use different strategies as needed is important.

Persistence. ... why not have a Save method on our domain object

This is rarely a good idea; I think there's plenty of shared experience to support that.

If I end up with an IAuthorizationService, IValidator, IFactory and IRepository for my aggregate root, what's left? Is having a Publish method that changes the state of the object from Draft to Published enough to consider the class a non-anemic domain object???

Perhaps a domain model isn't the correct choice for this part of your application.

  • 2
    "One tricky part that can be encountered is contextual authorization, where a command may or may not be allowed not only based on user roles but also business data/rules." -- And how do you approach this? More times than not, for me at least, our authorization rules are a combination of role and current state. – SonOfPirate Apr 27 '11 at 19:15
  • @SonOfPirate: event handlers that listen to domain events and update tables that are very specific to the needs of the queries that check authorization. Logic that looks at the state and determines if a role or individual is authorized or not lives in the event handler (so the tables are almost always a simple yes/no, making the auth check a simple lookup). Also, as soon as any of that logic is used in more than one place it gets refactored out of the handler and into a shared service. – quentin-starin Apr 27 '11 at 19:21
  • 1
    In general, over the last few years, I've moved further and further away from trying to consolidate everything into a domain or business object. My experience seems to be that making things more granular and less coupled is a long-term win. So while from one perspective this method is placing business logic outside the domain (to a degree), it also supports agile modifications later. It's all about striking a balance. – quentin-starin Apr 27 '11 at 19:25
  • 4
    Referencing the answer itself here: I've found the State Pattern very useful when dealing with validations that are dependent on both permissions and business rules. Create an abstract state which gets injected into the domain model and exposes methods which take the domain object as a parameter and validate domain-specific actions. This way if your permission rules change (as they almost always do), you never have to mess around with the model to accommodate it, because the state implementations live in your security component. – Aaronaught Apr 27 '11 at 21:57
  • 1
    Staying on the subject of authorization, let me throw a tangible example on the table to see how you (both) would handle it. I have a Publish operation on my domain object that requires the user to be in the Publisher role AND that the object is in a certain state. I want to hide or disable the Publish "button" in the UI. How would you accomplish this? – SonOfPirate Apr 28 '11 at 12:29
4

OK, here goes for me. I'll pre empt this by saying that:

  • Premature optimisation (and that includes design) can often cause problems.

  • IANMF (I am not Martin Fowler) ;)

  • A dirty little secret is that on small sized projects (even arguably medium sized ones), it's the consistency of your approach that will matter.

Authorization

For me Authentication and Authorisation is always a cross cutting concern. In my happy little Java world, that gets delegated to Spring security or the Apache Shiro framework.

Validation For me validation is part of the object, as I see it as defining what the object is.

e.g. A Car object has 4 wheels (OK there are some weird exceptions, but lets ignore the weird 3 wheeled Car for now). A Car simply isn't valid unless it has 4 (in my world), so that validation is part of what the definition of a Car is. That doesn't mean you can't have a helper validation classes.

In my happy Java world I use Bean validation frameworks and use simple annotations on most of my Bean fields. It's easy then to validate your object no matter what layer you're in.

Object Creation

I view Factory classes with caution. Too often I have see the xyxFactoryFactory class ;)

I tend to just create a new object as needed, until I run into a case where Dependency Injection is warranted (and since I try to follow a TDD approach, this does come up more often than not).

In my happy Java world that is increasingly Guice, but of Spring is still the King here.

Persistence

So this a debate that goes on in circles and roundabouts and I'm always in two minds about it.

Some say that if you look at object in a 'pure' way, persistence is not a core property, it's merely an outside concern.

Others take the view that your domain objects implicitly implement a 'persist-able' interface (yeah I know I'm stretching here). Therefore, it's fine to have the various save, delete etc methods on them. This is seen as a pragmatic approach and many ORM technologies (JPA in my happy Java world) deal with objects in this way.

From a cross cutting security concern I make sure that the edit/delete/add/whatever permissions are set correctly on the service that calls the save/update/delete method on the object. If I'm really paranoid I might even set the permissions on the domain object itself.

HTH!

2

Jimmy Nilsson touches on this topic in his book on DDD. He started with an anemic model, went to non-anemic models on a later project and finally settled on anemic models. His reasoning was that the anemic models could be re-used in multiple services with differing business logic.

The trade off is the lack of discover-ability. The methods you can use to operate on your anemic models are spread throughout a set of services located elsewhere.

  • Sounds like a specific requirement - reuse of data (stress 'data') structure - lead to that common part reduced to plain DTOs. – Victor Sergienko Apr 29 '11 at 11:01
  • Anemic models allow better reuse? Sounds more like a DTO, and I personally don't give a damn about reusing property definitions. I'd much rather reuse behaviors. – Andy Oct 22 '11 at 1:56
  • @Andy - I would agree however if your behaviors are within Domain Services and they operate on anemic objects (okay DTOs if you wish) then doesn't that increase the reuse of those behaviors? Just playing devil's advocate. – jpierson Dec 16 '11 at 5:20
  • @jpierson I've found though that the behaviors are typically specific to a particular use case. If there's reuse, that would belong in another class, but the consumer wouldn't use those classes, they'd use the ones specific to the use case. So any reuse is "behind the scenes," so to speak. Additionally, trying to reuse models typically makes the models harder for the consumer to use, so you end up creating view / edit models in the UI layer. Often then you end up violating DRY to give a richer user experience (for example, DataAnnotations of edit models). – Andy Dec 17 '11 at 1:18
  • 1
    I'd rather domain modles built for the use case, reused where it makes sense (that is, reuse can be done without modifying the behavior much or at all). So instead of anemic domain model, service class and edit model, you have a single smart editable domain model. Much easier to use, and maintain, I've found. – Andy Dec 17 '11 at 1:20
2

This question was asked a long time ago, but it's tagged with Domain Driven Design. I think the question itself contains a fundamental misunderstanding of the entire practice and the answers, including the accepted answer, perpetuate a fundamental misunderstanding.

There is no "the domain model" in a DDD architecture.

Let's take Authorization as an example. Let me ask you to think about a question: imagine two different users authenticate with your system. One user has permission to change a certain Entity, but the other does not. Why not?

I hate simple and contrived examples because they often confuse more than they enlighten. But let's pretend we have two different domains. First is a CMS platform for a marketing agency. This agency's has many customers that all have content online that needs to be managed by copy writers and graphic artists. The content includes blog posts as well as landing pages for different customers.

The other domain is inventory management for a shoe company. The system manages inventory from when it arrives from the manufacturer in France, to distribution centers in the continental USA, to retail stores in local markets, and finally to the customer who buys the shoes at retail.

If you think that the Authorization rules are the same for both companies, then yes that would be a good candidate for a service outside of the domain. But I doubt that the Authorization rules are the same. Even the concepts behind the users would be different. Certainly the language would be different. The marketing agency probably has roles like post author and asset owner, while the shoe company probably has roles like shipping clerk or warehouse manager, or store manager.

These concepts probably have all kinds of permission rules associated with them that need to be modeled in the domain. But that doesn't mean they are all part of the same model even within the same app. Because remember that there are different Bounded Contexts.

So perhaps one might consider a non-anemic domain model in the context of Authorization to be different from the context of routing shoe shipments to stores with low inventory or routing site visitors to the appropriate landing page depending on which ad they clicked.

If you find yourself with anemic domain models, perhaps you simply need to spend more time on context mapping before you start writing code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.