VO и валидация

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

VO и валидация

Сообщение delvin »

По идее 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
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

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

Сообщение zelenin »

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

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

Бизнес валидация - это валидация на основе бизнес-правил вашего домена. Например емейл должен быть уникальным и принадлежать зоне ru. Эта валидация не относится конкретно к VO и должна быть снаружи.
anton_z
Сообщения: 483
Зарегистрирован: 2017.01.15, 15:01

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

Сообщение anton_z »

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 рекомендуют делать как классы.
Аватара пользователя
yiijeka
Сообщения: 3103
Зарегистрирован: 2012.01.28, 09:14
Откуда: Беларусь
Контактная информация:

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

Сообщение yiijeka »

Просветление будет заключаться в том, что очень накладно на каждый чих делать VO ;)

Обычно использую VO, когда необходимо для атрибута сущности следующее API:
- перевод атрибута с одним значеним к другомуб
- сравнение значения атрибута с другими подобными значениями. Что больше, что меньше.

Очень удачный, всем известный пример - Деньги VO
https://github.com/githubjeka/value-obj ... ittle-more

Можно сравнить что больше, на определёный момент времени: 100 рублей или 3 доллара.
Можно перевести 100 долларов в доллары по определённому курсу.

Из практики, часто приходится иметь дела с единицами измерения СИ различных величин. Тут VO очень выручает.

По поводу изначального вопроса: По своему опыту скажу, что ничего плохого в валидации с выбросом исключений при установке VO не замечено. Валидация может быть выполнена с помощью стороннего инструментария(https://github.com/beberlei/assert) или с помощью Yii2 валидации.
Ответить