Re[7]: Опять валидация данных
От: stalcer Россия  
Дата: 18.03.05 07:56
Оценка:
Здравствуйте, GlebZ, Вы писали:

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


Т.е. объект с "изменяющимся видом" и кучей интерфейсов не считается навороченным? И с ним, наверное, очень просто работать (интуитивно понятно, так сказать).

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

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

Поэтому получаются две совершенно разные валидации:

Причем вторая не столь формализуема как первая.

GZ>Бизнес-правила разные для форм и для бизнес-логики.


Но есть бизнес объект с которым работает и форма и бизнес логика. И валидация с точки зрения самого объекта должна быть одна и та же.

GZ>Даже если ты описываешь операцию валидирования, многие операции можно выполнить только на 3 и 4 уровне.


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

GZ>Если, конечно, тебе не хватает функциональности System.Data.DataSet.


Вот люди. Я с ними как с художниками, про новый движок, про специальный язык, а они... Ширее надо мыслить .
http://www.lmdinnovative.com (LMD Design Pack)
Re[8]: Опять валидация данных
От: GlebZ Россия  
Дата: 18.03.05 12:29
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Здравствуйте, GlebZ, Вы писали:


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


S>Т.е. объект с "изменяющимся видом" и кучей интерфейсов не считается навороченным? И с ним, наверное, очень просто работать (интуитивно понятно, так сказать).

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

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

Бизнес-логика которая на клиенте, и бизнес-логика которая на сервере(пускай это даже сервер БД) разные. У них не просто разные возможности, но и разные цели.

S>Например, выше описанный Address:

S>Его смысл состоит в представлении информации о адресе, исходя из этого он (объект) и должен делать валидацию себя. Одной подсистеме, использующей данный объект может и не нужно знать существует ли такой адрес в реальности, а другой — нужно, исходя из этого подсистема делает (или не делает) соответствующую проверку.
S>И основная мысль в том, что эта проверка никоим образом к бизнес объекту не относится, она относится к способу использования этого бизнес объекта в конкретной подсистеме.

S>Поэтому получаются две совершенно разные валидации:

S>
S>Причем вторая не столь формализуема как первая.

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


GZ>>Бизнес-правила разные для форм и для бизнес-логики.


S>Но есть бизнес объект с которым работает и форма и бизнес логика. И валидация с точки зрения самого объекта должна быть одна и та же.

Частично да. Но например не обязательно объекты бизнес логики должны пользоваться функционалом бизнес-объекта. В случае уровня 3, легче проверять объект от а до я(или от a to z) полностью. Особенно в случае доменной модели. На 4 уровне — это может быть обязательным условием.

GZ>>Даже если ты описываешь операцию валидирования, многие операции можно выполнить только на 3 и 4 уровне.


S>На третьем — да, об этом я написал выше в данном посте, но повторюсь, что это не валидирование объекта, а валидирование способа его использования в како-либо подсистеме.

S>Четвертый уровень — только физический. Никакой дополнительной логической нагрузки он не несет. В нормальном фреймворке с базой напрямую никто и работать-то не должен, только с бизнес объектами и специальным языком запросов. А то, что в реальности некоторые проверки удобно выполнять в СУБД (ссылочную целостность, например), так это только оптимизация (ну и еще успокоение нервов админа СУБД), их принципиально можно делать и сервере приложений.

Если данные используемые при проверке больше чем оперативная память, то принципиально нельзя.

GZ>>Если, конечно, тебе не хватает функциональности System.Data.DataSet.


S>Вот люди. Я с ними как с художниками, про новый движок, про специальный язык, а они... Ширее надо мыслить .

Не ширее а ширше. Диревня.
Функциональность датасета (или вернее сказать xsd) достаточно продвинута и достаточна. Еще добавить регуляры, то вообще был бы класс.

С уважением, Gleb.
Re[9]: Опять валидация данных
От: stalcer Россия  
Дата: 18.03.05 13:52
Оценка: 8 (1)
Здравствуйте, 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;
    };
}


Вот про какие идеи я спрашивал. Можно ведь пофантазировать про идеальный вариант.
http://www.lmdinnovative.com (LMD Design Pack)
Re[10]: Опять валидация данных
От: GlebZ Россия  
Дата: 18.03.05 17:29
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Возмем, например, 1С. Так бизнес объект — это строка справочника. И все. База данных — невидима прикладному программисту. Форма — это всего лишь подсистема, работающая с бизнес объектом(ами), но сама бизнес объектом не считаюшаяся. Любой другой алгоритм (расчет) — это тоже подсистема, работающая с бизнес объектом.

Чем больше узнаю 1С, тем больше мне нравятся другие продукты. Ну хорошо, я его хреново знаю, пройдем. Хотя то что я описал универсально как сама философия.

Ну хорошо, ты говоришь только о прикладном программисте.

S><бизнес логика> != <бизнес объект>. Бизнес логика — это набор сервисов, использующих бизнес объекты. Так что логика то разная, а бизнес объекты использует одни и те же. И любая логика должна подчиняться правилам, установленным в самом бизнес объекте.

Это я тебе и хочу сказать.
Кратко:
1. У нас есть некоторый язык с помощью который мы пишем сервиса то бишь бизнес-логику.
2. У нас есть некоторый (обычно декларативный) язык с помощью которого мы описываем бизнес-объект.
Теперь мы начинаем разбираться, где у нас бизнес-логика и где у нас бизнес-объект.
Завернули мы крутой бизнес-объект с бизнес-логикой. Ура. Тут пришла теинька бухгалтер и сказала, дядька а мне нужен новый сервис(то есть как мы уже разобрались бизнес-логика). И тут оказывается, что бизнес-логика декларированная на объекте, не очень то совместима с новыми функционалом. И этих бизнес-объектов хренова туча. Например половина аналитических счетов.

S>Это все детали реализации подсистемы GUI.

GUI — это такая же бизнес логика реализуемая прикладным программистом как и остальное. Это не детали. Причем то куда уходит большинство времени и нервов прикладника — ты называешь деталями. И именно то, за что обычно клиенты платят деньги

GZ>>Если данные используемые при проверке больше чем оперативная память, то принципиально нельзя.


S>Все зависит от сложности сервера приложений. Сама же СУБД как то справляется.

Какими средствами! Не будешь же ты держать индексы от многомиллионной таблицы в памяти сервера приложений. Декларация о объекте должна указывать и на то, как хранить объект, и какие бизнес правила хранения объекта. Но не дай бог получится что мы начнем в этой области конфликтовать с новыми бизнес-процессами.

GZ>>Функциональность датасета (или вернее сказать xsd) достаточно продвинута и достаточна. Еще добавить регуляры, то вообще был бы класс.


S>Какой бы функциональностью не обладал датасет — он всего лишь класс в библиотеке языка универсального назначения и поэтому не может быть идеально удобным. Я немного не об этом. Ну, например так объявил:


---скипнуто----
S>Вот про какие идеи я спрашивал. Можно ведь пофантазировать про идеальный вариант.
А если новый сервис предполагает заполнение некоторых полей на стороне сервера? (что бывает достаточно часто). Идеально бывает только там, куда нас не пускают.

Я стараюсь отвязывать сервиса предоставляемые бизнес-объектом от самого бизнес-объекта. Это создает некоторую избыточность в кол-ве классов, но зато структура становится значительно гибче. IMХО В случае использования некоторого доменного языка, к этому тем более надо стремиться. Иначе получится полный бардак при изменениях в коде. Тогда и объекты легко добавлять, и бизнес-логику. Доменная модель не предполагает что сервиса представленные бизнес-объектом инкапсулированы в бизнес-объекте. Она лишь определяет модель связывания объектов. А все остальное — чистый ООD. А бизнес-логика на клиенте и сервере — все равно — сильно отличается.

С уважением, Gleb.
Re[11]: Опять валидация данных
От: stalcer Россия  
Дата: 21.03.05 08:28
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Чем больше узнаю 1С, тем больше мне нравятся другие продукты.


Чем 1С тебе не нравится? Я тоже его плохо знаю, просто интересно услышать мнение со стороны.

GZ>Завернули мы крутой бизнес-объект с бизнес-логикой. Ура. Тут пришла теинька бухгалтер и сказала, дядька а мне нужен новый сервис(то есть как мы уже разобрались бизнес-логика). И тут оказывается, что бизнес-логика декларированная на объекте, не очень то совместима с новыми функционалом. И этих бизнес-объектов хренова туча. Например половина аналитических счетов.


Да я и не предлагаю все засовывать в бинес объект. Должно быть разумное разделение, что-то в самом бизнес-объекте, что-то в сервисах.
Но, некоторая логика в бизнес-объекте тоже полезна. Например, ты пишешь: "и тут оказывается, что бизнес-логика декларированная на объекте, не очень то совместима с новыми функционалом". А какая разница была ли эта логика в самом объекте или в сервисе? Если она несовместима — ее все равно надо переделывать. Только если она была в самом объекте, я наткнусь на это сразу, а в противном случае могу и забыть .

GZ>GUI — это такая же бизнес логика реализуемая прикладным программистом как и остальное. Это не детали. Причем то куда уходит большинство времени и нервов прикладника — ты называешь деталями. И именно то, за что обычно клиенты платят деньги


Это да. 1С в этом плане как раз позволяет снизить количество нервов.

GZ>Какими средствами! Не будешь же ты держать индексы от многомиллионной таблицы в памяти сервера приложений.


Ну, разные есть техники. Я же говорю: все зависит от сложности сервера приложений. Здесь, например. Конечно, если Вы пишите отлельную прикладную систему, на этом не стоит заморачиваться. Но если пишется движок...

Кстати любимую здесь всеми проблему низкой производительности при навигационном доступе к объектам по моему можно относительно просто решить .

GZ>Декларация о объекте должна указывать и на то, как хранить объект, и какие бизнес правила хранения объекта.


Здесь я в корне не согласен. Есть логическая модель, а есть физическая. Их нужно отделять друг от друга.
Это как в СУБД, таблицы, представления — логическая модель; индексы, кластеры — физическая.
Физическая модель не должна влиять на логику приложения, поэтому при разработке ее не нужно учитывать. В процессе оптимизации или профилирования — да, она нужна.

GZ>Я стараюсь отвязывать сервиса предоставляемые бизнес-объектом от самого бизнес-объекта. Это создает некоторую избыточность в кол-ве классов, но зато структура становится значительно гибче.


Здесь я спорить не буду. Это дело вкуса.
Только я никак не пойму: Вот появилась необходимость добавить новый сервис. Если он с уже существующей логикой не входит в противоречие, то все нормально — менять ничего не надо. А если входит, то значит где-то есть концептуальное противоречие, и тогда нужно мучить тетку, пусть уж решит, что ей надо. А потом и изменять соответственно. Только какая разница что менять — сервисы или сам бизнес объект. Если есть концептуальное противоречие — что-то переписывать все равно придется.

Повторюсь, я ни в коем случае не за то, чтобы включать в бизнес объект все что ни попадя. Необходимо разумное разделение.
http://www.lmdinnovative.com (LMD Design Pack)
Re[12]: Опять валидация данных
От: GlebZ Россия  
Дата: 21.03.05 15:04
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Чем 1С тебе не нравится? Я тоже его плохо знаю, просто интересно услышать мнение со стороны.

Низкая производительность и ненадежность в условиях многопользовательской системы. Вплоть до выпендрежей в виде терминального доступа. Вообще, с моей стороны что-то говорить некоректно (ввиду малых знаний 1С), но то как его выпремляет Serginio1, много говорит. Лучше это спросить у него.

S>Да я и не предлагаю все засовывать в бинес объект. Должно быть разумное разделение, что-то в самом бизнес-объекте, что-то в сервисах.

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

S>Ну, разные есть техники. Я же говорю: все зависит от сложности сервера приложений. Здесь, например. Конечно, если Вы пишите отлельную прикладную систему, на этом не стоит заморачиваться. Но если пишется движок...

В принципе, подобный результат можно более просто получить страничным доступом, и организацией кэша с доступом по идентификатору.

S>Кстати любимую здесь всеми проблему низкой производительности при навигационном доступе к объектам по моему можно относительно просто решить .

Разговор становится интересным. Интересная тема. Я весь во внимании.

S>Здесь я в корне не согласен. Есть логическая модель, а есть физическая. Их нужно отделять друг от друга.

S>Это как в СУБД, таблицы, представления — логическая модель; индексы, кластеры — физическая.
S>Физическая модель не должна влиять на логику приложения, поэтому при разработке ее не нужно учитывать. В процессе оптимизации или профилирования — да, она нужна.
Абсолютно согласен. Как хранить физически, должен знать некоторый уровень логики (который часто один на всех). Но абсолютной независимости никогда не бывает. Физический уровень — это отражение логического уровня. Может кластеры и нет, но сохранение целостности во многом задача управления физикой со стороны логического уровня.

S>Только я никак не пойму: Вот появилась необходимость добавить новый сервис. Если он с уже существующей логикой не входит в противоречие, то все нормально — менять ничего не надо. А если входит, то значит где-то есть концептуальное противоречие, и тогда нужно мучить тетку, пусть уж решит, что ей надо. А потом и изменять соответственно. Только какая разница что менять — сервисы или сам бизнес объект. Если есть концептуальное противоречие — что-то переписывать все равно придется.

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

S>Повторюсь, я ни в коем случае не за то, чтобы включать в бизнес объект все что ни попадя. Необходимо разумное разделение.

Согласен. Но чем меньше бизнес-объект будет делать сам, тем легче потом будешь спать. Изменение одного объекта не должно приводить к перетестированию всего проекта. Именно это я подразумевал.

С уважением, Gleb.
Re[13]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 23.03.05 13:37
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Здравствуйте, stalcer, Вы писали:


S>>Да я и не предлагаю все засовывать в бинес объект. Должно быть разумное разделение, что-то в самом бизнес-объекте, что-то в сервисах.

GZ>Дело в том, что в разных бизнес-процессах используются разные сервисы. Поэтому достаточно вероятно что сервиса просто не пересекаются. Например, бизнес-объект аналитического счета в складском учете и бухгалтерском имеет мало общего (кроме самих данных).

Вот тут я с вашего позволения встряну в вашу милую беседу Если внимательно почитать Фаулера, то он собственно и говорит, что нужно четко разделять логику домена и логику приложения. Соответственно, мухи отдельно, котлеты отдельно. Я лишь категорически против того, чтобы БО превратился в DTO: он должен обладать поведением, тем самым моделируя соответствующий объект реального мира. А уж что и как с ним будут делать — зависит от приложений.
Писать какие-нибудь "сервисы" (то есть нечто без состояния которое умеет только молотить что-то) далеко не самый удобный способ решить проблему с реализацией бизнес-логики, а уж тем более с ее поддержкой и развитием.

S>>Повторюсь, я ни в коем случае не за то, чтобы включать в бизнес объект все что ни попадя. Необходимо разумное разделение.

GZ>Согласен. Но чем меньше бизнес-объект будет делать сам, тем легче потом будешь спать. Изменение одного объекта не должно приводить к перетестированию всего проекта. Именно это я подразумевал.

Это верно. Выбрав правильные абстракции и промоделировав их бизнес-объектами можно достичь такого эффекта. С другой стороны, если у приложений есть пересечения по функциональности (пусть и неявные, например, приложения меняют одни данные пусть и в разных контекстах и этот факт должен приводить к каким-то еще действиям, хотя бы журналированию), то куда страшнее будет ее продублировать и потом забывать вносить модификации во все реплики.
Да хранит вас господь в сухом прохладном месте...
Re[14]: Опять валидация данных
От: GlebZ Россия  
Дата: 23.03.05 14:06
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

КП>Вот тут я с вашего позволения встряну в вашу милую беседу Если внимательно почитать Фаулера, то он собственно и говорит, что нужно четко разделять логику домена и логику приложения. Соответственно, мухи отдельно, котлеты отдельно. Я лишь категорически против того, чтобы БО превратился в DTO: он должен обладать поведением, тем самым моделируя соответствующий объект реального мира. А уж что и как с ним будут делать — зависит от приложений.

КП>Писать какие-нибудь "сервисы" (то есть нечто без состояния которое умеет только молотить что-то) далеко не самый удобный способ решить проблему с реализацией бизнес-логики, а уж тем более с ее поддержкой и развитием.
Проблема в том, что Фаулер описал свои паттерны не для всего что имеется в нашем мире. Мир значительно больше и разнообразнее. В данном случае мы имеем ситуацию с DSL (Domain Specific Language). А в нем, несколько другие правила. Основное правило — простота разработки и изменения. Поэтому здесь более важны сервисы и ясность логики. Разные неясные сущности плодить — все-таки не рекомендуется. Дизайн должен быть проще чем в решении без DSL. Поэтому разделение БО и DTO — не рекомендуется.

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

Журналирование — нормальный сервис. Даже, я бы сказал, со многими особенностями сервис.

С уважением, Gleb.
Re[13]: Опять валидация данных
От: stalcer Россия  
Дата: 23.03.05 16:18
Оценка:
Здравствуйте, GlebZ, Вы писали:

S>>Ну, разные есть техники. Я же говорю: все зависит от сложности сервера приложений. Здесь, например. Конечно, если Вы пишите отлельную прикладную систему, на этом не стоит заморачиваться. Но если пишется движок...

GZ>В принципе, подобный результат можно более просто получить страничным доступом, и организацией кэша с доступом по идентификатору.

Как это "организация кэша с доступом по идентификатору" может нам помочь в отслеживании ссылочной целостности на сервере приложений?
Ведь для того, чтобы узнать, можно ли удалить какой-либо хранимый объект, мне необходимо знать, ссылаются ли на него какие-либо другие объекты. Для этого нужно, как ты правильно сказал, держать на сервере "индекс многомиллионой таблицы", либо выполнить запрос. А вот сможет ли запрос воспользоваться кэшированными данными или ему придется лесть в базу?

Это, кстати, тоже интересная тема. Я бы проблему так сформулировал: Когда на сервере приложений в какой-то программе (бизнес логике) я удаляю объект, например, так:

    obj.Delete();
    // Some actions...
    Transaction.Commit();


как сделать так, чтобы ошибку о нарушении ссылочной целостности я гарантированно получил в строчке obj.Delete(), а не в Transaction.Commit() (или где-нибудь посередине, когда сервер приложений решит сбросить в базу очередные накопившиеся изменения). И при этом обеспечивалась бы приемлимая производительность, т.е. сервер не лез бы в базу каждый раз.

Честно говоря — ответа пока я не вижу . Но, очень хочется .
То же самое и про проверку уинкальности по полю (полям).


S>>Кстати любимую здесь всеми проблему низкой производительности при навигационном доступе к объектам по моему можно относительно просто решить .

GZ>Разговор становится интересным. Интересная тема. Я весь во внимании.

Пусть, есть некий сервер приложений, к которому коннектятся пользователи, т.е. на сервере есть открытые сессии. Каждая сессия имеет свой экземпляр VM доменного языка, свой объектный кэш (небольшой!), и свое подключение к базе (отдельную текущую SQL транзакцию). Пусть, для простоты применяются сериализованные транзакции, потому-что так меньше гемороя с инвалидацией объектов в кэше сессии, т.е. мы можем утверждать, что объект, прочитанный в определенный момент транзакции, будет иметь валидное состояние аттрибутов до ее конца, поскольку изменения, сделанные другими сессиями нам не видны.

Далее хочу отметить отличие роли СУБД и сервера приложений в общей картине:
Во первых, СУБД предназначена для хранения данных и поэтому должна быть надежной, сервер приложений предназначен для обработки данных и поэтому должен быть быстрым, но для него не так критична надежность, как для СУБД.
Во вторых, иметь несколько серверов приложений, одновременно работающих с одной базой — это нормально, а иметь несколько баз и синхронизировать информацию в них — это геморрой. Отсюда следует, что сервер приложений может быть гораздо менее масштабируемым, чем СУБД.

Теперь о самой проблеме: Низка производительность при навигационном доступе определяется необходимостью выполнения большого количества маленьких запросов и непредсказуемостью этих запросов.
Во первых, это плохо с точки зрения клиент-серверной идеологии, так как передавать данные по сети лучше малым количеством больших пакетов.
Во вторых, современные реляционные СУБД просто не приспособлены к такому сценарию работы. Причем последнее — чисто проблема их (СУБД) реализации.

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

Будет ли реализация такого подхода сравнима по сложности с реализацией СУБД? Я думаю — нет. Потому-что:

По сути — это всего лишь кэш. Можно называть его кэшем второго уровня. Вроде, в hibernate нечто такое есть, только не совсем такое.
Как я мыслю, характеристики, примерно, должны быть следующие:

Один из хитрых моментов — это то, как сессия узнает какую именно версию объекта ей необходимо получить из этого кэша. Для того, чтобы обеспечить согласованность данных, получаемых из кэша с данными из СУБД (и результатами запросов к СУБД), требуемая версия может быть и не последней из имеющихся в кэше. Но, и эту проблему решить можно.

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

Если в кэше не оказалось необходимых объектов, они, естесственно, подгружаются из базы. Но! Так как кэш второго уровня рассчитан на больший объем памяти, подгружать объекты можно не по одному, а пачками. Например, я проверял, если к Oracle делать запросы, возвращающие по одной записи, то это займет примерно столько же время сколько и такое-же количество запросов, возвращающих по 10-20 записей .
Так как с кэшем второго уровня работают несколько сессий и так как он сериализуется в файл для последующего использование данных, то вероятность, что эти лишние данные будут востребованы возрастает, по сравнению с сессионным кэшем.

Вот и все. Примером реализации такой идеи с некоторой натяжкой можно считать Янус .

Сильно уж не бейте, плиззз!
http://www.lmdinnovative.com (LMD Design Pack)
Re[15]: Опять валидация данных
От: stalcer Россия  
Дата: 23.03.05 16:26
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Дизайн должен быть проще чем в решении без DSL.


Дизайн прикладного решения от наличия DSL мало зависит. Реализация — да, так как фремворк берет на себя все что можно формализовать и автоматизировать. Способ выражения мыслей — разный и в случае с DSL — более удобный. Но, мысли-то и их комбинирование — одни и те же.

GZ>Поэтому разделение БО и DTO — не рекомендуется.


И эта одна из интересных тем. ИМХО, ты прав, крайне не желательно. А то прикладной программист запутается нафиг.
Правда непонятно вот что: иногда DTO специально делаются по структуре не такие как БО. Как в этом-то случае поступать ?
http://www.lmdinnovative.com (LMD Design Pack)
Re[14]: Опять валидация данных
От: GlebZ Россия  
Дата: 23.03.05 17:44
Оценка: +1
Здравствуйте, stalcer, Вы писали:


S>Как это "организация кэша с доступом по идентификатору" может нам помочь в отслеживании ссылочной целостности на сервере приложений?

Я рассматривал эти системы только как организация кэша.
S>Ведь для того, чтобы узнать, можно ли удалить какой-либо хранимый объект, мне необходимо знать, ссылаются ли на него какие-либо другие объекты. Для этого нужно, как ты правильно сказал, держать на сервере "индекс многомиллионой таблицы", либо выполнить запрос. А вот сможет ли запрос воспользоваться кэшированными данными или ему придется лесть в базу?

S>Это, кстати, тоже интересная тема. Я бы проблему так сформулировал: Когда на сервере приложений в какой-то программе (бизнес логике) я удаляю объект, например, так:


S>
S>    obj.Delete();
S>    // Some actions...
S>    Transaction.Commit();
S>


S>как сделать так, чтобы ошибку о нарушении ссылочной целостности я гарантированно получил в строчке obj.Delete(), а не в Transaction.Commit() (или где-нибудь посередине, когда сервер приложений решит сбросить в базу очередные накопившиеся изменения). И при этом обеспечивалась бы приемлимая производительность, т.е. сервер не лез бы в базу каждый раз.

Прежде всего реши, где ты обрабатываешь транзакции, на сервере приложений, или на БД. Сбрасывать посередине, нельзя. См. Блокировки БД.

S>Честно говоря — ответа пока я не вижу . Но, очень хочется .

S>То же самое и про проверку уинкальности по полю (полям).
Если очень хочется, организуй запросы. Но по сравнению со стандартным механизмом — чрезвычайно тормозно и чрезвычайно сложно.


S>>>Кстати любимую здесь всеми проблему низкой производительности при навигационном доступе к объектам по моему можно относительно просто решить .

GZ>>Разговор становится интересным. Интересная тема. Я весь во внимании.

S>Пусть, есть некий сервер приложений, к которому коннектятся пользователи, т.е. на сервере есть открытые сессии. Каждая сессия имеет свой экземпляр VM доменного языка, свой объектный кэш (небольшой!), и свое подключение к базе (отдельную текущую SQL транзакцию). Пусть, для простоты применяются сериализованные транзакции, потому-что так меньше гемороя с инвалидацией объектов в кэше сессии, т.е. мы можем утверждать, что объект, прочитанный в определенный момент транзакции, будет иметь валидное состояние аттрибутов до ее конца, поскольку изменения, сделанные другими сессиями нам не видны.

1. Потеря масштабируемости. Причем достаточно громадное.
2. Неправильное понимание сериализованных транзакций. Посмотри за счет чего они реализуются. Если вручную то ты ляжешь, если с помощью сервера БД — он ляжет. Да и вручную ты это реализовать вряд-ли возможно(логгинг изменений + откаты).
То есть насколько я понял — это statefull.

S>Далее хочу отметить отличие роли СУБД и сервера приложений в общей картине:

S>Во первых, СУБД предназначена для хранения данных и поэтому должна быть надежной, сервер приложений предназначен для обработки данных и поэтому должен быть быстрым, но для него не так критична надежность, как для СУБД.
Неверно. Сервер приложений должен иметь такую-же надежность как и сервер БД. Однако ты наверно имел ввиду, что сессия может сбрасываться.
S>Во вторых, иметь несколько серверов приложений, одновременно работающих с одной базой — это нормально, а иметь несколько баз и синхронизировать информацию в них — это геморрой. Отсюда следует, что сервер приложений может быть гораздо менее масштабируемым, чем СУБД.
Для этого и делают кластеризацию СУБД. Что-бы мы как меньше задумывались об этом. Но в кластеризации ничего хорошего нет.

S>Теперь о самой проблеме: Низка производительность при навигационном доступе определяется необходимостью выполнения большого количества маленьких запросов и непредсказуемостью этих запросов.

S>Во первых, это плохо с точки зрения клиент-серверной идеологии, так как передавать данные по сети лучше малым количеством больших пакетов.
S>Во вторых, современные реляционные СУБД просто не приспособлены к такому сценарию работы. Причем последнее — чисто проблема их (СУБД) реализации.
Проблема не только в тяжелом механизме SQL запросов. Локальные базы нормально справляются с навигационным доступом. Большие базы обычно находятся на другом сервере, соответсвенно, большое кол-во межпроцессорных вызовов обеспечено.

S>Исходя из рассуждений последнего абзаца напрашивается решение "в лоб":

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

S>Будет ли реализация такого подхода сравнима по сложности с реализацией СУБД? Я думаю — нет. Потому-что:

S>
S>По сути — это всего лишь кэш. Можно называть его кэшем второго уровня. Вроде, в hibernate нечто такое есть, только не совсем такое.

S>Как я мыслю, характеристики, примерно, должны быть следующие:
S>
S>Один из хитрых моментов — это то, как сессия узнает какую именно версию объекта ей необходимо получить из этого кэша. Для того, чтобы обеспечить согласованность данных, получаемых из кэша с данными из СУБД (и результатами запросов к СУБД), требуемая версия может быть и не последней из имеющихся в кэше. Но, и эту проблему решить можно.

Значит версионификация. Понятненько. Только механизм транзакций всегда достаточно сложный и нетривиальный для всех систем. Ты его как-то обходишь стороной.

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

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

S>Если в кэше не оказалось необходимых объектов, они, естесственно, подгружаются из базы. Но! Так как кэш второго уровня рассчитан на больший объем памяти, подгружать объекты можно не по одному, а пачками. Например, я проверял, если к Oracle делать запросы, возвращающие по одной записи, то это займет примерно столько же время сколько и такое-же количество запросов, возвращающих по 10-20 записей .

Здесь есть зависимость от сложности объекта. Объект в базе нормализован. И подгружается обычно либо распределнным запросом, либо он разделяется на несколько объектов.
S>Так как с кэшем второго уровня работают несколько сессий и так как он сериализуется в файл для последующего использование данных, то вероятность, что эти лишние данные будут востребованы возрастает, по сравнению с сессионным кэшем.
Вот это не понял.

S>Вот и все. Примером реализации такой идеи с некоторой натяжкой можно считать Янус .


S>Сильно уж не бейте, плиззз!

Нет уж позвольте.

1. Такая система уже есть, и называется Prevalyer. Мое мнение о нем, можно посмотреть здесь
Автор: Poudy
Дата: 10.03.05

2. В данном случае описана statefull модель. Основные недостатки statefull модели — низкая масштабируемость. Основная нагрузка идет даже не за счет недостатка памяти, а за счет синхронизации сессий и их транзакций. Тут уж балансировкой не отделаешься.
3. Держать коннекты на базе — очень плохо для такого решений. После 200 коннектов практически любой БД умрет. Притом в тексте какое-то противоречие между транзакциями БД и ручными.
4. Я так и не понял систему транзакций. Насколько я понял, используется версионный механизм. Он достаточно хорош для оптимистических транзакций. Но для пессимистических — нужно очень постараться. Правда, гарантированные пес. транзакции сложны везде.

С уважением, Gleb.
PS: ничего личного, бизнес-есть бизнес. Если чем-то задел, не обижайтесь.
Re[16]: Опять валидация данных
От: GlebZ Россия  
Дата: 23.03.05 18:03
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Здравствуйте, GlebZ, Вы писали:


GZ>>Дизайн должен быть проще чем в решении без DSL.


S>Дизайн прикладного решения от наличия DSL мало зависит. Реализация — да, так как фремворк берет на себя все что можно формализовать и автоматизировать. Способ выражения мыслей — разный и в случае с DSL — более удобный. Но, мысли-то и их комбинирование — одни и те же.

+1. Только замечу. В случае DSL — прикладной программист обязан делать код, в котором многие параметры могут быть изменены в процессе эксплуатации (например законодательство изменилось). Для этого собственно DSL и предназначен. Для простого внесения изменений. В случае не DSL, у одной команды степеней свободы значительно больше.

GZ>>Поэтому разделение БО и DTO — не рекомендуется.


S>И эта одна из интересных тем. ИМХО, ты прав, крайне не желательно. А то прикладной программист запутается нафиг.

S>Правда непонятно вот что: иногда DTO специально делаются по структуре не такие как БО. Как в этом-то случае поступать ?
Именно об этом и говорю. Не надо так поступать.

С уважением, Gleb.
Re[15]: Опять валидация данных
От: stalcer Россия  
Дата: 24.03.05 08:11
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Прежде всего реши, где ты обрабатываешь транзакции, на сервере приложений, или на БД. Сбрасывать посередине, нельзя. См. Блокировки БД.


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

Одним из основных критериев дизайна фреймворка я ставлю согласованность данных с точки зрения прикладной программы.


S>><Skip'нуто про проверку ссылочной целостности на серврере приложений>.

GZ>Если очень хочется, организуй запросы. Но по сравнению со стандартным механизмом — чрезвычайно тормозно и чрезвычайно сложно.

Да уж, торомозно. И по этому не подходит. Но, это же решение "в лоб". Может быть есть более интеллектуальные подходы ?


S>>Пусть, есть некий сервер приложений, к которому коннектятся пользователи, т.е. на сервере есть открытые сессии. Каждая сессия имеет свой экземпляр VM доменного языка, свой объектный кэш (небольшой!), и свое подключение к базе (отдельную текущую SQL транзакцию). Пусть, для простоты применяются сериализованные транзакции, потому-что так меньше гемороя с инвалидацией объектов в кэше сессии, т.е. мы можем утверждать, что объект, прочитанный в определенный момент транзакции, будет иметь валидное состояние аттрибутов до ее конца, поскольку изменения, сделанные другими сессиями нам не видны.


GZ>1. Потеря масштабируемости. Причем достаточно громадное.


Ето про что? Про статефул сессию или сериализованные транзакции? Подробнее, плиз.


GZ>2. Неправильное понимание сериализованных транзакций. Посмотри за счет чего они реализуются. Если вручную то ты ляжешь, если с помощью сервера БД — он ляжет. Да и вручную ты это реализовать вряд-ли возможно(логгинг изменений + откаты).


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


GZ>То есть насколько я понял — это statefull.


Йес. Хотя, это к кэшу второго уровня никак не относится. Даже если бы был стателесс, то кэш второго уровня все равно бы хранил объекты на протяжении работы сервера приложений.


GZ>Неверно. Сервер приложений должен иметь такую-же надежность как и сервер БД. Однако ты наверно имел ввиду, что сессия может сбрасываться.


Это я подготавливал почву для следующей мысли: так как сервер приложений не отвечает за хранение данных, то в случае его падения данные, в целом, не пострадают. И поэтому, алгоритмы, применяемые для его реализации могут быть оптимизированы по скорости, и вовсе не обязательно применение супер-пупер отказоустойчивых алгоритмов, какие применяются в СУБД. Т.е. алгоритмы становяться возможно проще, и возможно производительнее.
И, в частности, алгоритмы кэша второго уровня тоже.


GZ>Для этого и делают кластеризацию СУБД. Что-бы мы как меньше задумывались об этом. Но в кластеризации ничего хорошего нет.


Нет ничего плохого в наличии нескольких серверов приложений. Разве не так? Я вижу только плюсы.


GZ>Проблема не только в тяжелом механизме SQL запросов. Локальные базы нормально справляются с навигационным доступом. Большие базы обычно находятся на другом сервере, соответсвенно, большое кол-во межпроцессорных вызовов обеспечено.


Одна проблема в том, что реляционные СУБД для этого просто не предназначены. Ни их способ хранения данных в файлах, ни их механизм запросов, ни даже струтура клиентского API.
Другая, как ты правильно сказал, — "большое кол-во межпроцессорных вызовов".

У меня Oracle стоит и локально и на другой машине локальной сети (100Мбит). Разницы — никакой! Так что первая проблема получается больше второй.


S>>- Он один на весь сервер приложений, а не на сессию.

GZ>Сразу встречаем проблему балансировки.

Ето что такое за зверь?

GZ>Значит версионификация.


Йес.


GZ>Да, но он будет в кэше в несогласованном состоянии. А если один и тот-же объект будет изменять сразу две сессии? А если на основе старой версии будет созданы новые объекты?


GZ>В любом случае кэш надо синхранизировать. При любом изменении кэша у тебя пойдет копирование между серваками(нельзя держать уже протухшие данные, пользователи обидятся). В результате, получишь сильнейший трафик который нужно еще реализовать.


Транзакционность кэша — вот ответ на эти вопросы. Все будет абсолютно согласованно! Я же сказал — транзакционность — один из главных моментов.


GZ>Понятненько. Только механизм транзакций всегда достаточно сложный и нетривиальный для всех систем. Ты его как-то обходишь стороной.


Просто отделяю мух от котлет. Чтобы не запутаться. Это отдельный вопрос, более того он зависит от применения или не применения сериализованных SQL транзакций. Вечером попытаюсь сформулировать и запостить.


GZ>Здесь есть зависимость от сложности объекта. Объект в базе нормализован. И подгружается обычно либо распределнным запросом, либо он разделяется на несколько объектов.


С точки зрения производительности нет никакой разницы, что скачивать: "сложный объект" пятью разными запросами или пять простых объектов (тем же количеством запросов).
Что такое "распределенный запрос"? Просто join нескольких таблиц?


S>>Так как с кэшем второго уровня работают несколько сессий и так как он сериализуется в файл для последующего использование данных, то вероятность, что эти лишние данные будут востребованы возрастает, по сравнению с сессионным кэшем.

GZ>Вот это не понял.

Не понял, что здесь можно не понять ?


GZ>1. Такая система уже есть, и называется Prevalyer. Мое мнение о нем, можно посмотреть здесь
Автор: Poudy
Дата: 10.03.05


Посмотрю . Я думал, что это не кэш поверх базы, а просто некая маленькая СУБД-подобная штука.


GZ>2. В данном случае описана statefull модель. Основные недостатки statefull модели — низкая масштабируемость. Основная нагрузка идет даже не за счет недостатка памяти, а за счет синхронизации сессий и их транзакций. Тут уж балансировкой не отделаешься.


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


GZ>3. Держать коннекты на базе — очень плохо для такого решений. После 200 коннектов практически любой БД умрет. Притом в тексте какое-то противоречие между транзакциями БД и ручными.


Ну пусть будут не коннекты, изначальное требование — одна текущая SQL транзакция на одну сессию. С точки зрения OCI, например, коннект и транзакция — это разные вещи. Я бы даже сказал в определенной степени независимые.
В принципе, сразу после того, как сессия сделает очередной коммит и до следующего первого обращения к базе этой текущей транзакции может и не быть.


GZ>4. Я так и не понял систему транзакций. Насколько я понял, используется версионный механизм. Он достаточно хорош для оптимистических транзакций. Но для пессимистических — нужно очень постараться. Правда, гарантированные пес. транзакции сложны везде.


То, что понимается обычно под версионным механизмом, и то, что хочу сделать я — разные вещи.
Оычно весионный механизм используется для, того, чтобы ругнуться сбрасывая изменения в базу, если другой сеанс успел первым сбросить свои изменения.
Дык, между прочим, Oracle'овские сериализованные транзакции делают это автоматически! И этот факт я собираюсь всячески юзать.

Я же здесь пишу про механизм именно для поддержания согласованности данных взятых из кэша для отдельной сессии по отношению к отдельной SQL транзакции и для возможности ре-использования закэшированных (в кэше второго уровня) данных другими сессиями или этой же сессией позже, т.е. в контексте другой SQL транзакции.


GZ>PS: ничего личного, бизнес-есть бизнес. Если чем-то задел, не обижайтесь.


Наоборот, спасибо за проявленный интерес. Просто идея мне кажется несколько авантюрной, поэтому я и просил сильно не бить и сразу далеко не посылать .
http://www.lmdinnovative.com (LMD Design Pack)
Re[17]: Опять валидация данных
От: stalcer Россия  
Дата: 24.03.05 09:19
Оценка:
Здравствуйте, GlebZ, Вы писали:

S>>Правда непонятно вот что: иногда DTO специально делаются по структуре не такие как БО. Как в этом-то случае поступать ?

GZ>Именно об этом и говорю. Не надо так поступать.

Как "так"? Не делать DTO отличными от БО?
http://www.lmdinnovative.com (LMD Design Pack)
Re[18]: Опять валидация данных
От: GlebZ Россия  
Дата: 24.03.05 17:20
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Здравствуйте, GlebZ, Вы писали:


S>>>Правда непонятно вот что: иногда DTO специально делаются по структуре не такие как БО. Как в этом-то случае поступать ?

GZ>>Именно об этом и говорю. Не надо так поступать.

S>Как "так"? Не делать DTO отличными от БО?

Для прикладника, зачем?

С уважением, Gleb.
Re[16]: Опять валидация данных
От: GlebZ Россия  
Дата: 24.03.05 17:56
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Здравствуйте, GlebZ, Вы писали:


GZ>>Прежде всего реши, где ты обрабатываешь транзакции, на сервере приложений, или на БД. Сбрасывать посередине, нельзя. См. Блокировки БД.


S>Это почему еще. Даже у Фаулера, если мне не изменяет память , говориться, что в случае маленьких транзакций можно откладывать сброс до конца, а для транзакций, работающих с большим объемом данных — можно и сбрасывать (но, точно не помню, может и вру).

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

S>Одним из основных критериев дизайна фреймворка я ставлю согласованность данных с точки зрения прикладной программы.

+1.


S>>><Skip'нуто про проверку ссылочной целостности на серврере приложений>.

GZ>>Если очень хочется, организуй запросы. Но по сравнению со стандартным механизмом — чрезвычайно тормозно и чрезвычайно сложно.

S>Да уж, торомозно. И по этому не подходит. Но, это же решение "в лоб". Может быть есть более интеллектуальные подходы ?

Нет. По крайней мере я о них не слышал.


S>>>Пусть, есть некий сервер приложений, к которому коннектятся пользователи, т.е. на сервере есть открытые сессии. Каждая сессия имеет свой экземпляр VM доменного языка, свой объектный кэш (небольшой!), и свое подключение к базе (отдельную текущую SQL транзакцию). Пусть, для простоты применяются сериализованные транзакции, потому-что так меньше гемороя с инвалидацией объектов в кэше сессии, т.е. мы можем утверждать, что объект, прочитанный в определенный момент транзакции, будет иметь валидное состояние аттрибутов до ее конца, поскольку изменения, сделанные другими сессиями нам не видны.


GZ>>1. Потеря масштабируемости. Причем достаточно громадное.


S>Ето про что? Про статефул сессию или сериализованные транзакции? Подробнее, плиз.

statefull+connection.


GZ>>2. Неправильное понимание сериализованных транзакций. Посмотри за счет чего они реализуются. Если вручную то ты ляжешь, если с помощью сервера БД — он ляжет. Да и вручную ты это реализовать вряд-ли возможно(логгинг изменений + откаты).


S>В Oracle на версионности, так же как и не сериализованные . А вообще, у достаточно широкого класса прикладных задач статических данных гораздо больше, чем часто меняющихся. Так что базе вообщем-то по барабану.

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

S>И вообще-то под сериализованными транзакциями я имел в виду именно Oracle'овские сериализованные транзакции, которые, как было выяснено общими усилиями форума про базы данных, нельзя считать строго сериализованными. Но они обладают главным достоинством — предоставляют согласованные данные на протяжении всей транзакции.

Дай ссылку на обсуждение.


GZ>>То есть насколько я понял — это statefull.


S>Йес. Хотя, это к кэшу второго уровня никак не относится. Даже если бы был стателесс, то кэш второго уровня все равно бы хранил объекты на протяжении работы сервера приложений.

Stateless хранит объекты на протяжении запроса. Будут ли они дальше хранится или перечитываться — уже не важно.


GZ>>Неверно. Сервер приложений должен иметь такую-же надежность как и сервер БД. Однако ты наверно имел ввиду, что сессия может сбрасываться.


S>Это я подготавливал почву для следующей мысли: так как сервер приложений не отвечает за хранение данных, то в случае его падения данные, в целом, не пострадают. И поэтому, алгоритмы, применяемые для его реализации могут быть оптимизированы по скорости, и вовсе не обязательно применение супер-пупер отказоустойчивых алгоритмов, какие применяются в СУБД. Т.е. алгоритмы становяться возможно проще, и возможно производительнее.

S>И, в частности, алгоритмы кэша второго уровня тоже.


GZ>>Для этого и делают кластеризацию СУБД. Что-бы мы как меньше задумывались об этом. Но в кластеризации ничего хорошего нет.


S>Нет ничего плохого в наличии нескольких серверов приложений. Разве не так? Я вижу только плюсы.

Синхронизация кеша между различными серверами.


S>Одна проблема в том, что реляционные СУБД для этого просто не предназначены. Ни их способ хранения данных в файлах, ни их механизм запросов, ни даже струтура клиентского API.

S>Другая, как ты правильно сказал, — "большое кол-во межпроцессорных вызовов".

S>У меня Oracle стоит и локально и на другой машине локальной сети (100Мбит). Разницы — никакой! Так что первая проблема получается больше второй.

Maybe. Oracle — очень тяжелая вещь.

S>>>- Он один на весь сервер приложений, а не на сессию.

GZ>>Сразу встречаем проблему балансировки.

S>Ето что такое за зверь?

Балансировка — распределение нагрузки между несколькими серверами. Но я оговорился. Проблема синхронизации кэша.

GZ>>Значит версионификация.


S>Йес.



GZ>>Да, но он будет в кэше в несогласованном состоянии. А если один и тот-же объект будет изменять сразу две сессии? А если на основе старой версии будет созданы новые объекты?


GZ>>В любом случае кэш надо синхранизировать. При любом изменении кэша у тебя пойдет копирование между серваками(нельзя держать уже протухшие данные, пользователи обидятся). В результате, получишь сильнейший трафик который нужно еще реализовать.


S>Транзакционность кэша — вот ответ на эти вопросы. Все будет абсолютно согласованно! Я же сказал — транзакционность — один из главных моментов.

Слова-слова. Уже писал ниже.

GZ>>Понятненько. Только механизм транзакций всегда достаточно сложный и нетривиальный для всех систем. Ты его как-то обходишь стороной.


S>Просто отделяю мух от котлет. Чтобы не запутаться. Это отдельный вопрос, более того он зависит от применения или не применения сериализованных SQL транзакций. Вечером попытаюсь сформулировать и запостить.

Ждемс.


S>С точки зрения производительности нет никакой разницы, что скачивать: "сложный объект" пятью разными запросами или пять простых объектов (тем же количеством запросов).

S>Что такое "распределенный запрос"? Просто join нескольких таблиц?
Да.


S>>>Так как с кэшем второго уровня работают несколько сессий и так как он сериализуется в файл для последующего использование данных, то вероятность, что эти лишние данные будут востребованы возрастает, по сравнению с сессионным кэшем.

GZ>>Вот это не понял.

S>Не понял, что здесь можно не понять ?

Сессионный кеш обычно содержит только измененные данные в контексте транзакции. Остальное в кэше application.


GZ>>1. Такая система уже есть, и называется Prevalyer. Мое мнение о нем, можно посмотреть здесь
Автор: Poudy
Дата: 10.03.05


S>Посмотрю . Я думал, что это не кэш поверх базы, а просто некая маленькая СУБД-подобная штука.



GZ>>2. В данном случае описана statefull модель. Основные недостатки statefull модели — низкая масштабируемость. Основная нагрузка идет даже не за счет недостатка памяти, а за счет синхронизации сессий и их транзакций. Тут уж балансировкой не отделаешься.


S>Масштабируемость можно обеспечить за счет применения нескольких серверов приложений, работающих с одной базой. Про синхронизацию сессий — не понял в чем проблема?

Неправильно выразился, измененные объекты+2-3 фазная фиксация+в твоем случае кэш.

S>Эх, были бы сервера приложений легковесные, я бы их в каждом отделе вешал, как сетевые принтеры .

Нежелательно. Трафик будет за дай боже.

GZ>>3. Держать коннекты на базе — очень плохо для такого решений. После 200 коннектов практически любой БД умрет. Притом в тексте какое-то противоречие между транзакциями БД и ручными.


S>Ну пусть будут не коннекты, изначальное требование — одна текущая SQL транзакция на одну сессию. С точки зрения OCI, например, коннект и транзакция — это разные вещи. Я бы даже сказал в определенной степени независимые.

S>В принципе, сразу после того, как сессия сделает очередной коммит и до следующего первого обращения к базе этой текущей транзакции может и не быть.
Именно для Oracle — коннект дорого обходится. MSSQL в этом смысле дешев.


GZ>>4. Я так и не понял систему транзакций. Насколько я понял, используется версионный механизм. Он достаточно хорош для оптимистических транзакций. Но для пессимистических — нужно очень постараться. Правда, гарантированные пес. транзакции сложны везде.


S>То, что понимается обычно под версионным механизмом, и то, что хочу сделать я — разные вещи.

S>Оычно весионный механизм используется для, того, чтобы ругнуться сбрасывая изменения в базу, если другой сеанс успел первым сбросить свои изменения.
S>Дык, между прочим, Oracle'овские сериализованные транзакции делают это автоматически! И этот факт я собираюсь всячески юзать.
Ну-ну. После ссылки на обсуждения выскажу мнение.

S>Я же здесь пишу про механизм именно для поддержания согласованности данных взятых из кэша для отдельной сессии по отношению к отдельной SQL транзакции и для возможности ре-использования закэшированных (в кэше второго уровня) данных другими сессиями или этой же сессией позже, т.е. в контексте другой SQL транзакции.

Теперь уже транзакции? В любом случае дорого. После ссылки на обсуждения.


С уважением, Gleb.
Re[17]: Опять валидация данных
От: GlebZ Россия  
Дата: 24.03.05 18:24
Оценка:
Ну не пойму. Сериализованные транзакции без блокировки невозможны. Притом блокировки на чтение. Притом блокировки должны быть упорядочены. Может ты ошибся с сериализованными транзакциями?

С уважением, Gleb.
Re[18]: Опять валидация данных
От: stalcer Россия  
Дата: 25.03.05 07:05
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Ну не пойму. Сериализованные транзакции без блокировки невозможны. Притом блокировки на чтение. Притом блокировки должны быть упорядочены. Может ты ошибся с сериализованными транзакциями?


Обсуждение здесь
Автор: Merle
Дата: 26.02.04
.

Но, Oracle никогда не ставит блокировки на чтение. Там вообще нет такого понятия.

И Oracle'овские сериализованные транзакции нельзя считать строго соответстующими ANSI SQL. По сравнению с обычными read committed транзакциями Oracle-сериализованные (назовем их так ) дают лишь следующее преимущество:
В таких транзакциях текущее соединение не видит никаких изменений, сделанных другими соединениями, после начала транзакции!
Т.е. read committed видит только подтвержденные изменения, а Oracle-сериализованные не видят никаких, даже подтвержденных.

Т.е. Oracle-сериализованная транзакция на протяжении всей своей жизни видит все данные в виде как они были на момент ее начала.


Это и есть главное полезное ее свойство. Для моего случая.

Все! Это единственное их отличие. Никаких дополнительных блокировок такие транзакции не ставят. Это тот компромис, на который пошел Oracle, отступая от стандарта, чтобы обеспечить данное свойство с приемлимой производительностью.

Предлагаю принять это как факт для дальнейших обсуждений основного вопроса.
http://www.lmdinnovative.com (LMD Design Pack)
Re[17]: Опять валидация данных
От: stalcer Россия  
Дата: 25.03.05 10:42
Оценка: 18 (1)
Здравствуйте, GlebZ, Вы писали:

Ладно. Я все поскипал, а то мы уже отвлеклись от главного вопроса.

Решение которое я предлагаю — это ведь не только кэш второго уровня. Это некая система, в которой каждый из компонентов важен. И только все вместе они будут работать. Так что предлагаю не натягивать мою архитектуру на стандартные подходы (типа statefull или stateless), а постараться понять ее в целом — как систему взаимосвязанных идей.

Итак, что я хочу сделать (читай — исходные требования к функциональности):


Некоторые соображения по поводу предыдущих пунктов:


Немного о реализации "framework-транзакции":

Скажу только то, что нужно для дальнейших рассуждений. Каждая "framework-транзакция" опирается на отдельную транзакцию БД. Т.е. в начале "framework-транзакции" открывается транзакция БД, в конце — она соответственно подтверждается или откатывается. В течении "framework-транзакции" сессия взаимодействует с базой. Неважно каким образом и для чего, важно, что взаимодействует, и поэтому состояние кэша должно соответствовать видимому (с учетом уровня изоляции) состоянию базы. Если не всегда, то хотя бы в некоторых контрольных точках. Например, перед выполнением OQL запроса, использующего SQL запросы БД. Поэтому, изменения, накопившиеся в кэше, придется в таких контрольных точках сбрасывать в базу, независимо от того, хорошо это или плохо! Вот!

Далее, о кэшах:

Я рассматриваю два кэша — сессионный кэш и кэш второго уровня. Больше никаких кэшей в данной архитектуре нет.

Для ясности , я хочу объяснить, что я понимаю под сессионным кэшем:

Пусть, для простоты, пока не будет кэша второго уровня, и все данные в сессионный кэш поступают из базы.

— Сессионный кэш — один на сессию! Он небольшой. Объекты в нем лежат в формате, в котором они и используются в доменном языке. Т.е. объект, лежащий в сессионном кэше и объект, используемый в доменном языке — это один и тот же объект.
— Так как объекты лежащие в кэше одновременно используются и в языке, и так как состояние программы (не полей бизнес объектов) держится на протяжении всей сессии (а не только одной транзакции), то кэш после завершения транзакции полностью тоже не сбрасывается. Те объекты, на которые программа держит ссылки (возможно в глобальных переменных) — остаются в кэше гарантированно. Таким образом identity map сессии обеспечивает уникальность объектов (по OID) не только в контексте одной транзакции, но и в контексте всей сессии.
— Вообще, какие-либо объекты из сессионного кэша могут быть удалены в любой момент (учитывая ограничение предыдущего пункта). Т.е. на протяжении транзакции они могут быть несколько раз прочитаны и удалены. Работает обычный алгоритм LRU или MRU. Т.е. транзакция сама по себе не держит объекты в кэше.

Далее, доменный объект имеет специальный тип полей, назовем их хранимые аттрибуты. Система (и в частности компилятор доменного языка) генерит для них необходимый код.
Хранимые аттрибуты отличаются от простых полей тем, что они транзакционны. Т.е. даже если объект не был удален из кэша по завершению транзакции, состояние его хранимых аттрибутов будет правильным по отношению к следующей транзакции (он попросту перечитает свое состояние из БД, при необходимости).

Как я реализовал такое поведение хранимых аттрибутов:
Во первых, по скольку транзакции SQL — сериализованные, то объект, прочитанный в каком-либо месте "framework-транзакции" больше не нуждается в перечитке до конца этой транзакции.
И, повторюсь, в соответствии с требованиями (см. выше в данном посте) "framework-транзакция" может быть только одна в текущий момент.
Исходя из этого каждой транзакции я присваиваю номер (просто автоинкрементный, но в пределах сесиии, т.е. он локальный и нигде не сохраняемый). И в заголовке объекта, также хранится номер. При обращении к аттрибуту (как на чтение так и на запись) значения этих номеров сравниваются. Если они одинаковы — объект уже был подгружен в течении этой транзакции, если разные — объект подгружается и номер в заголовке изменяется на текущий. При таком подходе при откате или подтверждении транзакции достаточно просто увеличить одну переменную "номер текущей транзакции" на единицу. Даже по кэшированным объектам пробегать не нужно. ИМХО очень эффективно.

Таким образом, обеспечивается строгая синхронизация сессионного кэша с видимым состоянием БД.

Еще один вывод: Из способа реализации хранимых аттрибутов видно, что объект какое-то время может находится в кэше в неподгруженном состоянии. В некоторых научных статьях говориться, что это даже может быть хорошо, так как объект не всегда используется для доступа к хранимым аттрибутам. Например, может быть я просто хочу сравнить две ссылки на идентичность, в этом случае объект уже должен быть в IdentityMap, а подгружать его поля не обязательно.

Ну, на последок: Сессионный кэш сделан имеено так, а не иначе, для того, чтобы он был небольшой, относительно простой в реализации, имел относительно малый овехед. Он предназначен для кэширования объектов, в которыми в данный момент работает программа.
Привязка IdentityMap к сессии, а не к транзакции, отсутствие удержания объектов в кэше до конца транзакции (и использование LRU для очиски кэша) позволяют прикладному программисту вообще не знать о кэше и работать так как будто бы он работает напрямую с объектами, хранящимися в базе. Что есть несомненный Good!

И, на самый последок: Может быть эта архитектура и не оптимально производительна, но она абсолютно не противоречива. И вероятно более проста в понимании для прикладного программиста.

В этом посте я описал архитектуру самого framework как бы без кэша второго уровня. Кэш второго уровня должен быть вставлен между сессией и базой. О нем в следущем посте ( ). Но, описывать его я буду опираясь именно на эту архитектуру.
http://www.lmdinnovative.com (LMD Design Pack)
Re[19]: Опять валидация данных
От: GlebZ Россия  
Дата: 25.03.05 10:48
Оценка:
Здравствуйте, stalcer, Вы писали:

S>

S>Т.е. Oracle-сериализованная транзакция на протяжении всей своей жизни видит все данные в виде как они были на момент ее начала.


Вы взяли некоторое определение не понимая смысла и самого механизма. Постараюсь объяснить как работают сериализованные транзакции, и их исключения для Oracle.
Сначало что такое двухфазный протокол блокировок.
1 Фаза. Фаза накопления. Блокировки накопляются и не могут быть сброшены.
2 Фаза. Фаза сброса. При коммите или откате — блокировки после сохранения данных сбрасываются.

Итого, у нас есть serializable транзакция. Она отличается тем, что выполняет блокировки на чтение любой прочитанной информации. И за счет этого гарантирует консинсентность данных. Ни одна другая транзакция, не может изменять данные, которые задействованы в сериализованной транзакции.
1. Транзакция читает некоторые данные. При этом, при чтении сериализованная транзакция обязана заблокировать данную запись X блокировкой. X-блокировка — обозначает, что ни одна другая транзакция не может прочитать(и уж тем более записать) значение в этот объект.
2. Транзакция записывает значение в эту строку, и вообще, она может с ней делать все что угодно. Поскольку у нас X — блокировка — все остальные ждут в саду.
3. Транзакция коммитится. Блокировка снимается.
Насколько ты понял, что все транзакции которые пытаются даже прочитать данные, ожидают фазы сброса данной транзакции. К тому же повышается вероятность deadlock. Поэтому и кладутся сервера. И если бы не это свойство, мы бы давно уже жили при сериализованных транзакциях.
Теперь об Oracle. Дело в том, что у него нет X-блокировки. Точнее его блокировка не подпадает под это определение. И у него только один тип блокировок. Скорее она похожа на U-блокировку + ручное управление. И в данном случае получается так, что при сериализованной транзакции, любая прочитанная информация блокируется. То же самое можно сделать с помощью команды SELECT .... FOR UPDATE. Если она была уже заблокирована, то идет ожидание когда блокировка будет снята. Но поскольку блокировка действует только для других сериализованных транзакций, или для запросов в виде SELECT ... FOR UPDATE, то другие виды транзакций могут спокойно читать данные (в отличие от блокировочников). Для других видов транзакций (которые не сериализабле), существование блокировки определяется только при изменении данных.

Ну и что у нас получается. Для выполнения протокола, ты обязан перечитать данные с Oracle, чтобы он смог заблокировать данные. Но это совершенно не клеится в твою задачу.

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