Здравствуйте, GlebZ, Вы писали:
GZ>Допустим, у тебя есть набор полей в форме, которое переводится в бизнес-объект с клиентской бизнес-логикой, которое переводится в некоторый объект DTO, которое переводится в бизнес-объект доменной модели, которое в свою очередь переводится в набор строк в базе данных. Никакой кучи интерфейсов. Просто состояние объекта находится в том виде, которое нужно в данный момент. Естественно данный список приведен от балды.
Возмем, например, 1С. Так бизнес объект — это строка справочника. И все. База данных — невидима прикладному программисту. Форма — это всего лишь подсистема,
работающая с бизнес объектом(ами), но сама бизнес объектом не считаюшаяся. Любой другой алгоритм (расчет) — это тоже подсистема,
работающая с бизнес объектом.
В архитектуре моего фреймворка под бизнес объектом я понимаю объект как часть Domain Model. Т.е. объект имеющий identity, находящийся в IdentityMap (в кэше) на сервере приложений. Всякие техничесткие детали, типа, как он туда подгружается и как сбрасываются изменения, меня вообще не интересуют, так как это делает система автоматически без участия прикладного программиста.
А почему он самый важный. Потому-что, изначально, прикладной программист (или постановик) должен взять тетку-бухгатершу и устроить ей допрос с пристрастием на тему, что такое, например, табель. Затем, исходя из смысла (в человеческом понимании) он должен запрограммировать бизнес объект (см. выше). По всем правилам ООП (ведь оно и создано для того, чтобы удобно было моделировать предметную область). Получится некий относительно умный бизнес объект, которому:
— Во первых, по барабану как его будут использовать (будет к нему GUI или нет, и т.д.);
— Во вторых, он задает правила игры для всех, кто будет его использовать.
Именно бизнес объект в таком понимании как бы "живет" внутри системы.
А все остальные формы представления информации находящейся в бизнес объекте — либо временные, либо относятся к какой-нибудь отдельной подсистеме (например, GUI). А то так можно и до маразма дойти, и назвать одной из форм бизнес объекта — набор TCP/IP пакетов. Оно конечно, в каком-то смысле и правильно будет, но желательно, чтобы прикладной программист об этом не думал.
GZ>Бизнес-логика которая на клиенте, и бизнес-логика которая на сервере(пускай это даже сервер БД) разные. У них не просто разные возможности, но и разные цели.
<бизнес логика> != <бизнес объект>. Бизнес логика — это набор сервисов,
использующих бизнес объекты. Так что логика то разная, а бизнес объекты использует одни и те же. И любая логика должна подчиняться правилам, установленным в самом бизнес объекте.
GZ>Давай классифицируем когда происходит валидация данных на форме. Есть 3 случая:
GZ>1. При вводе каждого символа. Например, бизнес задачей определено что в данном поле может быть только цифра. Тогда поле не должно воспринимать ничего кроме нажатие на клавиши с цифрами.
GZ>2. При потере фокуса. Если неверное значение, то фокус не должен уходить
GZ>3. Перед отправлением объекта на другой уровень.
GZ>1-2 случаи логикой бизнес-объекта не управляются. В случае создания нового бизнес-объекта, его может еще и не сущестовать. Плюс к этому, значения выбранные из справочника — вообще незачем на клиенте валидировать.
GZ>Более криминальный случай, например:
GZ>у тебя объект должен показываться иконкой в зависимости от значения. И на разных формах(клиентах) показ поля разный. Так что запихнуть всю бизнес логику на бизнес-объект, даже на уровне клиента не удастся.
Это все детали реализации подсистемы GUI.
GZ>Если данные используемые при проверке больше чем оперативная память, то принципиально нельзя.
Все зависит от сложности сервера приложений. Сама же СУБД как то справляется.
GZ>Не ширее а ширше. Диревня.
GZ>Функциональность датасета (или вернее сказать xsd) достаточно продвинута и достаточна. Еще добавить регуляры, то вообще был бы класс.
Какой бы функциональностью не обладал датасет — он всего лишь класс в библиотеке языка универсального назначения и поэтому не может быть идеально удобным. Я немного не об этом. Ну, например так объявил:
persistent class A
{
public persistent int X; required; // В специальном языке 'int' может содержать значение
// undefined, что примерно тоже, что и NULL в SQL,
// и совсем не тоже, что C# null.
public persistent byte Y;
constraint (Y) // Перечень полей, по изменению которых делать проверку.
{
if (y < 0)
throw new ConstraintException("бла-бла-бла файлед, нафиг!");
}
constraint (X, Y)
{
if (x > y)
throw new ConstraintException("бла-бла-бла 2 файлед, блин!");
}
}
А так использовал:
void P(A a)
{
a.X = 7;
a.Y = 5; // Ошибка. Второй констрейнт.
a.Y = -2; // Ошибка. Первый констрейнт.
deffer (a) // 'deffer' - ключевое слово. Проверки откладываются до конца блока.
{
a.X = 19; // Нет ошибки. Проверка отложена.
a.Y = 20;
};
}
Вот про какие идеи я спрашивал. Можно ведь пофантазировать про идеальный вариант.