Опять валидация данных
От: 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[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[33]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 31.03.05 12:37
Оценка: 55 (2)
Здравствуйте, stalcer, Вы писали:
S>Вот пример, который я приводил выше:
Совершенно верный подход к проблеме. Именно из-за этого я не очень люблю O/R Mapping — системы.
В идеальной ООСУБД такой проблемы возникнуть не может, т.к. сам механизм обеспечивает все что надо. Движок запросов в курсе про кэш, и использует его как обычно — чтобы минимизировать трафик с диском. При выполнении запроса сначала строится план, потом он исполняется. Фактически, все предикаты вычисляются именно в кэше, в который по мере необходимости поднимаются объекты. Именно так работают RDBMS.

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


Еще я хотел бы отметить, что в данном контексте мы неявно перешли от OQL, который позволяет очень-очень много чего, к чему-то типа OCL. Потому что все обсуждаемые запросы сводятся к получению списка объектов. OQL позволяет возвращать самые дикие структуры, которые не соответствуют никакому исходному типу данных. Попытка реализовать полноценный OQL поверх РСУБД, что с кэшированием, что без — это практически самоубийство.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[46]: Опять валидация данных
От: GlebZ Россия  
Дата: 07.04.05 12:31
Оценка: 36 (1)
Здравствуйте, Sinclair, Вы писали:

S>Очень вряд ли. Там же фиксированный список будет. Сколько у тебя может быть потомков у класса в системе? 1000? Ерунда — полетит со страшной скоростью.


S>Ага. Это, конечно, правильно. Но мы даем шикарную возможность вынудить сервер заниматься бессмысленной работой. Все должно быть оправдано. Если ты не можешь придумать реальный пример, который бы требовал именно as, то незачем его и делать.

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

Я вообще пока пошел по другому пути. Ввел понятие typeing. Например такой запрос:
select FucObjects

возвращает все объекты наследованные от FucObject — то есть, практически все объекты находящиеся в БД. А вот так не надо строить много as.
select FucObjects typeing typeas(FucObjects, FucDocument, FucMessage)

вернуть array<FucObjects> у которых реальный тип объектов FucDocument и FucMessage.
И еще одну феньку сделал. Можно в одном запросе возвращаеть сразу несколько наборов.

select a, b where a=10 and b=20

будет определено что это два графа выполнения, и будет возвращено два результирующих набора.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[24]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.03.05 08:15
Оценка: 34 (1)
Здравствуйте, stalcer, Вы писали:

S>Ну не знаю. Зачем тогда делают язык на клиенте. Это же геморрой. Но все же делают. Видимо — тормозит.

Кто делает? Какой язык?

S>Посмотрю .


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

Не, тут поинт в том, чтобы специально разрабатывать интерфейс с учетом минимизации общения между клиентом и сервером. Бинарность передачи данных сама по себе — не панацея. HTML клиент может даже порвать rich клиента за счет того, что он прокачивает только необходимые данные. Ну и плюс встроенная поддержа gzip-компрессии для передаваемого контента вместе с интеллектуальным кэшированием способна на многое.
S>А хочу я, чтобы было похоже на WinForms клиент. Т.е. формочки в MDI, менюшки, панельки, ну и работа с данными — передача на клиент, чтоб не тормозила, сортировки там всякие, поиски, фильтры, кнопочки на формах и т.п.
Это все делается в рамках web-клиента без особых проблем. Многие особенности, присущие толстым клиентам, на практике малопригодны с точки зрения пользователя. Т.е. например воспроизвести всю MS VS 2005 как веб-клиента нереально. Все эти dockable tabbed interface и все такое... Но это интерфейс, ориентированный на очень специальную таргет группу. Нормальным людям, клиентам бизнес приложений, все это только вредит.
Более того, пересмотр самой модели взаимодействия приложения с пользователем в пользу "вебнутого" интерфейса помогает повысить масштабируемость приложения и улучшить user experience. Первое — потому, что там ты вынужден избегать лишних зависимостей и непроизводительной нагрузки; второе — потому, что ты вынужден тщательнее заботиться о реализации use-cases вместо хаотического запихивания всех возможностей в правую кнопку и тулбары.
S>Я больше склоняюсь в тому, что это все таки возможно сделать так, чтобы приемлимо производительно работало.
Я больше склоняюсь к тому, что при проектировании клиента надо очень критически относиться к решениям, диктуемым определенной технологией разработки. Программисту очень легко забыть о том, что приложение — не упражнение по кодингу, а средство решения проблем его пользователей.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
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[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[45]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.04.05 07:52
Оценка: 5 (1)
Здравствуйте, stalcer, Вы писали:

S>Хорошо. Но, если вершиной иерархии наследования является ClassA, то твой OQL запрос, после преобразования в SQL будет неявно содержать where условие. Так что, явно я его указываю или оно само неявно в SQL запрос вписывается — неважно. Вопрос в том, как это эффективно реализовать?

Хороший вопрос. С точки зрения теории кристалла, мы можем работать с глобальным экстентом, ограничивая его предикатами. Например, предикатом реализации интерфейса или наследования от класса:
public bool Predicate1(object o)
{
    return o is ClassA;
}
public bool Predicate2(object o)
{
    return o is Interface1 && o is Interface2;
}

В реальности, запросы типа Predicate1 встречаются чаще любых других, поэтому от нижележащего слоя требуется способность эффективно выполнять сканирование экстентов.
На практике при использовании RDBMS в качестве нижнего слоя проще всего строить работу на основе View. Тогда для каждого случая можно выбирать способ раскладывания объектов по таблицам:
— хранить всех потомков некоторого класса в одной большой табличке, зануляя "лишние" атрибуты (потребуется хранить еще и идентификатор класса, чтобы построить view для каждого потомка)
— хранить каждый класс в отдельной табличке (потребуется сделать union для всех потомков каждого класса)
— хранить для каждого класса только "новые" поля, при сборке объектов выполнять join
Это связано с тем, что эффективность каждой реализации можно оценивать только с учетом статистики реального использования — количества объектов каждого класса и частоты соответствующих запросов.
Хранение либо нехранение ссылки на тип в ссылке на объект не зависит от выбора схемы хранения объектов; как правило оно все же применяется для оптимизации навигационных запросов и запросов типа where myObject.SomeReference is SomeClass.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
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[26]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.03.05 10:08
Оценка: 4 (1)
Здравствуйте, stalcer, Вы писали:
S>1С, например. Язык — в смысле скрипт.
Гм. Так это же совсем про другое. Скрипт — это же средство расширения функционала прикладными программистами. Он сам никак не связан с моделью взаимодействия.
S>>Это все делается в рамках web-клиента без особых проблем.
S>Это как?
В смысле как? Ты что, никогда сайтов с менюшками не видел?
S>>Более того, пересмотр самой модели взаимодействия приложения с пользователем в пользу "вебнутого" интерфейса помогает повысить масштабируемость приложения и улучшить user experience. Первое — потому, что там ты вынужден избегать лишних зависимостей и непроизводительной нагрузки; второе — потому, что ты вынужден тщательнее заботиться о реализации use-cases вместо хаотического запихивания всех возможностей в правую кнопку и тулбары.
S>Хочу чтобы было так:
S>
S>А не так:
S>
Внимание, вопрос: почему ты хочешь так? Ты уверен, что так, как ты хочешь — удобнее пользователям?
S>Наезд не понял .
Это не наезд. Это призыв разрабатывать интерфейсы, удобные пользователю. Вот, к примеру, Inductive User Interface гораздо легче реализовать в веб-модели, и при этом он считается более удобным, чем классический deductive interface. То, что ты приводишь в примере, больше похоже на deductive interface. Поэтому, прежде чем задаваться вопросом "как его реализовать", хочется задаться вопросом "зачем его реализовывать", и "его ли надо реализовывать".
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Опять валидация данных
От: aefimov Россия
Дата: 14.03.05 12:54
Оценка: :)
Здравствуйте, Козьма Прутков, Вы писали:

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

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

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

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

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

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

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

Спасибо!
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[20]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.03.05 23:27
Оценка: +1
Здравствуйте, stalcer, Вы писали:

S>А вообще гораздо более интересный вопрос — это как сделать так, чтобы прикладная программа работала только на сервере приложений, а на клиенте находилось нечто, чем можно было-бы управлять с сервера и что не требовало бы наличия VM на клиенте. А по функциональности, желательно, чтобы это нечто приближалось к обычному оконному GUI.

S>Уж больно заманчивая эта идея с точки зрения прикладных программистов: все программы на сервере в единой среде.
Ты над Web-клиентом не думал?
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[37]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.04.05 14:58
Оценка: :)
Здравствуйте, GlebZ, Вы писали:

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


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

GZ>Прямой перебор не всегда возможен. Например:
GZ>
GZ>SELECT A WHERE A.f>20 and A.B.f>10 AND A.B.C.f>20
GZ>

GZ>при этом — у нас существуют в кэше набор добавленных С, при этом нет соответсвующих B. В результате, мы должны подгрузить все B которые завязаны на С.
Надо подумать....
Упс, похоже мы вообще попали. Если у нас к примеру есть один миллион объектов типа A, и все эти A ссылаются на ровно один B, и по чистой случайности у нас именно этот B изменен в транзации (B.d = 5 вместо хранимого в СУБД d = 10), то результат запроса "select A where B.d = 5" не будет иметь никакого отношения к реальности. Увы, при этом перебор кэша не спасает — даже если мы и поймем, что запрос зависит именно от этого B, ничего полезного сделать уже нельзя — все данные про А по-прежнему сидят в базе, в кэше пусто. Упес пипиндур. Был неправ. Прошу срочно расстрелять меня за сортиром.
GZ>Статистика уже желательна на этапе трансформации OQL в SQL. Если бы SQL не влиял на планы запросов, было-бы очень хорошо. Но это не так. Допустим:
GZ>
GZ>SELECT A WHERE (A.B.F>20 AND A.C.F>20 AND A.C.F1=A.B.F1)
GZ>

GZ>где A.B и A.C — коллекции.
GZ>В результате два варианта:
GZ>
GZ>SELECT A.* FROM A 
GZ>WHERE 
GZ>    A.B IN (SELECT B.OID FROM WHERE B>20 AND 
GZ>        B.F1 IN (SELECT C.F1 FROM C WHERE C.F>20))
GZ>

GZ>И
GZ>
GZ>SELECT A.* FROM A 
GZ>WHERE 
GZ>    A.С IN (SELECT C.OID FROM C WHERE C.F>20 AND 
GZ>        с.F1 IN (SELECT B.F1 FROM WHERE B>20 ))
GZ>

GZ>Стандартные БД не умеют развертывать такие запросы. А без информации о кардинальности, можно сделать очень неприлично долгий запрос.
Гм. Вообще-то не стоит заниматься такими излишествами. Текст запроса должен быть таким:
select * from A 
inner join B on A.B = B.OID 
inner join C on A.C = C.OID
where C.F1 = B.F1
and B.F > 20 and C.F > 20

Уверяю — современный сервер вполне развернет такой запрос. И никаких проблем с кардинальностями не будет. А попытки вынудить сервер к определенному плану путем запутывания запросами — глупость. Лучеш выкинуть такую СУБД, и взять ту, которой можно доверять . Она ведь ради того и берется — иначе надо тупо на файлухе все делать.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Опять валидация данных
От: Козьма Прутков Россия  
Дата: 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[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:45
Оценка:
Здравствуйте, Козьма Прутков, Вы писали:

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


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


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

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

<skipped>


а похоже я уже и ответил, в предыдущем ответе на этот топик. или нет?
Re[2]: Опять валидация данных
От: Козьма Прутков Россия  
Дата: 15.03.05 08:47
Оценка:
Здравствуйте, IT, Вы писали:

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


Отлично. Ясно и по полочкам.
Да, с форматами и длинами я пожалуй спорить не буду: такие вещи крайне редко меняются, особенно форматы .
Рассмотрим веб-приложение (ибо сложнее), но аналогично и винформовое. Пусть по первоначальным требованиям поле Заказчик обязательное. Ок, сделали. Через 3 месяца оказывается, что оно не является обязательным. И мы шагом марш по всем уровням валидации это дело править. Или я чего-то не понял?
Таперь рассмотрим винформс-приложение (в веб-приложении решается написанием метода установки пары значений). Вот подвязана у нас к свойствам Country и ZipCode (он же индекс для примера) пара контролов. По идее, если пользователь меняет один из них, то нужно проверить их пару. Так что пользователь, однажды введя US/12345 уже никогда не введет RU/131000, ибо перекрестные комбинации невалидны. Ну, либо позволить перевести БО в неконсистентное состояние, что вряд ли очень хорошо.
Да хранит вас господь в сухом прохладном месте...
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.
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[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[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[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.
Re[19]: Опять валидация данных
От: stalcer Россия  
Дата: 25.03.05 11:29
Оценка:
Здравствуйте, GlebZ, Вы писали:

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

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

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

А вообще гораздо более интересный вопрос — это как сделать так, чтобы прикладная программа работала только на сервере приложений, а на клиенте находилось нечто, чем можно было-бы управлять с сервера и что не требовало бы наличия VM на клиенте. А по функциональности, желательно, чтобы это нечто приближалось к обычному оконному GUI.
Уж больно заманчивая эта идея с точки зрения прикладных программистов: все программы на сервере в единой среде.
http://www.lmdinnovative.com (LMD Design Pack)
Re[20]: Опять валидация данных
От: stalcer Россия  
Дата: 25.03.05 12:02
Оценка:
Здравствуйте, GlebZ, Вы писали:

Мдяяя. Я вижу Вы Oracle больше теоретически знаете (да и то неправильно). Ну давай на примере:

Делаем таблицу так:

create table ST (
  x number,
    y number
)
/
insert into ST values (1, 2)
/
insert into ST values (3, 4)
/
commit


А тепеь открываем два соединения и делаем следующее (в той последовательности, как написано):

Соединение1:
set transaction isolation level SERIALIZABLE
/
select * from ST /* Типа прочитали данные в сериализованной транзакции,
                    по твоему они должны были заблокироваться! */


Соединение2:
update ST set y = 10 /* Думаешь здесь будет ошибка или соединение повиснет, 
                        фигушки, все сработает! */
/
commit /* И это сработает */


Соединение1:
select * from ST /* Читаем еще раз в той же транзакции, т.к. соединение1 ни 
                    коммита ни роллбака не делало.
                    И получаем следующий набор данных:
                    *X*   *Y*
                     1     2
                     3     4
                    т.е. не видим подтвержденных соединением2 данных,
                    т.е. транзакция на самом деле сериализованная. */
/
commit /* Ну и это не вызовет никаких ошибок. */


Не веришь — проверь сам!

Вот еще, первое что нашел, может где-то есть развернутее: Из Oracle 8i Concepts:

Because Oracle does not use read locks in either read-consistent or serializable
transactions, data read by one transaction can be overwritten by another...

http://www.lmdinnovative.com (LMD Design Pack)
Re[20]: Опять валидация данных
От: stalcer Россия  
Дата: 25.03.05 12:42
Оценка:
Здравствуйте, GlebZ, Вы писали:

А вот еще один веселенький примерчик. Для глбины понимания, так сказать :

Делаем таблицу так же:

create table ST (
  x number,
    y number
)
/
insert into ST values (1, 2)
/
insert into ST values (3, 4)
/
commit


А тепеь открываем два соединения и делаем следующее (в той последовательности, как написано):

Соединение1:
set transaction isolation level SERIALIZABLE /* Начинаем транзакцию до update'а во втором соединении.
                                                Это важно. */


Соединение2:
set transaction isolation level SERIALIZABLE
/
update ST set y = y + 1 /* Пройдет нормально */


Соединение1:
update ST set y = y + 1 /* Повесится до окончания транзакции в Соединении2 */


Соединение2:
commit /* Пройдет нормально */


Здесь Соединение1 перестанет висеть и самое интересное, что тот оператор update, на котором оно висело выдаст ошибку ORA-08177.

ORA-08177 can't serialize access for this transaction
Cause: Encountered data changed by an operation that occurred after the start
of this serializable transaction.
Action: In read/write transactions, retry the intended operation or transaction.

http://www.lmdinnovative.com (LMD Design Pack)
Re[21]: Опять валидация данных
От: GlebZ Россия  
Дата: 25.03.05 14:04
Оценка:
Здравствуйте, stalcer, Вы писали:

S>

S>Because Oracle does not use read locks in either read-consistent or serializable
S>transactions, data read by one transaction can be overwritten by another...


Б@@@,Б@@@,Б@@@
Чего-то я такого не ожидал от Oracle. Как раз то, о чем говорит Merle на каждом углу. Oracle сериальные транзакции отнюдь не serialize. Блин. Они не дают упорядоченного графика. Я никогда не использовал их, и сам додумал до нормального уровня. Не думал что так погано. Сериализованными они становятся только с ручной работой.
Итак, данные транзакции, если не использовать for update — отличаются только тем,
что более поздний update ты никогда не запишешь. Ну не могли как-то по другому обозвать.

Что мы получаем в результате. Возьмем твою таблицу.

create table ST (
  x number,
    y number
)
/
insert into ST values (1, 2)
/
insert into ST values (3, 4)
/
commit


Соединение1:
set transaction isolation level SERIALIZABLE
/
select y from ST where x=1;

выполняем на уровне бизнес-логики y=y+1, и запишем в y который стал 3 в строку где x=3
update st set y=3 where x=3;


Соединение2:
set transaction isolation level SERIALIZABLE
/
select y from ST where x=3;

выполняем на уровне бизнес-логики y=y-1, и запишем в y который стал 3 в строку где x=1
update st set y=3 where x=1;

Соединение1:
commit;

Соединение2:
commit;

В результате получаем результат, где везде y=3. То есть в результате ни та, ни другая транзакция своего не добилась. Обломс. И таких ситуаций можно придумать кучу. Потому как без блокировок на чтение или хотя бы таймстампы на чтение, согласованных данных не получишь.

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


S>Здесь Соединение1 перестанет висеть и самое интересное, что тот оператор update, на котором оно висело выдаст ошибку ORA-08177.


S>

S>ORA-08177 can't serialize access for this transaction
S>Cause: Encountered data changed by an operation that occurred after the start
S>of this serializable transaction.
S>Action: In read/write transactions, retry the intended operation or transaction.


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

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

GZ>Итак, данные транзакции, если не использовать for update — отличаются только тем,

GZ>что более поздний update ты никогда не запишешь. Ну не могли как-то по другому обозвать.

Нет. Главное тем, что ты не видишь подтвержденных изменений других транзакций. Это очень удобно.

GZ><skiped...>

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

Это как раз и есть Б@@@,Б@@@,Б@@@ . Но, это все равно лучше, чем read committed! Потому-что написать твой же пример правильно в read committed транзакциях тоже проблема.

Вообщем я выбрал такой режим как режим по умолчанию для framework'а. В отдельных ситуациях прикладная программа может накладывать блокировки явно, если есть необходимость.

У него ИМХО больше преимуществ, чем у какого-либо другого. Ты так не считаешь, — приведи лучший режим.
http://www.lmdinnovative.com (LMD Design Pack)
Re[18]: Опять валидация данных
От: GlebZ Россия  
Дата: 25.03.05 15:55
Оценка:
Здравствуйте, stalcer, Вы писали:

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

Согласен.

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

Честно говоря, мне это нравится. Я никогда не видел сложных и при этом "чистых" statefull или stateless моделей.
Все лишнее поскипаю. Либо я с этим согласен, либо оно как-то связано с другими предложениями.

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


S>- Система должна обеспечивать навигационный доступ и механизм запросов.

Маленький вопрос. В какой степени поддерживается навигационный доступ. Точнее, будет ли он работать по сети?

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

Было бы хорошо
S>- Однако уровень изоляции был выбран именно такой, для простоты реализации кэшей. При другом уровне изоляции, например, read committed, реализация была бы более сложной и производительность могла бы оказаться практически неприемлимой.
Как это не странно звучит, но в данной системе реализация read committed была бы сложней.
S>- Но, такой уровень изоляции имхо удобен и для прикладных программистов.
Честно говоря, согласно бизнес логике более важно понятие оптимистической и пессимистической транзакции. То есть, может ли юзер (а прикладному программисту надо эту ситуацию обрабатывать) получить отлуп по транзакции. Или он при загрузке какой-то формы (то есть открытии некоторой бизнес-транзакции) должен получить сообщение что данный объект редактируется таким-то таким, и пока не стоит его редактировать. Стандартная реализация БД транзакций — по умолчанию такого не дает. То есть, надо прописать — либо мы не будет никогда работать с пессимистической транзакцией, либо дать инструменты для из организации. Если второй вариант — напишу несколько неприятных проблем(с которыми сам встретился). К сожалению, если в проектах которых я участвовал нужен был транзакционный механизм, ни разу не пришлось ограничиваться оптимистическими. Постановщики излишне пессимистичны.

S>Например, перед выполнением OQL запроса, использующего SQL запросы БД.

OQL — это я люблю

S>- Вообще, какие-либо объекты из сессионного кэша могут быть удалены в любой момент (учитывая ограничение предыдущего пункта). Т.е. на протяжении транзакции они могут быть несколько раз прочитаны и удалены. Работает обычный алгоритм LRU или MRU. Т.е. транзакция сама по себе не держит объекты в кэше.

Хотелось бы в данном случае сказать. Скорее всегоIMHO, вероятность что будет обращение к измененным объектам — несколько выше, чем к остальным. Во вторых, непонятно все-таки из контекста, после транзакции практически все объекты в кэше становится невалидными?

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

Может ли объект хранить другие аттрибуты, которые зависят от транзакционных?

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

Здесь мне кажется, лучше пробежать. Ты занимаешь ресурсы — объектами которые уже никому никогда не понадобятся. И еще сразу вопрос: После отката транзакции — остаются или не остаются объекты DSL c ссылками. Если объект нельзя сбросить(перечитать) в случае отката (100% протухшие данные), то нужно что-то делать. Или я чего-то не усек.

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

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

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

Извиняюсь забыл разъяснить про момент отката транзакций. Меня интересует вопрос: ты написал про savepoint когда объекты сбрасываются на БД. Как будет обрабатываться ошибка, если она произойдет при сбросе?

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

S>У него ИМХО больше преимуществ, чем у какого-либо другого. Ты так не считаешь, — приведи лучший режим.

К сожалению, я так как-раз и не считаю. Сразу скажу, буду иметь ввиду, что как принято в ведущих SQL базах — вероятность ролбека на несколько порядков ниже чем вероятность коммита.
1. Как я уже показал, протокол не гарантирует что база будет находиться в кошерном состоянии. Хотя вероятность подобного не велика, но риск несогласованной базы значительно криминальней чем бы то ни было. И это должно лечь на плечи прикладного программиста.
2. Если транзакция не прошла, то ее уже никакими средствами не пропихнешь. Это плохо. При этом состояние ожидание (что отобразится у пользователя зависшим состоянием) все равно остается (мне непонятно зачем его сделали, но если они это сделали значит были причины(например откат старшей транзакции)).
3. Можно в любой момент получить откат транзакции. Тоже хреново — потому что прогнозировать нельзя. При этом, вероятность такого на порядок выше чем при остальных типах транзакций.
4. Вероятность дедлока высока.
5. При длинных транзакциях, вероятность что пользователи будут падать и виснуть увеличивается в несколько раз.(а у тебя как раз бизнес-транзакция завязана на системную, то есть вероятность длинной транзакции увеличивается).

Единственный плюс подобных транзакций — отчеты удобно делать

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

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


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

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

S>А какой изначальный смысл у DTO? Я всегда думал, что это не только объекты для передачи данных по сети, но в конечном счете DTO — это то с чем работает подсистема клиента. Ведь фактически в виде DTO данные приходят на клиент. А вдруг прикладная программа захочет показать (передать на клиент) информацию такой структуры, какого бизнес объекта и нет. Какую-нибудь сводную таблицу?

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

S>А вообще гораздо более интересный вопрос — это как сделать так, чтобы прикладная программа работала только на сервере приложений, а на клиенте находилось нечто, чем можно было-бы управлять с сервера и что не требовало бы наличия VM на клиенте. А по функциональности, желательно, чтобы это нечто приближалось к обычному оконному GUI.

S>Уж больно заманчивая эта идея с точки зрения прикладных программистов: все программы на сервере в единой среде.
Участвовал в разработке решения. В нем повторялась функциональность ASP сервера. На сервере скрипт в какой-то стрим. При встрече символов <% %> — выполнялось и результаты также в стрим. После этого все полученное выполнялось на клиенте. Практически — на клиента уходили только результаты и формы (все бизнес-логика находилась в <% %>, и выполнялась на сервере).
А не наличие VM — это Web-решение. Там VM поддерживается эксплорером.

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

S>Ты над Web-клиентом не думал?


Дело не во том, в какой технологии это будет реализовано. Можно, например, и в Delphi написать набор компонентов, которые будут по сути тонким клиентом.
Просто у меня сомнения — не тупиковая ли это идея в принципе. Т.е. идея в том, чтобы написать клиент, заложив в него какую-либо стандартную функциональность (отображение менюшек, показ форм, и в них работа с данными, и т.п.), так чтобы не нужно было выполнять прикладные программы (т.е. некоторую их часть) на клиенте. Не будет ли все это тормозить.
По моему в таком сценарии получается некое противоречие между производительностью и функциональностью. А я именно и хочу написать свой клиент (не веб), чтобы это противоречие насколько возможно сгладить. Потому как требование к функциональности у меня несколько больше, чем веб. Хочу чтобы внешне было похоже, ну скажем, на 1С.
http://www.lmdinnovative.com (LMD Design Pack)
Re[21]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 05:43
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>А не наличие VM — это Web-решение. Там VM поддерживается эксплорером.


Сделать VM на клиенте — не проблема. Это просто геморрой для прикладника. Так как единого вычислительного пространства не получается. Например, нельзя же домен-объекты вместе с идентити мапом держать и на клиенте. В принципе, можно, конечно извратиться, но че-то не хочется.
http://www.lmdinnovative.com (LMD Design Pack)
Re[24]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 05:53
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>К сожалению, я так как-раз и не считаю. <поскипано>


Дык, приведи пример лучшего режима.

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


Для прикладного программиста "framework-транзакция" — это и есть системная! Из них он сам должен лепить бизнес транзакции. Просто я другого универсального решения не вижу.
http://www.lmdinnovative.com (LMD Design Pack)
Re[22]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.03.05 06:09
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Дело не во том, в какой технологии это будет реализовано.

Ну, не совсем. Любая технология накладывает некоторые ограничения.
S>Можно, например, и в Delphi написать набор компонентов, которые будут по сути тонким клиентом.
S>Просто у меня сомнения — не тупиковая ли это идея в принципе. Т.е. идея в том, чтобы написать клиент, заложив в него какую-либо стандартную функциональность (отображение менюшек, показ форм, и в них работа с данными, и т.п.), так чтобы не нужно было выполнять прикладные программы (т.е. некоторую их часть) на клиенте. Не будет ли все это тормозить.
Гм. А с чего бы ему тормозить? Web-приложения же не тормозят.
S>По моему в таком сценарии получается некое противоречие между производительностью и функциональностью.
Зачем теоретизировать, когда есть практика? Посмотри, к примеру, на Exchange 2003 web access. Или на http://maps.google.com.
S>А я именно и хочу написать свой клиент (не веб), чтобы это противоречие насколько возможно сгладить.
Ну, тогда возьми удачные черты от веб, и дополни тем, чего нет.
S>Потому как требование к функциональности у меня несколько больше, чем веб.
Ты знаешь, я мало чего встречал такого, чтобы было заметно больше, чем веб. А если не заметно разницы, то зачем платить больше? (Конечно, я в курсе, что векторные интерфейсы от McSeem2 вряд ли удастся насколько-то близко воспроизвести в рамках HTML/CSS/JS)
S>Хочу чтобы внешне было похоже, ну скажем, на 1С.
Извини, я с ней незнаком. А что там есть такого, чего нету в вебе? Ты не мог бы объяснить + скриншоты там прислать...
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 07:01
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>Можно, например, и в Delphi написать набор компонентов, которые будут по сути тонким клиентом.

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

S>Гм. А с чего бы ему тормозить? Web-приложения же не тормозят.


Ну не знаю. Зачем тогда делают язык на клиенте. Это же геморрой. Но все же делают. Видимо — тормозит.

S>Зачем теоретизировать, когда есть практика?


Ну потеоретизировать тоже полезно.

S>Посмотри, к примеру, на Exchange 2003 web access. Или на http://maps.google.com.


Посмотрю .

S>>Хочу чтобы внешне было похоже, ну скажем, на 1С.

S>Извини, я с ней незнаком. А что там есть такого, чего нету в вебе? Ты не мог бы объяснить + скриншоты там прислать...

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

А хочу я, чтобы было похоже на WinForms клиент. Т.е. формочки в MDI, менюшки, панельки, ну и работа с данными — передача на клиент, чтоб не тормозила, сортировки там всякие, поиски, фильтры, кнопочки на формах и т.п.
Только без скриптов на клиенте .

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

GZ>Маленький вопрос. В какой степени поддерживается навигационный доступ. Точнее, будет ли он работать по сети?


Нафиг, нафиг. Не хочу по сети . Хочу чтобы вся программа выпонялась в одном месте (для этого и про клиент спрашиваю).

S>>- Однако уровень изоляции был выбран именно такой, для простоты реализации кэшей. При другом уровне изоляции, например, read committed, реализация была бы более сложной и производительность могла бы оказаться практически неприемлимой.

GZ>Как это не странно звучит, но в данной системе реализация read committed была бы сложней.

Дык, и я про то же.

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


Ну, никто не запрещает. Наверное это плохо. Я сам пока в сомнениях .

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


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

GZ>И еще сразу вопрос: После отката транзакции — остаются или не остаются объекты DSL c ссылками.


В смысле, остаются ли ссылки на объекты, дык — это дело прикладного программиста. Хочет держать объект (хранить ссылку на него в глобальной переменной) — пусть держит. Может он его овигенно сложным расчетом выбрал (состояние полей — да могут поменяться, но объект выбирать будет уже не нужно). Вобщем — дело программиста.

GZ>Если объект нельзя сбросить(перечитать) в случае отката (100% протухшие данные), то нужно что-то делать. Или я чего-то не усек.


В случае отката, так же как и в случае коммита, номер транзакции увеличивается. И все данные будут невалидными. И они при необходимости — перечитаются. А что значит "нельзя сбросить(перечитать)" — я не понял, всегда можно перечитать.

GZ>правда по опыту знаю, что они постепенно приводятся к стандартизованному виду.


Хм. Читаю Фаулера — вижу одно. Смотрю 1С — другое. Смотрю "Эталон" — третье. ИМХО просто нет оптимального решения — вот и извращается кто как может .

GZ>Что касается непротиворечивости, то остался вопрос по пессимистическим транзакциям (будут или нет), масштабируемости БД и еще пожалуй, момент отката транзакций.


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

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

Здесь в разделе 2.3.1 описывается несколько функций кэшей. В этой терминологии сессионный кэш у меня предназначен для обеспечения Temporal и Proximal Grain, а кэш второго уровня — Morphological Grain.
http://www.lmdinnovative.com (LMD Design Pack)
Re[20]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 07:53
Оценка:
Здравствуйте, stalcer, Вы писали:

Блин, неправльно все написал, надо так:

Здесь в разделе 2.3.1 описывается несколько функций кэшей. В этой терминологии сессионный кэш у меня предназначен для отработки Temporal, Proximal и Morphological fine grained действий, а кэш второго уровня — Proximal и Morphological coarse grained.
http://www.lmdinnovative.com (LMD Design Pack)
Re[19]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 08:12
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Извиняюсь забыл разъяснить про момент отката транзакций. Меня интересует вопрос: ты написал про savepoint когда объекты сбрасываются на БД. Как будет обрабатываться ошибка, если она произойдет при сбросе?


Желательно свести к минимуму такие ошибки. Например, я хочу использовать возможность отложить проверку констрейнтов до коммита (Re: реализация UnitOfWork
Автор: stalcer
Дата: 15.02.05
). Далее я ведь структуру базы тоже специальную делаю, в смысле тупых ошибок (типа, поле "аа" не найдено) при сбросе быть не должно.
Так что, получается таких ошибок не много: дед-лох, да сервер-даун.

Но, проблема такая остается. Я думаю сделать так: сделать специальный базовый класс для всех таких ексепшенов, и указать, что типа они могут возникать в любом месте транзакции, так что ловить их надо только на том логическом уровне, где идет управление транзакциями, не ниже.
Некие такие "ексепшены уровня транзакций".
http://www.lmdinnovative.com (LMD Design Pack)
Re[25]: Опять валидация данных
От: GlebZ Россия  
Дата: 28.03.05 09:10
Оценка:
Здравствуйте, stalcer, Вы писали:

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


GZ>>К сожалению, я так как-раз и не считаю. <поскипано>


S>Дык, приведи пример лучшего режима.

Раздели транзакции по следующему принципу:
1. Транзакции read-only snapshot. Такие транзакции не открывают транзакции на БД, и можно их использовать по версионному принципу как у тебя описано. Она будет корректна на какой-то момент времени. Удобно для работы отчетов. (если тебе очень хочется ее сделать, на здоровье).
2. Транзакции read-only read-commited. Такие транзакции не открывают транзакций на БД, но через них можно передавать изменения в режиме реального времени.
3. Оптимистические транзакции. Фаулер их достаточно описал. В случае бухгалтерии — маловероятно наличие большого кол-ва изменений в одной транзакции. Поэтому механизма сброса на диск — не особо надо. Транзакция БД открывается только на момент сброса транзакции на БД.
4. Пессимистические. Здесь уже есть тот вариант который я описал про версионные (но достаточно тормозные), либо ты предоставишь пользователю просто возможность заблокировать данные которые он будет изменять. Если произошла попытка блокировки уже заблокированного объекта, пользователю предоставляется информация кто работает с данным объекта. Так, чтобы он мог это сообщить пользователю. Тогда ты перекладываешь все на прикладника. Ему значительно проще, поскольку он знает что пользователю в данный момент нужно, и может гибче управлять ими. Предусмотреть все варианты прикладник врядли сможет. Так что можно называть этот ее псевдопессимистической. Второй вариант не должен отменять Оптимистическую транзакцию. Это обеспечит согласованность данных.

С уважением, Gleb.
Re[25]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 09:33
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Кто делает? Какой язык?


1С, например. Язык — в смысле скрипт.

S>Не, тут поинт в том, чтобы специально разрабатывать интерфейс с учетом минимизации общения между клиентом и сервером.


Да, да. Ето и есть основная мысль.

S>Бинарность передачи данных сама по себе — не панацея.


Это я для примера привел.

S>Это все делается в рамках web-клиента без особых проблем.


Это как?

S>Многие особенности, присущие толстым клиентам, на практике малопригодны с точки зрения пользователя. Т.е. например воспроизвести всю MS VS 2005 как веб-клиента нереально. Все эти dockable tabbed interface и все такое... Но это интерфейс, ориентированный на очень специальную таргет группу. Нормальным людям, клиентам бизнес приложений, все это только вредит.


Это понятно.

S>Более того, пересмотр самой модели взаимодействия приложения с пользователем в пользу "вебнутого" интерфейса помогает повысить масштабируемость приложения и улучшить user experience. Первое — потому, что там ты вынужден избегать лишних зависимостей и непроизводительной нагрузки; второе — потому, что ты вынужден тщательнее заботиться о реализации use-cases вместо хаотического запихивания всех возможностей в правую кнопку и тулбары.


Хочу чтобы было так:



А не так:



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


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

GZ>Раздели транзакции по следующему принципу:

GZ>1. Транзакции read-only snapshot. Такие транзакции не открывают транзакции на БД, и можно их использовать по версионному принципу как у тебя описано. Она будет корректна на какой-то момент времени. Удобно для работы отчетов. (если тебе очень хочется ее сделать, на здоровье).

Читать-то из базы все равно нужно. SQL запросы тоже идут в контексте SQL транзакции. И как ты сказал "snapshot" удобно не только для отчетов, но и практически для любого рассчета.

GZ>2. Транзакции read-only read-commited. Такие транзакции не открывают транзакций на БД, но через них можно передавать изменения в режиме реального времени.


Зачем они вообще нужны, read-commited в смысле?
Опять же, read-only или не read-only — разницы нет никакой.

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


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

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


Это часть подсистемы GUI. Выразимся по другому: У нас нет пессимистических транзакций, но формочки вот так блокировать умеют. Этот механизм можно надстроить над уровнем, который я описываю. Тем более, раз здесь предполагается блокирование надолго, то использовать SQL блокировки, создавая тем самым длительные транзакции, — нельзя.
И потом, я же не запрещаю программисту в рассчетах вручную блокировать, если хочет — наздоровье.
http://www.lmdinnovative.com (LMD Design Pack)
Re[27]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 10:34
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Гм. Так это же совсем про другое. Скрипт — это же средство расширения функционала прикладными программистами. Он сам никак не связан с моделью взаимодействия.


Скрипт — это язык программирования, пусть и простенький. И вопрос в том, существуют ли в системе прикладные программы, выполняющиеся на клиенте. Потому что если существуют, то это очень неудобно и прикладной программист будет ныть по поводу "почему эту функцию на сервере можно вызвать, а на клиенте — нет". Поэтому я и хочу обойтись без программ на клиенте в принципе.

S>В смысле как? Ты что, никогда сайтов с менюшками не видел?

S>Внимание, вопрос: почему ты хочешь так? Ты уверен, что так, как ты хочешь — удобнее пользователям?

Менюшки видел. Я не про то. Кроме менюшек есть более важные средства — средства работы с данными: сетки всякие, DB-Edit'ы, мастер-детальные сетки и т.д. Ну и как это в HTML страничке представлят. С учетом большого объекма информации в сетках (скроллинга).
WinForms интерфейс ИМХО богаче по выразительным средствам.
А пользователю ИМХО (даже не ИМХО, а по опыту работы знаю) удобнее такие сетки, чем интерфейс типа почты на рамблере, которую я показал, в котором при любом действии скроллинг в начало страницы убегает . Потому что тетка сидит, одним глазом в листок бумаги смотрит а другим в монитор и быстро-быстро-быстро вбивает данные.

S>Это не наезд. Это призыв разрабатывать интерфейсы, удобные пользователю.


Да я и не против подумать о пользователе.

S>Вот, к примеру, Inductive User Interface гораздо легче реализовать в веб-модели, и при этом он считается более удобным, чем классический deductive interface. То, что ты приводишь в примере, больше похоже на deductive interface. Поэтому, прежде чем задаваться вопросом "как его реализовать", хочется задаться вопросом "зачем его реализовывать", и "его ли надо реализовывать".


Это несколько ортогонально к сеткам и DB-Edit'ам. Очень интересно. Где почитать.
http://www.lmdinnovative.com (LMD Design Pack)
Re[28]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.03.05 11:11
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Менюшки видел. Я не про то. Кроме менюшек есть более важные средства — средства работы с данными: сетки всякие, DB-Edit'ы, мастер-детальные сетки и т.д. Ну и как это в HTML страничке представлят. С учетом большого объекма информации в сетках (скроллинга).

Гм. Ты сходил на maps.google.com? Там не то что сетка — картинка неограниченного размера скроллится! И ничего. Так что master/detail и сетки с load-on-demand — вовсе не предел технологии. Даже в MSDN была статья про то, как сделать грид с динамической подгрузкой.
S>А пользователю ИМХО (даже не ИМХО, а по опыту работы знаю) удобнее такие сетки, чем интерфейс типа почты на рамблере, которую я показал, в котором при любом действии скроллинг в начало страницы убегает . Потому что тетка сидит, одним глазом в листок бумаги смотрит а другим в монитор и быстро-быстро-быстро вбивает данные.
Ничему не противоречит. То, что у рамблера неудачный интерфейс, не означает, что надо ему детально следовать.
S>>Вот, к примеру, Inductive User Interface гораздо легче реализовать в веб-модели, и при этом он считается более удобным, чем классический deductive interface. То, что ты приводишь в примере, больше похоже на deductive interface. Поэтому, прежде чем задаваться вопросом "как его реализовать", хочется задаться вопросом "зачем его реализовывать", и "его ли надо реализовывать".
S>Это несколько ортогонально к сеткам и DB-Edit'ам. Очень интересно. Где почитать.
Ну, оригинал живет в MSDN. Перевод
Автор(ы): Microsoft Corporation
Дата: 19.03.2005
Эта статья описывает новую модель пользовательского интерфейса, названную «индуктивный пользовательский интерфейс» (inductive user interface, IUI). Называемая также «индуктивной навигацией», IUI-модель показывает, как сделать прикладные программы более простыми, разбивая функциональность на экраны или страницы, которые проще как описывать, так и понимать. IUI-модель проявляется в разнообразных проектах Майкрософт, наиболее заметно — в Microsoft Money 2000. Данная статья является скорее введением в IUI, чем утвержденным и всесторонним набором рекомендаций и правил.
можно почитать в RSDN #6/2004.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[29]: Опять валидация данных
От: stalcer Россия  
Дата: 28.03.05 14:26
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

Так что я буду делать формочки. А про Inductive User Interface посмотрю обязательно.
http://www.lmdinnovative.com (LMD Design Pack)
Re[27]: Опять валидация данных
От: GlebZ Россия  
Дата: 29.03.05 14:55
Оценка:
Здравствуйте, stalcer, Вы писали:

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


GZ>>Раздели транзакции по следующему принципу:

GZ>>1. Транзакции read-only snapshot. Такие транзакции не открывают транзакции на БД, и можно их использовать по версионному принципу как у тебя описано. Она будет корректна на какой-то момент времени. Удобно для работы отчетов. (если тебе очень хочется ее сделать, на здоровье).

S>Читать-то из базы все равно нужно. SQL запросы тоже идут в контексте SQL транзакции. И как ты сказал "snapshot" удобно не только для отчетов, но и практически для любого рассчета.

см. Ниже

GZ>>2. Транзакции read-only read-commited. Такие транзакции не открывают транзакций на БД, но через них можно передавать изменения в режиме реального времени.


S>Зачем они вообще нужны, read-commited в смысле?

Когда пользователь работает в snapshot транзакции — он работает в актуальных данных только на конкретный момент. То есть, он может работать в неактуальными данными и не сможет их даже обновить не закрывая транзакцию.
Например: первый продавец решил начать транзакцию продажи, открыл форму и посмотрел что товара достаточно после чего ушел обедать, второй продавец в это время взял и продал весь товар. Первый продавец уже сытый позвонил клиенту, сказал что дескать все ок — наличие товара проверено. И тут при проходе транзакции — получается что у него неактуальные данные. Он даже не может их обновить, так как — для этого нужно сбрасывать форму. В результате он получит ошибку транзакции, притом что вся логика проверки(которая работает в режиме устаревшей транзакции) говорит что все OK. И проверить в чем дело — никак нельзя.
S>Опять же, read-only или не read-only — разницы нет никакой.
Cходу не скажу, но по моему разница есть даже в твоем случае.

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


S>Ага.

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

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


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

Насчет GUI — по моему, не есть гуд. С одним объектом могут работать множество GUI форм. Каждая форма может редактировать одновременно сразу несколько объектов. Поэтому тут связь весьма неоднозначная. Что касается SQL блокировок — то нужен альтернативный механизм. Иначе прикладник будет открывать именно SQL транзакцию(если для него это будет возможно). Это уже проходил.
S>И потом, я же не запрещаю программисту в рассчетах вручную блокировать, если хочет — наздоровье.
Должен быть механизм единый для всех сессий и серверов.(snapshot — транзакции не подойдут для такого так как не могут предоставлять информацию для различных транзакций)

С уважением, Gleb
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[20]: Опять валидация данных
От: GlebZ Россия  
Дата: 29.03.05 14:55
Оценка:
Здравствуйте, stalcer, Вы писали:

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


S>Ну, никто не запрещает. Наверное это плохо. Я сам пока в сомнениях .

Это дополнительный механизм.

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


S>Хе. Доменный язык у меня — со сборшиком мусора (аля C#). И пока сборка мусора не пройдет — память фактически будет занята. Более того только сборщик мусора может сказать есть ли на объект ссылки или — нет. Поэтому, алгоритм удаления объектов из сессионного кэша тесно связан со сборкой мусора, и запускается как ее часть.

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

GZ>>И еще сразу вопрос: После отката транзакции — остаются или не остаются объекты DSL c ссылками.


S>В смысле, остаются ли ссылки на объекты, дык — это дело прикладного программиста. Хочет держать объект (хранить ссылку на него в глобальной переменной) — пусть держит. Может он его овигенно сложным расчетом выбрал (состояние полей — да могут поменяться, но объект выбирать будет уже не нужно). Вобщем — дело программиста.


GZ>>Если объект нельзя сбросить(перечитать) в случае отката (100% протухшие данные), то нужно что-то делать. Или я чего-то не усек.


S>В случае отката, так же как и в случае коммита, номер транзакции увеличивается. И все данные будут невалидными. И они при необходимости — перечитаются. А что значит "нельзя сбросить(перечитать)" — я не понял, всегда можно перечитать.

Если программер содержит значение (что часто бывает) которое было связано со старым значением объекта. То это уже ошибка, притом которая практически не может быть выявлена. Прикладнику придется выделять два поведения на нетранзакционный объект — при успешной транзакции, и при откате.

GZ>>правда по опыту знаю, что они постепенно приводятся к стандартизованному виду.


S>Хм. Читаю Фаулера — вижу одно. Смотрю 1С — другое. Смотрю "Эталон" — третье. ИМХО просто нет оптимального решения — вот и извращается кто как может .

Оптимальные решения бывают применительно к конкретной задаче. Поэтому лучше забирать только лучшее. А лучшее можно только получив знание о всех существующих. Здесь я не помошник. Единственное подобное решение в котором я участвовал и которое знаю я уже привел (Re[20]: Опять валидация данных
Автор: GlebZ
Дата: 27.03.05
)

GZ>>Что касается непротиворечивости, то остался вопрос по пессимистическим транзакциям (будут или нет), масштабируемости БД и еще пожалуй, момент отката транзакций.


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

Мне не очень нравится идея насчет механизма GUI. Почему я уже писал...

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

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

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[21]: Опять валидация данных
От: stalcer Россия  
Дата: 29.03.05 16:07
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Если программер содержит значение (что часто бывает) которое было связано со старым значением объекта. То это уже ошибка, притом которая практически не может быть выявлена. Прикладнику придется выделять два поведения на нетранзакционный объект — при успешной транзакции, и при откате.


Если не хочет — пусть так не делает.

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


GZ>После транзакции — IdentityMap уже никому не нужен. Все изменения уже сделаны либо откачены. Все объекты становятся стандартными.


И появляется дыра в системе в виде возможности существования двух реплик одного по сути хранимого объекта. Т.е. источник потенциальных ошибок.

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

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

Мы же говорим об убирании из кэша объектов после завершения транзакции. С этой точки зрения ресурсы — это место в кэше, т.е. память.
http://www.lmdinnovative.com (LMD Design Pack)
Re[28]: Опять валидация данных
От: stalcer Россия  
Дата: 29.03.05 16:07
Оценка:
Здравствуйте, GlebZ, Вы писали:

S>>Зачем они вообще нужны, read-commited в смысле?

GZ>Когда пользователь работает в snapshot транзакции — он работает в актуальных данных только на конкретный момент. То есть, он может работать в неактуальными данными и не сможет их даже обновить не закрывая транзакцию.
GZ>Например: первый продавец решил начать транзакцию продажи, открыл форму и посмотрел что товара достаточно после чего ушел обедать, второй продавец в это время взял и продал весь товар. Первый продавец уже сытый позвонил клиенту, сказал что дескать все ок — наличие товара проверено. И тут при проходе транзакции — получается что у него неактуальные данные. Он даже не может их обновить, так как — для этого нужно сбрасывать форму. В результате он получит ошибку транзакции, притом что вся логика проверки(которая работает в режиме устаревшей транзакции) говорит что все OK. И проверить в чем дело — никак нельзя.

Я уже говорил, что для прикладника "framework-транзакции" — это системные транзакции, а не бизнес транзакции. Так что "транзакция продажи" должна быть реализована на основе нескольких системных транзакций (каждая из которых будет сериализованной). Т.е.:
— Открыл форму (читай, скачал данные) — это одна системная транзакция
— Запустил расчет продажи — вторая.
И смотри ниже про GUI-блокировки.

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

GZ>В данном случае мы говорим не о запросах, а об изменениях. И эти изменения должны быть согласованные. Предлагаю тебе все-таки вернуться к декларативному языку описания объекта. В него закладываются правила которые выполняются как на уровне сервера приложений, так и на уровне БД. Если нужно работать с большим объемом данных, к сожалению я альтернативы БД не вижу. Возможно часть бизнес правил проверять запросами БД. Это притормозит систему, зато гарантирует корректную ошибку.

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

  // Пусть obj.Name изначально равно "aaa"
    obj.Name = "bbb";
    cursor = #oql select x from SomeObjects x where x.Name = "aaa";


Т.е. меняем obj.Name и делаем запрос. Вопрос: должен ли, собственно, obj попасть в результаты запроса? Ответ — нет. Потому что непосредственно перед запросом поле Name было изменено. Так вот, как добиться этого эффекта не сбрасывая накопившиеся изменения в базу непосредственно перед выполнением запроса?

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

GZ>Насчет GUI — по моему, не есть гуд. С одним объектом могут работать множество GUI форм. Каждая форма может редактировать одновременно сразу несколько объектов. Поэтому тут связь весьма неоднозначная.

Хорошо, уточню: У нас нет пессимистических транзакций, но формочки вот так блокировать объекты (не строчки грида) умеют.

GZ>Что касается SQL блокировок — то нужен альтернативный механизм. Иначе прикладник будет открывать именно SQL транзакцию(если для него это будет возможно). Это уже проходил.


Это понятно. И как раз специальный механизм позволяет разбить одну бизнес транзакцию, типа "транзакцию продажи" на несколько системных.

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

GZ>Должен быть механизм единый для всех сессий и серверов.(snapshot — транзакции не подойдут для такого так как не могут предоставлять информацию для различных транзакций)

Получается два механизма блокировок:
— Обычные блокировки, которые используются при расчетах, например, заблокировал все табеля и гуляй по ним циклом, делай любые изменения. Я думаю, что для этого подойдут обыкновенные SQL блокировки (select for update).
— И GUI-блокировки объектов. Для которых, как ты сам сказал нужен "альтернативный механизм". Я бы добавил, что нужен механизм блокировок, которые умеют переживать границы системных транзакций.

Оба механизма — глобальные, т.е. для всех сессий и всех серверов.

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

И с точки зрения уровня вычислительной среды наличие двух разных типов транзакций (оптимистических и пессимистических) — это прямое противоречие. Вот ответь на вопрос: Те данные, которые заблокировала пессимистическая транзакция (прочитав их), другая оптимистическая может прочитать? Или она должна повеситься и ждать?
http://www.lmdinnovative.com (LMD Design Pack)
Re[22]: Опять валидация данных
От: GlebZ Россия  
Дата: 29.03.05 17:33
Оценка:
Здравствуйте, stalcer, Вы писали:

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


GZ>>После транзакции — IdentityMap уже никому не нужен. Все изменения уже сделаны либо откачены. Все объекты становятся стандартными.


S>И появляется дыра в системе в виде возможности существования двух реплик одного по сути хранимого объекта. Т.е. источник потенциальных ошибок.

Нет. Все остается в той-же степени как и было. Ты же сам писал — IdentityMap один на всю сессию. Так что это получается один из объектов сессионного кэша.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[29]: Опять валидация данных
От: GlebZ Россия  
Дата: 29.03.05 17:33
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Я уже говорил, что для прикладника "framework-транзакции" — это системные транзакции, а не бизнес транзакции. Так что "транзакция продажи" должна быть реализована на основе нескольких системных транзакций (каждая из которых будет сериализованной). Т.е.:

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

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


S>
S>  // Пусть obj.Name изначально равно "aaa"
S>    obj.Name = "bbb";
S>    cursor = #oql select x from SomeObjects x where x.Name = "aaa";
S>


S>Т.е. меняем obj.Name и делаем запрос. Вопрос: должен ли, собственно, obj попасть в результаты запроса? Ответ — нет. Потому что непосредственно перед запросом поле Name было изменено. Так вот, как добиться этого эффекта не сбрасывая накопившиеся изменения в базу непосредственно перед выполнением запроса?

Как и всегда, пропуская чтение объекта который уже загружен. Считываешь его гуид, и если он есть в hash, то пропускаешь.

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

GZ>>Насчет GUI — по моему, не есть гуд. С одним объектом могут работать множество GUI форм. Каждая форма может редактировать одновременно сразу несколько объектов. Поэтому тут связь весьма неоднозначная.

S>Хорошо, уточню: У нас нет пессимистических транзакций, но формочки вот так блокировать объекты (не строчки грида) умеют.

На каком уровне. Если ты уровень GUI переместишь на клиента — то об этом никто не узнает. Блокировки должны быть на уровне бизнес-логики. Именно там они и используются.

GZ>>Что касается SQL блокировок — то нужен альтернативный механизм. Иначе прикладник будет открывать именно SQL транзакцию(если для него это будет возможно). Это уже проходил.


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

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

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

GZ>>Должен быть механизм единый для всех сессий и серверов.(snapshot — транзакции не подойдут для такого так как не могут предоставлять информацию для различных транзакций)

S>Получается два механизма блокировок:

S>- Обычные блокировки, которые используются при расчетах, например, заблокировал все табеля и гуляй по ним циклом, делай любые изменения. Я думаю, что для этого подойдут обыкновенные SQL блокировки (select for update).
S>- И GUI-блокировки объектов. Для которых, как ты сам сказал нужен "альтернативный механизм". Я бы добавил, что нужен механизм блокировок, которые умеют переживать границы системных транзакций.
Они не должны переживать границы транзакции. Это жутко неудобно. Вместе с транзакцией, должны быстро освобождаться блокировки. Они после нее не нужны. А если прикладник забудет их забить, то вообще пурга.

S>Оба механизма — глобальные, т.е. для всех сессий и всех серверов.



S>И с точки зрения уровня вычислительной среды наличие двух разных типов транзакций (оптимистических и пессимистических) — это прямое противоречие. Вот ответь на вопрос: Те данные, которые заблокировала пессимистическая транзакция (прочитав их), другая оптимистическая может прочитать? Или она должна повеситься и ждать?

Прочитать, да. Не факт что большинство заблокированных объектов будут изменены. Пользователь может просматривать форму. Оптимистическая потому и называется оптимистическая, что у нее хватает оптимизма проверять согласованность только на этапе сохранения. Но если при сохранении стоит блокировка, то пессимистическая всегда главней. Либо ждать по таймауту (как это делает Oracle, чтобы после того как блокировка будет сброшена проверить были ли изменения), либо сразу отбивать.
С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[23]: Опять валидация данных
От: stalcer Россия  
Дата: 30.03.05 06:28
Оценка:
Здравствуйте, GlebZ, Вы писали:

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


GZ>>>После транзакции — IdentityMap уже никому не нужен. Все изменения уже сделаны либо откачены. Все объекты становятся стандартными.

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

Мдя. Странный у нас диалог получается. Сначала ты говоришь "После транзакции — IdentityMap уже никому не нужен", потом я объясняю зачем он все таки нужен, а ты на это отвечаешь "нет" и аргументируешь — "Ты же сам писал — IdentityMap один на всю сессию". Ты уж реши — нужен он после транзакции или нет.
http://www.lmdinnovative.com (LMD Design Pack)
Re[30]: Опять валидация данных
От: stalcer Россия  
Дата: 30.03.05 07:48
Оценка:
Здравствуйте, GlebZ, Вы писали:

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


S>>Я уже говорил, что для прикладника "framework-транзакции" — это системные транзакции, а не бизнес транзакции. Так что "транзакция продажи" должна быть реализована на основе нескольких системных транзакций (каждая из которых будет сериализованной). Т.е.:

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

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

S>>
S>>  // Пусть obj.Name изначально равно "aaa"
S>>    obj.Name = "bbb";
S>>    cursor = #oql select x from SomeObjects x where x.Name = "aaa";
S>>

S>><skipped>
GZ>Как и всегда, пропуская чтение объекта который уже загружен. Считываешь его гуид, и если он есть в hash, то пропускаешь.

Во первых, не пропуская, а выполняя для него проверку x.Name = "aaa" вручную, на сервере приложений. Так как если бы я не присвоил "bbb" в поле Name, то объект должен бы был попасть в результаты запроса. И это не зависит от того, был ли он загружен в кэш или нет, и даже не должно зависеть от того, был ли он изменен (локально, на сервере приложений) или нет.
Во вторых, для примера я привел простой запрос. А могут быть и более сложные, где такие локальные проверки сделать будет практически невозможно. Поэтому, здесь получается дилемма: либо делать более менее функциональный (с подзапросами, группировками и т.п.) OQL, который выполняется в базе полностью, либо делать оооооочень ограниченный по функциональности, но зато он сможет корректировать свои результаты с учетом текущих изменений в кэше.

GZ>Они не должны переживать границы транзакции. Это жутко неудобно. Вместе с транзакцией, должны быстро освобождаться блокировки. Они после нее не нужны. А если прикладник забудет их забить, то вообще пурга.


Они должны переживать границы системной транзакции. Это если разделять системные транзакции и бизнес транзакции.

S>>И с точки зрения уровня вычислительной среды наличие двух разных типов транзакций (оптимистических и пессимистических) — это прямое противоречие. Вот ответь на вопрос: Те данные, которые заблокировала пессимистическая транзакция (прочитав их), другая оптимистическая может прочитать? Или она должна повеситься и ждать?

GZ>Прочитать, да. Не факт что большинство заблокированных объектов будут изменены. Пользователь может просматривать форму. Оптимистическая потому и называется оптимистическая, что у нее хватает оптимизма проверять согласованность только на этапе сохранения. Но если при сохранении стоит блокировка, то пессимистическая всегда главней. Либо ждать по таймауту (как это делает Oracle, чтобы после того как блокировка будет сброшена проверить были ли изменения), либо сразу отбивать.

Ладно. Просто я вчера вечером стормознул. Я вот о чем хотел сказать: Пессимистические транзакции, как и блокировки, которые они ставят, должны быть более менее быстродействующими. Т.к. я по прежнему говорю о системных транзакциях, т.е. о рассчетах. Тогда, единственный приемлимый (по скорости) способ — использовать SQL блокировки.
А у Oracle нет shared блокировок, ну нет и все. А закладывать с систему заведомо тормознутые (причем сильно) транзакции, основанные на своем механизме блокировок — не хочу. Блоее того, тормознутыми транзакциями будут все, а не только пессимистические. Потому что shared-блокировка, наложенная одной пессимистической транзакцией на объект при его чтении, должна быть проверена (с соответствующими последствиями) в другой оптимистической транзакции при изменении объекта. Т.е. при изменении любого объекта в оптимистической транзакции необходимо хотябы проверить, есть или нет на него блокировки (shared, которые не являются SQL блокировками).

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

Типа один рассчет делает так:
NamedLocks.Lock("Табеля", LockKind.Shared);
// Здесь работаем с табелями...
Commit; // Блокировка снялась.


Другой, точно также, сначала блокирует, потом работает. Конечно, это на совести программиста — не забыть заблокировать, но зато будет нормальная производительность.
http://www.lmdinnovative.com (LMD Design Pack)
Re[30]: Опять валидация данных
От: stalcer Россия  
Дата: 30.03.05 11:44
Оценка:
Здравствуйте, GlebZ, Вы писали:

Предлагаю опять все поскипать и обсудить транзакции вот к каком ключе:

1:
Мы не понимаем друг друга в мелочах, потому что о разном думаем.
Я говорю о системных транзакциях, ты — о бизнес транзакциях.

2:
Следует четко разделить характеристики транзакций:

2.1: Есть уровень изоляции: мы рассматриваемт только два: snapshot транзакция (не будем больше называть ее сериализованной) и read-committed транзакция.
2.2: Есть оптимистичность (блокировки): опимистическая транзакция и пессимистическая транзакция.
2.3: 2.1 и 2.2 — это ортогональные характеристики. Возможны все четыре комбинации.
2.4: Если транзакция пессимистическая — это само по себе уровень изоляции snapshot не обеспечивает! Это не надо путать.

3:
Следует принимать во внимание технологические ограничения:

3.1: В Oracle нет shared блокировок, необходимых для пессимистических транзакций и для правильного взаимодействия пессимистических транзакций с оптимистическими. Так что тормозить будут все.
3.2: Практически нереально сделать OQL, который бы правильно работал с учетом еще не сброшенных в базу изменений, находящихся в сессионном кэше.
3.3: Read committed транзакции сводят все попытки кэширования на нет. Потому что состояние базы меняется на каждом следующем запросе и для обеспечения согласованости кэшированных данных, в соответствии с read committed уровнем изоляции ранее прочитанные объекты, находящиеся в кэше, нужно инвалидировать: либо все либо иметь специальный механизм, который позволяет определить какие именно.
3.4: И даже если read committed транзакции сделать еще и пессимистичными, то все равно кэширование будет работать на много хуже, причину можно узреть в комбинации 2.4 и 3.3.

4:
О том нужно или нет периодчески сбрасывать изменения:

Так как я делаю универсальный framework, то он должен обеспечивать возможность работы с большим объемом данных в одной транзакции. И простой сериализацией в файл здесь не обойтись.
Так как, например, я изменил какой-либо объект X, затем сделал много изменений, так, что памяти не хватило и этот объект (вместе с другими) сериализовался в файл. Для чего мы делаем сериализацию — для того, чтобы освободить оперативную память, т.е. место в кэше. То есть из сессионного кэша объект X надо убрать. А дальше в течении этой же транзакции я опять захотел поработать с объектом X. То есть мне его нужно перечитать. Но не из базы, а из файла.
А это уже называется не сериализация, а кэш, умеющий работать с файлом (в realtime).
4.1: Во первых, совсем другой уровень сложности реализации такого механизма.
4.2: Во вторых, что главное, см. пунк 3.2.

5:
Несколько рассуждений о бизнес транзакциях:

5.1:
Например, есть транзакция подажи товаров. Примерный ее сценарий:
5.1.1: В GUI подготавливаем список того что хотим продать (долго, с перерывами на обед и т.п.).
5.1.2: Запускаем рассчет продажи.

Дык вот:

5.2: Уровень изоляции: В фазе 5.1.1 я вообще-то хочу чтобы транзакция имела уровень изоляции read committed, т.к. то окошко из которого я набираю товары должно отражать последние данные. А в фазе 5.1.2 я хочу работать с уровнем изоляции snapshot, причем snapshot не на момент начала бизнес транзакции, а на момент запуска фазы 5.1.2. Потому что, любому рассчету удобнее работать с уровнем изоляции snapshot. Это, заметь, никоим образом не про блокировки.
5.3: Блокировки: В фазе 5.1.1 применительно к форме, в которую я набираю товары, транзакция должна быть пессимистична. Т.е. если я отобрал товар для продажи, то до конца бизнес транзакции его менять никто не может. А применительно к форме из которой я набираю товары (ну типа списов всех имеющихся товаров) — транзакция должна быть оптимистична, т.е. не ставить блокировок на все показанные в этой форме товары.
5.4: Подробнее о форме в которую я набираю товары. Товары, набранные в эту форму должны быть заблокированы — сам товар (объект, представляющий товар: имя + характеристики) — shared блокировкой, а соответствующий ему объект, представляющий количество этого товара имеющееся в наличии — noshare блокировкой (или как она там правильно называется).
5.5: Пунктом 5.4 я хотел сказать, что объекты, которые следует блокировать во время бизнес транзакции должны выбираться из смысла этой транзакции. И формально (автоматически) их выбрать невозможно.
5.6: Важно: Будем называть блокировки из 5.4 — блокировки уровня бизнес транзакций (чтобы внести ясность — не будем их больше называть GUI-блокировками). Т.е. это специальный механизм блокировок, которые держатся на протяжении всей бизнес транзакции, которые могут быть shared и noshare, которые автоматически снимаются при коммите или откате бизнес транзакции. Ну и естественно, что эти блокировки видны между сессиями и серверами приложений. И естественно, что устанавливать эти блокировки можно и программно — т.е. из бизнес логики (рассчета). Но важно что они устанавливаются явно, т.е. прикладным программистом (потому что см. 5.5). И это не SQL блокировки, потому что смотри 3.1.



Это все были предпосылки.

6:
А теперь решение которое предлагаю я:

Не приравнивать системную транзакцию к бизнес транзакции. Бизнес транзакция должна состоять из нескольких системных транзакций.

6.1: Например, транзакция продажи из 5.1 состоит из следующих системных транзакций:
— Из нескльких транзакций чтения данных для формы из которой я набираю товары (при открытии формы или при нажатии на Refresh).
— Из одной транзакции рассчета продажи.

6.2: И тогда получается, что эти несколько системных транзакций — короткие (какие и должны быть SQL транзакции) и без интерактива с пользователем. При таком подходе для точной реализации задачи из пункта 5 (важны 5.1, 5.2 и 5.3) нам нужно всего лишь два механизма:
6.2.1: Оптимистические snapshot системные транзакции.
6.2.2: Механизм "блокировок уровня бизнес транзакций". См. 5.6.

6.3: Благодаря 6.2.1 будет удобно делать кэширование (см. 3.3)
6.4: Так как системные транзакции короткие (см. 6.2), то все изыскания из пункта (4) уже не имеют принципиального значения и изменения можно спокойненько сбрасывать в процессе системной транзакции.

7:
Проблемы моего подхода:

7.1: Как обеспечить (и в какой степени это необходимо) взаимодействие неявных (а также и явных) SQL блокировок возникающих вследствии update'ов с механизмом "блокировок уровня бизнес транзакций" (из 5.6). Дело в том, что это не должны быть полностью независимые механизмы. Например, если один объект заблокирован даже shared "блокировкой уровня бизнес транзакций", то какой-либо рассчет из другой сессии не должен иметь возможности этот объект изменить. Даже если он не использует "блокировки уровня бизнес транзакций". Так что в соответствии с (3.1) все равно тормозить будут все .

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

8:
Вывод:

Для концептуального завершения моего подхода нужны:

8.1: Эффективный как по скорости так и по масштабируемости механизм "блокировок уровня бизнес транзакций" и механизм его взаимодействия с рассчетами не пользующимися "блокировками уровня бизнес транзакций". Пока не знаю как сделать .
Однако, возможно, что практически "блокировками уровня бизнес транзакций" будут блокироваться лишь небольшое количество объектов. Как этот факт использовать. Надо подумать .

8.2: И соответственно нужен механизм накопления изменений. А здесь самый хитрый вопрос вот в чем: изменения надо копить в тех же объектах или можно в отдельных. В смысле объектах другого класса. А то можно сделать специальные классы временно хранимых объектов. И хранить эти объекты во Oracle'овских временных таблицах. А по завершению бизнес транзакции — их чистить (это быстро, так как временные таблицы Oracle — не транзакционные и работают быстрее обычных). Это, конечно не идеальное решение, так как прикладная программа будет видеть исходный объект и временый — как абсолютно два разных объекта, и даже возможно разной структуры.

А с другой стороны некоторые объекты должны быть временными по своей сути. Например, в бизнес транзакции из (5), пользователь набирает товары для продажи, т.е. выбирает товар и ставит продаваемое количество. Список таких отобранных товаров и показывает одна из GUI форм. Так вот, что является строчкой в этом списке? ИМХО, некий служебный объект:

class SellingItem 
{
    public Ware SellingWare;  // Ссылка на товар.
    public int  Amount;       // Продаваемое количество.
};

Именно его в данном случае и нужно сделать временно хранимым (если конечно не делать его полностью хранимым, для логирования продаж, например).

И последнее: с такими "временно" хранимыми объектами можно обращаться гораздо фривольнее, чем с нормальными хранимыми объектами, так как таблицы по завершению программ чистятся, и никакого геморроя с обновлением версий при изменении структуры таких объектов не будет. Так что таблицы для таких объектов вообще могут генериться фреймворком автоматически, а все что нужно программисту сделать — это объявить класс в исходнике программы. Хе. Мне это даже нравиться начинает .
http://www.lmdinnovative.com (LMD Design Pack)
Re[31]: Опять валидация данных
От: GlebZ Россия  
Дата: 30.03.05 14:09
Оценка:
Здравствуйте, stalcer, Вы писали:

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


S>Предлагаю опять все поскипать и обсудить транзакции вот к каком ключе:


S>1:

S>Мы не понимаем друг друга в мелочах, потому что о разном думаем.
S>Я говорю о системных транзакциях, ты — о бизнес транзакциях.
Бизнес-транзакция есть конечный результат. И полусделанная бизнес-транзакция потерявшая свою атомарность или консинсентность — не очень приятная вещь ведущая к завалу базы.

S>2:

S>Следует четко разделить характеристики транзакций:

S>2.1: Есть уровень изоляции: мы рассматриваемт только два: snapshot транзакция (не будем больше называть ее сериализованной) и read-committed транзакция.

S>2.2: Есть оптимистичность (блокировки): опимистическая транзакция и пессимистическая транзакция.
S>2.3: 2.1 и 2.2 — это ортогональные характеристики. Возможны все четыре комбинации.
S>2.4: Если транзакция пессимистическая — это само по себе уровень изоляции snapshot не обеспечивает! Это не надо путать.
Уровень snapshot даже оптимистической проверки не обеспечивает. Так что оптимистическая проверка должна быть обязательна.

S>3:

S>Следует принимать во внимание технологические ограничения:

S>3.1: В Oracle нет shared блокировок, необходимых для пессимистических транзакций и для правильного взаимодействия пессимистических транзакций с оптимистическими. Так что тормозить будут все.

У диспетчера блокировок 3 функции: наложить блокировку, убрать блокировку, проверить блокировку. То есть функции одного Hashtable, где быстрота доступа O(1)(если реализация на C#). Это значительно быстрее и эффективнее чем блокировки на уровне БД. Особенно в условиях кэша.
S>3.2: Практически нереально сделать OQL, который бы правильно работал с учетом еще не сброшенных в базу изменений, находящихся в сессионном кэше.
А зачем он должен этим заниматься. Сама задача трансформации OQL запроса в эффективный SQL достаточно интересна и сложна. Уж поверь, я этим занимался. А решается данная проблема просто, при загрузке результатов сначало загружаешь OID объекта, если таковой в кэше присутсвует то делаешь MoveNext, а наверх выдаешь ссылку на кешируемый объект(если надо).
S>3.3: Read committed транзакции сводят все попытки кэширования на нет. Потому что состояние базы меняется на каждом следующем запросе и для обеспечения согласованости кэшированных данных, в соответствии с read committed уровнем изоляции ранее прочитанные объекты, находящиеся в кэше, нужно инвалидировать: либо все либо иметь специальный механизм, который позволяет определить какие именно.
Механизм? Может быть. Подумай о том, что любое подтвержденное изменение объекта гарантирует что ни одна текущая транзакция (в особенности snapshot) не сможет его изменить.(Хотя бы оптимистическая проверка отобьет). И подумай о том, что используя устаревшие данные просто на чтение, ты можешь базу завалить. Что связано с пунктом 7.2.
S>3.4: И даже если read committed транзакции сделать еще и пессимистичными, то все равно кэширование будет работать на много хуже, причину можно узреть в комбинации 2.4 и 3.3.

S>4:

S>О том нужно или нет периодчески сбрасывать изменения:

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

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

S>5:

S>Несколько рассуждений о бизнес транзакциях:

S>5.1:

S>Например, есть транзакция подажи товаров. Примерный ее сценарий:
S>5.1.1: В GUI подготавливаем список того что хотим продать (долго, с перерывами на обед и т.п.).
S>5.1.2: Запускаем рассчет продажи.

S>Дык вот:


S>5.2: Уровень изоляции: В фазе 5.1.1 я вообще-то хочу чтобы транзакция имела уровень изоляции read committed, т.к. то окошко из которого я набираю товары должно отражать последние данные. А в фазе 5.1.2 я хочу работать с уровнем изоляции snapshot, причем snapshot не на момент начала бизнес транзакции, а на момент запуска фазы 5.1.2. Потому что, любому рассчету удобнее работать с уровнем изоляции snapshot. Это, заметь, никоим образом не про блокировки.

S>5.3: Блокировки: В фазе 5.1.1 применительно к форме, в которую я набираю товары, транзакция должна быть пессимистична. Т.е. если я отобрал товар для продажи, то до конца бизнес транзакции его менять никто не может. А применительно к форме из которой я набираю товары (ну типа списов всех имеющихся товаров) — транзакция должна быть оптимистична, т.е. не ставить блокировок на все показанные в этой форме товары.
S>5.4: Подробнее о форме в которую я набираю товары. Товары, набранные в эту форму должны быть заблокированы — сам товар (объект, представляющий товар: имя + характеристики) — shared блокировкой, а соответствующий ему объект, представляющий количество этого товара имеющееся в наличии — noshare блокировкой (или как она там правильно называется).
S>5.5: Пунктом 5.4 я хотел сказать, что объекты, которые следует блокировать во время бизнес транзакции должны выбираться из смысла этой транзакции. И формально (автоматически) их выбрать невозможно.
S>5.6: Важно: Будем называть блокировки из 5.4 — блокировки уровня бизнес транзакций (чтобы внести ясность — не будем их больше называть GUI-блокировками). Т.е. это специальный механизм блокировок, которые держатся на протяжении всей бизнес транзакции, которые могут быть shared и noshare, которые автоматически снимаются при коммите или откате бизнес транзакции. Ну и естественно, что эти блокировки видны между сессиями и серверами приложений. И естественно, что устанавливать эти блокировки можно и программно — т.е. из бизнес логики (рассчета). Но важно что они устанавливаются явно, т.е. прикладным программистом (потому что см. 5.5). И это не SQL блокировки, потому что смотри 3.1.

S>

S>Это все были предпосылки.

S>6:

S>А теперь решение которое предлагаю я:

S>Не приравнивать системную транзакцию к бизнес транзакции. Бизнес транзакция должна состоять из нескольких системных транзакций.


S>6.1: Например, транзакция продажи из 5.1 состоит из следующих системных транзакций:

S>- Из нескльких транзакций чтения данных для формы из которой я набираю товары (при открытии формы или при нажатии на Refresh).
S>- Из одной транзакции рассчета продажи.

S>6.2: И тогда получается, что эти несколько системных транзакций — короткие (какие и должны быть SQL транзакции) и без интерактива с пользователем. При таком подходе для точной реализации задачи из пункта 5 (важны 5.1, 5.2 и 5.3) нам нужно всего лишь два механизма:

S>6.2.1: Оптимистические snapshot системные транзакции.
S>6.2.2: Механизм "блокировок уровня бизнес транзакций". См. 5.6.

S>6.3: Благодаря 6.2.1 будет удобно делать кэширование (см. 3.3)

S>6.4: Так как системные транзакции короткие (см. 6.2), то все изыскания из пункта (4) уже не имеют принципиального значения и изменения можно спокойненько сбрасывать в процессе системной транзакции.
Это мне нравится все больше и больше.

S>7:

S>Проблемы моего подхода:

S>7.1: Как обеспечить (и в какой степени это необходимо) взаимодействие неявных (а также и явных) SQL блокировок возникающих вследствии update'ов с механизмом "блокировок уровня бизнес транзакций" (из 5.6). Дело в том, что это не должны быть полностью независимые механизмы. Например, если один объект заблокирован даже shared "блокировкой уровня бизнес транзакций", то какой-либо рассчет из другой сессии не должен иметь возможности этот объект изменить. Даже если он не использует "блокировки уровня бизнес транзакций". Так что в соответствии с (3.1) все равно тормозить будут все .

Не плоди системы. Забудь о SQL блокировках. Только проверка оптимизма(версии) данных тебе даст гарантию корректности (хотя бы на уровне системной транзакции). И до SQL блокировок дело не дойдет (которые также работают на уровне системной транзакции).

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

Блокировки на уровне бизнес-транзакций — уже спасают в некоторой степени.



S>8:

S>Вывод:

S>Для концептуального завершения моего подхода нужны:


S>8.1: Эффективный как по скорости так и по масштабируемости механизм "блокировок уровня бизнес транзакций" и механизм его взаимодействия с рассчетами не пользующимися "блокировками уровня бизнес транзакций". Пока не знаю как сделать .

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

S>8.2: И соответственно нужен механизм накопления изменений. А здесь самый хитрый вопрос вот в чем: изменения надо копить в тех же объектах или можно в отдельных. В смысле объектах другого класса. А то можно сделать специальные классы временно хранимых объектов. И хранить эти объекты во Oracle'овских временных таблицах. А по завершению бизнес транзакции — их чистить (это быстро, так как временные таблицы Oracle — не транзакционные и работают быстрее обычных). Это, конечно не идеальное решение, так как прикладная программа будет видеть исходный объект и временый — как абсолютно два разных объекта, и даже возможно разной структуры.

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

S>А с другой стороны некоторые объекты должны быть временными по своей сути. Например, в бизнес транзакции из (5), пользователь набирает товары для продажи, т.е. выбирает товар и ставит продаваемое количество. Список таких отобранных товаров и показывает одна из GUI форм. Так вот, что является строчкой в этом списке? ИМХО, некий служебный объект:


S>
S>class SellingItem 
S>{
S>    public Ware SellingWare;  // Ссылка на товар.
S>    public int  Amount;       // Продаваемое количество.
S>};
S>

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

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

Не знаю насколько это нужно(зависит от самой задачи), но ничего криминального здесь я не вижу.

С уважением, Gleb.
PS: если я делаю несколько голословные утверждения и ляпы, прошу извинить. Поскольку попутно занимаюсь основной производственной деятельностью. Поэтому прошу не принимать это только как информацию к размышлению и то, во многом субъективную и даже неверную.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[32]: Опять валидация данных
От: stalcer Россия  
Дата: 30.03.05 14:50
Оценка:
Здравствуйте, GlebZ, Вы писали:

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

Вот пример, который я приводил выше:

Пусть на начало транзакции есть объект с Id = 1 и полем Name = "ааа". Вот он есть в базе.
Затем читаю его в кэш и изменяю поле Name:

obj.Name = "bbb";

Т.е. в базе у объекта поле Name по прежнему равно "aaa". А в кэше имеется измененная версия, у которой Name = "bbb".
Затем, я делаю запрос:

cursor = #oql select x from SomeObjects x where x.Name = "aaa";

Так как запрос выполняется в базе, то объект с Id = 1 будет частью результата этого запроса. А он не должен быть. Так как с точки зрения прикладного программиста у объекта значение поля Name уже равно "bbb".

Далее ты пишешь:

А решается данная проблема просто, при загрузке результатов сначало загружаешь OID объекта, если таковой в кэше присутсвует то делаешь MoveNext, а наверх выдаешь ссылку на кешируемый объект(если надо).


Так вот в этом "если надо" и состоит главная проблема. Потому что, если состояние объекта, который в кэше (т.е. измененный!!!, т.е. то состояние о котором думает прикладной программист), удовлетворяет условию where, то надо, а если не удовлетворяет — то не надо. А как это проверить. Никак! Ну то есть для данного запроса еще как-то можно, но для более сложного — нет.
http://www.lmdinnovative.com (LMD Design Pack)
Re[33]: Опять валидация данных
От: GlebZ Россия  
Дата: 30.03.05 15:44
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Далее ты пишешь:


S>

S>А решается данная проблема просто, при загрузке результатов сначало загружаешь OID объекта, если таковой в кэше присутсвует то делаешь MoveNext, а наверх выдаешь ссылку на кешируемый объект(если надо).


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


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

Что касается фанатсва OID то я фанат GUID. В некоторой степени это обсуждалось http://gzip.rsdn.ru/Forum/Message.aspx?mid=1046863&amp;only=1
Автор: GlebZ
Дата: 27.02.05
. Знаешь, сильно спасало.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[34]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 06:36
Оценка:
Здравствуйте, GlebZ, Вы писали:

Причем здесь OID? Я OID и делаю так, как ты говоришь, т.е. уникальными по всей системе и т.п. Но то, что ты сказал, к данному вопросу не имеет отношения.

Далее ты говоришь "За счет уменьшения функциональности OQL мы не перечитываем объекты БД". Это тоже совершенно другой вопрос. Да он может и важный, в чем я сомневаюсь, но к данной проблеме не имеет никакого отношения.

Последний раз , ооооочень подробно пишу пример!

1:
Начальное состояние базы:

OID Name
---------------
1 "xxx"
2 "yyy"
3 "aaa"
4 "aaa"
5 "aaa"

2:
Процесс с точки зрения прикладного программиста:

2.1:
obj = GetById(5);
obj.Name = "zzz";

cursor = #oql select x from SomeObjects x where x.Name = "aaa";

foreach (cursor)
{
  System.WriteLn(cursor.OID + "  " + cursor.Name);
};


2.2:
Внимание! Что хочет увидеть прикладной программист в качестве результата работы программы:

OID Name
---------------
3 "aaa"
4 "aaa"

2.3:
Т.е. он не должен увидеть объекта с OID = 5 в результатах запроса, так как он сменил его поле x.Name на "zzz" перед выполнением запроса, а в запросе стоит where x.Name = "aaa".

3:
Теперь, как этот процесс предлагаешь реализовать ты:

3.1:
В первых двух строчках программы, а именно:

obj = GetById(5);
obj.Name = "zzz";

В кэш выберется объект с OID = 5 и его поле Name изменится на "zzz". Это как раз понятно. А состояние базы после этого шага не измениться, т.е. останется как в (1), потому-что мы не сбрасываем изменения в базу, а держим их только в кэше (это опять же по твоему).

3.2:
Далее выполняем OQL запрос:

cursor = #oql select x from SomeObjects x where x.Name = "aaa";

Этот OQL запрос преобразуется в SQL запрос и уже SQL запрос выполняется в базе. И поскольку база находится в состоянии (1), то результатом этого SQL запроса будет:

OID Name
---------------
3 "aaa"
4 "aaa"
5 "aaa"

3.3:
Т.е. результат из (3.2) не совпадает с желаемым (2.2)!!!. Следовательно этот результат (SQL запроса) необходимо скорректировать, чтобы получить правильный результат OQL запроса.

3.4:
И в качестве корректировки для (3.3) ты предлагаешь, просто заменять те записи из результата SQL запроса, которые есть в кэше, на собственно кэшированные, т.е. после замены получится следующее:

OID Name
---------------
3 "aaa"
4 "aaa"
5 "zzz" // Эта строчка была в кэше, ее и заменили.

3.5:
Результат в (3.4) опять не соответствует ожидаемому (в 2.2). Это же очевидно! Хотели с where x.Name = "aaa", а получили (5, "zzz").



В пункте (3) я описал, как ты предлагаешь сделать. Результат получается неверным. Если ты не согласен — найди ошибку.

PS: Читай, пожалуйста, сообщения внимательней. Мы же сложные вещи обсуждаем. И они еще более сложные, потому что одно зависит от другого.
http://www.lmdinnovative.com (LMD Design Pack)
Re[34]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 07:02
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Что касается фанатсва OID то я фанат GUID. В некоторой степени это обсуждалось http://gzip.rsdn.ru/Forum/Message.aspx?mid=1046863&amp;only=1
Автор: GlebZ
Дата: 27.02.05
. Знаешь, сильно спасало.


Читал, читал.
Я выбрал следующий вид OID: OID у меня — 64'ех битное число (ну как long в C#). Оно разбито на несколько секций:
— 24 бита — TypeId
— 32 бита — HighVal
— 8 бит — LowVal

Я как бы не собираюсь работать с несколькими СУБД одновременно, и не собираюсь делать супер масштабируемое приложение. Ну, 500 юзеров — это максимум.
По этому я хотел ограничить размер OID (в битах), чтобы запихивать его в одно поле базы с типом NUMBER. Ну и чтобы память в кэше экономить тоже.
GUID для меня — слишком тяжелая штука.
http://www.lmdinnovative.com (LMD Design Pack)
Re[32]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 07:48
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Уровень snapshot даже оптимистической проверки не обеспечивает. Так что оптимистическая проверка должна быть обязательна.


В моем случае — эту проверку сам Oracle обеспечивает. Т.е. автоматически. И ничего для этого делать не нужно. Смотри здесь
Автор: GlebZ
Дата: 25.03.05
.
Ну и, вероятно, Oracle это несколько быстрее делает, чем если бы я сам вручную.

GZ>У диспетчера блокировок 3 функции: наложить блокировку, убрать блокировку, проверить блокировку. То есть функции одного Hashtable, где быстрота доступа O(1)(если реализация на C#). Это значительно быстрее и эффективнее чем блокировки на уровне БД. Особенно в условиях кэша.


В условиях нескольких серверов приложений с отдельными кэшами. И еще в условиях нескольких сессионных кэшей в каждом из серверов приложений. И еще в условиях (это не обсуждается, я так хочу и все!), когда кэш может выгружать ненужные в данный момент объекты, как измененные, так и просто прочитанные, неким LRU-подобным алгоритмом.

GZ>Сама задача трансформации OQL запроса в эффективный SQL достаточно интересна и сложна. Уж поверь, я этим занимался.


Да уж. Задолбался я с этим. Дык я еще только прототип сделал, над эффективностью SQL особо не думал. Так что многое еще впереди .

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

Напомню, что мы говорили о snapshot транзакции.

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

А сериализованные бизнес транзакции, даже если представить, что их можно было бы реализовать, противоречат самой сути бизнес транзакций. Так как тетка иногда нажимает на Refresh в формочках и хочет видет обновленные данные.

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

GZ>Не плоди системы. Забудь о SQL блокировках.


Ok. Забыли.

Давай пример для дальнейших рассуждений вот это (повторяю из поста выше):

6.2: И тогда получается, что эти несколько системных транзакций — короткие (какие и должны быть SQL транзакции) и без интерактива с пользователем. При таком подходе для точной реализации задачи из пункта 5 (важны 5.1, 5.2 и 5.3) нам нужно всего лишь два механизма:
6.2.1: Оптимистические snapshot системные транзакции.
6.2.2: Механизм "блокировок уровня бизнес транзакций". См. 5.6.


Т.е. системные транзакции у нас только оптимистические. И некоторую, желаемую, долю пессимизма они получают при использовании "блокировок уровня бизнес транзакций". Эту же долю пессимизма наследует и parent бизнес транзакция.




А теперь, собственно, дальнейшие рассуждения:

Мы забыли про SQL блокировки, предположив, что можно создать свой механизм блокировок. Такой механизм должен быть достаточно производительным и глобальным по отношению к разным сессиям и серверам приложений.
Здесь можно основываться на взаимодействии через базу данных, т.е. создать специальные таблички для хранения блокировок и т.п. Но, думаю, что это будет безбожно тормозить.
Значит нужен некий центральный сервис, через который сервера приложений и общаются. Типа "сервис блокировок".

Некий абстрактный интерфейс этого сервиса, предоставляемый серверу приложений, должен быть такой:

enum LockMode
{
    Shared,
    Noshare
};

interface LockService
{
    void LockObject(long objID, LockMode lockMode, long businessTransactionId);
    void LockObjects(long[] objIDs, LockMode[] lockModes, long businessTransactionId);
    void RemoveAllTransactionLocks(long businessTransactionId);
};


Функция LockObjects чисто для оптимизации по производительности, никакой дополнительной логической нагрузки в себе не несет.
Реализовать такой интерфейс, конечно, не проблема. Пусть все работает в оперативной памяти, исходя из предположения, что блокировок будет немного.

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

Итак: как, когда и зачем используется сервис блокировок:

10:
Одно важное замечание: Блокировки не подчиняются уровню изоляции транзакций. То есть, если одна транзакция установила noshare блокировку, а потом вторая попытается тоже установить блокировку, то у второй не должно этого получиться.
То есть я хочу сказать, что изменения данных транзакции сразу не видят, а блокировки должны видеть сразу, т.е. получается realtime. И это плохо.

11:
В соответствии с (5.5 отсюда
Автор: stalcer
Дата: 30.03.05
) блокировки накладываются явно бизнес логикой бизнес транзакции.

12:
Но блокировки еще и накладываются неявно при любом изменении объекта в течении бизнес транзакции. То есть если я делаю:

obj.Name = "zzz";

Все! Это само по себе должно приводить к неявной устаноке noshare блокировки. Ну естественно, если она еще не была установлена для данной транзакции.
Иначе грош-цена всем этим явным блокировкам, и ни от чего они не защитят.

13:
Так как блокировние в (11) и (12) должно выполняться в realtime (см. 10), т.е. при помощи синхроного взаимодействия с сервисом блокировок, то могут быть тормоза.
Блин. Даже число — и то 13 получилось .

14:
Хотел еще вот что сказать: Использование проверки версии при оптимистическом подходе никак картину с блокировками не меняет. Все равно неявные блокировки из (12) должны остаться!

Ну вот. Если ты знаешь еще какой-нибудь интересный подход — напиши .
http://www.lmdinnovative.com (LMD Design Pack)
Re[33]: Опять валидация данных
От: GlebZ Россия  
Дата: 31.03.05 10:52
Оценка:
Здравствуйте, stalcer, Вы писали:

1. Давай сначала о U блокировках. Рассмотрим когда они нужны. Они нужны в самом начале бизнес-транзакции. Это даст большую вероятность на успех блокирования. Какими методами принудить прикладника их устанавливать, это уже другой вопрос (выделением обязательных шагов, или просто через документацию).
2. Давай посмотрим что происходит чаще: — проверка блокировки, или ее установка. По моему мнению — проверка. Поэтому предлагаю следующий вариант:
1. При начале транзакции (сессии) копируется весь список заблокированных объектов.
2. При установке новой блокировки — она распространяется на основной сервис(где проверяется нужна ли она), и затем по всем спискам блокировок.
Памяти для одной блокировки нужно не так уж много. Поэтому на копирование не должно уходить много времени.
Еще, я пока не врублюсь, а нужны ли S-блокировки при snapshot транзакции?

В интерфейсе забыл еще метод: проверка заблокирован ли объект.

п.12 неоднозначен. Есть два пути, оставить на усмотрение прикладника (он все равно получит отлуп при фиксировании транзакции), либо так.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[35]: Опять валидация данных
От: GlebZ Россия  
Дата: 31.03.05 11:36
Оценка:
Здравствуйте, stalcer, Вы писали:

S>PS: Читай, пожалуйста, сообщения внимательней. Мы же сложные вещи обсуждаем. И они еще более сложные, потому что одно зависит от другого.

thanks, облажался
С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[35]: Опять валидация данных
От: GlebZ Россия  
Дата: 31.03.05 11:36
Оценка:
Здравствуйте, stalcer, Вы писали:

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

Просто, информация для размышлений об уникальности данных.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[34]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 11:56
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>2. Давай посмотрим что происходит чаще: — проверка блокировки, или ее установка.


Где вообще может понадобиться проверка блокировки. Я даже и не думал ее вообще делать.
ИМХО неявная проверка обязательно нужна в момент установления блокировки, то есть внутри сервиса блокировок.

GZ>Еще, я пока не врублюсь, а нужны ли S-блокировки при snapshot транзакции?


Мы говорим о блокировках на уровне бизнес транзакций! Бизнес транзакция у нас — не snapshot. Это системная транзакция — snapshot. Т.е. каждый из шагов бизнес транзакций — snapshot, в целом она — нет.
А S-блокировки — они ИМХО нужны. И именно для бизнес транзакций.

GZ>В интерфейсе забыл еще метод: проверка заблокирован ли объект.


См. выше.

GZ>п.12 неоднозначен. Есть два пути, оставить на усмотрение прикладника (он все равно получит отлуп при фиксировании транзакции), либо так.


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

Первая:
obj.Lock(LockMode.Shared); // Заблокировали, специально, чтобы никто в течении 
                           // этой бизнес транзакции не изменил этот объект.
                           // Причем сами мы менять его не собираемся.
// Долго-долго работаем с obj.
commit;

Вторая:
obj.Name = "xxx";
commit;


Если вторая не блокирует объект неявно при изменении, то спрашивается навига первая блокировала. И если эти две транзакции писали разные прикладники, то первый будет очень сильно удивлен поведением системы. Потому-что с его точки зрения он объект заблокировал. И этот объект не должен был измениться на протяжении всей бизнес транзакции (т.е. нескльких системных snapshot транзакций).

Аналогично, при любом update'е СУБД тоже ставит неявную U-блокировку. Но мы же забыли про SQL блокировки, тем более что в Oracle нет S-блокировок. Так что надо самим теперь это делать.
http://www.lmdinnovative.com (LMD Design Pack)
Re[36]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 12:06
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>thanks, облажался


Ну дык вот, что я изначально хотел сказать-то этим:

Так как язык запросов является неотемлимой частью системы, и так как теперь ясно, что необходимо сбрасывать накопившиеся изменения в базу перед выполнением запроса, то это значит, что кэш будет сбразывать изменения в ходе транзакции.
Это в свою очередь означает, что на протяжении всей системной транзакции (не бизнес транзакции) должна быть соответствующая SQL транзакция, тем более что через нее мы не только сбрасываем изменения, но и читаем данные.
А так как системная транзакция должна быть короткой, а бизнес транзакция вполне может быть длинной, то их придется разделить!

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

Да-да-да. Эволюция структуры — это отдельный разговор.

Давай-ка посмотрим, в какой степени сама СУБД поддерживает эволюцию структуры реляционной базы. Сразу скажу, ИМХО в недостаточной.
Но, такую же примерно степень я могу устроить для бизнес объектов.

Так же как и запись в БД не может быть перенесена в другую таблицу, а может быть лишь скопирована, т.е. это будет пусть и такая-же, но не та-же запись, также и у меня можно копировать объекты . Ну, и где разница?
http://www.lmdinnovative.com (LMD Design Pack)
Re[35]: Опять валидация данных
От: GlebZ Россия  
Дата: 31.03.05 12:24
Оценка:
Здравствуйте, stalcer, Вы писали:

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


GZ>>2. Давай посмотрим что происходит чаще: — проверка блокировки, или ее установка.


S>Где вообще может понадобиться проверка блокировки. Я даже и не думал ее вообще делать.

S>ИМХО неявная проверка обязательно нужна в момент установления блокировки, то есть внутри сервиса блокировок.
Maybe. Ты выбрал путь.

S>Мы говорим о блокировках на уровне бизнес транзакций! Бизнес транзакция у нас — не snapshot. Это системная транзакция — snapshot. Т.е. каждый из шагов бизнес транзакций — snapshot, в целом она — нет.

S>А S-блокировки — они ИМХО нужны. И именно для бизнес транзакций.
Именно. Попробуй опиши что должна делать S-блокировка при условии что у нас нет X-блокировок.

GZ>>п.12 неоднозначен. Есть два пути, оставить на усмотрение прикладника (он все равно получит отлуп при фиксировании транзакции), либо так.


S>Аналогично, при любом update'е СУБД тоже ставит неявную U-блокировку. Но мы же забыли про SQL блокировки, тем более что в Oracle нет S-блокировок. Так что надо самим теперь это делать.

Ты выбрал путь.
Считаю достоинством второго пути — принуждение прикладника явно блокировать объекты перед изменением. Может быть и с использованием дополнительных средств.
Недостаток в данном случае которые я вижу:
— то что прикладник никогда не знает откуда он может получить отлуп. Он может произвести большое кол-во действий, и при этом получить откат в неизвестном месте.
— то что прикладник явно блокируя объекты, может заблокировать их в начале бизнес-транзакции. Этим он обеспечит большую вероятность успеха транзакции. А неуспех при пессимистической транзакции (а она предназначена именно для максимального успеха транзакции) не очень приятно.

С уважением, Gleb.

PS:Только что получил очередной дедлок в Janus'e. Прикольно.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[36]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 12:54
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Именно. Попробуй опиши что должна делать S-блокировка при условии что у нас нет X-блокировок.


Так. Стоп-стоп. Чего-то я перепутался. Я говорю о двух типах блокировок: shared и noshare. Насколько я понял, это тоже самое, что ты называешь S-блокировкой и U-блокировкой. X-блокировка, это на сколько я понял — блокировка на чтение. Если да, то таких у нас нет.

Под shared я понимаю такую блокировку: При блокировнии объекта shared блокировкой:
— если объект не был заблокирован — блокировка возможна.
— если объект был заблокирован shared блокировкой — блокировка возможна.
— если объект был заблокирован noshare блокировкой — блокировка невозможна.

Под noshare я понимаю такую блокировку: При блокировнии объекта noshare блокировкой:
— если объект не был заблокирован — блокировка возможна.
— если объект был заблокирован shared блокировкой — блокировка невозможна.
— если объект был заблокирован noshare блокировкой — блокировка невозможна.

Здесь
Автор: stalcer
Дата: 30.03.05
в пункте (5.4) я описал, что объект, представляющий сам товар я блокирую shared блокировкой. Это потому, что я хочу, чтобы на протяжении всей бизнес транзакции этот объект не менялся. Но сам я его тоже менять не хочу, и поэтому позволяю остальным аналогичным транзакциям тоже блокировать его shared блокировкой.

Т.е. на трех кассах одновременно продают "ириску". Каждая блокирует объект "товар-ириска", т.е. они блокируют его одновременно, по этому и блокировка называется shared. Но зато пока они не закончат свои транзакции, тетка на складе не сможет удалить или изменить этот объект.

Т.е. shared блокировка не запрещает никому читать данные, но запрещает их изменять. Но от noshare отличается тем, что не запрещает также, другим устанавливать shared блокировку, т.е. не запрещает другим запрещать изменение объекта .

S>>Аналогично, при любом update'е СУБД тоже ставит неявную U-блокировку. Но мы же забыли про SQL блокировки, тем более что в Oracle нет S-блокировок. Так что надо самим теперь это делать.

GZ>Ты выбрал путь.

Путь-то я выбрал, т.е. предложил. И хочу посоветоваться не будет ли этот путь тормозить. А еще лучше, как сделать так, чтобы этот путь не тормозил. Как сделать сервис блокировок?

GZ>PS:Только что получил очередной дедлок в Janus'e. Прикольно.


Ни разу не видел .
http://www.lmdinnovative.com (LMD Design Pack)
Re[34]: Опять валидация данных
От: GlebZ Россия  
Дата: 31.03.05 13:14
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Если мы хотим получить в рамках апп-сервера функциональность, аналогичную ООСУБД, то придется следовать той же стратегии. Есть два с половиной варианта:

S>1. Использовать полностью свой движок запросов. РСУБД при этом отвечает исключительно за хранение данных, несколько упрощая манипуляции по сравнению с "голой" файловой системой.
S>При этом можно даже получить не слишком плохую производительность, но ценой написания весьма и весьма дорогостоящего оптимизатора запросов — иначе в память будет подниматься слишком много лишних объектов.
Не слишком плохую производительность? Уменьшая селективность запроса? Не очень верю.
S>2. По максимуму использовать движок SQL запросов. Тогда надо дать ему достаточное количество данных, т.е. все модификации должны прозрачно скидываться в БД. Кэш объектов в таком разе может быть полезен только для навигационных запросов, т.к. ассоциативные запросы его не используют (ну, точнее все равно будет некоторая экономия на инстанцировании объектов).
+1
S>2,5. Смешанный подход. Запросы выполняются по двум хранилищам — СУБД и кэшу. Результаты соответствующим образом мерджатся. В принципе, при аккуратной реализации можно сочетать лучшие черты обоих подходов. Потому как оптимизацией "массовой" части запроса будет заниматься движок СУБД, а анализ измененных объектов в кэше можно сделать и прямым перебором. Он будет не слишком плох, т.к. во-первых этих измененных объектов в каждый момент не так много, а во-вторых они все уже в памяти (не секрет, что основная потеря производительности в БД уходит на дисковый обмен).
+21


S>Еще я хотел бы отметить, что в данном контексте мы неявно перешли от OQL, который позволяет очень-очень много чего, к чему-то типа OCL. Потому что все обсуждаемые запросы сводятся к получению списка объектов. OQL позволяет возвращать самые дикие структуры, которые не соответствуют никакому исходному типу данных. Попытка реализовать полноценный OQL поверх РСУБД, что с кэшированием, что без — это практически самоубийство.

OQL — это уже имя нарицательное. Под ним, можно иметь ввиду уже любой язык который может адресовать объектные структуры. Будет ли это объектом, или нет — не важно. Но намек понравился, правильный.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[34]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 13:21
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


Возможно, но не подходит. Слишком сложно в реализации, и не практично. Все таки именно в СУБД должны выполняться запросы (хатя бы их часть, как в твоем пункте 2,5), для того чтобы сервер приложений не обрабатывал громадные массивы данных.

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


Спорить не буду. Я для этого еще слишком маленький .

S>2. По максимуму использовать движок SQL запросов. Тогда надо дать ему достаточное количество данных, т.е. все модификации должны прозрачно скидываться в БД. Кэш объектов в таком разе может быть полезен только для навигационных запросов, т.к. ассоциативные запросы его не используют (ну, точнее все равно будет некоторая экономия на инстанцировании объектов).


Это тот вариант который я выбрал.

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


Это тот вариант в который может быть когда-нибудь перерастет мой текущий. Я пока тоже не готов обсуждать этот вариант, так как знаний недостаточно, но думаю, здесь одной из самых острых проблем будет так называемая cache-compliteness-problem.
И еще не известно, насколько после решения этой проблемы производительность будет лучше чем в варианте (2).
И также неизвестно, вообще, в принципе возможно ли выполнение любого запроса без сброса кэша в базу. Т.е. всегда ли возможно обойтись одной лишь коррекцией результатов запроса, с учетом кэшированных данных, пусть и очень сложной. Вероятнее всего в некоторых случаях дешевле будет все-таки сбросить кэш.

S>Еще я хотел бы отметить, что в данном контексте мы неявно перешли от OQL, который позволяет очень-очень много чего, к чему-то типа OCL. Потому что все обсуждаемые запросы сводятся к получению списка объектов. OQL позволяет возвращать самые дикие структуры, которые не соответствуют никакому исходному типу данных. Попытка реализовать полноценный OQL поверх РСУБД, что с кэшированием, что без — это практически самоубийство.


Ты, наверное когда говоришь "OQL", имеешь ввиду какой-нибудь стандарт. Я же просто имею ввиду некоторый язык запросов, где прикладнику не нужно писать имена таблиц, а можно писать имена классов объектов, ну и другие полезные фишечки. И проверка синтаксиса у учетом метаданных.

Я вообще думаю, что не стоит делать сложный язык запросов. Я вижу роль языка запросов с общей картине следующую: он больше нужен, чтобы минимизировать объем данных, прокачиваемый через сервер приложений. То есть с его помощью делается первичная выборка, которая затем может дополнительно фильтроваться просто циклом на сервере приложений. Т.е. прикладной программой.
http://www.lmdinnovative.com (LMD Design Pack)
Re[35]: Опять валидация данных
От: stalcer Россия  
Дата: 31.03.05 13:23
Оценка:
Здравствуйте, GlebZ, Вы писали:

Да, конечно. Пункт (2,5) — красивая мечта!
http://www.lmdinnovative.com (LMD Design Pack)
Re[37]: Опять валидация данных
От: GlebZ Россия  
Дата: 31.03.05 13:58
Оценка:
Здравствуйте, stalcer, Вы писали:

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


GZ>>Именно. Попробуй опиши что должна делать S-блокировка при условии что у нас нет X-блокировок.


S>Так. Стоп-стоп. Чего-то я перепутался. Я говорю о двух типах блокировок: shared и noshare. Насколько я понял, это тоже самое, что ты называешь S-блокировкой и U-блокировкой. X-блокировка, это на сколько я понял — блокировка на чтение. Если да, то таких у нас нет.

Да.

S>Под shared я понимаю такую блокировку: При блокировнии объекта shared блокировкой:

S>- если объект не был заблокирован — блокировка возможна.
S>- если объект был заблокирован shared блокировкой — блокировка возможна.
Много блокировок на один объект?
S>- если объект был заблокирован noshare блокировкой — блокировка невозможна.

S>Под noshare я понимаю такую блокировку: При блокировнии объекта noshare блокировкой:

S>- если объект не был заблокирован — блокировка возможна.
S>- если объект был заблокирован shared блокировкой — блокировка невозможна.
S>- если объект был заблокирован noshare блокировкой — блокировка невозможна.

S>Здесь
Автор: stalcer
Дата: 30.03.05
в пункте (5.4) я описал, что объект, представляющий сам товар я блокирую shared блокировкой. Это потому, что я хочу, чтобы на протяжении всей бизнес транзакции этот объект не менялся. Но сам я его тоже менять не хочу, и поэтому позволяю остальным аналогичным транзакциям тоже блокировать его shared блокировкой.

U-блокировка делает то же самое.
Основное свойство S-блокировки, не допустить X-блокировку или как ты сказал блокировку на чтение. В данном случае я не вижу в ней смысл.
S>>>Аналогично, при любом update'е СУБД тоже ставит неявную U-блокировку. Но мы же забыли про SQL блокировки, тем более что в Oracle нет S-блокировок. Так что надо самим теперь это делать.
GZ>>Ты выбрал путь.

S>Путь-то я выбрал, т.е. предложил. И хочу посоветоваться не будет ли этот путь тормозить. А еще лучше, как сделать так, чтобы этот путь не тормозил. Как сделать сервис блокировок?

Видоизмени то что я предложил. По моему — шняга с копированием списков должна убыстрить. Но ессно IMHO.

GZ>>PS:Только что получил очередной дедлок в Janus'e. Прикольно.


S>Ни разу не видел .

Не знаю в чем дело (я недавно им пользуюсь) но чего-то оно происходит достаточно часто.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[6]: Опять валидация данных
От: Сомов Александр Россия  
Дата: 31.03.05 14:06
Оценка:
S>Таким образом получается, что для работы с формами лучше иметь бизнес объекты с:
S>

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

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


На самом деле это решается паттерном builder. Т.е. есть объект builder, который используется для построения бизнес-объекта. Конструктор пустой, и все свойста для заполнения присутствуют. Как только программист решает, что все данные собраны, он делает newBusinessObject = builder.Create(). И вот Create либо возвращает объект в согласованном состоянии, либо выкидывает исключение. (Кстати, самый простой пример — это StringBuilder (из .NET), правда он как раз всегда может создать строку в согласованном состоянии, но зато мы не увидим строку до того, как всё её содержимое будет собрано).
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Re[7]: Опять валидация данных
От: stalcer Россия  
Дата: 01.04.05 06:08
Оценка:
Здравствуйте, Сомов Александр, Вы писали:

СА>На самом деле это решается паттерном builder. Т.е. есть объект builder, который используется для построения бизнес-объекта. Конструктор пустой, и все свойста для заполнения присутствуют. Как только программист решает, что все данные собраны, он делает newBusinessObject = builder.Create(). И вот Create либо возвращает объект в согласованном состоянии, либо выкидывает исключение. (Кстати, самый простой пример — это StringBuilder (из .NET), правда он как раз всегда может создать строку в согласованном состоянии, но зато мы не увидим строку до того, как всё её содержимое будет собрано).


Вы это программистам-прикладникам расскажите . Который просто хотят добавить в систему, например, "справочник городов". И хотят сделать это за 2 минуты. И преимущественно кликаньем мышкой по мастерам. И чтобы форма сама построилась. И. т.д. и .т.п.

Они за вами после этого неделю с топором носиться будут.
И ведь поймают в конце-концов. Потому что их больше.

Если серьезно, то мне в этом отношении нравиться Delphi. Вот с какой точки зрения: Delphi не заставляет среднего пользователя писать объектно-ориентированные вещи. Пользователи преимущественно используют уже готовые (т.е. VCL).
А как известно, писать библиотеки в ОО стиле гораздо-гораздо-гораздо сложнее, чем использовать их.

Поэтому в фреймворке я хочу, чтобы всякие справочники (и бизнес объекты для них) создавались мастерами, т.е. визуальными средствами, например, как в 1С.
А использовать их в бизнес логике, естественно программно.
http://www.lmdinnovative.com (LMD Design Pack)
Re[38]: Опять валидация данных
От: stalcer Россия  
Дата: 01.04.05 06:30
Оценка:
Здравствуйте, GlebZ, Вы писали:

S>>Под shared я понимаю такую блокировку: При блокировнии объекта shared блокировкой:

S>>- если объект не был заблокирован — блокировка возможна.
S>>- если объект был заблокирован shared блокировкой — блокировка возможна.
GZ>Много блокировок на один объект?

В этом весь и смысл. Ну например, могут же две проги держать открытым один и тот же файл, но только в read режиме. Вот каждая из них и блокирует этот файл shared блокировкой.
А зачем они (проги) ставят блокировки — чтобы не разрешить третьей проге открыть файл в режиме write (так как открывая файл в режиме write третья прога должна наложить noshare блокировку, и у нее это не получится).

S>>Здесь
Автор: stalcer
Дата: 30.03.05
в пункте (5.4) я описал, что объект, представляющий сам товар я блокирую shared блокировкой. Это потому, что я хочу, чтобы на протяжении всей бизнес транзакции этот объект не менялся. Но сам я его тоже менять не хочу, и поэтому позволяю остальным аналогичным транзакциям тоже блокировать его shared блокировкой.

GZ>U-блокировка делает то же самое.

Что "то же самое"? Разве можно наложить много U-блокировок на один объект. Я же написал "...и поэтому позволяю остальным аналогичным транзакциям тоже блокировать его..."

S>>Путь-то я выбрал, т.е. предложил. И хочу посоветоваться не будет ли этот путь тормозить. А еще лучше, как сделать так, чтобы этот путь не тормозил. Как сделать сервис блокировок?

GZ>Видоизмени то что я предложил. По моему — шняга с копированием списков должна убыстрить. Но ессно IMHO.

Ладно, над некоторым кэшированием блокировок на сервере приложений надо подумать.

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

Да, еще дед-локи надо определять. Не так все тривиально получается.
http://www.lmdinnovative.com (LMD Design Pack)
Re[39]: Опять валидация данных
От: GlebZ Россия  
Дата: 01.04.05 10:04
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Что "то же самое"? Разве можно наложить много U-блокировок на один объект. Я же написал "...и поэтому позволяю остальным аналогичным транзакциям тоже блокировать его..."

OK. Структура сервиса усложняется.

S>>>Путь-то я выбрал, т.е. предложил. И хочу посоветоваться не будет ли этот путь тормозить. А еще лучше, как сделать так, чтобы этот путь не тормозил. Как сделать сервис блокировок?

GZ>>Видоизмени то что я предложил. По моему — шняга с копированием списков должна убыстрить. Но ессно IMHO.

S>Ладно, над некоторым кэшированием блокировок на сервере приложений надо подумать.


S>У меня еще вот какой вопрос: сервис блокировок — центральный сервис. И он должен быть живучее отдельно взятого сервера приложений.

S>И главный вопрос, как сделать так чтобы он мог засекать падения серверов приложений, ну и обрабатывать их.
Для серверов приложений это не проблема. Просто нужен сервис который будет опрашивать сервера приложений через какой-то промежуток времени. В случае недоступности (а тут возможна некоторая усложненная процедура определения недоступности) то закрытие блокировок. Как только сервер-приложений вновь стал видимым, то он должен переслать свои блокировки еще раз. В случае невозможности блокирования — заинтересованные транзакции должны быть отбиты.
S>А то сессия заблокирует и накроется. И все остальные будут висеть.
Значительно хуже если надо делать зависимость от удаленных клиентов. В этом случае можно говорить только об одностороннем канале связи. То есть, клиент должен удерживать свою сессию.
S>Да, еще дед-локи надо определять. Не так все тривиально получается.
А тут все просто.
Вариант 1.
Тебе на фиг не сдались ожидание разблокирования. Обычно в серверах приложений так и делают.
Вариант 2.
Ожидание по некоторому небольшому timeout. В ожидании того, что конкурирующая транзакция достаточно коротка.
Вариант 3.
Наиболее сложный. Построение ациклического графа блокировок. Но спасибо Кодту, за готовую реализацию
Re[7]: Дедлоки!
Автор: Кодт
Дата: 21.10.04

Или ты имел ввиду дедлоки БД?

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[40]: Опять валидация данных
От: stalcer Россия  
Дата: 01.04.05 12:01
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Просто нужен сервис который будет опрашивать сервера приложений через какой-то промежуток времени. В случае недоступности (а тут возможна некоторая усложненная процедура определения недоступности) то закрытие блокировок.


Да. Это понятно. Непонятна уже конкретная реализация процедуры определения недоступности. Я буду на CORBA все делать. Что, сделать просто метод ping() на сервере приложений, который ничего не делает, и периодически вызывать его из сервиса блокировок? Типа если системной ошибки CORBA не произошло, то усе окей?

GZ>Как только сервер-приложений вновь стал видимым, то он должен переслать свои блокировки еще раз. В случае невозможности блокирования — заинтересованные транзакции должны быть отбиты.


А вот это уже хуже. Так как если сервис блокировок, считая что сервер приложений сдох, снял его блокировки, то потом их восстанавливать уже нельзя. Так как время уже упущено.

S>>Да, еще дед-локи надо определять. Не так все тривиально получается.

GZ>А тут все просто.
GZ>Вариант 1.
GZ>Тебе на фиг не сдались ожидание разблокирования. Обычно в серверах приложений так и делают.

Не понял о чем ты.

GZ>Вариант 2.

GZ>Ожидание по некоторому небольшому timeout. В ожидании того, что конкурирующая транзакция достаточно коротка.
GZ>Вариант 3.
GZ>Наиболее сложный. Построение ациклического графа блокировок. Но спасибо Кодту, за готовую реализацию
GZ>Re[7]: Дедлоки!
Автор: Кодт
Дата: 21.10.04


Oracle вроде так делает: сначала ждет некоторое короткое время, и если за это время блокировка не освободилась, то начинает по графу определять дед-лок.

Я еще вот о чем. Ты сам говорил, и я здесь с тобой согласен, что всякие подвисания из-за блокировок необходимо показывать юзеру в виде, например, всплывающего окошка. Типа "Объект такой-то заблокирован тем-то. Ждите." Так вот не ждать же ему вечно. То есть в этом окошке должна быть кнопка "Задолбало ждать. Виг с ней, с этой транзакцией.". Ну и по этой кнопке клиент посылает на сервер приложений соответствующй сигнал, и сервер приложений прерывает процесс блокирования, а для прикладной программы генерится специальное исключение.

GZ>Или ты имел ввиду дедлоки БД?


Нет. Ты верно понял.
http://www.lmdinnovative.com (LMD Design Pack)
Re[41]: Опять валидация данных
От: GlebZ Россия  
Дата: 01.04.05 12:35
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Да. Это понятно. Непонятна уже конкретная реализация процедуры определения недоступности. Я буду на CORBA все делать. Что, сделать просто метод ping() на сервере приложений, который ничего не делает, и периодически вызывать его из сервиса блокировок? Типа если системной ошибки CORBA не произошло, то усе окей?

Наверно да. Чем проще, тем лучше. Надо только проверить как работает CORBA. Для DCOM такого просто так не сделаешь. Он может зависнуть на несколько минут при посылке сообщения(на сколько зависает — в документации не описано, долго удивлялся на такое поведение).
Кстати, подобный сервис может еще для других вещей пригодится. Кто знает.

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

Для тех-кто не сможет (блокировками заняты), придется так и так поубивать. Ну для остальных, чем им жить запрещать? Как недавно правильно замечали, ошибки канала и на локалке вещь достаточно частая.

S>>>Да, еще дед-локи надо определять. Не так все тривиально получается.

GZ>>А тут все просто.
GZ>>Вариант 1.
GZ>>Тебе на фиг не сдались ожидание разблокирования. Обычно в серверах приложений так и делают.

S>Не понял о чем ты.

О том, что пользователю сразу откатывают транзакцию и сообщают об этом.

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

А он о другом пользователе подумал? А если это генеральный директор? Этак можно до увольнительной донажиматься.
Варианты:
1. Все делает администратор. Пользователь звонит, так-то и так-то, хочу редактировать. У администратора есть инструмент. Он отбивает по своему усмотрению.
2. Не делал, но мысль показалась интересной. Выстраивается дерево подчинения (если в базе уже прописаны подчинение пользователей то удобно). Например: Администратор — высшая ступень. Он имеет право перебивать блокировки кому-угодно. Генеральный директор — может отбить блокировку кому-угодно кроме Администратора, замы ген. соответсвенно всем кроме генерального или администратора, и т.д.
Еще есть такая вещь. У блокировок есть время жизни. Обычно это нужно для offline клиентов. В случае если пользователь взял документ на редактирование, ушел из online и уехал. Например — на следующий день, если пользователь не предпринял действий, то блокировка снимается автоматически. Но здесь время блокировки зависит от самого бизнес-объекта.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[42]: Опять валидация данных
От: stalcer Россия  
Дата: 01.04.05 13:15
Оценка:
Здравствуйте, GlebZ, Вы писали:

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

GZ>Для тех-кто не сможет (блокировками заняты), придется так и так поубивать. Ну для остальных, чем им жить запрещать? Как недавно правильно замечали, ошибки канала и на локалке вещь достаточно частая.

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

GZ>О том, что пользователю сразу откатывают транзакцию и сообщают об этом.


А, понятно.

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

GZ>А он о другом пользователе подумал? А если это генеральный директор? Этак можно до увольнительной донажиматься.

Да нет. Я же свою транзакцию имел ввиду. Т.е. пользователь нажимая на эту кнопку прерывает свою транзакцию. В старой версии системы "Эталон" такое было (новую я не видел). И у нас народ этим пользуется. А чего ждать-то бесконечно. Отменил да и нафиг. Занялся пока чем-нибудь другим.
Да, только такой подход может привести к длительным системным транзакциям.
http://www.lmdinnovative.com (LMD Design Pack)
Re[34]: Опять валидация данных
От: GlebZ Россия  
Дата: 04.04.05 09:10
Оценка:
Здравствуйте, Sinclair, Вы писали:

Что-то посмотрел как теоретически реализовать вариант 2.5. Хреновенько чего-то получается. И логика достаточно сложная, и запросы избыточны, а без статитики вообще каюк. Посмотрел старые записи, я оказывается не раз к нему возвращался. Только забивал на это дело.

Существуют ли какие-нибудь реализации п.1 и п 2.5?

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[43]: Опять валидация данных
От: GlebZ Россия  
Дата: 04.04.05 09:10
Оценка:
Здравствуйте, stalcer, Вы писали:

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

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

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[44]: Опять валидация данных
От: stalcer Россия  
Дата: 04.04.05 10:10
Оценка:
Здравствуйте, GlebZ, Вы писали:

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


Этот "скоп" (множество блокируемыз объектов) еще определить нужно. В большинстве случаев в начале бизнес-транзакции его определить как раз и нельзя. Т.к. пользователь выбирает его посредством GUI.
http://www.lmdinnovative.com (LMD Design Pack)
Re[45]: Опять валидация данных
От: GlebZ Россия  
Дата: 04.04.05 12:30
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Этот "скоп" (множество блокируемыз объектов) еще определить нужно. В большинстве случаев в начале бизнес-транзакции его определить как раз и нельзя. Т.к. пользователь выбирает его посредством GUI.

Слушай, я сейчас подумал. В принципе, у транзакции существует и можно определить момент когда она становится пишущей. То есть, пользователь прочитал данные, начал редактировать. А если в этот момент переводить все S-блокировки в U. Просто, интересно твое мнение по применимости и возможности.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[46]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.04.05 13:04
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>Слушай, я сейчас подумал. В принципе, у транзакции существует и можно определить момент когда она становится пишущей. То есть, пользователь прочитал данные, начал редактировать. А если в этот момент переводить все S-блокировки в U. Просто, интересно твое мнение по применимости и возможности.
Проблема в том, что такая стратегия с большой вероятностью приведет к дедлоку. U -блокировку нельзя наложить, пока есть чужая S-блокировка. Два процесса, выполняющих одинаковые сценарии, неизбежно друг друга запрут. Именно поэтому ввели U-блокировку в дополнение к S и X, чтобы можно было гарантировать ее конверсию в X, все еще разрешая наложение S.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[47]: Опять валидация данных
От: GlebZ Россия  
Дата: 04.04.05 13:19
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Проблема в том, что такая стратегия с большой вероятностью приведет к дедлоку. U -блокировку нельзя наложить, пока есть чужая S-блокировка.

Как раз наоборот. С помощью такой тактики, можно упорядочить последовательность блокировок и кардинально решить проблему блокировок.
S> гарантировать ее конверсию в X, все еще разрешая наложение S.
Ты что-то странное написал. Не понял.
С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[35]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.04.05 13:24
Оценка:
Здравствуйте, GlebZ, Вы писали:

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


GZ>Что-то посмотрел как теоретически реализовать вариант 2.5. Хреновенько чего-то получается. И логика достаточно сложная, и запросы избыточны, а без статитики вообще каюк.

Гм. Да вроде бы не очень нужна статистика-то. Тут ведь ".5" предполагается реализовать прямым перебором списка измененных объектов. Какая уж там статистика. Статистику пусть РСУБД внути себя ведет.
GZ> Посмотрел старые записи, я оказывается не раз к нему возвращался. Только забивал на это дело.

GZ>Существуют ли какие-нибудь реализации п.1 и п 2.5?

Если честно, то не в курсе. Ну вот Versant вроде как использует первый подход, судя по тому, что запросы в них на самом деле реляционные — скромно упоминая про невозможность использования методов объектов в запросах, они практически выдают реляционную природу своей серверной стороны. С другой стороны, там все-таки не вполне традиционная РСУБД стоит — некоторые фишечки там сделаны нарошно для оптимизации навигационнных запросов сделаны.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[48]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.04.05 13:57
Оценка:
Здравствуйте, GlebZ, Вы писали:

S>>Проблема в том, что такая стратегия с большой вероятностью приведет к дедлоку. U -блокировку нельзя наложить, пока есть чужая S-блокировка.

GZ>Как раз наоборот. С помощью такой тактики, можно упорядочить последовательность блокировок и кардинально решить проблему блокировок.
S>> гарантировать ее конверсию в X, все еще разрешая наложение S.
GZ>Ты что-то странное написал. Не понял.
GZ>С уважением, Gleb.
Гм. Я может неправильно применяю термины, т.к. несколько отстал от вашей беседы Именование блокировок я трактую согласно доке от MS SQL Server. Концепция пессимистичного блокирования вместе с причинами введения промежуточных блокировок между shared и eXclusive кратко изложена вот здесь
Автор: Sinclair
Дата: 27.08.02
.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[36]: Опять валидация данных
От: GlebZ Россия  
Дата: 04.04.05 13:57
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

Прямой перебор не всегда возможен. Например:
SELECT A WHERE A.f>20 and A.B.f>10 AND A.B.C.f>20

при этом — у нас существуют в кэше набор добавленных С, при этом нет соответсвующих B. В результате, мы должны подгрузить все B которые завязаны на С. Ессно, навигационный доступ при этом не эффективен. Для измененных С — другая логика. В них уже можем что-то прогнозировать.
S>Какая уж там статистика. Статистику пусть РСУБД внути себя ведет.
Статистика уже желательна на этапе трансформации OQL в SQL. Если бы SQL не влиял на планы запросов, было-бы очень хорошо. Но это не так. Допустим:
SELECT A WHERE (A.B.F>20 AND A.C.F>20 AND A.C.F1=A.B.F1)

где A.B и A.C — коллекции.
В результате два варианта:
SELECT A.* FROM A 
WHERE 
    A.B IN (SELECT B.OID FROM WHERE B>20 AND 
        B.F1 IN (SELECT C.F1 FROM C WHERE C.F>20))

И
SELECT A.* FROM A 
WHERE 
    A.С IN (SELECT C.OID FROM C WHERE C.F>20 AND 
        с.F1 IN (SELECT B.F1 FROM WHERE B>20 ))

Стандартные БД не умеют развертывать такие запросы. А без информации о кардинальности, можно сделать очень неприлично долгий запрос.

GZ>>Существуют ли какие-нибудь реализации п.1 и п 2.5?

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

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[49]: Опять валидация данных
От: GlebZ Россия  
Дата: 04.04.05 14:17
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


S>>>Проблема в том, что такая стратегия с большой вероятностью приведет к дедлоку. U -блокировку нельзя наложить, пока есть чужая S-блокировка.

GZ>>Как раз наоборот. С помощью такой тактики, можно упорядочить последовательность блокировок и кардинально решить проблему блокировок.
Блин, сам описался. Ессно имелось ввиду проблему дедлоков. Да еще, ее можно не упрорядочить по наложению, а вообще сделать кооперативным (в каждый момент времени только одна транзакция конвертирует пакет блокировок).
S>>> гарантировать ее конверсию в X, все еще разрешая наложение S.
GZ>>Ты что-то странное написал. Не понял.
Как ты правильно заметил, гарантируется отсутсвие дедлоков при конверсии. Но гарантировать саму конверсию? Хотя это уже буквоедство.
S>Гм. Я может неправильно применяю термины, т.к. несколько отстал от вашей беседы Именование блокировок я трактую согласно доке от MS SQL Server. Концепция пессимистичного блокирования вместе с причинами введения промежуточных блокировок между shared и eXclusive кратко изложена вот здесь
Автор: Sinclair
Дата: 27.08.02
.

У нас здесь несколько другое. Нет запрещения на чтение, то бишь X блокировок. Плюс к этому ораклоидная сериализация без явного блокирования (считай что snapshot).

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[38]: Опять валидация данных
От: GlebZ Россия  
Дата: 04.04.05 16:00
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Надо подумать....

S>Упс, похоже мы вообще попали. Если у нас к примеру есть один миллион объектов типа A, и все эти A ссылаются на ровно один B, и по чистой случайности у нас именно этот B изменен в транзации (B.d = 5 вместо хранимого в СУБД d = 10), то результат запроса "select A where B.d = 5" не будет иметь никакого отношения к реальности. Увы, при этом перебор кэша не спасает — даже если мы и поймем, что запрос зависит именно от этого B, ничего полезного сделать уже нельзя — все данные про А по-прежнему сидят в базе, в кэше пусто. Упес пипиндур. Был неправ. Прошу срочно расстрелять меня за сортиром.
Во первых — сейчас это уже не модно. Вот замочить в сортире, это по путински.
Во-вторых — еще не все потеряно. В принципе, имея нормальный граф выполнения запроса, можно выделять важную информацию из кэша по B и строить избыточные запросы. Правда, сразу начинаются проблемы ограничения SQL по длине. И еще важна информация по измененному полю. Иначе придется генерить по всем B которые были изменены.
Ну в общем, ничего хорошего это не предвещает.

S>
S>select * from A 
S>inner join B on A.B = B.OID 
S>inner join C on A.C = C.OID
S>where C.F1 = B.F1
S>and B.F > 20 and C.F > 20
S>

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

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[46]: Опять валидация данных
От: stalcer Россия  
Дата: 05.04.05 06:01
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Слушай, я сейчас подумал. В принципе, у транзакции существует и можно определить момент когда она становится пишущей.


Согласен. Об этом ниже.

GZ>То есть, пользователь прочитал данные, начал редактировать. А если в этот момент переводить все S-блокировки в U. Просто, интересно твое мнение по применимости и возможности.


Как правильно заметил Sinclair, "shared" не всегда можно сконвертировать в "noshare". Именование блокировок отсюда
Автор: stalcer
Дата: 31.03.05
.

О моменте, когда транзакция становится пишущей:

Мне кажется, что ты все упрощаешь, говоря "пользователь прочитал данные, начал редактировать".
Я бы разделил бизнес транзакцию на следующие этапы:
1: Интерактивное взаимодействие с пользователем.
2: Окончательный рассчет + коммит.

Дык вот этап (1) — длительный (с перерывами на обеды и т.п. ). И на протяжении этого этапа пользователь при помощи GUI (а также и некоторой бизнес логики) может набирать данные, причем это не одно действие, т.е. он может открывать различные дополнительные справочники и т.п. То есть данные подчитываются на протяжении всего первого этапа. То есть на протяжении всего интерактивного диалога с пользователем.

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

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

— Вводим "временно хранимые объекты", как описано здесь
Автор: stalcer
Дата: 30.03.05
.
— На этапе (1) запрещаем изменение любых данных, кроме "временно хранимых объектов". Зато этот этап может быть длительным и состоять из нескольких системных транзакций.
— Этап (2) делаем из только одной системной транзакции, и в нем производим все необходимые модификации данных, на основе сформированных "временно хранимых объектов".

Такми образом — атомарность обеспечена.
Следует заметить, что на этапе (2) работает рассчет написанный прикладником, т.е. изменения реальных данных (на основе "временно хранимых объектов") система автоматически не делает. И вообще структура "временно хранимых объектов" не соответствует настоящим хранимым объектам. Т.е. временно хранимые объекты — это дополнительная сущность, с которой работает прикладная программа.

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

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

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

GZ>Как ты правильно заметил, гарантируется отсутсвие дедлоков при конверсии. Но гарантировать саму конверсию? Хотя это уже буквоедство.


Это не буквоедство, как раз сама конверсия во многих сдучаях и не пройдет.
http://www.lmdinnovative.com (LMD Design Pack)
Re[39]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.04.05 10:07
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Во первых — сейчас это уже не модно. Вот замочить в сортире, это по путински.

GZ>Во-вторых — еще не все потеряно. В принципе, имея нормальный граф выполнения запроса, можно выделять важную информацию из кэша по B и строить избыточные запросы. Правда, сразу начинаются проблемы ограничения SQL по длине. И еще важна информация по измененному полю. Иначе придется генерить по всем B которые были изменены.
GZ>Ну в общем, ничего хорошего это не предвещает.
GZ>Забыл distinct поставить, но это уже мелочи.
Не нужен там никакой дистинкт. Inner join по FK/PK не вернет больше одной записи для A.
GZ>Вобщем у меня получались такие запросы, что хоть вешайся. В основном связано с обработкой IN. Сейчас на взгляд уже не помню. Надо дома посмотреть.
Ну, если честный OQL конвертить, то могут и не такие кошмары присниться. Товарищь Fegaras, например, считает, что надо план запроса строить статически — при компиляции. Он как раз собаку съел на оптимизации запросов типа "выбрать отделы, все менеджеры в которых старше среднего возраста своих подчиненных".
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[40]: Опять валидация данных
От: GlebZ Россия  
Дата: 05.04.05 15:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

GZ>>Вобщем у меня получались такие запросы, что хоть вешайся. В основном связано с обработкой IN. Сейчас на взгляд уже не помню. Надо дома посмотреть.

S>Ну, если честный OQL конвертить, то могут и не такие кошмары присниться.
Потому OQL и адаптируют, чтобы спать спокойно.
S>Товарищь Fegaras, например, считает, что надо план запроса строить статически — при компиляции. Он как раз собаку съел на оптимизации запросов типа "выбрать отделы, все менеджеры в которых старше среднего возраста своих подчиненных".
А я с ним согласен. (Это который Leonidas Feragas? Интересные статейки у него есть? Если не в лом дай ссылки).

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[41]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.04.05 02:59
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>А я с ним согласен. (Это который Leonidas Feragas? Интересные статейки у него есть? Если не в лом дай ссылки).
Ссылок не дам — те, что у меня, скачаны с платного ACM. Если хочешь, то стукнись в icq 12209728 — я тебе их намылю.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[42]: Опять валидация данных
От: stalcer Россия  
Дата: 06.04.05 05:39
Оценка:
Здравствуйте, Sinclair, Вы писали:

А может подскажете как делать работу с наследованием, т.е. запросы вида:

1:
select x from ClassA x where x is ClassB


2:
select (x as ClassB).F1 from x where (x as ClassB).F2 = 7


Как реализовать операторы is и as. Оператор as семантически думаю как в C# сделать, чтобы возвращал NULL если приведение не удалось, потому как делать эксепшены при выполнении OQL запроса (читай при выполнении соответствующего SQL запроса) — никак.
Как их реализовать, чтобы было эффективно, в идеале чтобы индексы БД работали? Как для этого построить структуру таблиц? Может какие-нибудь хитрые дополнительные поля включать?

Все это интересует для случая, когда все наследники хранятся в той же таблице, что и предки. Т.е. одна таблица содержит все необходимые поля.
http://www.lmdinnovative.com (LMD Design Pack)
Re[43]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.04.05 06:29
Оценка:
Здравствуйте, stalcer, Вы писали:

S>1:

S>
S>select x from ClassA x where x is ClassB
S>

А, пардон, зачем? Ведь можно сразу сделать
select * from ClassB

S>2:
S>
S>select (x as ClassB).F1 from x where (x as ClassB).F2 = 7
S>

Ну вот, уже пошли даункасты. Зачем???
Надо так:
select x.F1 from ClassB x where x.F2 = 7


S>Как реализовать операторы is и as.

Хм. Я не очень понимаю контекст... В моем понимании is и as могут быть полезны только в таком контексте:
select * from Order where Order.CounterAgent is Person

или вот так:
select * from Order where (Order.CounterAgent is Person) and (Order.CounterAgent as Person).LastName like 'Peter%'

Во втором случае мы видим источник потенциальной проблемы с оператором as. С одной стороны, мы защитили результат даункаста при помощи is, с другой стороны, порядок вычисления термов оператора AND не определен. Что означает, что мы нарвемся либо на Invalid Cast либо на Null Reference (в зависимости от семнтики as).
Я бы запретил as совсем. Вышеприведенный запрос можно переписать как
select * from Order where Order.CounterAgent in (select * from Person where Person.LastName like 'Peter%')

Как видно, исчезла потребность не только в as, но и в is.
Тем не менее, применение такой же техники для самого is не оправдано с точки зрения производительности:
select * from Order where Order.CounterAgent in (select * from Person)


Поэтому многие собаководы включают идентификатор класса прямо в ссылку. Тогда запрос
select * from Order where Order.CounterAgent is Person

превращается в
select * from Order where Order.[CounterAgent.TypeID] in ({PersonDescendantsList})


S>Оператор as семантически думаю как в C# сделать, чтобы возвращал NULL если приведение не удалось, потому как делать эксепшены при выполнении OQL запроса (читай при выполнении соответствующего SQL запроса) — никак.

Как я уже упомянул, само по себе приведение к null ничем не поможет.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[44]: Опять валидация данных
От: stalcer Россия  
Дата: 06.04.05 07:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А, пардон, зачем? Ведь можно сразу сделать


Это же просто для примера. Я же не спрашиваю как переписать запрос, чтобы не использовать as. Я спрашиваю, как реализовать as в общем случае.

S>Ну вот, уже пошли даункасты. Зачем???


Для полноты поддержки концепции наследования в языке запросов. Это тоже был просто пример.

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

S>
S>select * from Order where Order.CounterAgent is Person
S>

S>превращается в
S>
S>select * from Order where Order.[CounterAgent.TypeID] in ({PersonDescendantsList})
S>


[CounterAgent.TypeID] это что ?
Значит, in используется. Это, наверное, тоже тормозить будет. Но, это уже идея. А может быть некоторые другие сабаководы как-нибудь по другому поступают ?

S>>Оператор as семантически думаю как в C# сделать, чтобы возвращал NULL если приведение не удалось, потому как делать эксепшены при выполнении OQL запроса (читай при выполнении соответствующего SQL запроса) — никак.

S>Как я уже упомянул, само по себе приведение к null ничем не поможет.

Ну, почему. Это же NULL в понимании SQL. То есть — неизвестное значение. Что получается:

(x as ClassB).F2

если здесь (x as ClassB) вернет NULL, то это означает, что мы хотим узнать значение поля F2 у неизвестного объекта. Результат этой операции (оператора ".") будет — неизвестное значение, т.е. NULL. И никакого эксепшена.
http://www.lmdinnovative.com (LMD Design Pack)
Re[44]: Опять валидация данных
От: stalcer Россия  
Дата: 06.04.05 07:12
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>
S>>select x from ClassA x where x is ClassB
S>>

S>А, пардон, зачем? Ведь можно сразу сделать
S>
S>select * from ClassB
S>


Хорошо. Но, если вершиной иерархии наследования является ClassA, то твой OQL запрос, после преобразования в SQL будет неявно содержать where условие. Так что, явно я его указываю или оно само неявно в SQL запрос вписывается — неважно. Вопрос в том, как это эффективно реализовать?
http://www.lmdinnovative.com (LMD Design Pack)
Re[45]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.04.05 07:31
Оценка:
Здравствуйте, stalcer, Вы писали:
S>[CounterAgent.TypeID] это что ?
Имеется в виду то, что для атрибута CounterAgent в таблице RDBMS хранится два поля: [CounterAgent.TypeID] и [CounterAgent.OID]. Тогда
S>Значит, in используется. Это, наверное, тоже тормозить будет.
Очень вряд ли. Там же фиксированный список будет. Сколько у тебя может быть потомков у класса в системе? 1000? Ерунда — полетит со страшной скоростью.
S>Но, это уже идея. А может быть некоторые другие сабаководы как-нибудь по другому поступают ?
Второй вариант честнее, но медленнее: переписывать is именно как
... where ([Order.CounterAgent.OID] in select OID from Person)

где Person — это view, содержащее всех потомков класса Person.

S>Ну, почему. Это же NULL в понимании SQL. То есть — неизвестное значение. Что получается:

S>если здесь (x as ClassB) вернет NULL, то это означает, что мы хотим узнать значение поля F2 у неизвестного объекта. Результат этой операции (оператора ".") будет — неизвестное значение, т.е. NULL. И никакого эксепшена.

Ага. Это, конечно, правильно. Но мы даем шикарную возможность вынудить сервер заниматься бессмысленной работой. Все должно быть оправдано. Если ты не можешь придумать реальный пример, который бы требовал именно as, то незачем его и делать.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[47]: Опять валидация данных
От: GlebZ Россия  
Дата: 07.04.05 13:02
Оценка:
Здравствуйте, GlebZ, Вы писали:


GZ>возвращает все объекты наследованные от FucObject — то есть, практически все объекты находящиеся в БД. А вот так не надо строить много as.

Извиняюсь. Описка. Вместо as ессно is.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[46]: Опять валидация данных
От: stalcer Россия  
Дата: 08.04.05 05:59
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>[CounterAgent.TypeID] это что ?

S>Имеется в виду то, что для атрибута CounterAgent в таблице RDBMS хранится два поля: [CounterAgent.TypeID] и [CounterAgent.OID]. Тогда

Ясно. Думал какой-нибудь наворот MS SQL.

S>>Значит, in используется. Это, наверное, тоже тормозить будет.

S>Очень вряд ли. Там же фиксированный список будет. Сколько у тебя может быть потомков у класса в системе? 1000? Ерунда — полетит со страшной скоростью.

Да, верно. Я и сам доодумался после того как запостил сообщение. Только тогда SQL может длинный получиться.

S>>Но, это уже идея. А может быть некоторые другие сабаководы как-нибудь по другому поступают ?

S>Второй вариант честнее, но медленнее: переписывать is именно как
S>
S>... where ([Order.CounterAgent.OID] in select OID from Person)
S>

S>где Person — это view, содержащее всех потомков класса Person.

Это понятно. Решение "в лоб".

S>>Ну, почему. Это же NULL в понимании SQL. То есть — неизвестное значение. Что получается:

S>>если здесь (x as ClassB) вернет NULL, то это означает, что мы хотим узнать значение поля F2 у неизвестного объекта. Результат этой операции (оператора ".") будет — неизвестное значение, т.е. NULL. И никакого эксепшена.

S>Ага. Это, конечно, правильно. Но мы даем шикарную возможность вынудить сервер заниматься бессмысленной работой. Все должно быть оправдано. Если ты не можешь придумать реальный пример, который бы требовал именно as, то незачем его и делать.


Скажем так: Хочу и все. А чем меньше реальных примеров, тем меньше as использовать будут на практике, тем меньше и сервер будет фигней страдать.
http://www.lmdinnovative.com (LMD Design Pack)
Re[46]: Опять валидация данных
От: stalcer Россия  
Дата: 08.04.05 05:59
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


Ниииичего не понял .

S>- хранить всех потомков некоторого класса в одной большой табличке, зануляя "лишние" атрибуты (потребуется хранить еще и идентификатор класса, чтобы построить view для каждого потомка)


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

S>На практике при использовании RDBMS в качестве нижнего слоя проще всего строить работу на основе View.


Процитирую из сообщения выше:

select x from ClassA x where x is ClassB

А, пардон, зачем? Ведь можно сразу сделать:

select * from ClassB


В данном контексте мой вопрос про оператор as можно перевразировать так: Как эффективно построить view для ClassB, при "хранении всех потомков некоторого класса в одной большой табличке".
Вводить что-ли дополнительное поле в таблицу, например, IsClassBOrItsDescandant (1/0), строить по нему индекс и во view по этому полю фильтровать.
Дык сколько же таких поле нужно .
http://www.lmdinnovative.com (LMD Design Pack)
Re[47]: Опять валидация данных
От: stalcer Россия  
Дата: 08.04.05 06:13
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Я вообще пока пошел по другому пути. Ввел понятие typeing. Например такой запрос:

GZ>
GZ>select FucObjects
GZ>

GZ>возвращает все объекты наследованные от FucObject — то есть, практически все объекты находящиеся в БД. А вот так не надо строить много as.
GZ>
GZ>select FucObjects typeing typeas(FucObjects, FucDocument, FucMessage)
GZ>

GZ>вернуть array<FucObjects> у которых реальный тип объектов FucDocument и FucMessage.

Фишка интересная, но только как дополнительная возможность. Все таки is и as должны быть.

GZ>И еще одну феньку сделал. Можно в одном запросе возвращаеть сразу несколько наборов.

GZ>

GZ>select a, b where a=10 and b=20

GZ>будет определено что это два графа выполнения, и будет возвращено два результирующих набора.

ИМХО, здесь ты перемудрил. А может я просто не понял, т.к. ты from пропустил.

Дык все-таки интересно, можно ли сделать хоть как-то is и as, чтобы индексы работали.
http://www.lmdinnovative.com (LMD Design Pack)
Re[47]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.04.05 06:21
Оценка:
Здравствуйте, stalcer, Вы писали:
S>Ниииичего не понял .
Это означает, что мы в качестве from всегда используем что-то вроде "everywhere". Никаких "встроенных" коллекций для нашего удобства нет, и даже просто "все объекты класса а" нужно выбирать.
S>>- хранить всех потомков некоторого класса в одной большой табличке, зануляя "лишние" атрибуты (потребуется хранить еще и идентификатор класса, чтобы построить view для каждого потомка)
S>В данном контексте мой вопрос про оператор as можно перевразировать так: Как эффективно построить view для ClassB, при "хранении всех потомков некоторого класса в одной большой табличке".
Ну так это же элементарно! Классика жанра — операции над древовидными данными
S>Вводить что-ли дополнительное поле в таблицу, например, IsClassBOrItsDescandant (1/0), строить по нему индекс и во view по этому полю фильтровать.
S>Дык сколько же таких поле нужно .
Вовсе так не надо. С учетом того, что изменения в структуре классов как минимум на три порядка реже, чем чтение данных, можно воспользоваться способом Joe Celko — он дает максимальную производительность чтения при минимальном оверхеде по объему. Способ описан например здесь
Автор(ы): Михаил Голованов
Дата: 28.01.2002
(структура с хранением границ ветви).
Главное — аккуратно перенумеровывать классы (и, соответственно, объекты) при изменении наследования.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[48]: Опять валидация данных
От: stalcer Россия  
Дата: 08.04.05 07:39
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Это означает, что мы в качестве from всегда используем что-то вроде "everywhere". Никаких "встроенных" коллекций для нашего удобства нет, и даже просто "все объекты класса а" нужно выбирать.


И что это дает?

S>>В данном контексте мой вопрос про оператор as можно перевразировать так: Как эффективно построить view для ClassB, при "хранении всех потомков некоторого класса в одной большой табличке".

S>Ну так это же элементарно! Классика жанра — операции над древовидными данными

А где здесь дерево то ты увидел.

S>Главное — аккуратно перенумеровывать классы (и, соответственно, объекты) при изменении наследования.


Аааа . Об этом я уже думал. Менять TypeId (или что там еще) у объектов тоже плохо. Так-то оно понятно, если специальным образом раздавать TypeId, то вместо:
  ...where x.TypeId in [<список TypeId наследников>]

Можно делать:
  ...where x.TypeId <= MIN_TYPE_ID and x.TypeId >= MAX_TYPE_ID

Для этого естественно необходимо, чтобы все TypeId всех наследников от, например, ClassB были в диапазоне [MIN_TYPE_ID..MAX_TYPE_ID], ну и соответственно, TypeId остальных типов — не были в этом диапазоне.
Что сказать, это тоже идея. Может даже неплохая.
http://www.lmdinnovative.com (LMD Design Pack)
Re[49]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.04.05 08:05
Оценка:
Здравствуйте, stalcer, Вы писали:
S>А где здесь дерево то ты увидел.
Дерево наследования классов.
S>Можно делать:
S>
S>  ...where x.TypeId <= MIN_TYPE_ID and x.TypeId >= MAX_TYPE_ID
S>

Именно об этом я и говорю. Это и называется структурой с хранением границ ветвей.
S>Для этого естественно необходимо, чтобы все TypeId всех наследников от, например, ClassB были в диапазоне [MIN_TYPE_ID..MAX_TYPE_ID], ну и соответственно, TypeId остальных типов — не были в этом диапазоне.
Можно ввести дополнительную косвенность — хранить соответствие TypeID/TypeSearchID в таблице типов. Тогда не придется апдейтить табличку с объектами при вставке класса.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[50]: Опять валидация данных
От: stalcer Россия  
Дата: 08.04.05 08:29
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Можно ввести дополнительную косвенность — хранить соответствие TypeID/TypeSearchID в таблице типов. Тогда не придется апдейтить табличку с объектами при вставке класса.


Если уж вводить дополнительную косвенность, то никакие LOW/HIGH не нужны, так как в таблице типов запросто можно сделать поля типа IsClassBOrItsDescandant (1/0). Для каждого типа по одному полю.
http://www.lmdinnovative.com (LMD Design Pack)
Re[51]: Опять валидация данных
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.04.05 08:51
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Если уж вводить дополнительную косвенность, то никакие LOW/HIGH не нужны, так как в таблице типов запросто можно сделать поля типа IsClassBOrItsDescandant (1/0). Для каждого типа по одному полю.

Не, ну если тебя не смущает отведение под это N*N ячеек, то вперед. Ограничим максимальное количество классов в базе 254.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[52]: Опять валидация данных
От: stalcer Россия  
Дата: 08.04.05 09:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Не, ну если тебя не смущает отведение под это N*N ячеек, то вперед. Ограничим максимальное количество классов в базе 254.


Не смущает. Тем более что в большинстве случаев наследников не так и много бывает.
Этот способ, как и способ с HIGH/LOW имеет преимущество в том, что можно заставить работать индексы БД.
Но, основной его недостаток в том, что необходимо делать join'ы.

Зато, если использовать HIGH/LOW без дополнительной таблицы, то и индексы работают, и join делать не нужно. Но, нужно менять TypeId у объектов.

Блин ! Ненавижу такие кубики-Рубика. В одном месте собираешь — в другом разбирается.

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

S>Фишка интересная, но только как дополнительная возможность. Все таки is и as должны быть.

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

GZ>>И еще одну феньку сделал. Можно в одном запросе возвращаеть сразу несколько наборов.

GZ>>

GZ>>select a, b where a=10 and b=20

GZ>>будет определено что это два графа выполнения, и будет возвращено два результирующих набора.

S>ИМХО, здесь ты перемудрил. А может я просто не понял, т.к. ты from пропустил.

Это допущение языка. Если в select описан тип объекта, то from можно пропустить. Поскольку в большинстве случаев выборка идет по объектам а не по полям, то очень удобно.

S>Дык все-таки интересно, можно ли сделать хоть как-то is и as, чтобы индексы работали.

Зачем? У меня по крайней мере так. Если предполагается то, что в одной таблице находится только один тип, то проверяется на метаданных. То есть, проверяется до генерации запросов. Если это тип находится в разных таблицах, то проверяется по нахождению в таблице(обычно обрубается inner join'ом). Ну а если есть несколько типов в одной таблице, то тут уже есть обязательный typeID (если тип находится в нескольких таблицах — то он может находится в любой из них). Что приколько, натягивал эти метаданные на несколько баз — никаких доработок. Сейчас есть только одно условие которое необходимо для работы — наличие primary или unique индекса в таблице. Больше проблем с существующими реляционками нет (по крайней мере не нашел). А тебе легче — ты реляционку делаешь сам.

С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.