26

Martin Fowler considers Anemic Domain Model as an anti-pattern.

Rolling the Persistence Model as the Domain Model seems severely off too due to Object Relational Impedence Missmatch. For persistence and normalization sakes, we tend to break down classes to very small tiny pieces, slapping methods on top of these classes is silly. Plus persistence rarely changes, but business logic changes a fair bit.

So we need a DomainModel that builds on the persistence model (instead of being one and the same). This Domain Model will then contains business logic properties and method.

But now these Domain Models are still behind the service, and in order to expose them out to the outside world we need to convert them over to DTOs.

We are doing so manny mappings here.

  1. Persistence to Domain Model
  2. To convert Domain Model into DTOs to pass along between services

It doesn't end there, since the DTO may need to be mapped into the ViewModel.

All that and the problem of duplicating validation logic still doesn't go away, because the client wants real time validation. ViewModel knows nothing about validation, so in an SPA for example, you're forced to rewrite the validation logic again, on the client side (usually in javascript).

Also services are by nature stateless (message or RPC oriented), so we're doing all these mapping, between Persistence, to OO then back to Procedural, to what benefit? How would you justify the cost in practical terms of most IT budget?

I get how having full DDD, with Aggregate Roots, Domain Models etc. would be "cool" but how can you justify the cost and the hit on dev productivity?

anti-pattern (or antipattern) is a pattern used in social or business operations or software engineering that may be commonly used but is ineffective and/or counterproductive in practice

And if so, wouldn't DDD and Rich Domain Model fit into the anti-pattern definition above than the "Lean" Domain Model. Sorry, I despise the loaded word, "Anemic".

By keeping the Domain Model, "Lean" you actually allow it to be shared without violating the "Abstract Dependency Principle", "Don't Repeat Yourself" and the time consuming, tedious and error prone process of mapping one data carrier to another, and whatever associated Unit Test that goes on top of that (unless you're thinking of doing mapping w/o unit testing and hope for the best).

Jan B.
  • 6,030
  • 5
  • 32
  • 53
Alwyn
  • 8,079
  • 12
  • 59
  • 107

3 Answers3

9

tl;dr The domain model is not well defined, it's probably designed with a db centric approach in mind.

The main purposes of DDD is to model in code the Business concepts and processes. I really doubt that your business concepts and processes are just bags of properties. But if they really are then yes, the Domain Model can be the same as the Persistence Model so you don't have to do any mapping.

The persistence model models how object state is stored. If you're not in the domain of databases, then domain and persistence model can't have the same purpose. One of the biggest mistakes I see with DDD is thinking about the domain model like it's still data driven. In DDD you don't have a concrete database. You have repositories. There are no one-to-many, many-to-many etc relations. There are no tables and no rows. There are just objects which try to represent the Domain as accurate as possible.

Simply put, the Domain cares about modeling business behavior while the Persistence cares about storing object state. I see two different responsibilites here.

About validation, you have 2 types: validation of input data format and then validation of other business rules according to what you change in an object state.

About the duplication, I think you are referring to the input format but like @EbenRoux said there are mechanism which can help with that . In asp.net mvc most of those validation rules have the js version included as well.

Let me tell you a little secret with services. While their interface can be defined in the Domain, their implementation can sit in the Persistence Layer, thus allowing them to work directly with the storage. And since the rest of the app uses the service in their abstract form (the interface), only the DI Container will know the dirty secret.

DDD is not about being cool, it's about designing an application according to the domain. I'll bet few develop an app for the sole purpose to be an UI for the db. The majority aims to provide a service with their software,to build a virtual product which solves a problem. It makes sense that the design the app to be driven the problem you want solved and not by the technical tools you just happen to use.

How does this sound, you want a brick house but the constructor says:" Sorry but my saw only works with wood". Well, don't use a saw, use another tool wich can help cut a brick. The tools need to be adapted at the problem, not viceversa.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • So the Domain in the DDD is it stateful or stateless? Should the Domain then expose its properties? If not what would be the parameter and return types of the Domain methods?, DTOs? If it does expose its properties how is this any better than the Anemic Model? – Alwyn Jan 17 '13 at 08:49
  • Domain is primarly about behavior. Of course, a domain object can have properties but it doesn't have only properties. And those properties aren't only primitives. How do you save IFormattedContent directly in a column? I'm beginning to think your current domain is just a collection of data driven procedural code that just uses DDD terms. – MikeSW Jan 17 '13 at 08:56
  • @Alwyn part of the domain is stateful - it's precisely the point of Entities to have a state as well as an identity so that we can track changes in that state. Value objects on the other hand are not stateful (state-frozen if you will). Domain services should clearly be stateless. – guillaume31 Jan 17 '13 at 14:55
9

It seems you're mixing up a lot of concepts, blaming the rich domain model approach for things it isn't directly responsible for.

  • Rich domain model is orthogonal to layered architecture, especially having a rich domain model doesn't dictate the number of layers you have, what data structures should be exchanged between these layers and how they should be mapped.

  • Rich domain model is orthogonal to validation and says nothing about the need for client-side checking in addition to back-end validation.

In other words, making your domain model anemic with all business logic in services won't necessarily save you from writing a lot of boilerplate DTO mapping code, nor will it remove the need for client-side "double checking" (which is by the way a commonly accepted best practice).

This doesn't mean your point about the cost and weight of a full-fledged multi-layered architecture isn't valid. You might find interest in this post by Mark Seemann discussing similar concerns : http://blog.ploeh.dk/2012/02/09/IsLayeringWorthTheMapping.aspx

guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • I think the article you linked sums up the dilemma. Except that I don't believe in sending Domain Model out thru the wire, that seems like the job of a DTO. It makes no sense to have behavior on the DTO and exposing that to the client. So to me the architecture is only "doable" with another layer of abstraction and mapping in addition to the 3 he mentioned. And that is a LOT of mapping! Not saying the other way of introducing UI concern to the domain for the sake of reuse, is right either. I think there's a "happi-er" medium in between the 2 pollar extremes. – Alwyn Jan 17 '13 at 17:57
  • "Move less data around and things are likely to become simpler" - His own conclusion at the end of the article, that sounds like Lean Model to me. – Alwyn Jan 17 '13 at 18:28
  • "It makes no sense to have behavior on the DTO and exposing that to the client" - now I understand the connection you're making between rich/anemic domain model and layering. Do you imply that domain objects should be stripped from as much business logic as possible in an effort to send them directly to the UI layer without the need for DTO's ? Or is it something else you're referring to as "Lean Model" ? – guillaume31 Jan 17 '13 at 21:21
  • No, it might work, I just think you need another layer in between the Domain Model and the DTO. One of the commentors in that link made the same observation. I can see this working it's just a lot of overhead and I can't tell if the trade off is well worth it. – Alwyn Jan 17 '13 at 21:45
5

First off I do not think that you can really easily get away from duplicating validation logic on the client and on the server. This is not limited to DDD, though. There are some mechanisms to ease the pain but some effort will always be required.

The other part is this whole mapping business :)

What you are doing is effectively using to perform reads. You may be thinking that you need to read your entity in order to edit it. That is true if you are performing entity-based (entity probably more in DB terms here - whole record) operations instead of task-based operations on your entity object. A silly example may be that a customer phones in to the call centre to change an address. The operator calls up the customer record and edits the address. This is entity-based and leads to typical issues w.r.t. concurrency since 2 actions may be performed on the same record (however unlikely). This is a very traditional approach to UX design: "Edit the record".

Contrast this with a button on the screen that says: "change an address". You only change the address on the record and although this seems like the same thing it really is quite different. The chances for 2 operations that change the same address are rather more slim than that of changing the same record. If required concurrency checking can be done on this part.

Now if one does not read the domain what would one read. Where would the data come from. This is where CQRS (Command/Query Responsibility Segregation) comes in. In the past it has been confused/combined with Event Sourcing but this is not required. You can create a simple query side to your application focused on returning the data you need. In C# I used a DataRow if it is a single instance, a DataTable for multiple instances, and a custom DTO for anything more complex. There may be a way one get even get away with anonymous types (haven't investigate this yet).

Therefore:

Domain Model = operations / calculation / write Query Services = read

There are situation where you can get away with simply loading an entity/aggregate such as in a web application since it is aware (or may be aware) of your domain model but a smart client would be a bit of an anti-pattern.

The justification is rather tricky but it does boil down to maintenance. If your approach is not easing your maintenance burden then chances are something is not applied correctly and needs some refactoring.

DDD is not only about the technical implementation although that goes a long way, pushing in the direction of proper OO modeling. I guess the other ideas feed into the software anyway so the software seems to be the focus anyway. We all want to see where the rubber meets the road.

Like most things DDD can be done wrong :)

Eben Roux
  • 12,983
  • 2
  • 27
  • 48