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?