Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com

DDD: Validity, Consistency and Immutability

There seems to be some confusion around these and similar concepts, so I thought it might be an idea to provide some clarification. Now these things aren’t specific to DDD, but they certainly have a lot of relevance there, and often provoke furious debate.

In this series I first mentioned these things back when I introduced Entities and Value Objects, I said that you should try and ensure Entities are valid at all times, and that Value Objects should be immutable. The discussion around Aggregates and Aggregate Roots has also proved to be of some confusion, the definition from Eric Evans of an Aggregate says “A set of consistency rules applies within the Aggregate's boundaries”.

Validity

The term “valid” has many meanings in many contexts. When it was mentioned with regards to an Entity, I suggested that you should attempt to ensure that your Entities are always in a valid state, and cannot become invalid. I followed up that this could be achieved by removing property accessors, and only using either constructors or strongly named methods.

Let us go back to our Customer example, and presume that for a Customer to be valid within our Domain, it must have a CustomerNumber, a FirstName, and a LastName. It may also have half a dozen other properties.

So we can ensure this Entity never becomes invalid by removing the property accessors for the CustomerNumber, FirstName, and LastName, and providing a single constructor that allows us to create a new Customer … Customer(customerNumber, firstName, lastName)

Now there is no possibility that this Customer can become invalid – it either has these three properties or it cannot be created. If we want to be able to change the Customer’s name, we can create a new method .UpdateName(firstName, LastName)

By taking this approach, we ensure that the entity can never be put into an invalid state, for example a developer setting a .FirstName property, but forgetting to set the LastName at the same time.

Some have taken this concept too far, and assume that as a Customer also has a Policy, that it must always have one of these or it is invalid. Of course, there are things we may want to do with our Customer that will require it to have a Policy, but that does not constitute an invalid Customer, it constitutes a rule that must be applied before we attempt to take the action.

The purpose of ensuring the Entity is always valid prevents us having to do messy things like checking an .IsValid() method every time we want to persist our entity, or we write a function that accepts an instance of our entity. Enforcing an “always valid” approach will mean that we do not have to code multiple guard clauses scattered across our applications.

Consistency

The term consistency has come up in this series and around DDD mailing lists. In this respect, consistency is the idea that one piece of data in the system is consistent with another. Here is the bad news:

You cannot ever achieve total consistency

OK – headline over. The point is that something in your application will always be inconsistent. The best example is that when your users have chosen to edit the Customer on their screen they have a copy of that data. By the time they have received that data it will potentially be inconsistent with the domain, and with your persistence store – after all this is why we have the concepts of optimistic and pessimistic locking. When they submit a change to the Customer, it is probably minutes out of date.

Back to our headline, when you accept that it is impossible to achieve total consistency, you can deal with the real problem – how you achieve eventual consistency. Eventually messages will make their way through our domain, eventually data will be persisted, eventually you will have consistency.

While our reporting domain may lag behind our primary domain, does it honestly matter? How important is it that they are both totally consistent? You can certainly achieve a close facsimile of total consistency, but it will come at a high price – does the business want to pay for this?

When you let go of the premise that your data is ever really consistent, it now just becomes an issue of an SLA agreement, if the business really wants data that accurate, then explain the costs and tradeoffs and go with it. If after an explanation they understand that “almost consistent” is good enough for almost all applications, then they just have to make a decision about how important this is to them.

Consistency also applies at a much more granular level, with the domain for example. Entities and Aggregates may be valid, but not consistent with each other at all times. Eventually they should become consistent, but ensuring they are all consistent at all times is very tricky to say the least.

While an Aggregate Root is responsible for ensuring consistency with the Aggregate, it is acceptable, and almost inevitable that Aggregates will be inconsistent with each other at some point in their lifetime.

Again, letting go of the myth of total consistency here will give you far more flexibility.

Immutability

I would hope this is familiar to all – but perhaps some of you saw me mention it and didn’t quite get my context.

The concept of immutability is pretty much what it says – the thing cannot be mutated – or in context, an Immutable Value Object can be created, but can never be changed.

If you want to change an immutable object, then you can create a new one and replace the original.

By making objects immutable, we avoid many problems with validation and consistency, only the constructors on the object matter, and they only need to validate the parameters passed in. It is far easier to check all the parameters at a single time than to check individual properties against each other at a later stage.

I'm interested how you handle validation feedback in such a system. On submission of a form in the UI, do you apply a set of rules to the raw data before updating the model? What if rules depend on existing values of the model? Or do you create some intermediate objects mimicking the model and apply validation there?

For example, suppose that when updating a customer's delivery addresses, one of the adresses must match their billing address. This rule requires data from the model to determine the validity of the update.

My approach is to bind the incoming data to the domain object then execute a set of validation rules, collect the feedback and only persist the changes if the object is valid.

Tricky question ... and as I have a terrible cold - I'll only answer briefly

Firstly, the UI probably has different validation to the domain - it is validating input and operations not entities

Secondly, where the validation really is domain validation, then the validation rules should be separated from the entities - the entities/service may call the same logic, but it is not part of them. This allows you to reuse the code in the UI layer, and to use it to generate client validation.

Lastly, trying to throw data into an Entity is the line of last resort ...

When I read things like this, the domain modeler in me starts immediately nodding in agreement.

One thing I'm struggling with at the moment is how best to strike the right balance between a domain centric design and an interoperable SAO strategy. We have a swath of WCF services being consumed by .NET winforms apps, legacy C++ apps, java web apps, etc. and the scale and performance requirements are high.

I assume you're not passing around DTO representations of your domain and not the domain entities themselves in a scenario like this. In my case we only control the server side processing, and apply a rich domain to a high scale, stateless, SOA architecture for servicing requests at our service layer seems like a mismatch.

If you have any resources on domain design in a scenario like this, I'd love to hear about them. From what can gather, 98% of the people building web services on the .NET platform are designing them for .NET clients, and therefore have a lot more options working in a domain model approach between client and server.