johnnietheblack
johnnietheblack

Reputation: 13310

Validate a domain entity upon setting each property, or all at once later?

When validating a domain entity, is it better to validate the values as they are set, or all at once with a validator (such as in Symfony2) later on?

For example:

Option 1. Validate while being set

public function setEmail($email)
{
    if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        throw new EntityException('The specified email address ' . $email . ' is invalid.');
    }

    $this->_email = $email;
    return $this;
}

Option 2. Validate later...

$user = new UserEntity();
$user->setEmail('[email protected]');
$validator = new Validator();
$validator->validate($user);

Option 3. Both of the above (although seems a little redundant and not worth the overhead).

I know that the first one probably makes for more airtight entities, but the second one makes for more user friendly error handling.

Also, the second option seems easier to configure and maintain...as I don't have to adjust the setters, and I can centralize my validation logic to a single class.

What it boils down to...
So basically, it sounds like Option 2 is what I WANT to do, but feel like sacrificing the airtight-ness of the entity (for example, if I forget to run the entity through the validator), might be stupid.

Upvotes: 2

Views: 1022

Answers (2)

Keyne Viana
Keyne Viana

Reputation: 6202

Single Responsibility Principle

The best is to have all necessary validations in a separated layer. With that will be easier to maintain and test the validators. Also easier to validate data across your application.

Don't Repeat Yourself

You don't have to call validate() for each entity.

All you have to do is to implement the validation on your repository layer or service layer if you have one.

$user = new User();
// [...]
$user->setEmail('myinvalidemail#blah,com');
$repository->save($user);

So in your user's repository

UserRepository extends AbstractRepository {}

And the common validation for all entities:

abstract class AbstractRepository {
    public function save($entity) {
        $validator = // Get your validator based on the entity's name or something else
        $validator->validate($entity); // Throws exceptions or flag the  fields for future use

         // Now save it...
    }
}

Upvotes: 1

user212218
user212218

Reputation:

There are doubtless going to be situations where validation is unnecessary at the application level (i.e., you know you are working with valid data at a particular point). Although there's nothing wrong with applying validation in these cases, it's certainly superfluous.

In addition, you might find yourself in a scenario where you want to perform a "mass validation" of incoming data. This would likely apply more to a service or to custom-implemented forms where you don't have e.g., Symfony's form validation framework to fall back on.

These would tend to indicate that Option 2 is the more desirable way to go, perhaps with caveat that the validator should be invoked automatically when attempting to persist the object (e.g., during the model's pre-save event; I'm not familiar with Doctrine 2 yet, but Doctrine 1.2 does have its own validation framework that can accomplish this).

Having invalid data is surely never a desirable scenario, but so long as you can be assured that invalid data are not persisted, this gives you the freedom to trust that any data you pull from the database are valid (note that I say "valid" here, not "trustworthy"!).

Upvotes: 2

Related Questions