Здравствуйте, Козьма Прутков, Вы писали:
КП>Рассмотрим веб-приложение (ибо сложнее), но аналогично и винформовое. Пусть по первоначальным требованиям поле Заказчик обязательное. Ок, сделали. Через 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>>