101

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?

Adam Lear
  • 31,939
  • 8
  • 101
  • 125
SonOfPirate
  • 2,885
  • 4
  • 25
  • 28
  • 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
  • 2
    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
  • 1
    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 09: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 01:49
  • Here is an example of some techniques used when modeling domain from behavioral (non-data-centric) perspective: https://medium.com/@wrong.about/how-to-avoid-anemic-domain-model-5e1c3e6fe4d0 – Vadim Samokhin Nov 02 '17 at 06:59

5 Answers5

74

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.

Aaronaught
  • 44,005
  • 10
  • 92
  • 126
  • Excellent response. I'm with you for the most part. I threw persistence in there just to highlight another aspect but completely agree & have been preaching for years (before I knew anything about DDD) that our domain should be persistence ignorant. I still wonder about authorization, though, as security does play a role in the operations our domain objects perform. What about checking access before performing a task such as verifying a user is in the Publishers role before executing the Publish method? – SonOfPirate Apr 28 '11 at 12:39
  • And given the scenario where we automatically increase a customer's line of credit in response to some criteria such as reaching an order level, I suspect that you recommend using domain events where the handler then evaluates whether a credit increase is applicable based on the customer's state and any other rules including authorization checks. Yes? – SonOfPirate Apr 28 '11 at 12:41
  • @SonOfPirate: Your second question, about the line of credit, that's a business rule, not authorization. That *is* a domain concern, although the specific threshold might be externalized. For actions where the business/domain rules *themselves* change based on the security context, see my comment to qes' answer, specifically the one on State Pattern. – Aaronaught Apr 28 '11 at 14:12
  • @SonOfPirate: Back to the first question, the problem with doing something such as *"verifying a user is in the Publishers role before executing the Publish method"* is that those kinds of rules change very frequently and you don't want those changes to cascade through the entire system and possibly break other things. Far better to perform authorization checks at the point of *request*; once an action gets to your domain model, it should already be authorized by the caller. – Aaronaught Apr 28 '11 at 14:16
  • 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
  • @Aaronaught, my second question (about the credit increase) was directed more at using domain events versus a coordinating domain service and whether you would include authorization checks within a domain event handler. Wrt "once an action gets to your domain model, it should already be authorized by the caller" - does this imply an application service layer that coordinates this behavior or are you suggesting that we TRUST client code is performing authorization checks??? – SonOfPirate Apr 30 '11 at 03:22
  • @SonOfPirate: Yes, the domain layer is *one* layer (the bottom one) in an architecture, not the entire architecture. If you have a domain model then there is an expectation of some additional layer of indirection, whatever you may call it. Otherwise you pretty much just have client-server. Security rules affect every single operation in every single service, so it is a bit silly to be bloating up your domain code with all those checks. – Aaronaught Apr 30 '11 at 15:37
  • 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
  • I know I am kind of late, but persistence/database access *may* be part of the domain. I work in the business intelligence domain and we need to connect to a generic data warehouse and extract data from it. So all the knowledge of relational database and SQL goes straight in the domain, because those are in the language of the user and of the domain expert. Actually, I think the real persistence rule is similar to one you gave "if a persistence module can be re-implemented anytime without impacting the business logic, it doesn't belong in the domain". Not exactly *never ever*, but close. – Laurent Bourgault-Roy Jan 21 '14 at 21:44
  • @LaurentBourgault-Roy: Are you talking about designing an actual BI *product*, like SSIS or Business Objects? In that instance I could see persistence as being a necessary part of the domain. Although if you're merely *using* a data warehouse to supply data to some part of the application, then I still fail to see how it could be considered part of the domain. – Aaronaught Jan 21 '14 at 21:49
  • We have a BI product. The user is required to enter the database info for our software to connect and display the data in graphic form. So he need to know how his database well, and a lot of our code is interpreting this input to send the correct SQL query to show his statistics. This is our domain, and half the application logic exist to correctly connect to an arbitrary relational database. We need to validate the connection info, pull the table schema, link them together, ask for dimension structure, etc. So our domain is full of Database, FactTable, StarSchema, SqlQuery, etc. – Laurent Bourgault-Roy Jan 21 '14 at 22:17
  • @LaurentBourgault-Roy: That's not a domain model. For one thing, domain models are inherently mutable; if it doesn't expose any *operations*, it's not a *model*. Don't get me wrong, I'm not trying to downplay the complexity of it, but not every object in an application has to be part of a domain model, and a "StarSchema" definitely isn't (unless, as I said, you're actually developing software for *building* these and e.g. exposing operations to manipulate the schemas, tables, etc. Doesn't sound like the case here.) – Aaronaught Jan 21 '14 at 23:54
  • Well have to agree to disagree on that one. The point of a domain model is to create a metaphor of your domain in code, and push away the technical detail. The database schema in our app is not a technical detail. We could not swap it out without impact. Its important. Thus, its part of our model. But look, you can have your own definition :) . By the way you can create a domain model in scala and functional language. Nothing say it has to be mutable. – Laurent Bourgault-Roy Jan 22 '14 at 14:23
  • 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 01:49
  • Simply put: Would your sales force understand these "models" describing database schema? Would customer service? Would the customers themselves? Domain models are expressed in the language of the *business* and should be clearly comprehensible to anyone who's worked in the industry for a while, even someone who knows nothing whatsoever about your specific system. If that really is your situation, then I'm sorry to say you've failed to convince us, and I suggest you write a full answer to defend your position instead of carrying on the discussion in comments. – Aaronaught Jan 23 '14 at 01:51
  • Would your sales force understand these "models". Hum yes. I sat with a sale rep that *explained to me* all of these models. I didn't invent them. I'm currently working on supporting non-aggregated fact tables (not supported yet). And yes, we have big fat button labeled "Connect to an aggregated fact table". The user get it, the support team get it, and our sale rep get it. If you don't believe me, [read about my domain yourself I guess?](http://en.wikipedia.org/wiki/Data_warehouse#Information_storage). Does the maker of MySQL workbench need to abstract MySQL away? That wouldn't make sense! – Laurent Bourgault-Roy Jan 23 '14 at 18:25
  • @LaurentBourgault-Roy: Nobody *needs* to abstract anything away, I'm not making judgments as to good or bad design, I'm simply trying to explain what a domain model is. And, like I said before, if BI is your actual *product* (as opposed to a tool that you use to help your business make decisions) then you could reasonably call it a domain model - same way that grammars and abstract syntax trees would be a domain model for someone who writes compilers or static analysis tools - but not likely for anyone outside that domain. – Aaronaught Jan 24 '14 at 00:26
  • 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
  • @Andy I would say that what you're deeming _Authorization_ is really a _Policy_, which could change at any time. And this sort of _policy_ does belong in the domain. But authorization in and of itself being in the domain, I'm not convinced. (I'm not saying no, I'm just saying, I'm not sure--which is why I'm here reading this answer! But I like what I've read so far.) – fourpastmidnight Aug 24 '17 at 20:01
  • @Andy - And now reflecting on my comment for a few minutes, I ask myself: What really, is the difference between _authorization_ and a _policy_, where the _policy_ is a restriction on actions that can be undertaken in the domain? Perhaps I'm missing a nuance--some distinction between an application-level security concern vs. some domain-level authorization/policy concern? – fourpastmidnight Aug 24 '17 at 20:17
  • 1
    @fourpastmidnight I think authorization is always part of the domain layer. After all, the one who decides that only X can be done by certain people is always the business analysts or product owner or whatever. They decide that some people can see billings, and a smaller set of people can approve said billings. And they also say they need to know who EXACTLY made the changes. That's the key here; anything the business users tell you about who can do what in the system is a business rule, which belongs to the domain. – Andy Aug 24 '17 at 21:07
  • @Andy, I can't disagree. :) – fourpastmidnight Aug 25 '17 at 15:17
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.

quentin-starin
  • 5,800
  • 27
  • 26
  • 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
  • qes - at an architectural level you may expose a fairly large collection of classes and functionality as a single business object, i.e. through a service. There's nothing stopping you from writing loosely-coupled implementations underneath it. Of course that all calls into question what precisely is the definition of a "domain model" - is it the thing that's inside your application or the thing that you expose to the rest of the world? Fortunately for most developers, they never have to answer those questions because a business object isn't that big or complex, but it happens occasionally. – Aaronaught Apr 27 '11 at 21:54
  • 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
  • @aarounaught: I agree with you entirely. My reference to avoiding consolidation was meant in terms of the implementation. In practice, I've seen *waaay* too many "services" that do nothing more than aggregate related functions that are one-liners forwarding to another implementation. Not always bad, but in the context of a Domain they almost always seem pointless. Personally, I just use Command classes grouped under a namespace (MyApp.Domain.Accounts.DoSomeCommandClass) rather than wrap them in methods inside a service class. Just my current preference. – quentin-starin Apr 27 '11 at 22:14
  • 2
    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
  • The "rich object" approach would be a CanPublish property on the domain object that evaluates the rules (possibly using a CanPublishSpecification class to encapsulate the rules) and returns true/false to the UI or other client. I get the feeling that's not how you'd do it(?) – SonOfPirate Apr 28 '11 at 12:29
  • Also, going back up the thread a bit, I'm not sure I follow how domain events are used to support authorization. Can you explain this some more? – SonOfPirate Apr 28 '11 at 12:43
  • "Validation occurs in different contexts, and the validations rules often differ between contexts. " This is true, but its wrong to use as a reason not to have validation in the domain. The proper answer is that you create separate domain models for each context, each with their own validation. It seems that there's this idea there can only be one Customer domain entity, which is certainly not the case. – Andy Jul 15 '17 at 18:13
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!

Martijn Verburg
  • 22,006
  • 1
  • 49
  • 81
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.

RibaldEddie
  • 3,168
  • 1
  • 15
  • 17
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.

Todd Smith
  • 375
  • 1
  • 6
  • 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 01: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 05: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 01: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 01:20
  • We're using DTOs to keep data, but business logic tends to be organised in Aggregates instead of services. AFAIU DTOs to keep data are fine, but they depend on particular bounded context. E.g. I'm in e-commerce and we have Buyers, which occasionally leave Reviews as Authors on products they buy. So, Buyer and Author are basically the same things - same people in offline - and thus they share some properties, but they are in different bounded contexts. I'm not sure it's possible to reuse much of an Author or Buyer in different bounded contexts. Although I didn't read the book you mentioned. – evgenii Jul 28 '22 at 05:51