3

I am designing library which is supposed to help me with designing domains in future projects. I made some basic Value Objects like EmailAddress or PhoneNumber. Those are easy. It starts to get problematic for me when such Value Object may have different ruleset that say if it is valid or not.

Lets use Password as example here since it is actual reason of me writing this question. In previous projects I had password rulesets validated in Password construtor. But it makes this implementation project specific, and violates - I think - concern separation principle.

I was thinking of Strategy Patten as solution here. But construction such VO in this way: new Password("123456", new AwfullyLoosePasswordValidationStrategy()) sounds terrible to me. I was also thinking of static setter in VO setValidationStrategy(PasswordValidationStrategy strategy), but this still is against concern separation and sounds really odd to me.

So the first part of response is - I think - that Password should do only basic sanity check like isNullOrEmptyString and nothing more. But when I should do proper validation? During entity creation? Before persisting somewhere in service layer? Entity idea sounds not that bad for me, but how setPassword(Password password) would know about strategy I want to use? I try to avoid singletons in my projects and almost everything is done via DI there.

tl;dr: Where should I validate Value Object that cannot be validated in its constructor?

Mateusz
  • 418
  • 3
  • 17
  • 2
    Well, I would suggest to validate before you create your entity. It is easier to not create something that contains wrong content (versus allowing to create it; and then to handle the special case that you now have to deal with it). You might also consider to validate twice (for example directly in some web page - you could know right there when the provided password is not valid; of course that can lead to code duplication). – GhostCat Mar 16 '16 at 23:47

3 Answers3

2

Where should I validate Value Object that cannot be validated in its constructor?

I don't believe you have such a thing. You should never be creating invalid value objects. The constructor (substitute factory or factory method if you prefer) validates the arguments, and if they are acceptable creates a well formed, immutable, value object then you are done.

I was thinking of Strategy Patten as solution here. But construction such VO in this way: new Password("123456", new AwfullyLoosePasswordValidationStrategy()) sounds terrible to me.

I don't know of any cases where the strategy pattern makes sense in a value object. It seems much more likely that if a query of a value type needed a strategy, you would pass the strategy as a parameter on the query, rather than making it inherent on the type.

That said, it seems to me that you have gotten really close to the right idea here; you are just backwards

PasswordValidator validator = new AwfullyLoosePasswordValidator();
Password password = validator.createPassword("123456");

Which is to say, the factory validates the input against your policy, and if it is acceptable then it passes that input along to the Password constructor (which performs its own checks as well).

Alternatively, you could implement your password policy as part of the entity creation, rather than part of the password creation

class EntityFactory {
    private final PassswordValidator passwordValidator;

    Entity create(Password password) {
        passwordValidator.check(password);
        return new Entity(password);
    }

Entity idea sounds not that bad for me, but how setPassword(Password password) would know about strategy I want to use?

Now that is a super important question, and one you should dig into very carefully.

Because if you look at the requirements carefully, you may well discover that the setPassword() method doesn't live in the obvious place.

If you model password as a property of your entity, then the entity would also need to know about the password policy, and how is it supposed to know that? Does changing the password policy require changing every entity? can you have two entities that have different password policies, etc.

Alternatively, there might be an aggregate in your system that owns the password policy. In which case, that aggregate might also be responsible for all of the passwords (all within the scope of that policy, anyway). That is, instead of password being a property of the entity, it might really be a value in a dictionary, where you use the entityId to look it up.

Digging around in your ubiquitous language and reviewing the requirements with your domain experts is the point of . Don't be shy about making sure you have a thorough understanding of your domain.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
0

You can use the Builder pattern for complex object creation.

public class Password{ private String password;

private Password(String password){

}


public static class Builder{
    private String password;
    private Validation validation;

    public Builder(){
    }

    public Builder setPassword(String password){
        this.password = password;
    }

    public Builder setValidation(Validation validation){
        this.validation = validation;
    }

    public Password build(){
        if (null == validation){
             return null;
        }
        if (validation.validate(password)){
             return new Password(password);
        }
        else{
             return null;
        }
    }
}
}

You can then use it as

Password password = new Password.Builder().setPassword("123456")
                                          .setValidation( new AwfullyLoosePasswordValidationStrategy())
                                          .build();
Radu Ionescu
  • 3,462
  • 5
  • 24
  • 43
0

Your question doesn't really sound like you're trying to go the DDD way, but you tagged your question with the DDD tag - so I'll assume you want a DDD answer :-) .

First, don't put complex validation in VOs. It will make them hard to use. VOs are an inherently simple concept, so try to keep it that way. Especially adding references to services (like the strategy you suggested) is usually a bad idea.

Where to put value object validation

As a consequence, you should only validate the most basic stuff like null checks in the VO. A regex check is already too much IMHO, but I'm sure there are different opinions about this.

Now that you don't have validation logic in VOs, you need to be prepared to see invalid VOs. Your domain model should validate VOs as soon as they enter the domain, e.g. in a method of an entity that takes the VO as parameter.

Making validation logic reusable

If you put VO validation logic in entity methods, you will soon have the case that you want to validate the same VO from another entity method. The best approach to handle this is the specification pattern.

This answer provides a description of the pattern. The nice thing about specifications is that they are reusable and composable, e.g. to make a bigger spec out of a few smaller ones. Also, they tend to document how validation works for a specific VO really well, and they can have dependencies to services.

For your specific case with different password policies, you could then just implement a bunch of different specifications, one spec per policy. And you can combine the simpler ones to make more complex ones.

Community
  • 1
  • 1
theDmi
  • 17,546
  • 6
  • 71
  • 138
  • Perhaps it didn't sound like one but that's what I wanted to achieve! Probably I also couldn't articulate it to google :) – Mateusz Mar 17 '16 at 10:05