VO и валидация

Обсуждаем, как правильно строить приложения
Ответить
Аватара пользователя
delvin
Сообщения: 83
Зарегистрирован: 2009.11.13, 15:29

VO и валидация

Сообщение delvin » 2018.04.25, 15:31

По идее VO - это тупой класс для хранения определенного значения. И знать ничего о других объектах не должен.
Но хочется что бы в нем еще и валидация хранимого значения происходила.
На сколько корректно с точки зрения архитектуры прокидывать валидатор в контсрукторе VO?
Так:

Код: Выделить всё

class SomeVO
{
    public function __construct(string $value, callable $validator)
    {
        $validator($value);
    }
}

class SomeValidator
{
    public static function validate ($value) : void
    {
        if ($value !== 'test') {
            throw new InvalidArgumentException('Invalid value.');
        }
    }
}

$vo1 = new SomeVO('test', 'SomeValidator::validate');
$vo2 = new SomeVO('test', function ($value){
    if ($value !== 'test') {
        throw new InvalidArgumentException('Invalid value');
    }
});
или так:

Код: Выделить всё

interface VOValidator {
    public function validate($value) : bool;
}

class TestValidator implements VOValidator
{
    public function validate($value) : bool
    {
        return ($value === 'test');
    }
}

class SomeVO
{
    public function __construct(string $value, VOValidator $validator)
    {
        if (!$validator->validate($value)) {
            throw new InvalidArgumentException('Invalid value');
        }
    }
}

$vo1 = new SomeVO('test', new TestValidator);
$vo2 = new SomeVO('test1', new TestValidator);

zelenin
Сообщения: 10492
Зарегистрирован: 2013.04.20, 11:30

Re: VO и валидация

Сообщение zelenin » 2018.04.25, 17:18

давайте разделим валидацию на бизнес-валидацию и валидацию типа.

Валидация типа - это базовая валидация. Email VO должен быть строкой, емейлом, с определенным набором символов. Эта валидация может быть в конструкторе и отдельный валидатор для этого не нужен. Возможен, но зачем усложнять?

Бизнес валидация - это валидация на основе бизнес-правил вашего домена. Например емейл должен быть уникальным и принадлежать зоне ru. Эта валидация не относится конкретно к VO и должна быть снаружи.

anton_z
Сообщения: 336
Зарегистрирован: 2017.01.15, 15:01

Re: VO и валидация

Сообщение anton_z » 2018.04.26, 13:01

zelenin писал(а):
2018.04.25, 17:18
Бизнес валидация - это валидация на основе бизнес-правил вашего домена. Например емейл должен быть уникальным и принадлежать зоне ru. Эта валидация не относится конкретно к VO и должна быть снаружи.
Смотря какой VO сделать.

Код: Выделить всё


class UniqueRuEmail

А где именно снаружи, в сервисах что-ли?

Код: Выделить всё


class SomeVO
{
    public function __construct(string $value, callable $validator)
    {
        $validator($value);
    }
}

Прокидывать callable в конструктор, по мне как-то слишком гибко и надо знать детали реализации класса - то бишь чего хотят от колбека, что туда будет передано, что должен вернуть, какие исключения может кинуть - все это будет неявно. А неявность это не очень хорошо.

Оффтоп. По теме VO могу такую вещь сказать. В книгах из 90-х, когда ООАП только набирало популярность встречается такая дилемма - как смоделировать какое-либо понятие из предметной области - в виде отдельного типа(класса) или атрибута элементарного типа. И для нее было очевидное правило - если это понятие не является строкой или числом, тогда класс, если нет, элементарный атрибут)))
Не знаю, почему сейчас многие так перестали делать - плодите, дескать VO на каждый чих и достигнете просветления))) Даже статусы и ID рекомендуют делать как классы.

Ответить