// codeart.ru / Офтопик / Про валидацию Форум

Про валидацию rss подписка

Автор: Evgeniy Sergeev

Вчера сходил на встречу клуба «Вышиби мозг», послушал доклад на тему «Валидация в Ruby on Rails». Я и раньше не был сторонником Рельсов, а теперь у меня появился еще один повод их не любить. Все потому, что я не согласен с двумя соглашениями этого фреймворка:

1. Код валидируется в модели;

2. Модель должна быть ActiveRecord, иначе валидацию необходимо реализовывать самостоятельно.

На мой взгляд правильнее использовать такие соглашения:

1. Код валидируется в одном классе (месте);
2. Правила валидации определяются по имени параметра и едины для всего проекта;
3. В модель передаются только валидные данные;

На практике данные требования реализуются довольно просто — создается класс ValidDataObject в котором прописываются правила валидаци (не буду приводить содержимое класса, так как его реализация очевидна). Тогда метод контролера выглядит следующим образом:

Public function action_index () {
$u = new Model_User( new ValidDataObject($_POST) );
}

Примечание. Для обработки ошибок валидации нужно использовать исключения. Тогда в коде выше добавится еще try/catch.

Преимущества такого подхода:
1. Облегчается повторное использование правил валидации, да и самих моделей;
2. Все ограничения (параметры валидации) собраны в одном месте и нигде не дублируются (отсюда — их легко править);
3. Задавать ограничения можно когда угодно, не опасаясь пропустить какую-то модель.(лично я никогда не делаю валидацию сразу после создания модели, жду когда модель будет окончательно готова).

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

  1. По-моему всё немного не так:
    1. Повторное использование модели в вашем случае усложняется, добавляется бессмысленный копипейст кода контроллера, если надо работать с моделью в нескольких местах. Тем более, один набор правил вы вряд-ли примените к двум разным моделям.
    2. В модели они также собраны и не дублируются.
    3. Дело привычки.

    Кстати, не уверен, что требуется именно AR. В Yii, который в какой-то степени ориентировался на рельсы, валидация вынесена в CModel, от которого уже наследуется CActiveRecord.

  2. 2. Модель должна быть ActiveRecord, иначе валидацию необходимо реализовывать самостоятельно.
    А вот нихрена подобного. В Rails3 можно подмешать валидацию вообще в любой объект! И этот объект не обязательно должен сохраняться в БД. Например, валидацию можно подмешать в класс Message, который отвечает за отправку сообщений на почту.

  3. Вот, кстати, мои мысли про валидацию: http://torqueo.net/why-zend-form-validation-is-bad-or-how-to-do-proper-validation/
    Там еще много людей в комментах высказалось.

  4. Sam Dark,
    1. по-моему код контролера будет копипаститься в любом случае. Так как инициализировать модель нужно в любом случае.
    2. В модели собраны толкько часть правил относящихся к данным модели. Чтобы увидеть общую картину придется просматривать все модели.
    3. Никогда нельзя быть уверенным в том что одни и те же данные одинаково валидируется в разных моделях.
    4. Валидация в модели так же нарушает принцип персональной ответственности

  5. Evgeny Sergeev,
    1. То инициализировать, а то ещё и вызов валидации копипейстить.
    2. Т.е. вы хотите запихать в один класс-валидатор правила для вообще всех моделей? Если нет, то видение общей картины как раз ухудшится. Да и вообще, работа обычно идёт с одной моделью (при добавлении и редактировании), так что на правила в остальных можно не смотреть.
    3. Ну так я и предлагаю в разных моделях писать разные правила.
    4. Что это за принцип такой?

  6. Sam Dark,

    1. а какая разница передать в модель «$params» или «new DataValidation($params)?
    2. Да, я хочу запихать в класс-валидатор правила валидации всех данных проекта. А объект (модель) обязать в качестве данных принимать только объекты реализующие интерфейс DataValidator.
    3. Т.е. в одной модели длина пароля должна быть от 8-10 символов, в другой от 6-8 и это нормально на Ваш взгляд? (пример притянут за уши, но реальный пример тоже можно придумать)
    4. Принцип персональной ответственности (Single Responsibility Principle) – класс обладает только 1 ответственностью, поэтому существует только 1 причина, приводящая к его изменению.

    Валдиация данных — 1-ая задача;
    Сохранение, загрузка данных — 2-ая задача.

Leave a Reply

« »