6

I have just read the following blog entry: Validation and DDD By Vladimir Khorikov.

The blog talks about using the following patterns for validating an entity object:

  1. IsValid method
  2. Check validity in application services layer
  3. TryExecute pattern
  4. Execute/CanExecute pattern

Please see the code below:

public Person(AbstractValidator<Applicant> validator, IRulesOfferCalculator rulesOfferCalculator, int iD,
            string name, DateTime dateOfBirth, string Address)
        {
            _iD = iD;
            _name = name;
            _dateOfBirth = dateOfBirth;
            _Address = Address;
            _validator = validator;
            _rulesOfferCalculator = rulesOfferCalculator;
            _validator.ValidateAndThrow(this);
        }

Note that the validation is done inside the constructor here. Why is this not an option? Is this an anti pattern?

Please note that I am asking specifically in the context of a rich domain model. I am using Fluent Validation rather than attributes.

Greenonline
  • 145
  • 2
  • 2
  • 11
w0051977
  • 7,031
  • 6
  • 59
  • 87
  • For one the object might be altered after being instantiated, and may as such no longer be valid. Entity validation might also be more complex than just the validations you'd want when you instantiate an entity. Just some ideas off the top of my head. – Robzor Jun 27 '17 at 11:46

1 Answers1

7

Is this an anti pattern?

I see two anti-patterns here

  1. passing around references to objects before their initialization is complete is a bad idea.
  2. using an abstract validator to do the checking suggests that you aren't respecting the principal of cohesion.

More generally, I think there's a bit of confusion in Khorikov's essay: we don't validate entities, we validate state. The entity is just an identity progressing from one state to the next.

enter image description here

For more on this point, see Stuart Halloway's 2011 talk.

The state that you are validating is a value object, in Evans's language.

Throwing an ArgumentException in the constructor when the state you've been given doesn't satisfy your invariant is a perfectly reasonable thing to do.

But I still wouldn't inject a validator to do the state checking -- that sounds as though we are treating the entity as a dumb bag of state, with all of the state living elsewhere. Compare with Martin Fowler's discussion of anemic domain models, and you'll see what I mean.

Would you suggest something like: Execute / CanExecute pattern for the validation?

I'm not a fan; but the reasoning is a bit complicated.

public IReadOnlyList<string> CanDeliver(string address, DateTime time)

So the first thing to notice is that this is a query, which means it should be safe; it doesn't induce a mutation in the entity.

What distinguishes this query from being a full function is the current state of the entity. That is to say, CanDeliver is partial application, with an implicit variable bound to the current (immutable) state. So let's make that binding explicit:

public IReadOnlyList<string> CanDeliver(Order.State currentState, string address, DateTime time)

Notice that the entity now goes away -- that is, the law of Demeter is telling us that CanDeliver belongs on the state, not on the entity.

If that's the case, then you can call State.CanDeliver any time you like, in the controller, or even in the client when composing the request. But as David Arno points out, you still have the race, which is why Khorikov still needs the check.

I have also injected RulesOfferCalculator into this class. What do you think of that?

Injecting domain behaviors into an entity is weird, and my guess probably wrong in most cases.

Review the definition of SERVICE in Domain Driven Design

  1. The operation relates to a domain concept that is not a natural part of an ENTITY or VALUE OBJECT
  2. The interface is defined in terms of other elements of the domain model
  3. The operation is stateless

In common cases, a domain service is passed to an entity as an argument, rather than embedded within the entity as though it were a piece of state.

VoiceOfUnreason
  • 32,131
  • 2
  • 42
  • 79
  • 1
    Please see this webpage: http://enterprisecraftsmanship.com/2016/09/13/validation-and-ddd/. Would you suggest something like: Execute / CanExecute pattern for the validation? – w0051977 Jun 27 '17 at 13:18
  • I have also injected RulesOfferCalculator into this class. What do you think of that? I believe it follows the open close principle. – w0051977 Jun 27 '17 at 13:19
  • 1
    "*Would you suggest something like: Execute / CanExecute pattern for the validation?*". No! Non-atomic "test then set" operations like this are an anti-pattern as, unless you have exactly one copy of the application, operating on a single thread, then the state can change between the "test" and the "set". So use either an "execute and throw" pattern or a "try execute" pattern that returns success or the error result. – David Arno Jun 27 '17 at 15:19
  • @David Arno, thanks. The author of the article states that: TryExecute is problematic because it breaks the CQS principle. Do you not agree? Also do you mean return the word: "success" as a string? – w0051977 Jun 29 '17 at 12:52
  • @w0051977, it probably won't surprise you to discover that I have as little time for CQS as for RDM. CQS creates unnecessary complexity and is generally a nightmare in multi-threaded situations. I prefer my commands to return a success or an error result. – David Arno Jun 29 '17 at 16:10
  • By "return a success", I definitely don't mean return the string "success". In C#, there are multiple options: use `null` to indicate success (horrible in my view though), return a `bool` success/failure and use `out` to return the error if there is one (also horrible), return a tuple, eg `(bool success, T error)`. My personal favourite though is to copy functional languages and return a union of `true` or an error result, eg as offered by [`Success`](https://github.com/DavidArno/SuccincT/wiki/Success_T_) in my own Succinc library. – David Arno Jun 29 '17 at 16:13
  • @David Arno, could you explain/post a link to the execute/throw pattern? – w0051977 Oct 14 '17 at 15:10