Anemic Domain Model: Pros/Cons
Asked Answered
F

17

87

I would like to know what the pros and cons are for using an Anemic Domain Model (see link below).

Fowler Article

Frondescence answered 3/11, 2008 at 12:49 Comment(0)
C
37

The pros:

  • You can claim it's a domain model and brag to your developer friends and put it on your resume.
  • It's easy to generate automagically from database tables.
  • It maps to Data Transfer Objects surprisingly well.

The cons:

  • Your domain logic exists somewhere else, probably in a class full of class(static) methods. Or your GUI code. Or in multiple places, all with conflicting logic.
  • It's an anti-pattern, so other developers will ask if you understand the concepts of object oriented design.
Cass answered 7/11, 2008 at 19:15 Comment(16)
+1 The point about generating the code from database tables is very important for some people. If you're in a rapid-prototyping mode of development, automatic code generation is extremely helpful. We don't pretend this is proper OO design, and putting things together in a sloppy way produces "technical debt." Nevertheless, in many projects time-to-market is a higher priority.Srini
No. Whether an anemic model is an anti-pattern is a matter of opinion. Fowler (whose work I respect and typically follow) says it is. I disagree (not that my word has any weight), and many in the OO trenches disagree as well. Pure OO modeling is not generally applicable in every case, that the whole industry knows from experience. Furthermore, an anemic model can still abide by OO modeling guidelines. So seeing specific cases where one applies does not bring into question one's understanding of OO design.Ta
Whether any pattern is an anti-pattern is a matter of opinion. A robust domain model is good OO design and an anemic domain model is bad OO design. Therefore, in the context of OO, it's an anti-pattern. That doesn't mean it doesn't get used or is inappropriate in all cases, but from personal experience I consider it worse than singleton addiction.Cass
I feel there is a trend towards functional programming, and domain model tend to have a lot of side effects. I'm getting a feeling anemic domain model is making a comeback because it allows for a more functional style of programming, where your business logic expects data in and returns processed data out. Your service layer supervises the flow of it all, by knowing which data is required to be processed by which business logic method.Egis
The Domain Model pattern (and Anemic version) both deal with objects. It doesn't make much sense to use object oriented design patterns in functional programming, does it?Cass
@TerryWilcox Well, I'm no functional expert, but functional programming have data structures too. An anemic domain model uses object just as containers of data, they are more like structs. My point is that with ADM, you can kind of move toward a more functional way, where you have immutable data that is transformed over time into newer and newer states. I can see this being done in Scala for example, trying to leverage a bit of OOP and apply some FP to it. A bit like they explain it here: slideshare.net/debasishg/qconny-12Egis
If you want structs, use structs. If you must use objects for it, dump accessor methods and just leave public variables. Accessor methods can have side effects.Cass
@TerryWilcox I don't see any argument in your answer as to why one is better than the other. You simply stated an opinion. -1Merari
@Merari Yes, this is all opinion. Functional programming likes to avoid side effects. OO uses side effects, sometimes in accessor methods. In my opinion, having accessor methods makes side effects more possible than using naked public variables.Cass
@TerryWilcox If only a constructor and getters are available you'd be wrong. If getters and setters are available it would depend upon the developers tendencies. I'm sure you know the advantages of getters and setters. If they're verbose, it's a problem with your language.Merari
I'm curious to know whether you still stick to this answer, seven years later. These days, the ADM is widely recognised as being the better option as it better complies with SOLID principles, is easier to unit test and easier to maintain and refactor. The RDM is arguably the anti-pattern and ADM the better use of OO.Endogenous
@DavidArno Do you have any references to where that is widely recognized in the OO context?Cass
@TerryWilcox, references, no. What I've been doing is going through SO/Programmers questions related to the Anaemic Data Model and comparing the dates of the answers against up/down votes. There seems to be two trends. Older questions have answers saying it's an anti-pattern, lots of up-votes for those answers, but also lots of down votes for the same answers (such as your one here). Questions in the last couple of years though tend to have answers saying the ADM is a good thing, which have been highly up-voted and suffer little down-votes.Endogenous
@TerryWilcox, whilst this is far from a rigorous analysis of prevaling opinion, it certainly suggests that those still supporting Fowler's opinion from over a decade ago are becoming the minority and the majority view is shifting to the ADM being the better choice (no doubt significantly driven by both the shift to TDD and to more functional-orientated approaches to programming).Endogenous
@DavidArno I would guess the majority of down votes come from programmers who use functional languages, but mistakenly cling to OO concepts. The Domain Model pattern, anemic or otherwise, is an OO pattern. It makes no sense to speak of it in a non-OO context, like functional programming.Cass
@DavidArno So to answer your original question; in hindsight I wouldn't have answered this question at all.Cass
F
140

With "Anemic Domain Model" being anti-pattern, why are there so many systems that implement this?

I think there are several reasons

1. Complexity of the system

In a simple system (which is almost all the examples and sample code you find on internet) if I want to implement:

Adding product to Order

I put this function on the Order

public void Order.AddOrderLine(Product product)
{
    OrderLines.Add(new OrderLine(product));
}

Nice and super object oriented.

Now let's say that I need to make sure that I need to validate that the product exists in inventory and throw exception if it doesn't.

I can't really put it on Order any longer, since I don't want my order to be dependent on Inventory, so now it needs to go on the service

public void OrderService.AddOrderLine(Order order, Product product)
{
    if (!InventoryService.Has(product)
       throw new AddProductException

    order.AddOrderLine(product);
}

I could also pass IInventoryService to Order.AddOrderLine, which is another option, but that still makes Order dependent on InventoryService.

There is still some functionality in Order.AddOrderLine, but usually it is limited to Order scope, while in my experience there is a lot more Business Logic out of Order scope.

When the system is more then just basic CRUD, you will end up with most of your logic in OrderService and very little in Order.

2. Developer's view of OOP

There are a lot of heated discussions on the internet about which logic should go on entities.

Something like

Order.Save

Should Order know how to save itself or not? Let's say we have repositories for that.

Now can Order add order lines? If I try to make sense of it using simple English, it doesn't really make sense either. User adds Product to Order, so should we do User.AddOrderLineToOrder()? That seems like overkill.

How about OrderService.AddOrderLine(). Now it kinda makes sense!

My understanding of OOP is that for encapsulation you put functions on classes where the function will need to access class's internal state. If I need to access Order.OrderLines collection, I put Order.AddOrderLine() on Order. This way class's internal state doesn't get exposed.

3. IoC Containers

Systems that use IoC containers are usually fully anemic.

It is because you can test your services/repositories which have interfaces, but can't test domain objects (easily), unless you put interfaces on all of them.

Since "IoC" is currently lauded as solution for all your programming problems, a lot of people blindly follow it and this way end up with Anemic Domain Models.

4. OOP is hard, procedural is easy

I have a bit of a "Curse of Knowledge" on this one, but I have discovered that for newer developers having DTOs and Services is a lot easier than Rich Domain.

Possibly it is because with Rich Domain it is more difficult to know on which classes to put the logic. When to create new classes? Which patterns to use? etc..

With stateless services you just slap it in the service with closest name.

Faught answered 1/5, 2011 at 8:10 Comment(7)
I think it would depend on how complex it would get. 1. If it simple as in 1-2 dependencies - I would keep it on Order class. 2. If moderate complexity - I would create OrderLines class and use Order.OrderLines to handle Order <-> OrderLines communication as well as related dependencies. 3. But in case of high complexity - I would use Application service OrderService to allow for most external dependencies, while keeping any Order module scoped logic in Order.Faught
Great summary - all of these reasons are why its not an anti-pattern. Slavish devotion to OO is an antipattern. Now add in concurrency without projection and watch how you tie yourself in knots with Fowler style OO. Look at companies doing concurrency at scale (e.g. google) and see how much OO they are doing.Reinareinald
Nicely said. Using Grails, I'm not sure 3° leads to anemia. As for 1°, indeed, you end moving logic in the service layer in any non trivial application. But I still find myself with a domain-centric approach using Grails. Which makes it actually not so good, since your domain is your preferred place for logic but you move bits up one layer when needed.Heymann
I don't see the IoC-to-Anemic correlation. It seems like a completely unrelated issue. Whether your services/repositories OR domain objects implement interfaces has nothing to do with testing them. Rather, you test services/repositories/domain objects and decouple them from their dependencies which themselves implement interfaces. And whether you do this right or not doesn't have any correlation to IoC that I can see.Bonne
The thing about DDD that I'm struggling to Grok is your first point: "When the system is more then just basic CRUD, u will end up with most of your logic in OrderService and very little in Order." That makes sense to me, but isn't the purpose of DDD to be used for systems that are more complex than that?Jamima
Great discussion, but I also don't see IoC containers causing anemic model at all. There is an interesting point: In order for a model to have rich behaviors it will often need to collaborate with dependencies (the validation service for example). A problem that is often unsolved: How to give dependencies to model objects, simply hard-wiring them can lead to the problems outlined that occur from not doing DI, so another approach is required. But other approaches have complexities of their own.Patinous
Although I don't disagree with your points (which boil down to 'OOP is hard' maybe?) 1 is based on a straw man argument - an OOP solution would be to ask product.in_stock? NOT to draw in a service. Once could also invoke "tell don't ask" and, well, a lot of other design techniques. Basically your example is good as to WHY OOP is hard, but isn't a good example of why services can/should be used.Mechling
C
37

The pros:

  • You can claim it's a domain model and brag to your developer friends and put it on your resume.
  • It's easy to generate automagically from database tables.
  • It maps to Data Transfer Objects surprisingly well.

The cons:

  • Your domain logic exists somewhere else, probably in a class full of class(static) methods. Or your GUI code. Or in multiple places, all with conflicting logic.
  • It's an anti-pattern, so other developers will ask if you understand the concepts of object oriented design.
Cass answered 7/11, 2008 at 19:15 Comment(16)
+1 The point about generating the code from database tables is very important for some people. If you're in a rapid-prototyping mode of development, automatic code generation is extremely helpful. We don't pretend this is proper OO design, and putting things together in a sloppy way produces "technical debt." Nevertheless, in many projects time-to-market is a higher priority.Srini
No. Whether an anemic model is an anti-pattern is a matter of opinion. Fowler (whose work I respect and typically follow) says it is. I disagree (not that my word has any weight), and many in the OO trenches disagree as well. Pure OO modeling is not generally applicable in every case, that the whole industry knows from experience. Furthermore, an anemic model can still abide by OO modeling guidelines. So seeing specific cases where one applies does not bring into question one's understanding of OO design.Ta
Whether any pattern is an anti-pattern is a matter of opinion. A robust domain model is good OO design and an anemic domain model is bad OO design. Therefore, in the context of OO, it's an anti-pattern. That doesn't mean it doesn't get used or is inappropriate in all cases, but from personal experience I consider it worse than singleton addiction.Cass
I feel there is a trend towards functional programming, and domain model tend to have a lot of side effects. I'm getting a feeling anemic domain model is making a comeback because it allows for a more functional style of programming, where your business logic expects data in and returns processed data out. Your service layer supervises the flow of it all, by knowing which data is required to be processed by which business logic method.Egis
The Domain Model pattern (and Anemic version) both deal with objects. It doesn't make much sense to use object oriented design patterns in functional programming, does it?Cass
@TerryWilcox Well, I'm no functional expert, but functional programming have data structures too. An anemic domain model uses object just as containers of data, they are more like structs. My point is that with ADM, you can kind of move toward a more functional way, where you have immutable data that is transformed over time into newer and newer states. I can see this being done in Scala for example, trying to leverage a bit of OOP and apply some FP to it. A bit like they explain it here: slideshare.net/debasishg/qconny-12Egis
If you want structs, use structs. If you must use objects for it, dump accessor methods and just leave public variables. Accessor methods can have side effects.Cass
@TerryWilcox I don't see any argument in your answer as to why one is better than the other. You simply stated an opinion. -1Merari
@Merari Yes, this is all opinion. Functional programming likes to avoid side effects. OO uses side effects, sometimes in accessor methods. In my opinion, having accessor methods makes side effects more possible than using naked public variables.Cass
@TerryWilcox If only a constructor and getters are available you'd be wrong. If getters and setters are available it would depend upon the developers tendencies. I'm sure you know the advantages of getters and setters. If they're verbose, it's a problem with your language.Merari
I'm curious to know whether you still stick to this answer, seven years later. These days, the ADM is widely recognised as being the better option as it better complies with SOLID principles, is easier to unit test and easier to maintain and refactor. The RDM is arguably the anti-pattern and ADM the better use of OO.Endogenous
@DavidArno Do you have any references to where that is widely recognized in the OO context?Cass
@TerryWilcox, references, no. What I've been doing is going through SO/Programmers questions related to the Anaemic Data Model and comparing the dates of the answers against up/down votes. There seems to be two trends. Older questions have answers saying it's an anti-pattern, lots of up-votes for those answers, but also lots of down votes for the same answers (such as your one here). Questions in the last couple of years though tend to have answers saying the ADM is a good thing, which have been highly up-voted and suffer little down-votes.Endogenous
@TerryWilcox, whilst this is far from a rigorous analysis of prevaling opinion, it certainly suggests that those still supporting Fowler's opinion from over a decade ago are becoming the minority and the majority view is shifting to the ADM being the better choice (no doubt significantly driven by both the shift to TDD and to more functional-orientated approaches to programming).Endogenous
@DavidArno I would guess the majority of down votes come from programmers who use functional languages, but mistakenly cling to OO concepts. The Domain Model pattern, anemic or otherwise, is an OO pattern. It makes no sense to speak of it in a non-OO context, like functional programming.Cass
@DavidArno So to answer your original question; in hindsight I wouldn't have answered this question at all.Cass
H
21

Following this, there has been a thought in my head for a very long time now. It is my belief that the term "OOP" has taken on a meaning not truly intended for it. The anagram mean "object oriented programming", as we all well know. The focus of course is on the word "oriented". It isn't "OMP", meaning "object mandated programming". Both ADM and RDM are examples of OOP. They make use of object, properties, methods interfaces and so forth. However, there is a difference between ADM and RDM in how we choose to encapulate things. They are two different things. To say that ADM is bad OOP is not an accurate statement. Maybe we need different terms for vaious levels of encapsulation instead. In addition, I never liked the term anti-pattern. It is usually assigned to something by members of an opposing group. Both ADM and RDM are valid pattern, they simple have different goals in mind, and are intended to solve different business needs. Those of us who practice DDD should, at the very least, appreciate this, and not fall to the level of others by bashing those who choose to implement ADM. Just my thoughts.

Hydrolyse answered 26/9, 2011 at 23:12 Comment(0)
C
20

"It's an anti-pattern, so other developers will ask if you understand the concepts of object oriented design."

"An anemic domain model is an anti-pattern. Anti-patterns don't have pros."

Whether the anemic domain model is an anti-pattern is a matter of opinion. Martin Fowler says it is, a number of developers who know OO inside out say it isn't. Stating opinion as fact is rarely helpful.

An, even if it was universally accepted to be an anti-pattern, the chances are it would still have some (though relatively little) upside.

Cobblestone answered 28/2, 2009 at 14:29 Comment(5)
... which are? I am not trying to trick you or anybody, but I'm really curious abou the pros. The cons have been mentioned a thousand times, but I am still seeking resilient pros of the ADM (aside from polemic phrases).Diastyle
...this seems like someone trying to play the devil's adovcate with little show for it. the chances are it would still have some (though relatively little) upside. Then please name some! At least one, instead of hypothesising!Quartern
It's easier to know where some logic belongs for anything that's not single-class related (any real business). As said in other places, "rich domain model" end up having logic in multiple places (service layer, multiple classes involved in object graphs, ...). Also, RDM doesn't let you have an easy view of the full business logic, doesn't make it easy to avoid cycles, etc. Dumb data structures without logic have their place in an OO application.Peril
I find this article gives a good argument to say ADM is not an antipattern blog.inf.ed.ac.uk/sapm/2014/02/04/…Audun
Antipatterns create always problems and we have successfully shipped several somewhat big applications (2 or 3 years development of 10 developers work >300KLOC) with high quality solutions using the pattern and without feeling something was wrong with it, so it cannot be that bad if it allows you to create good code while using it.Coel
P
13

It seems to me that Fowler's main objection is that ADMs are not OO, in the following sense. If one designs a system "from scratch" around passive data structures that are manipulated by other pieces of code, then this certainly smells more like procedural design than object-oriented design.

I suggest that there are at least two forces that can produce this kind of design:

  1. Designers/programmers who still think procedurally being required to work in an object-oriented environment (or assuming that they can...) to produce a new system, and

  2. Developers working to put a service-like "face" on a legacy system designed in a non-OO fashion (regardless of language).

If, for example, one were building a set of services to expose the functionality of an existing COBOL mainframe application, one might define services and interfaces in terms of a conceptual model that does not mirror the internal COBOL data structures. However, if the service maps the new model to the legacy data to use the existing-but-hidden implementation, then the new model might very well be "anemic" in the sense of Fowler's article -- e.g. a set of TransferObject-style definitions and relationships with no real behavior.

This kind of compromise may very well be common for the boundaries at which idealistically-pure OO systems must interact with an existing, non-OO environment.

Patrica answered 3/11, 2008 at 14:1 Comment(0)
C
8

The anemic domain model (ADM) may be a good choice if your team is unable or unwilling to build a rich domain model (RDM) and maintain it over time. Winning with an RDM requires careful attention to the dominant abstractions used in the system. Figure that, in any dev group, no more than one half and perhaps only one tenth of its members are competent with abstractions. Unless this cadre (perhaps only a single developer) is able to maintain influence over the whole group's activities, the RDM will succumb to entropy.

And the entropic RDM hurts, in particular ways. Its developers will learn harsh lessons. At first they will be able to meet the expectations of their stakeholders, because they will have no history to live up to. But as their system becomes more complicated (not complex) it will become brittle; the developers will try to reuse code but tend to induce new bugs or back-track in development (and thus overrun their estimates).

In contrast, the ADM developers will set lower expectations for themselves, because they won't expect to reuse as much code for new features. Over time they will have a system with many inconsistencies, but it probably won't break unexpecredly. Their time to market will be longer than with a successful RDM, but their stakeholders are unlikely to perceive this possibility.

Cenac answered 12/5, 2011 at 18:47 Comment(0)
G
5

"Developers working to put a service-like "face" on a legacy system designed in a non-OO fashion (regardless of language)."

If you think of many LOB applications, these legacy systems will often not use the same domain model as you do. The Anemic Domain Model solves this with the use of business logic in service classes. You could put all this interface code inside your model (in the traditional OO sense) - but you typically end up losing modularity.

Gimpel answered 5/5, 2009 at 17:32 Comment(1)
Bingo. This is where a lot of people seem to miss the boat. ADMs do have a purpose. Their misuse is an anti-pattern, but they themselves are not.Ta
M
5

Having worked with a 'mature' system with an ADM and feel I can provide some, at least, anecdotal feedback to this question.

1) Lack of Encapsulation

In a live system with an ADM there is the possibility to write e.g. 'obj.x = 100; obj.save', even if this violates business logic. This leads to a number of bugs that would not be encountered if the invariants were modelled on the object. It is the severity and pervasiveness of these bugs that I feel is the most serious negative to an ADM.

I feel it important to point out here that this is where a functional solution, and the procedural solutions of an ADM differ significantly and any similarities that others may have drawn to the surface similarities between an ADM and a functional solution are incidental.

2) Code bloat

I estimate that the amount of code produced in an ADM is 5-10x that which an OOP/RDM solution would create. This is accounted for by perhaps 50% being code repetition, 30% being boiler plate code, and 20% being the solving or resolving of problems which arise from the lack of a RDM.

3) Poor understanding of the domain problems

An ADM and a poor understanding of the domain problems go somewhat hand in hand. Naive solutions arise, requirements are poorly considered due to the difficulty of supporting them with the existing DM, and the ADM becomes a significant barrier to business innovation given the longer development times and lack of flexibility.

4) Difficulty of maintenance

A certain level of rigour is required to ensure that a domain concept is changed in all the places it is expressed, given that the concept may not be just a copy and paste re-implementation. This often leads to the same bugs being investigated and fixed on multiple occasions.

5) Increased difficulty with on-boarding

I think one of the benefits of a RDM is the cohesion of concepts which allow a faster understanding of the domain. With an ADM concepts may be fragmented and lacking clarity hence harder for new developers to acquire.

I was also tempted to include the operational support costs for an ADM being higher than for an RDM but this would depend on a number of factors.

As others have pointed out, look at DDD (Greg Evans, Vince Vaughn, and Scott Millett) for the benefits of a RDM.

Mechling answered 26/3, 2017 at 11:0 Comment(2)
Is Greg Evans the secret child of Greg Young and Eric Evans? I didn't know that Vince Vaughn was writing DDD books either, but maybe Vaughn Vernon has started acting too :)Brachium
Oh dear, seems my memory when I wrote the above was somewhat muddled. Thanks for pointing that out :)Mechling
G
4

When I first came across the Anemic Domain Model article I thought "holy s***, that's what I do. horror!" I persevered and followed the references to Eric Evan's book, held to be a good example, and downloaded the source. It turns out that "not using an Anemic Domain Model" does not mean "not using service classes, not using mediators, not using strategies" or even "putting logic on the class being manipulated".

The DDD examples have service classes, XyzUpdaters, singletons and IoC.

I remain confused by exactly what an Anemic Domain Model is. I expect "I'll know it when I see it". For now I'm content with a positive example of good design.

Geilich answered 21/6, 2012 at 0:15 Comment(1)
I have subsequently purchased Eric Evan's book and I highly recommend it. It provides solid examples of the opposite of anemic domain models.Geilich
H
2

It's the same pro as with most anti-patterns: it allows you to keep a lot of people busy for a long time. As managers tend to be paid more when they manage more people, there is a strong incentive not to improve.

Hydrolytic answered 8/11, 2010 at 21:42 Comment(6)
In that case, let me rephrase it. ^^^ Purely anecdotal evidence used to infer a general-sounding proposition.Ta
When we find enough anecdotal evidence, we might be able to derive a pattern. And this pattern is well known and described adequately in literature on change management.Hydrolytic
"And this pattern is well known and described adequately in literature on change management." - Citations please. More to the point, correlation does not imply causation. Meaning, just because you see people spinning their wheels in red tape because of in-place anti-patterns (software patterns specifically, and anemic domain models to the point), that does not imply that the later exists to justify the former, which is what you just trumpeted. Rhetorical slogans are poor caricatures to explanations of complex issues. So again, correlation does not mean causation.Ta
You might want to read Quality Software Management by Gerald M. Weinberg, especially Volume 4. And I only claim a possible cause for the continued existence, not for its occurrence. The Peter Principle provides an adequate alternative.Hydrolytic
Thank you, I will read that when I get the chance (+1 for providing a citation). Does that book presents it as a well-known anti pattern? In addition to that, does it claim/show not just correlation but also causation? You claim it as a "possible" explanation now. Your original text puts it as a certainty, with more rhetoric than detail (which is why I called it 'pure speculation'). Whether that was your intention then, or simply an editorial accident, who knows, and I can only infer from what is present in text at the time of reading it.Ta
The OP asked for pro's and cons. This pro (or perhaps con) was missing. For understanding change resilience on a larger scale, try "The Collapse of Complex Societies" by Tainter. There is a nice blog post applying its findings to business models: shirky.com/weblog/2010/04/…Hydrolytic
S
2

In line with Eric P's answer as well as what some others above wrote, it seems that the main disadvantage of an ADM is the loss of OOD, specifically of keeping the logic and data of a domain concept together so that the implementation details are hidden while the API can be rich.

Eric goes on to point out that there's often information outside a domain class that is necessary for the logic of acting on that class, such as checking an inventory before adding an item to an order. I question, though, whether the answer is a Service layer that holds this overarching logic, or whether it's better handled as part of the object design. Somebody has to know about the Inventory object, the Product object and the Order object. Perhaps it's simply an OrderSystem object, which has an Inventory member, a list of Orders and so forth. This won't look very different from a Service, but I think it's conceptually more coherent.

Or look at it this way: You can have a User with an internal credit balance, and every time that User.addItemToOrder(item) is called it gets the item's price and checks the credit before adding it, etc. That seems a reasonable OO design. I'm not sure precisely what's lost by replacing that with Service.addItemToUserOrder(user, item), but I'm not sure what's gained, either. I guess a loss would be the extra layer of code, plus the clunkier style of writing and the enforced ignorance of the underlying Domain Model.

Sturrock answered 27/6, 2011 at 19:47 Comment(0)
N
2

After I first read Eric Evans book about Domain-driven design I did not really understand that it is not just a bunch of tactical patterns for designing good domain model classes.

After learning more about the topic and using the strategical patterns as well I finally started to understand that at first it is all about getting a deep understanding of the business problems you are trying to solve.

And only after that you can decide what parts of the system will fit for applying tactical patterns such as aggregates, entities, repositories, etc. along with so called rich domain models (as opposed to anemic ones). But in order to benefit from these patterns there has to be enough complexity concerning business logic for that part of the system.

So at when it comes to implementing the solution to the problem at hand it should first be determined if this specific problem is better approached with using a CRUD based approach or investing into a rich domain model along with the mentioned tactical patterns.

If CRUD makes more sense, e.g. if there is no complex business logic and most of the logic is concerned with transforming, transferring and persisting data implementing a domain model can be an unncessary overkill. This does not mean that there won't be a lot of work to do but simply the it's not the business rules which produce the most implementation effort. But in this case there is no such thing as an anemic domain model, simply because there is no domain model at all. What you will rather see are such things as DTOs (Data Transfer Objects) or DAOs (Data Access Objects) and service classes that will operate on the data. And the corresponding operations are to a high extent concerned with transforming data from one representation to another and moving data around with very little or almost no business logic at all.

If you determined that there is a lot of complex business logic which will also change over time than investing into a domain model is - from my experience - a good idea. The reason is that it is easier to represent the business perspective via code and make it easier to understand the corresponding operations that mirror the business domain and it's rules. This does not mean that there have to be domain model classes in every use case. For instance, if there is no state to be mutated and persisted there can also only be domain services which contain the domain logic are implemented more like pure functions.

But if there is also state to be mutated and persisted that also has purpose and meaning in the business domain the state and the behaviour that changes this state should be encapsulated. With that no one can get around the business rules that easy and by that lead to invalid states along with serious failures. So called anemic domain models are often sources of such problems. This is often the case if you see code where different components operate on the same "anemic" domain model class checking some part of it's state and changing some part of it's state without caring about or knowing the overall invariants of that business entity. It is not necessary to call this an anti-pattern but it is important to understand that you lose lots of benefits of rich domain models in a DDD based approach along with the mentioned problems. When using a domain model where behaviour and it's data are placed in the same class there can also be lot's of different "clients" calling operations of that class but they don't need to care that the business invariants of the business entity are adhered as the domain model class will always take care of that and can also inform the "client" about invalid operations or even throw exceptions as a safety net.

So bottom line, I think it is important to not confuse data-structure like classes (such as DTOs or DAOs) with anemic domain model classes. In a carefully and intentionally chosen CRUD based approach there is no advantage of trying to use a domain model because there is too less complex business logic.

By anemic domain model I would refer to code from which I can see that there is a lot of complex business logic and business rules that are spread across different components which should rather be close to the data these logic is changing.

There is also another lesson I learned along the way: if you try to use the same business language (also referred to as the Ubiquituous Language) in your code that the steakholders are using in their daily worklife you already win so many advantages concerning understanding of the business domain and improving the readability of your code that will help you so much no matter if you use a CRUD based or domain model based approach.

Nicholson answered 28/7, 2020 at 23:36 Comment(0)
U
1

It should be noted that as systems grow in complexity and granularity of variation, the encapsulation and consolidation of interface points afforded by a well designed message-passing object model make it much safer to change and maintain critical code without widespread refactoring.

The service layers created by the ADM, while certainly easier to implement (since they require relatively little thought and have many decentralized interface points) will likely create trouble down the road when it is time to modify a live and growing system.

I might add also that not all cases call for a domain model at all (let alone the ADM one). Sometimes it is better to use a more procedural / functional style of the task is data driven and does not depend on application-wide logic / business rules.

If you are trying to decide on the pros and cons for a whole app, I think it is important to first design what each one might look like for your given application BEFORE you even start writing a single line of code. Once you've CRC'd or wire-framed your application in both styles, take a step back and decide which one makes more sense and fits the application better.

Also think ahead to which one will be easier to maintain...

Unintelligent answered 14/7, 2012 at 12:31 Comment(0)
H
1

It gives better predictability. Managers like that, especially if the project is paid time & materials. Every change means a lot of work, so difficult work can be hidden behind lots of repetitive work. In a well-designed DRY system, predictability is very bad, as you are constantly doing new things.

Hydrolytic answered 2/3, 2013 at 14:12 Comment(0)
U
0

To extend Michael's answer I'd have thought it's (fairly) clear where that code should go: into a dedicated Mediator that handles the interaction betwene the Order and the Inventory.

From my POV the key thing about the domain is that it MUST hold the simple testing behaviour the isInThisState() methods etc. In my experience these are also scattered throughout the service tears (sic :)) in most companies, and either copied ar endlessly rewritten. All of which breaks standard conhesion rules.

In my view the approach should be to aim for a DM that holds as much of the biz beahaviour as is practical, put the rest in clearly designated areas (ie not in the services)

Unsteel answered 5/1, 2012 at 14:42 Comment(1)
The thing about a Mediator is there's very little difference between that and procedural programming anyway; you're just grouping some functions that don't belong in either object. The fact that you group them in another object doesn't make much difference.Ingredient
K
0

My team personally prefers the ADM. we have a set of business objects that represent specific parts of our domain. We use services to save these objects to the db. Our business objects do have methods, however these methods only manipulate it's internal state.

The benefit for us in using the ADM over RDM can be seen in how we persist the objects to db. Developers working on our legacy code systems can use our business objects(from the new system)and continue using their current data access layer to persist these objects to the db. Using the RDM would force developers of our legacy system to inject Repository objects into our business model...which would not be consistent with their current data access layer.

Kajdan answered 18/3, 2012 at 11:15 Comment(0)
V
-18

An anemic domain model is an anti-pattern. Anti-patterns don't have pros.

Viniferous answered 6/11, 2008 at 20:54 Comment(5)
I disagree. Most Antipatterns have corner cases in which they are a better solution than other alternatives.Srini
Anti-patterns do have pros. That's why people use them, even though they are usually bad ideas.Viens
Parroting that something is an anti-pattern as a fact when it is just an opinion (even if it's something of Fowler's caliber), that is not a valid form of answering.Ta
@luis: Just what I was about to write before I saw you comment. Additionaly, tools exist to serve a purpose. If Fowler doesn't want to call it OO, that's fine. But that does not automatically indicate a bad solution/architecture/etc.Milkwhite
Usually in Software Engineering every decision has pros and cons, even the all mighty Design Patterns can be problematic or an overkill if you don't apply them correctly or where they are not needed. To say something is 100% good or bad is not a good practice. I guess with time and experience you learn these things. I am still in the process but this much I can tell.Tristis

© 2022 - 2024 — McMap. All rights reserved.