4

Since I got into learning about MVC I have always validated my form data in my controllers which is a habit I picked up while skimming through CodeIgniters code but I have learned that its way of doing certain operations is not the best, it just gets the job done.

Should all form data be validated by the domain objects? And if so should it be done in the setters like so

public function setFirstName($firstName) {

    // Check if the field was required
    if(!$firstName) {
        throw new InvalidArgumentException('The "First name" field is required');
    }

    // Check the length of the data
    // Check the format 
    // Etc etc
}

Also, for example, if I am handling a basic user registration my User class does not have a $confirmPassword property so I would not be doing

$user->setConfirmPassword($confirmPassword);.

One way of checking if the two passwords entered are equal would be to set the $password and do something like

$user->setPassword($password);
if(!$user->matchPassword($confirmPassword)) {
    throw new PasswordsNotEqualException('Some message');
}

and this would be done in the Service layer I would think?

Any advice to help me in the correct direction would be great. Thanks.

ibanore
  • 1,500
  • 1
  • 12
  • 25
  • I think Rails and Django do it on the model level, of that helps. – Waleed Khan Feb 23 '13 at 13:23
  • Do they do it the way I am doing it above? By doing it in the properties setters and throwing exceptions? – ibanore Feb 23 '13 at 13:26
  • 1
    @WaleedKhan , neither of which even implement MVC. They do not even have model layer. Only a collection of active record instances. – tereško Feb 23 '13 at 15:09
  • @tereško am I doing it correctly by doing the validation in the setters? and if so, am I checking if the "Password" and "Confirm password" fields are equal the correct way? – ibanore Feb 23 '13 at 15:17

2 Answers2

3

Should all form data be validated by the domain objects? And if so should it be done in the setters like so

IMO you should only let creation of valid objects, and the best way to archieve this is to make those checks in the method that creates an object.

Assuming that the first name of an user cannot be changed, you would validate that upon the user creation. This way, you forget about the setter because you won't need it anymore.

There may be cases when you want a property to be changed, and you would need to validate them too (because that change could lead form a valid object to an invalid object, if that's the case).

One way of checking if the two passwords entered are equal would be to set the $password and do something like...

You can handle this one the same way: have a Password object that checks both the password and confirmation upon its creation. One you have a valid Password instance, you can use it knowing that it passed all the validations you specified.

References

Those design principles (complete and valid objects from the start, etc) are from Hernan Wilkinson's "Design Principles Behind Patagonia".Be sure to check the ESUG 2010 Video and the presentation slides.

I've recently answered another question about validating properties I think you may come in handy: https://stackoverflow.com/a/14867390/146124

Cheers!

Community
  • 1
  • 1
nick2083
  • 1,953
  • 13
  • 16
  • -1: your "solution" advocates one of three things, as it is now written: either validation in the constructor or validation in factory method, or validation outside of domain object. And, if it is one of first two: then it is harmful practice. If latter, then it is not a domain object anymore. – tereško May 21 '14 at 05:09
3

TL;DR

No, setters should not be validating the data. And nick2083 is completely wrong.

Longer version ...

According to Tim Howard's provided definition [source], the domain objects can verify the state of domain information that they contain. This basically states, that for you to actually have a domain object, said object need to be able to validate itself.

When to validate

You basically have to options:

  • validate in each setter
  • have one method to validate whole object

If the validation is a part of setter, there is one major drawback: the order of setters matters.

Example: lets say you are making an application which deals with life insurance. It is quite probable, that you will have a domain object which contains the person that is insured and the person that gets awarded the premium, when policy is triggered (the insured on dies). You would have to make sure that the recipient and the insured are not the same person. But there is no rule to govern in which order you execute the setters.

When you have two or more parameters in domain object, which have to be validated against each-other, the implementation becomes a bit fuzzy. The most feasible solution is to check when all parameters are assigned, but at that point you have already lost the benefit of in-setter validation: the execution of code has moved past the origin of invalid data.

And how would you deal with situations, where the valid state of domain object is not having a parameter A set if parameter B is large then 21 and C is already set?

Conclusion: validation in setters is only the viable solution, when you have very simple domain objects, with no tangled validation rules.

tereško
  • 58,060
  • 25
  • 98
  • 150
  • Also .. what is this obsession with throwing exception that you have? – tereško Feb 23 '13 at 17:41
  • 6
    you said "setters should not be validating the data" at the top of your post, then you said I have two validation options one of which is "validation in each setter" and then at the bottom said "validation in setters is only the viable solution". And on this post from today http://stackoverflow.com/questions/15050497/ you said "Data validation on setters fails, when you have multiple bound parameters." You seem to be saying different things all the time no wonder I am so confused. – ibanore Feb 24 '13 at 11:55
  • 2
    @David , did you (and 4 others) also read the rest of the sentence?: *"validation in setters is only the viable solution, **when you have very simple domain objects**, with no tangled validation rules."* Did the sentence come across somehow flawed? It says that: "The only case, when it is not completely retarded to use setter validation, is when you have domain objects with no tangled validation rules." Basically - it talks about glorified value objects. – tereško May 21 '14 at 05:12