Who Knew Domain Validation Was So Hard?

Who Knew Domain Validation Was So Hard?

I’ve been following intently the conversation that has been going around recently surrounding Domain Driven Design and validation within the domain. I have been swirling it around in my head for a bit,  and I’m still not quite sure that I am 100% in the game, but I wanted to get my thoughts out on paper (or at least on my blog) so that others would have a chance to respond.

In case you have not been following it, the core of the discussion has been revolving around the appropriate place for validation to reside in your application. For many the result was surprising…it should never be in your entities. And interestingly enough, this conclusion seemed to be supported fairly universally by the people responding to this post.

Nagging Fears

While I guess this should be surprising for me, especially considering the fact that I recently helped design a system where there is a significant amount of validation within entities, I can’t honestly say that it did. The idea of having domain entities validate themselves never really set easy with me. But at the same time, I struggled a bit with the proposed solutions for it. I mean, I can completely understand how contextual validation is, but moving it out of the entities can leave the validation strewn about in the application. And don’t think that just because you are still using “IsValid” on your entities that you are doing something wrong, even Jimmy was proposing this not too long ago, we all have a long way to go guys. He may have been talking about external validator classes, but he was still proposing this validation being kicked off from within the entity. Or as Sean referred to it, “Reactive Validation”.

Now, some of you may be saying “so what if validation is contextual, the entity will have context so you can execute validation based on that context”. And yes, that is true to a certain extent. The entity will have knowledge of its own context, but validation could easily be based on context outside of the entities. Or it could be based on context which has little bearing on the domain at all. The example given in a comment on Jimmy’s post revolved around some data coming in from the UI being invalid for a particular context, while being perfectly acceptable when coming in through a batch process.

While this may seem like an edge case, these are the kinds of business rules that trip up our applications all the time. These are the types of rules that just scream “technical debt” because as soon as we see something like that come up we immediately get out the duct tape and glue gun. We obviously can’t redesign our application for a single screwy business rule, but sadly they rarely come in singles.

Cursed Context

So context is the problem, sweet sweet context. What is valid in situation A may or may not be valid in situation B. In the system I referred to above, we had two levels of validation. We had persistence valid and business rules valid. We recognized that valid was not black and white, and therefore created a finite amount of grayness that fit in with a database persistence model. At least in this case we could save off an entity to the database that was technically invalid, so that a user could come back later, finish it up, and make it valid. I’m starting to see now that the idea was there, but it stopped short of what was needed.

One of the ideas that comes out of the idea of moving validation outside of the entities, is that you can no longer simply as an entity, are you valid? So some people began to suggest that you simply never allow invalid entities. You should always make sure that your entities are valid, which is possible if you are pushing your validation into a service layer. If the data is coming in via a message or view model then you can validate the data before the entity ever sees it. This way you could operate on purely valid entities. But again, what is valid?

If I take this approach and say that I’ll only ever create valid entities, then it is really only valid within a particular context. If I create an entity via one service, validate it, and then persist it, what happens when it gets pulled up and passed to another service? I’m either missing something here or this can create issues. You would have to validate the entity immediately upon retrieval or you would have “invalid” entities. The issue in my mind is how do you immediately know what context to validate within before you create the entity? Would this happen within the repository? That isn’t kosher at all. But if we aren’t doing it within the repository then we are returning potentially invalid entities from the repository. At least invalid by the context that we are currently operating within.

Sean’s recommendation would be to create different version of your entities that were valid under different contexts, but that doesn’t make sense to me. If I am already having different validations in different contexts, then if I am going to have different entities in different contexts then why not just move my validation back into my entities, since I am going to have one for each context? It just doesn’t jibe with me, and I’m not sure you could make it work without a lot of headaches. Someone prove me wrong!

Putting all of that aside, if we are to move validation out of our entities, then how should we validate them consistently? My mind right now is still clinging to the concept of having IValidator classes which are capable of validating entities or groups of entities in different contexts. It may sound like you’d end up with hundreds of validation classes, but I would think that any given entity or aggregate would only have a handful of different contexts in which they are validated. The trick would be to make sure that they were validated properly in the correct places, but I guess that is what tests are for!

Summary

So anyways, after putting some serious thought into it (and reading many a blog post about it) here is what I think:

  1. Validation should not be inside of domain entities except for under the most simplistic of circumstances.
  2. Validation does need to be put into well defined areas of the application, it should not just be strewn throughout. If you aren’t using well defined command objects or have a strict service layer, then you are probably just better off putting it in your business objects because you’ll have no consistent means of ensuring validation.
  3. You should have a consistent strategy for validation, in order to make redundant validation as easy as possible. It is likely that for many entities their validation will always look the same.
  4. I’m not sure that I agree with the concept that entities should always be valid. I think this poses some problems, but I’d love to see someone prove me wrong here.

I’m really glad that this discussion is taking place currently, and it is good to see it happening across several different people’s blogs. My thoughts are certainly nothing new, but I think that getting them written down will help me think through them a bit more. It has me itching a good bit to try and re-implement a few things that I have been working on to do validation in this manner.

Anyways, I hope you enjoyed the post, and please let me know if you think I have gone off the deep end!

Loved the article? Hated it? Didn’t even read it?

We’d love to hear from you.

Reach Out

Comments (17)

  1. V. interesting. If your entities implemented INotifyPropertyChanged, you could, upon instatiation of each entity, bind a call to an AssertValid method for each proeprty change. This could pull back all the currently registered instances of IValidator<TEntity> and test them all.

    The IValidators could even have a bool IsApplicable(string changedPropertyName) method which means only the validators that actually test something to do with the changed property are executed.

  2. @Harry Yep, you could put code to check for property changes and run validation rules when you create an entity from a persistence store, off the wire, etc… the problem becomes at this point [b]which[/b] validation do you run?

    If you have validation for different contexts, then you would somehow have to get the validation code to run down inside of where you are creating your entities from your persistence layer. And the validation code might not just depend on the class you are instantiating, but upon other state. Maybe state that hasn’t even been pulled from the database. How would you easily deal with that?

    Either I am overcomplicating the problem in my head, or there are some serious holes in implementing a domain in this way.

  3. I’d like to drill a bit further because all this seems also a bit fuzzy to me.
    I think we should try to find what could be those different context.

    In my current case, contracts can be created and persisted. The can go through partial/invalid states before being activated. So there is a persistence validation (that is mainly data integrity) and activation validition.
    The activation validation is here to enable the activation action. Is this a context or simply a ‘can do this’ specification ?
    It’s true that I don’t want to get a not activated contract in the code that use activated contracts, but I have an Activated property for that… so no need to revalidate.

    The problem is then, what happens when modifiying an activated contract ?
    I surely should spilt edition state from activated state and make transactionnal valid changes to activated state.

    When thinking about contexts, what do you foresee ?

  4. use something like

    static void Validate<TEntity>(TEntity ent){
    var validators = IoC.Resolve<IEnumerable<IValidator<TEntity>>();
    var results = validators.v => v.Validate(ent));
    var failedResults = results.Where(r => r.Failed);
    if (failedResults.Any()) throw new ValidationException(results);
    }}

    you’d have to add and remove validators from ioc in other classes (when the state changes). i.e. in the example of the web app vs batch process, you’d register extra validators for the web app

  5. A Domain Object should always be valid for its particular context. You can either use one Domain Object for multiple contexts, use a Domain Object per context pattern, and/or blend in data structures (e.g., dto’s). Policies (strategies) can then be plugged-in for a particular context to validate instantiation of instances (in a factory perhaps), and whenever attempting to change the state or associations of an instance.

    Factoring the domain model to raise concepts that are usually defined as simple primitive types (e.g. Postal Code) to first class status can help also. The policies that are developed for the primitive types can be reused in other layers if necessary (and different layers also present additional contexts).

  6. I have been playing with the idea of just have a policy that contains the validation logic needed and then have the entity depend on abstraction of this policy. This way I can use the contextual resolution of containers to create the entity in the correct context with the right validation in place.

  7. I took the approach of having my context knowing the rules for object validation. In fact, I abstracted all of my validation code into its own namespace and I simple pass it the list of rules to validate along with the list of items.

    If the application contexts’ rules were all going to be the same, then I could store this list of rules somewhere else to pass along for each context; however, the context still makes the decision.

    Here’s a sample… anyone see anything wrong with this?

    Here’s the "Rule" class:

    public class Rule
    {
    public Expression<Func<bool>> Expression { get; set; }
    public string ErrorMessage { get; set; }
    }

    And the validator:

    public RuleViolationCollection Validate<T>(T item, IList<Rule> rules)
    {
    var violations = new RuleViolationCollection();

    foreach (var rule in rules)
    {
    var expression = rule.Expression.Compile();
    var passed = expression.Invoke();
    if (!passed)
    {
    violations.Add(new RuleViolation{ErrorMessage = rule.ErrorMessage});
    }
    }

    return violations;
    }

  8. @Brian Yeah, that is a very similar approach to what we are taking now with the Rule class and using delegates to store rules that will later be run on the entities. Where are you running the rules against your entities though?

    I was also wondering, why are you using Expression<Func<T>> instead of just using Func<T>? Are you doing any manipulation of the expression tree, or were you just leaving it open for future manipulation? It seems that this would keep you from using multi-line delegates which might make more complex rules readable.

  9. Context is bound to some sort of action.

    So when the system gets a request, I should be able to load all data needed and validate if the data is valid for the given request.

    If a user want to cancel his subscription via email, a valid email should be present. On the other hand if the user wants to cancel subscriptions via snail mail, address, city, area, country etc. must be valid.

    Just my 2 cents…

  10. @Justin,

    I’ll take your point into consideration. It is more or less a draft which I’ll expand on as I use it in more places.

    The website I created it for would probably call it from an OnValidating event from a custom form usercontrol, handled by the current page.

    In the case of adding/updating users, the rules would differ from updating a password, but I would still use the User entity for both forms as part of the EventArgs from the control.

  11. Definitely a tough call.

    On the one hand, I am tempted to suggest that entities should simply never allow themselves to become invalid, and that any entity that can be valid in one context and invalid in another is a call for the creation of Bounded Contexts, each with their own entirely distinct representation of that entity (and its BC-specific validation rules).

    On the other hand, forcing Bounded Contexts to be created risks fragmenting a system that might be suffering from a different problem, one that doesn’t need Bounded Contexts.

    Braingstorming for a moment, I suspect that in at least some of the scenarios that tend to bring up this kind of issue we really aren’t looking to validate an entity. What we’re really interested in is validating a set of _inputs_ for applicability to an entity before we attempt to apply them to it. And that, while the entity must still be either valid or invalid based on its own single set of rules given its Bounded Context (even if there is only a single assumed Bounded Context for the entire system), one could benefit from at least being able to package up bundles of oft-used pre-validation behavior that is aligned to some combination of source of input, type of input, type of mutation, or what have you.

    This suggests adopting something akin to Specification pattern. The inputs that might mutate an entity could be fed into a Specification object along with the entity itself (and whatever other contextual information might be required) and that the Specification object can then do its thing and return back (in your preferred form) information about whether or not your inputs meet the specification.

    To sum up, my temptation is to suggest this: If you are really validating inputs (and optionally their applicability in a specific situation), validate your inputs using whatever mechanism provides for the best expression and maintenance of them. Once you get to the entities, though, an entity can only be valid or invalid based on a single set of rules within any given Bounded Context. If you need another set of rules to be applied selectively, it is either a different entity within the same Bounded Context or an analogous entity in a different Bounded Context.

    Todd’s suggestion regarding policies provides a bit of wiggle room, certainly, and I’ll have to have a think about it, but off the top of my head I would be tempted to suggest that if you are changing the policy on the fly for a given entity then you are probably looking at a Bounded Context in need of establishment, or at input validation, or some other problem entirely. If the policy for a given entity is effectively invariant, however, I would concede that a policy approach might be a good way to handle those cases where creating a whole new entity and/or bounded context might be overkill.

  12. I think validation will sit in different places depending on what you’re validating. I’m a big fan of CQRS and DDD. The way I usually split my validation is as follows (p.s. Java based):

    Command: this uses JSR 303 / Assertions to validate the inputs of the command. This will ensure that every command sent to the Domain Aggregates will be valid.

    CommandHandler: this contains multi-aggregate validation (inside a Bounded Context), for example, are we trying to create a User with an ID (or email) that already exists? (this could be done via unique keys in the DB but let’s assume it’s not)

    Event Handlers: if there is a dependency between contexts then this will exist via Events and Event Handlers. The receiving Bounded Context’s event handler will make sure that it has valid information to trigger the relevant Command on the Context.

    This way all the validation is encapsulated where it belongs and where it is relevant. By looking at each component I can understand what is required for it to be valid.

Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

More Insights

View All