C# – DDD – How to do informative validation (specifically on entity creation)

cdomain-driven-designvalidation

For my domain entities currently, all validation errors cause exceptions to be thrown. I don't like this as it doesn't allow me to compile all validation errors before exiting a method. I'd like to pursue something similar to what's described here:
https://enterprisecraftsmanship.com/2016/09/13/validation-and-ddd/
…in particular, the idea of returning IReadOnlyList from all entity methods. The problem I'm running into is regarding entity creation… how do I utilize this technique? I see no other way than to throw exceptions from the constructor when validation rules aren't met with the given parameter values.

Best Answer

Object creation is a technical concern that has nothing to do with enforcing business invariants. I would go as far as to say that absolutely zero business validation should occur in constructors. Validation is best left for during the processes within which invariants need to be enforced (where the data is used). Following this rule helps keep your system much more declarative and, therefore, easier to understand. Remember DDD is about modeling rules about behavior, not modeling rules about data.

What that means is that, given that a Customer has to be over 25 years old to register, the enforcement of that invariant occurs in the register method, not the Customer constructor. This allows the possibility of another rule that requires a Customer to be under 25 years old for some other process.

The only exception to the above is when the values passed to the object are, themselves, what the object intends to abstract (it's identity) e.g. EmailAddress. In this case the string passed into an EmailAddress constructor must conform to a certain specification in order to be considered a valid address. This means that the above exception only applies to ValueObjects.

Here is a link to an answer I posted to a similar question that may be of interest to you: Zero argument constructors and Always Valid entities

All that said, you don't want to go down the road of compiling all validation errors before exiting. Not only does it make your methods much more complicated, it only works for the simplest of processes where all validations can occur before any real logic is executed. It seems like a good idea when the only invariants are the existence of address and dayOfWeek strings, but falls apart for more complicated operations. Furthermore, many domain errors aren't meant to be viewed directly by clients (so what are you going to do with them? Parse a DomainErrorList into a ClientErrorList? Overkill!).

Leave simple validation out of your domain altogether, and raise it "upwards" into your view. This is precisely why ViewModels exist in the first place. What I mean is, if the purpose of collecting error messages for some input is to then expose them to your client, then keep all of that validation in the view itself (and do it the way MS does it in their ViewModels -> procedurally). I may feel redundant, but it's also decoupled.