Опять валидация данных
От: Козьма Прутков Россия  
Дата: 14.03.05 08:55
Оценка:
Друзья, объясните бестолковому, как правильно производить валидацию с учетом того, что используется Domain Model или хотя бы Table Module. В поиск просьба носом не тыкать: там я уже все почитал, что нашел.
Проблема: есть пользовательский ввод. Этот ввод нужно валидировать, причем не только на форматы и длины строк (это-то примитивно и нормально решается UI) но и диапазоны (в процедуре проверки которых может участвовать множество объектов), и валидные переходы (например, состояний объекта) и т.д. Понятное дело, требуется гибкость на том уровне, что пользователю по его команде сразу показать все его ошибки (естественно, если проверки определены; так например не стоит же говорить о несоблюдении диапазонов если формат данных неверный), с другой стороны — крайне разумно выглядит отсутствие дублирования кода (ведь объект домена, по идее, не должен позволять перевести себя в некорректное состояние, то есть уже в UI без дублирования не вынесешь).
Если не жалко, поделитесь идеями, как организовать подобную функциональность, либо ткните пальчиком в книжку, где доходчиво написано.

Заранее спасибо.
Да хранит вас господь в сухом прохладном месте...
Re: Опять валидация данных
От: AlexandrV  
Дата: 14.03.05 09:05
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

КП>Друзья, объясните бестолковому, как правильно производить валидацию с учетом того, что используется Domain Model или хотя бы Table Module. В поиск просьба носом не тыкать: там я уже все почитал, что нашел.

КП>Проблема: есть пользовательский ввод. Этот ввод нужно валидировать, причем не только на форматы и длины строк (это-то примитивно и нормально решается UI) но и диапазоны (в процедуре проверки которых может участвовать множество объектов), и валидные переходы (например, состояний объекта) и т.д. Понятное дело, требуется гибкость на том уровне, что пользователю по его команде сразу показать все его ошибки (естественно, если проверки определены; так например не стоит же говорить о несоблюдении диапазонов если формат данных неверный), с другой стороны — крайне разумно выглядит отсутствие дублирования кода (ведь объект домена, по идее, не должен позволять перевести себя в некорректное состояние, то есть уже в UI без дублирования не вынесешь).
КП>Если не жалко, поделитесь идеями, как организовать подобную функциональность, либо ткните пальчиком в книжку, где доходчиво написано.

КП>Заранее спасибо.


В моем инструменте генерации кода (http://www.rsdn.ru/forum/?mid=1057392
Автор: AlexandrV
Дата: 05.03.05
), формируется примерно такой код на уровне UI:


        protected virtual string Category_IsValidate()
        {
            string strResult = "";
            if (textboxCategory.Text == "")
            {
                strResult = "Поле не может быть пустым!";
                return strResult;
            }
            return strResult;
        }
        private void textboxCategory_Validating(object sender, CancelEventArgs e)
        {
            string rez = Category_IsValidate();
            if (rez != "")
            {
                this.objErrorProvider.SetError(textboxCategory, rez);
            }
            else
            {
                this.objErrorProvider.SetError(textboxCategory, "");
            }
        }


такой код генерится для каждого контрола на форме (плюс если поле не стринговое то проверяется возможность парсинга, например Int32.Parse (...) ).

При закрытии формы есть также общая проверка, выглядит примерно так:

protected override void FormClosing(System.ComponentModel.CancelEventArgs e)
{
try
{
if (blnNeedValidate)
{

string strCategory = Category_IsValidate();
if (strCategory != "")
{
e.Cancel = true;
System.Windows.Forms.MessageBox.Show(strCategory, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return;
}
}
}
finally
{
base.FormClosing(e);
}
}
Re[2]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 14.03.05 09:24
Оценка:
Здравствуйте, AlexandrV, Вы писали:

AV>В моем инструменте генерации кода (http://www.rsdn.ru/forum/?mid=1057392
Автор: AlexandrV
Дата: 05.03.05
), формируется примерно такой код на уровне UI:


AV>
AV>        protected virtual string Category_IsValidate()
AV>        {
AV>            string strResult = "";
AV>            if (textboxCategory.Text == "")
AV>            {
AV>                strResult = "Поле не может быть пустым!";
AV>                return strResult; //это, по моему, лишнее: даже если проверок несколько, проще воспользоваться else if(...)
AV>            }
AV>            return strResult;
AV>        }
AV>        private void textboxCategory_Validating(object sender, CancelEventArgs e)
AV>        {
AV>            string rez = Category_IsValidate();
AV>            if (rez != "")
AV>            {
AV>                this.objErrorProvider.SetError(textboxCategory, rez);
AV>            }
AV>            else
AV>            {
AV>                this.objErrorProvider.SetError(textboxCategory, "");
AV>            }
AV>        }

AV>


AV>такой код генерится для каждого контрола на форме (плюс если поле не стринговое то проверяется возможность парсинга, например Int32.Parse (...) ).


Да, верно, это форматы, обязательность и т.д., то есть простые первичные проверки (ну, обязательность, кстати, может быть и не простой, например, зависеть от статуса некоторого объекта и выполняемой команды пользователя). А как быть с диапазонами, валидация которых происходит по некоторым правилам, которые могут и измениться (не переписывать же их во всех местах реализации, в самом деле)?
Да хранит вас господь в сухом прохладном месте...
Re[3]: Опять валидация данных
От: AlexandrV  
Дата: 14.03.05 09:34
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

КП>Здравствуйте, AlexandrV, Вы писали:


AV>>В моем инструменте генерации кода (http://www.rsdn.ru/forum/?mid=1057392
Автор: AlexandrV
Дата: 05.03.05
), формируется примерно такой код на уровне UI:


AV>>[c#]

AV>> protected virtual string Category_IsValidate()
AV>> {
AV>> string strResult = "";
AV>> if (textboxCategory.Text == "")
AV>> {
AV>> strResult = "Поле не может быть пустым!";
AV>> return strResult; //это, по моему, лишнее: даже если проверок несколько, проще воспользоваться else if(...)
AV>> }
AV>> return strResult;
AV>> }

Да, проверок может быть несколько, а if .. else — имхо, смотрится еще хуже, чем два подряд return; да и, честно говоря, приведенный алгоритм легче генерировать, чем то, что предлагаете вы.

<skipped>

КП>Да, верно, это форматы, обязательность и т.д., то есть простые первичные проверки (ну, обязательность, кстати, может быть и не простой, например, зависеть от статуса некоторого объекта и выполняемой команды пользователя). А как быть с диапазонами, валидация которых происходит по некоторым правилам, которые могут и измениться (не переписывать же их во всех местах реализации, в самом деле)?


я не очень понимаю, что вы хотите, вот ваша фраза: валидация которых происходит по некоторым правилам эти правила не поддаются алгоритмизации? или вот: А как быть с диапазонами, валидация которых происходит по некоторым правилам, которые могут и измениться (не переписывать же их во всех местах реализации, в самом деле)? можно, например, сделать некую функцию проверки для каждого аттрибута сущности, и может даже вынести ее в отдельную dll, и использовать ее во всех местах, а исправлять только в одном.
Re[4]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 14.03.05 10:10
Оценка:
Здравствуйте, AlexandrV, Вы писали:

AV>Да, проверок может быть несколько, а if .. else — имхо, смотрится еще хуже, чем два подряд return; да и, честно говоря, приведенный алгоритм легче генерировать, чем то, что предлагаете вы.


спорить не стану, благо генератор и сам писал, и не один, так что проблема знакома. Просто есть некоторое соображение "единственного return'а" — это упрощает отладку если нужно узнать, что функция возвращает, не ползая по ее телу отладчиком.

AV>я не очень понимаю, что вы хотите, вот ваша фраза: валидация которых происходит по некоторым правилам эти правила не поддаются алгоритмизации? или вот: А как быть с диапазонами, валидация которых происходит по некоторым правилам, которые могут и измениться (не переписывать же их во всех местах реализации, в самом деле)? можно, например, сделать некую функцию проверки для каждого аттрибута сущности, и может даже вынести ее в отдельную dll, и использовать ее во всех местах, а исправлять только в одном.


нет, конечно же все алгоритмизируется, иначе это было бы невозможно автоматизировать
Это уже теплее, я бы даже сказал, похоже на правду. Вот только пример бы кто-нить привел... с учетом иерархических зависимостей процедур валидации (если одна не прошла, то 5 других делать бессмысленно), достаточно большого количества объектов предметной области (ну, положим, 50), каждый из которых имеет по десятку свойств.
Да хранит вас господь в сухом прохладном месте...
Re: Опять валидация данных
От: aefimov Россия
Дата: 14.03.05 12:54
Оценка: :)
Здравствуйте, Козьма Прутков, Вы писали:

КП>Друзья, объясните бестолковому, как правильно производить валидацию с учетом того, что используется Domain Model или хотя бы Table Module. В поиск просьба носом не тыкать: там я уже все почитал, что нашел.

КП>Проблема: есть пользовательский ввод. Этот ввод нужно валидировать, причем не только на форматы и длины строк (это-то примитивно и нормально решается UI) но и диапазоны (в процедуре проверки которых может участвовать множество объектов), и валидные переходы (например, состояний объекта) и т.д. Понятное дело, требуется гибкость на том уровне, что пользователю по его команде сразу показать все его ошибки (естественно, если проверки определены; так например не стоит же говорить о несоблюдении диапазонов если формат данных неверный), с другой стороны — крайне разумно выглядит отсутствие дублирования кода (ведь объект домена, по идее, не должен позволять перевести себя в некорректное состояние, то есть уже в UI без дублирования не вынесешь).
КП>Если не жалко, поделитесь идеями, как организовать подобную функциональность, либо ткните пальчиком в книжку, где доходчиво написано.

Я уже очень давно пытаюсь понять как бы правильней это сделать и постоянно упираюсь в сложность решения. Но вот в последнее время я более менее доработал видимую картину и начал реализовывать.

Во первых, я ввел понятие элементарной частицы (элемент) и уровень (Scope) данных элементов определяет общее состояние всех элементов на уровне. Уровни объединяются в пространства и дальше оперируем с пространством как с формой для ввода данных, где элементы — это контролы этой формы. Контролы, могут находится на разных уровнях — например уровень ошибок, уровень незаполненных данных и уровень успешно заполненных контролов.

Перемещать контролы с уровня на уровень должен специальный инспектор с помощью инспекций (проверок). Можно это делать как в рантайме по таймеру, так и по нажатии на кнопку.

Рендерер, который прорисовывает форму (пространство) рисует контролы с оформлением заданным, на уровне. Ввод продолжается до тех пор, пока все контролы не перейдут на успешный уровень.

Но данное решение пока применимо для клиентов и на Web труднопереносимо в плане runtime проверки и т.д.

Спасибо!
Re[2]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 14.03.05 13:30
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Я уже очень давно пытаюсь понять как бы правильней это сделать и постоянно упираюсь в сложность решения. Но вот в последнее время я более менее доработал видимую картину и начал реализовывать.


A>Во первых, я ввел понятие элементарной частицы (элемент) и уровень (Scope) данных элементов определяет общее состояние всех элементов на уровне. Уровни объединяются в пространства и дальше оперируем с пространством как с формой для ввода данных, где элементы — это контролы этой формы. Контролы, могут находится на разных уровнях — например уровень ошибок, уровень незаполненных данных и уровень успешно заполненных контролов.


A>Перемещать контролы с уровня на уровень должен специальный инспектор с помощью инспекций (проверок). Можно это делать как в рантайме по таймеру, так и по нажатии на кнопку.


A>Рендерер, который прорисовывает форму (пространство) рисует контролы с оформлением заданным, на уровне. Ввод продолжается до тех пор, пока все контролы не перейдут на успешный уровень.


A>Но данное решение пока применимо для клиентов и на Web труднопереносимо в плане runtime проверки и т.д.


A>Спасибо!

за что?

Да, идея интересная... Она по-моему применима и для веба в случае, если инспекции — по нажатию на кнопку, точнее, по запросу (не на всякую кнопку нужно инспектировать) с реакцией на результаты инспекции. А инспекторы — это не контроллеры? Их отношение один-к-одному с формами?
Я, честно говоря, нашел недосказанность в своем вопросе: мне было интересно также рассмотреть вариант, при котором источников изменений несколько (допустим, веб-приложение и веб-сервис): ситуация гипотетическая, но понимание не помешает. А в этой ситуации все страшнее: сама бизнес-энтити (БЭ) должна знать (возможно, опосредованно), что правильно, а что нет (этакой Defensive programming). Соответственно, нужны какие-то валидаторы, которыми можно пользоваться и в самой БЭ, и в UI (ну, или иных источниках изменений для предварительной проверки корректности данных, прежде чем совать их в БЭ). То есть UI просит валидатор, уточняет у него правомерность действия, которое хочет совершить, и в случае ок уже корежит БЭ.
Да хранит вас господь в сухом прохладном месте...
Re[3]: Опять валидация данных
От: AlexandrV  
Дата: 14.03.05 13:35
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

<skipped>

гипотетическая, но понимание не помешает. А в этой ситуации все страшнее: сама бизнес-энтити (БЭ) должна знать (возможно, опосредованно), что правильно, а что нет (этакой Defensive programming). Соответственно, нужны какие-то валидаторы, которыми можно пользоваться и в самой БЭ, и в UI (ну, или иных источниках изменений для предварительной проверки корректности данных, прежде чем совать их в БЭ). То есть UI просит валидатор, уточняет у него правомерность действия, которое хочет совершить, и в случае ок уже корежит БЭ.

в UI формато зависимая валидация а в BL Логико зависимая. и UI пишет в BL без предварительного разрешения (например байндингом, если формат введенных данных правильный) а при ошибке проверки уже в BL возникает exception, который и обрабатывается.
а логическая проверка может быть реализована в set-ах get-ах свойств БЭ.
Re[4]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 14.03.05 14:00
Оценка:
Здравствуйте, AlexandrV, Вы писали:

AV>Здравствуйте, Козьма Прутков, Вы писали:


AV><skipped>


AV>в UI формато зависимая валидация а в BL Логико зависимая. и UI пишет в BL без предварительного разрешения (например байндингом, если формат введенных данных правильный) а при ошибке проверки уже в BL возникает exception, который и обрабатывается.

AV>а логическая проверка может быть реализована в set-ах get-ах свойств БЭ.

Согласен. Но:
1) Допустим, операция не простая, требует изменения состояния нескольких объектов. При этом ошибка (связанная с некорректными данными) обнаруживается где-то посередине и летит исключение: в каком состоянии находятся данные? Понятное дело в неконсистентном.
2) Обычно пользователь хочет знать полный список допущенных им ошибок. В этом сценарии это трудновато получить: ну не тыкаться же с каждым изменением в БЭ, подставив ухо с готовностью к удару и коллекционируя синяки чтобы потом их скопом показать (это наиболее актуально в вебе; так демонстрирует результаты валидация в ASP.NET). Конечно, есть смысл постулировать: мелочь мы показываем скопом, а логические ошибки — по одиночке. Но для пользователя это разделение далеко не очевидно
Да хранит вас господь в сухом прохладном месте...
Re[5]: Опять валидация данных
От: AlexandrV  
Дата: 14.03.05 14:30
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

КП>Здравствуйте, AlexandrV, Вы писали:


AV>>Здравствуйте, Козьма Прутков, Вы писали:


AV>><skipped>


AV>>в UI формато зависимая валидация а в BL Логико зависимая. и UI пишет в BL без предварительного разрешения (например байндингом, если формат введенных данных правильный) а при ошибке проверки уже в BL возникает exception, который и обрабатывается.

AV>>а логическая проверка может быть реализована в set-ах get-ах свойств БЭ.

КП>Согласен. Но:

КП>1) Допустим, операция не простая, требует изменения состояния нескольких объектов. При этом ошибка (связанная с некорректными данными) обнаруживается где-то посередине и летит исключение: в каком состоянии находятся данные? Понятное дело в неконсистентном.

делаем самое простое, что приходит в голову: откат транзакции. и вообще, кажется вы меня просто хотите запутать — может пример привели бы?

КП>2) Обычно пользователь хочет знать полный список допущенных им ошибок. В этом сценарии это трудновато получить: ну не тыкаться же с каждым изменением в БЭ, подставив ухо с готовностью к удару и коллекционируя синяки чтобы потом их скопом показать (это наиболее актуально в вебе; так демонстрирует результаты валидация в ASP.NET). Конечно, есть смысл постулировать: мелочь мы показываем скопом, а логические ошибки — по одиночке. Но для пользователя это разделение далеко не очевидно


в том варианте что я сказал, так вполне можно реализовать, а именно:
— для каждого атрибута свой метод проверки
— и плюс общий метод проверки всего объекта
Re[3]: Опять валидация данных
От: aefimov Россия
Дата: 14.03.05 14:51
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

КП>А инспекторы — это не контроллеры? Их отношение один-к-одному с формами?


Нет, это именно еще один уровень. Контроллер отвечает за получение данных и транспортировку их куда нужно.
Получить данные он может только после того, как инспектор их проверит.

Я думаю правильней на каждый редактор (форму) создавать отдельного инспектора с заданным набором инспекций. Однако это не отменяет существование одного большого с инспекциями на все случае жижни для всех форм.

КП>Я, честно говоря, нашел недосказанность в своем вопросе: мне было интересно также рассмотреть вариант, при котором источников изменений несколько (допустим, веб-приложение и веб-сервис): ситуация гипотетическая, но понимание не помешает. А в этой ситуации все страшнее: сама бизнес-энтити (БЭ) должна знать (возможно, опосредованно), что правильно, а что нет (этакой Defensive programming). Соответственно, нужны какие-то валидаторы, которыми можно пользоваться и в самой БЭ, и в UI (ну, или иных источниках изменений для предварительной проверки корректности данных, прежде чем совать их в БЭ). То есть UI просит валидатор, уточняет у него правомерность действия, которое хочет совершить, и в случае ок уже корежит БЭ.


Ясно. Я тоже сталкнулся с тем вопросом — "когда заканчивать проверки". UI уровень, бизнес уровень и т.д. Но честно говоря, я пришел к тому, что проверять нужно только то, что вводит пользователь — ему это понятней. Т.е. только уровень отпользователя и до формирования валидных данных. Все остальное, ИМХО, должно отдаваться на усмотрение базы данных. Бесконечно проверяя "правильность данных" можно заткнуться в слишком сложной логике этих проверок, многие из которых должны делаться внутри БД. Это необходимо еще и по тому, что налицие бизнес проверок в коде приведет к нестабильности всяких импортов и т.д., т.е. когда с базой назнут работать напрямую.

Поэтому, я считаю, что в коде должна быть проверка UI и все — остальное в базе + перехват этих ошибок и вывод их пользователю.
Re[6]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 14.03.05 15:33
Оценка:
Здравствуйте, AlexandrV, Вы писали:

предлагаю сразу перейти на ты: проще и привычнее.

AV>делаем самое простое, что приходит в голову: откат транзакции. и вообще, кажется вы меня просто хотите запутать — может пример привели бы?

увольте, ни малейшего желания кого-либо запутать у меня и в мыслях не было. Транзакций пока нет: все в памяти, иначе и не спрашивал бы. То есть ситуация: есть сложная БЭ (этакой класс, с кучей свойств, коллекций аналогичных сложных объектов и т.п.) Форма для редактирования. Пользователь вводит некие данные и жмет ОК. Мне требуется внести запрошенные пользователем изменения в данные БЭ (или ассоциированных с нею БЭ) и выйти либо сказать, что не так. Сохраняться в БД это будет потом, минут через 10, например, когда пользователь налазается вволю по разным ассоциированным сущностям, поправит в них данные и т.д. Реального примера нету: хочу понять концептуально. Пример даже придумать не получается, видимо, крайне нетипичная ситуация. Все, что приходят в голову, проверяются достаточно просто прежде, чем запускать каскадное изменение данных. Но что, если проверка нетривиальная?

КП>>2) Обычно пользователь хочет знать полный список допущенных им ошибок. В этом сценарии это трудновато получить: ну не тыкаться же с каждым изменением в БЭ, подставив ухо с готовностью к удару и коллекционируя синяки чтобы потом их скопом показать (это наиболее актуально в вебе; так демонстрирует результаты валидация в ASP.NET). Конечно, есть смысл постулировать: мелочь мы показываем скопом, а логические ошибки — по одиночке. Но для пользователя это разделение далеко не очевидно


AV>в том варианте что я сказал, так вполне можно реализовать, а именно:

AV>- для каждого атрибута свой метод проверки
AV>- и плюс общий метод проверки всего объекта

вот тут мне не все ясно:
1) правильно я понимаю, что на каждое свойство есть метод а-ля bool canAssignStartDate(DateTime value)?
2) это подразумевает, что вызов этого метода сообщит, находится ли объект в валидном и консистентном состоянии, верно? То есть подразумевается, что его в неконсистентное состояние можно перевести.

Да, чувствую, замучил я народ глупостями
Да хранит вас господь в сухом прохладном месте...
Re[7]: Опять валидация данных
От: AlexandrV  
Дата: 14.03.05 15:42
Оценка: 4 (1)
Здравствуйте, Козьма Прутков, Вы писали:

отвечаю по частям:

<skipped>

AV>>в том варианте что я сказал, так вполне можно реализовать, а именно:

AV>>- для каждого атрибута свой метод проверки
AV>>- и плюс общий метод проверки всего объекта

КП>вот тут мне не все ясно:

КП>1) правильно я понимаю, что на каждое свойство есть метод а-ля bool canAssignStartDate(DateTime value)?
КП>2) это подразумевает, что вызов этого метода сообщит, находится ли объект в валидном и консистентном состоянии, верно? То есть подразумевается, что его в неконсистентное состояние можно перевести.
вообще-то наверное, не совсем так, скорей так:

class C
{
public C
{
}

protected string strA = "";
public string A
{
get { return strA; }
set
{
ValidateA( value ); // здесь будет exception в случае чего не правильного
strA = value;
}
public void ValidateA()
{
// проверка value на правильность и корректность
// если не правильно и не корректно то exception
}
public void Validate()
{
ValidateA( strA );
}

}


}

КП>Да, чувствую, замучил я народ глупостями

да нет, все нормально, объясняя другому и сам лучше понимаешь.
Re[7]: Опять валидация данных
От: AlexandrV  
Дата: 14.03.05 15:45
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

КП>Здравствуйте, AlexandrV, Вы писали:


КП>предлагаю сразу перейти на ты: проще и привычнее.


AV>>делаем самое простое, что приходит в голову: откат транзакции. и вообще, кажется вы меня просто хотите запутать — может пример привели бы?

КП>увольте, ни малейшего желания кого-либо запутать у меня и в мыслях не было. Транзакций пока нет: все в памяти, иначе и не спрашивал бы. То есть ситуация: есть сложная БЭ (этакой класс, с кучей свойств, коллекций аналогичных сложных объектов и т.п.) Форма для редактирования. Пользователь вводит некие данные и жмет ОК. Мне требуется внести запрошенные пользователем изменения в данные БЭ (или ассоциированных с нею БЭ) и выйти либо сказать, что не так. Сохраняться в БД это будет потом, минут через 10, например, когда пользователь налазается вволю по разным ассоциированным сущностям, поправит в них данные и т.д. Реального примера нету: хочу понять концептуально. Пример даже придумать не получается, видимо, крайне нетипичная ситуация. Все, что приходят в голову, проверяются достаточно просто прежде, чем запускать каскадное изменение данных. Но что, если проверка нетривиальная?

<skipped>


а похоже я уже и ответил, в предыдущем ответе на этот топик. или нет?
Опять валидация данных
От: IT Россия linq2db.com
Дата: 14.03.05 17:28
Оценка: 174 (17) +1
#Имя: FAQ.design.Validate
Здравствуйте, Козьма Прутков, Вы писали:

КП>Если не жалко, поделитесь идеями, как организовать подобную функциональность...


Прежде всего я бы рассмотрел различные стадии валидации и почему они необходимы, а уже потом её реализацию.

К сожалению, валидацию не получается делать в одном месте за один раз по ряду причин, поэтому обычно она разбивается на несколько уровней.

1. Базовая валидация допустимых параметров вводимых значений. Сюда входит проверка обязательности и длин полей, формат вводимых данных. Основное назначение данного уровня — минимизировать возможность неправильного ввода, исключить походы на сервер (в случае Web) и предоставить пользователю информацию о некорректно-введённых значениях.

2. Проверка валидности бизнес-энтити как единого целого. Этот уровень повторяет все проверки предыдущего, плюс добавляет проверки комбинации полей объекта. Например, если вводимый адрес принадлежит US, то Zip код должен быть 5 или 9 символов, если это Россия, то размер почтового индекса должен равняться 6-ти.

3. Проверка валидности объекта в пределах системы. Включает все предыдущие проверки, плюс всевозможные проверки на непротиворечивость объекта в системе. Например, тот же адрес обычно проверятся на существование такового с помощью специализированных систем. Email пользователя не должен дублироваться в системе и т.п.

4. Проверка целостности данных перед их сохранением в базе данных. Обычно с успехом выполняется средствами самой БД.

Теперь о реализации. С (4) всё понятно. Использвание констрейнов, пользовательских типов, уникальных индексов и FK решают эту проблему. Частично, например, в случае с e-mail, сюда можно перенести проверки 3-го уровня. В случае обычного UI (не-Web) приложения обычно удаётся совместить 1-й и 2-й уровни. Для Web-приложений 1-й (обычно не полностью) выполняется в браузере, 2-й и 3-й уровни можно совместить, если не используется выделенный сервер приложений. Если используется, то 2-й в Web-приложении, 3-й в сервере приложений.

Реализация 2-го и 3-го уровня обычно делается ручками. Ничего здесь автоматизировать, к сожалению, не получается. Причём 2-й следует делать как часть самого бизнес-объекта, а 3-й как метод бизнес логики. А вот с 1-м, который как правило самый занудный всё гораздо интереснее. Лучшая, на мой взгляд, реализация данного уровня — это применение атрибутов (речь, конечно идёт о .NET). В этом случае, т.к. мы фактически расширяем метадату объекта, удаётся по большей части автоматизировать проверки на UI, т.е. не только свести саму реализацию валидации объекта к описанию в виде атрибутов, но и натренировать UI компоненты понимать эти атрибуты.

Таким образом, 1-й и 2-й уровень удаётся инкапсулировать в самом объекте. 3-й уровень представляет собой один метод бизнес логики. 4-й реализуется средствами самой БД.

В общем, как-то так
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 15.03.05 08:47
Оценка:
Здравствуйте, IT, Вы писали:

IT>К сожалению, валидацию не получается делать в одном месте за один раз по ряду причин, поэтому обычно она разбивается на несколько уровней.


Отлично. Ясно и по полочкам.
Да, с форматами и длинами я пожалуй спорить не буду: такие вещи крайне редко меняются, особенно форматы .
Рассмотрим веб-приложение (ибо сложнее), но аналогично и винформовое. Пусть по первоначальным требованиям поле Заказчик обязательное. Ок, сделали. Через 3 месяца оказывается, что оно не является обязательным. И мы шагом марш по всем уровням валидации это дело править. Или я чего-то не понял?
Таперь рассмотрим винформс-приложение (в веб-приложении решается написанием метода установки пары значений). Вот подвязана у нас к свойствам Country и ZipCode (он же индекс для примера) пара контролов. По идее, если пользователь меняет один из них, то нужно проверить их пару. Так что пользователь, однажды введя US/12345 уже никогда не введет RU/131000, ибо перекрестные комбинации невалидны. Ну, либо позволить перевести БО в неконсистентное состояние, что вряд ли очень хорошо.
Да хранит вас господь в сухом прохладном месте...
Re[3]: Опять валидация данных
От: IT Россия linq2db.com
Дата: 15.03.05 15:08
Оценка: 22 (5) +1
Здравствуйте, Козьма Прутков, Вы писали:

КП>Рассмотрим веб-приложение (ибо сложнее), но аналогично и винформовое. Пусть по первоначальным требованиям поле Заказчик обязательное. Ок, сделали. Через 3 месяца оказывается, что оно не является обязательным. И мы шагом марш по всем уровням валидации это дело править. Или я чего-то не понял?

КП>Таперь рассмотрим винформс-приложение (в веб-приложении решается написанием метода установки пары значений). Вот подвязана у нас к свойствам Country и ZipCode (он же индекс для примера) пара контролов. По идее, если пользователь меняет один из них, то нужно проверить их пару. Так что пользователь, однажды введя US/12345 уже никогда не введет RU/131000, ибо перекрестные комбинации невалидны. Ну, либо позволить перевести БО в неконсистентное состояние, что вряд ли очень хорошо.

Ты говоришь о валидации непосредственно во время ввода, о валидации каждого введённого символа. Мне эта практика кажется крайне порочной как раз по причинам, которые ты описываешь. Формы, которые думают что они умней меня всегда раздражают. Валидация значений и их комбинаций должна делаться при сабмите формы. Во время ввода можно проверять только формат, типа ничего не давать пользователю вводить кроме цифр и т.п.

Что же касается первого вопроса об изменениях по всем уровням валидации, то здесь я видимо не совсем ясно выразился. Говоря "этот уровень повторяет все проверки предыдущего" я не имел ввиду дублирование кода, я имел ввиду его повторное использование. Например, имеем вот такой класс Address:

public class Address : BizEntityBase
{
    [MaxLength(35), Required] public string      Address1;
    [MaxLength(35)          ] public string      Address2;
    [MaxLength(35), Required] public string      City;
    [MaxLength(35), Required] public string      Region;
    [               Required] public string      PostalCode;
    [               Required] public CountryCode CountryCode;

    public override void Validate()
    {
        // 1-й уроовень.
        //
        base.Validate();

        // 2-й.
        //
        switch (CountryCode)
        {
            case CountryCode.US:
                if (PostalCode.Length != 5 || PostalCode.Length != 9)
                    throw new Exception("Zip must be 5 or 9 digits.");
                break;

            case CountryCode.RU:
                if (PostalCode.Length != 6)
                    throw new Exception("Почтовый индекс должен содержать 6 цифр.");
                break;
        }
    }
}

Здесь в одном месте реализованы 1-й и 2-й уровни валидации. Третий в бизнес объекте:

public class AddressService : ServiceBase
{
    public void AddAddress(Address address)
    {
        // 1-й, 2-й.
        //
        address.Validate();

        // 3-й. Вызываем код проверки адреса на существование.
        // Используем софт компании Address Validation, Inc.
        //
        new Agents.AddressValidator().Validate(address);

        // Сохраняем обхект в БД.
        //
        new AddressDataAccessor().AddAddress(address);
    }
}

4-й в БД.

IF EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'Address')
BEGIN
    PRINT 'Dropping Table Address'
    DROP   Table    Address
END
GO

PRINT 'Creating Table Address'
GO

CREATE TABLE dbo.Address
(
    AddressID  int IDENTITY (1,1) NOT NULL CONSTRAINT PK_Address PRIMARY KEY CLUSTERED,
    Address1       nvarchar(35)   NOT NULL,
    Address2       nvarchar(35),
    City           nvarchar(35)   NOT NULL,
    Region         nvarchar(35)   NOT NULL,
    PostalCode     nvarchar(11)   NOT NULL,
    CountryCode    udt_CountryCode
) ON [PRIMARY]

GRANT SELECT ON Customer TO PUBLIC
GO

Теперь, допустим, нам нужно одно из полей сделать необязательным. Сколько нужно сделать изменений? Правильно, две. Первое — убрать Required атрибут в классе, второе — NOT NULL в SQL скрипте. Готовоо.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 16.03.05 13:53
Оценка:
Здравствуйте, IT, Вы писали:

IT>Ты говоришь о валидации непосредственно во время ввода, о валидации каждого введённого символа. Мне эта практика кажется крайне порочной как раз по причинам, которые ты описываешь. Формы, которые думают что они умней меня всегда раздражают. Валидация значений и их комбинаций должна делаться при сабмите формы. Во время ввода можно проверять только формат, типа ничего не давать пользователю вводить кроме цифр и т.п.


Боже упаси! Как ты мог так плохо обо мне подумать! Просто насколько я помню в винформах при подвязке свойств к контролам "сбрасывание" значений в свойства происходит по одному, соответственно, либо страна либо индекс будет присвоен первым, и проверить это нельзя. Но это бог с ним, издержки технологии...

IT>Что же касается первого вопроса об изменениях по всем уровням валидации, то здесь я видимо не совсем ясно выразился. Говоря "этот уровень повторяет все проверки предыдущего" я не имел ввиду дублирование кода, я имел ввиду его повторное использование. Например, имеем вот такой класс Address:


<skipped />

IT>Теперь, допустим, нам нужно одно из полей сделать необязательным. Сколько нужно сделать изменений? Правильно, две. Первое — убрать Required атрибут в классе, второе — NOT NULL в SQL скрипте. Готовоо.


Класс. Но тут как раз и происходит та проблема, о которой я говорил: ты можешь перевести объект в неконсистентное состояние. То есть легко сунуть ему новую страну, а потом сразу в БД.

Ладно, я приблизительно понял твою мысль. Спасибо.
Да хранит вас господь в сухом прохладном месте...
Re[5]: Опять валидация данных
От: stalcer Россия  
Дата: 17.03.05 10:35
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

КП>Класс. Но тут как раз и происходит та проблема, о которой я говорил: ты можешь перевести объект в неконсистентное состояние. То есть легко сунуть ему новую страну, а потом сразу в БД.


Сразу в бд неполучится, т.к. насколько я понимаю AddressService.AddAddress должен быть единтвенным доступным способом сохранить объект, а он делает валидацию.

Но проблему это все равно не решает, так как с объектом еще необходимо работать и программно (из бинзес логики). И когда я передаю такой объект, например, параметром в какую-нибудь функцию, то я хочу, чтобы он был в валидном состоянии. А проверять каждый раз — это лучше сразу застрелиться.
Поэтому лучше, чтобы объект был написан таким образом, чтобы не было возможности перевести его в невалидное состояние. Ведь именно для этого и придумана инкапсуляция и свойства с сеттерами, не так ли?

Таким образом получается, что для работы с формами лучше иметь бизнес объекты с:

А для программной работы лучше иметь визнес объекты, написанные по всем правилам ООП:

Получается противочечие .

Я вот пишу движок для всего этого (времени много, начальство одобряет). Есть свой язык, своя VM. И если представить, что можно реализовать любые экзотические конструкции в языке, специально для объявления и работы с бизнес объектами, какие-бы вы предпочли? Так, чтобы удобно было и для форм и для бизнес логики? Есть идеи? .
http://www.lmdinnovative.com (LMD Design Pack)
Re[6]: Опять валидация данных
От: GlebZ Россия  
Дата: 17.03.05 17:45
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Получается противочечие .

Никакого противоречия нет. На разных уровнях разная бизнес-логика. И поэтому объект проходя по уровню либо меняет свой вид, или предлагает интерфейс, которым могут воспользоваться объекты бизнес логики нескольких уровней. Поэтому бизнес-объект и не делают сверх-навороченным.

S>Я вот пишу движок для всего этого (времени много, начальство одобряет). Есть свой язык, своя VM. И если представить, что можно реализовать любые экзотические конструкции в языке, специально для объявления и работы с бизнес объектами, какие-бы вы предпочли? Так, чтобы удобно было и для форм и для бизнес логики? Есть идеи? .

Бизнес-правила разные для форм и для бизнес-логики. Игорь хорошо это описал. Даже если ты описываешь операцию валидирования, многие операции можно выполнить только на 3 и 4 уровне. Если, конечно, тебе не хватает функциональности System.Data.DataSet.

С уважением, Gleb.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.