5

My (first and current) workplace (a .NET shop) suffers from an over-abundance of anemic domain models, to the extent that I don't really know how validation and data persistence should be handled in a proper domain model.

Data Persistence

One option would be to give the domain model a way to do persistence itself. You could, for example, inject an IFooRepository via constructor injection, and have that resolved by an IoC container to ensure you don't create a dependency on it (à la onion architecture). But I'm not sure if the code that uses the domain model should be responsible for calling methods to save the data, etc., or if it should be done implicitly behind the scenes on a background thread. Perhaps this breaks that purity of the domain model and is more along the lines of the active record pattern.

The other option I see is to not tie the domain model to data persistence at all and instead have a coordinating service layer responsible for that aspect.

What are the best practices for data persistence in the domain model pattern?

Validation

Another problem I don't know how to solve with a proper domain model is how to indicate to the UI why the current model state is invalid without coupling to (or at least catering to) the UI. For example, let's say I have a form an user fills out with various fields. We want to validate that input, and if something is wrong, indicate an error on that specific field with a message.

How would we handle validation with that level of granularity without adding significant complexity to the domain model, or doing hack-ish stringly-typed things (like throwing an validation exception with the property's name and a message)?

2 Answers 2

4

I could be mistaken in my understanding, but I believe your trying to redesign your Domain Model so that it isn't riddled with anemia. A couple of really, really great books on the matter are:

  • Martin Fowler - Patterns of Enterprise Application Architecture
  • Eric Evans: Domain-Driven Design: Tackling Complexity in the Heart Of Software
  • Vaughn Vernon: Implementing Domain Driven Design

They have a lot of content which answers quite a few questions on your goal. One of which is:

A rich Domain Model can look different from the database design, with inheritance, strategies, and other Gang of Four patterns, and complex webs of small interconnected objects. A rich Domain model is better for more complex logic, but is harder to map to the database.

A simple Domain Model can use Active Record, whereas a rich Domain Model requires a Data Mapper. Since the behavior of the business subject to alot of change, it's important to be able to modify, build, and test this layer easily.

That is an excerpt from Fowler. He will go into details about the model being anemic and bloated models as well. The scope of the question to me appears quite large; so I'm not sure I could delve far into it. Those books should point you in the right direction; also will allow you to gauge your current project and implementation to refactor it quickly.

From a relatively basic understanding:

You should be able to abstract your model, which will allow a brief overlay of the UI and Data Access into your Domain Model. But otherwise the model should allow a clear, clean, concise implementation which will help separate responsibility.

Sorry I couldn't be more help.

4

The question arises what your UI is using to get the data and how it sends the data to be persisted. I'm afraid since you mentioned you have no service layer and you suffer with finding the right place for your validation, that your UI works directly with your domain classes. That could be the way to go, however it does not sound like a very complex application and you can do persistance work and querying right in the UI code. You can check posts of Ayende Rahien and many others who talk about getting rid of repositories. In relatively simple scenarios ORM is capable to provide enough isolation of domain model from the persistance itself. Also it is a questionable matter if modern ORMs can be seen purely as DAL. Look at NHibernate, it can do so much more than just mapping simple tables to simple classes. And if you look at your repositories you might find a bunch of methods called GetByThis and GetByThat, which issue a simple query to the ORM (if you use one of course) and just play a silly role of unneeded abstraction to make an impression that you do DDD.

Concerning your comment about "not creating" dependencies by injecting repositories - you will onvert control but you will have dependency as soon as you use repository class instance in your domain object. It does not matter how it gets there. So this is the worse choice of all.

To your validation question I would recommend you to look closely to your validation as such and decide what validation is domain specific and what is more data entry specific. Data entry validation like mandatory fields should not be checked by the domain model. It is a simple job and UI layer is perfectly capable of doing that. Even more, most of modern UIs are able to do this validation very easily. However you need to find a way to inform your UI about the data input rules (I will get back to it below). Your domain model need to perform more business-oriented validation, like if customer with such name already exists. But you, again, cannot do this inside your domain class since you are unable to query existing data from there because it is not the domain object responsibility to care about anything outside of its own aggregate.

So if you want to go to deal DDD journey I would recommend you to look at CQRS principle. It is often bound to event sourcing but you can just skip that. Concentrate on this scenario, when using RDBMS with or without ORM or NoSQL for persistence:

  • Create input models and view models to be used solely by the UI.
  • Decorate your input models with data attributes for client-side validation.
  • Send commands from the UI to your backend to do business validation and persistence.
  • Send queries to your backend from the UI to get the data to show. Returned data should be placed in view models.
  • Use domain events to communicate between different bounded contexts

It does not necessarily require the backend logic to be put in an application server (although it is very desirable to enable having multiple UIs with the same backend). You can use in-memory events to send commands and queries too.

But again, look at what you really need, don't try to overscale your abstractions just because the book says so. Remember that very often abstractions are put in place just because someone heard this is a good thing. Repositories is a classic example, when people say it makes their system persistence ignorant and they can change their ORM but in fact no one does that. When ORM is changed it means almost full redesign and repositories get scrapped equally well together with all other code.

1
  • How does 100,000 LOC sound for not very complex ;) hehe
    – Jeff B
    Commented Oct 11, 2013 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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