Здравствуйте, Tissot, Вы писали:
T>Здравствуйте, gandjustas, Вы писали:
T>>>>>Если предполагается использовать security базу в более чем одной подсистеме, то: такой подход порождает дублирование всех security-таблиц. G>>>>Какой ужас... один скрипт в БД и все. Причем всегда одинаковый. T>>>Я имел в виду типы LINQ2SQL entity-ей или EF, если вы его используете.
G>>Update Model From Database решает.
T>Автомитизированное дублирование — это все равно дублирование.
Кто сказал что автоматизированное дублирование — плохо? Ручное неконтроллируемое дублирование — вот что плохо, а автоматизированное — это нормально.
T>К тому же в LINQ2SQL-е нет никакого update model.
Поэтому им и не пользуюсь.
T>>>>>Эти типы будут несовместимы меж собой. Нельзя будет написать для этих типов общий код. G>>>>Какие типы? Вы вообще о чем? T>>>Я имел в виду типы LINQ2SQL entity-ей или EF, если вы его используете. G>>Какой общий код?
T>Какие-нить хелперы.
Пусть хелперы реботают через общие интерфейсы.
T>>>Вот реализация AddSecurityCheck как раз и поменяется. G>>Ну да, реализацию одного метода. T>Везде где этот метод есть.
Не-а, в одном месте.
T>Конечно можно. Моя цель лишь показать, что все не так тривиально, как тут пытаются представить.
А никто не говорит про тривиальность. Все говорят что такой подход а)более правильный с точки зрения работы с данными б)обладает не меньшей мощью, по сравнению с императивным ООП подходом.
T>Я уже приводил пример, когда при регистрации кастомера нужно создать раздел в базе знаний. Ни UI, ни PL тут нет. А проверка может быть, например, что имя создаваемого раздела соответствует какой-то маске или что у раздела прописан хоть один администратор. Да мало ли чего может быть?
Ну так схему данных в студию, на словах все равно непенятно.
T>Вопрос лишь в том, стоит ли эти проверки делать именно в базе. Если вы ратуете за использование update-ов прямо из кода, то вам их придется туда запихнуть.
Элементарные проверки (not null, диапазоны значений и прочее) у вас и так будут в базе, более сложные можно запихнуть в дополнительные запросы.
T>Если же остаетесь в рамках domain model, то их можно расположить в бизнесе, что на мой взгляд, удобнее.
Чем удобнее?
Здравствуйте, gandjustas, Вы писали:
G>>>Update Model From Database решает.
T>>Автомитизированное дублирование — это все равно дублирование. G>Кто сказал что автоматизированное дублирование — плохо? Ручное неконтроллируемое дублирование — вот что плохо, а автоматизированное — это нормально.
Это лучше чем ручное дублирование, но хуже, чем его отсутствие.
T>>Какие-нить хелперы. G>Пусть хелперы реботают через общие интерфейсы.
Ок. Пусть работают.
T>>>>Вот реализация AddSecurityCheck как раз и поменяется. G>>>Ну да, реализацию одного метода. T>>Везде где этот метод есть. G>Не-а, в одном месте.
Неа, во всех.
T>>Конечно можно. Моя цель лишь показать, что все не так тривиально, как тут пытаются представить. G>А никто не говорит про тривиальность. Все говорят что такой подход а)более правильный с точки зрения работы с данными б)обладает не меньшей мощью, по сравнению с императивным ООП подходом.
Делайте. Главное чтобы по поговорке не получилось — "Гладко было на бумаге, да забыли про овраги"
T>>Я уже приводил пример, когда при регистрации кастомера нужно создать раздел в базе знаний. Ни UI, ни PL тут нет. А проверка может быть, например, что имя создаваемого раздела соответствует какой-то маске или что у раздела прописан хоть один администратор. Да мало ли чего может быть? G>Ну так схему данных в студию, на словах все равно непенятно.
T>>Вопрос лишь в том, стоит ли эти проверки делать именно в базе. Если вы ратуете за использование update-ов прямо из кода, то вам их придется туда запихнуть. G>Элементарные проверки (not null, диапазоны значений и прочее) у вас и так будут в базе, более сложные можно запихнуть в дополнительные запросы.
Не, в непосредственно в запросы запихнуть будет недостаточно, т.к. все равно останется возможность вставить данные, не добавляя эти проверки в insert. Это должно быть частью инфраструктуры, так чтобы избежать этой проверки нельзя было.
T>>Если же остаетесь в рамках domain model, то их можно расположить в бизнесе, что на мой взгляд, удобнее. G>Чем удобнее?
Тем, что у меня полный набор средств предоставляемых ооп, вплоть до того, что эти проверки могут быть сделаны декларативно, а то и вовсе вынесены в конфигурационный файл. В общем рамками SQL-я я ограничен не буду.
Здравствуйте, gandjustas, Вы писали:
T>>Резервируют не позиции, а заказ. G>Тут уже показывайте схему данных, формализованный бизнес-процесс, как работает сервис и какие тербования предьявляются к программе.
T>>>>>Вот реализация AddSecurityCheck как раз и поменяется. G>>>>Ну да, реализацию одного метода. T>>>Везде где этот метод есть. G>>Не-а, в одном месте. T>Неа, во всех.
У меня таким образом сделано получение даты последнего обновления списка сущностей в БД.
Причем код не поменялся даже при переходе от Linq2SQL к EF.
T>>>Вопрос лишь в том, стоит ли эти проверки делать именно в базе. Если вы ратуете за использование update-ов прямо из кода, то вам их придется туда запихнуть. G>>Элементарные проверки (not null, диапазоны значений и прочее) у вас и так будут в базе, более сложные можно запихнуть в дополнительные запросы. T>Не, в непосредственно в запросы запихнуть будет недостаточно, т.к. все равно останется возможность вставить данные, не добавляя эти проверки в insert. Это должно быть частью инфраструктуры, так чтобы избежать этой проверки нельзя было.
Ну и я о томже. Работа с базой всегда будет вестись через какой-то объект контекста, этот объект может выствлять событие оправки батча запросов на сервер с возможностью модификации. Вот через такое событие можно будет дополнительные запросы валидации добавлять.
Аналогично событию SavingChanges в EF.
T>>>Если же остаетесь в рамках domain model, то их можно расположить в бизнесе, что на мой взгляд, удобнее. G>>Чем удобнее?
T>Тем, что у меня полный набор средств предоставляемых ооп, вплоть до того, что эти проверки могут быть сделаны декларативно, а то и вовсе вынесены в конфигурационный файл. В общем рамками SQL-я я ограничен не буду.
А кто говорит про использование SQL?
Все про что я писал возможно именно при наличии Linq. Причем пока нету операторов для update\delete\insert все это остается только идеей.
Здравствуйте, gandjustas, Вы писали:
T>>Не, в непосредственно в запросы запихнуть будет недостаточно, т.к. все равно останется возможность вставить данные, не добавляя эти проверки в insert. Это должно быть частью инфраструктуры, так чтобы избежать этой проверки нельзя было. G>Ну и я о томже. Работа с базой всегда будет вестись через какой-то объект контекста, этот объект может выствлять событие оправки батча запросов на сервер с возможностью модификации. Вот через такое событие можно будет дополнительные запросы валидации добавлять.
Сможете сделать это просто и удобно — честь вам и хвала.
T>>Тем, что у меня полный набор средств предоставляемых ооп, вплоть до того, что эти проверки могут быть сделаны декларативно, а то и вовсе вынесены в конфигурационный файл. В общем рамками SQL-я я ограничен не буду. G>А кто говорит про использование SQL?
Если у тебя есть update типа update customer ... where type = vip, то валидацию ты сможешь сделать только на сервере, т.к. на клиенте неизвестно что именно будет изменено. А раз так, то и набор средств, предоставленых тебе будет ограничен SQL-ем.
G>Все про что я писал возможно именно при наличии Linq. Причем пока нету операторов для update\delete\insert все это остается только идеей.
Здравствуйте, Tissot, Вы писали: T>Конструктивнее. Давай лучшие в студию.
В зависимости от используемой СУБД строим код табличной функции, который возвращает нужный датасет в уже развернутом виде. В оракле это connect by, в MS SQL и DB2 — with, в Interbase — курсор и return.
Если не устраивает быстродействие такого подхода, то реализуем на стороне СУБД транзитивное замыкание.
В любом случае, код в application tier пишется так, как будто планаризованный датасет уже доступен. Способ преобразования дерева в список — избыточная подробность. Это азы декомпозиции.
T>Кэш — в топку.
Очень хорошо. Это — правильный подход.
T>Что такого сложного в том, чтобы сделать select и результат распихать по свойствам?
Рекомендую плотненько поработать с профайлером. Для начала — с SQL Server Profiler, так, для посмотреть, во что превращается unit of work применительно к SQL — запросам.
Потом можно напустить профайлер на application tier, чтобы посмотреть, насколько "просто" выполнить селект и распихать по свойствам.
Прикинуть, не влияет ли случайно на результат то, что тест проходит на машине, где и application и data tier стоят рядом и могут обмениваться по shared memory с низкой латентностью. Если влияет, то осознать, что с ростом масштаба data tier придется выносить на другую машину, а там будет TCP/IP и все радости латентности, вызванной лишними обращениями.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tissot, Вы писали:
A>>Планируется ли добавление в Nemerle insert, update и delete?
T>Кстати, это может оказаться той самой killer-feature, которая сподвигнет кого-то присмотреться к языку внимательнее.
Здравствуйте, Tissot, Вы писали: T>CR (через полгода): T>При резервировании заказа заказ должен сохранять в одном из полей номер запроса на упаковку (номер возвращается веб-сервисом).
Худший способ решения этой задачи — реализация данной бизнес-транзакции в виде одной транзакции уровня СУБД.
И худший он именно из-за того, что быстрое звено (СУБД) вынуждено удерживать блокировки до тех пор, пока медленное звено (веб-сервис) не проснется и не ответит.
Более того, в предлагаемой схеме временная проблема с веб-сервисом (банальное падение роутера между ним и application tier) иожет привести к откату транзакции резервирования товара. Так делать не надо.
Правильный способ, конечно же, в том, чтобы сделать у заказа дополнительное состояние — "передан на упаковку", куда можно перейти только если заказ "зарезервирован".
А теперь расскажи нам, как это работает в случае unit of work. Какие блокировки накладываются в какой момент, и в какой они отпускаются. Учти еще, что характерное время ответа от веб-сервиса — это 200мс, а одиночный апдейт в базе выполнится примерно за 10мс.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Tissot, Вы писали: T>>Конструктивнее. Давай лучшие в студию. S>В зависимости от используемой СУБД строим код табличной функции, который возвращает нужный датасет в уже развернутом виде. В оракле это connect by, в MS SQL и DB2 — with, в Interbase — курсор и return.
как поддеживать в Linq-е — рекурсивные запросы.
T>>Что такого сложного в том, чтобы сделать select и результат распихать по свойствам? S>Рекомендую плотненько поработать с профайлером. Для начала — с SQL Server Profiler, так, для посмотреть, во что превращается unit of work применительно к SQL — запросам.
Да вроде смотрел. Ничего особо криминального. Если не учитывать дурацкие алиасы t0, t1, ... вполне себе код как код.
S>Потом можно напустить профайлер на application tier, чтобы посмотреть, насколько "просто" выполнить селект и распихать по свойствам.
Проблема в том, что сравнивать мне придется с тем, чего еще нет.
S>Прикинуть, не влияет ли случайно на результат то, что тест проходит на машине, где и application и data tier стоят рядом и могут обмениваться по shared memory с низкой латентностью. Если влияет, то осознать, что с ростом масштаба data tier придется выносить на другую машину, а там будет TCP/IP и все радости латентности, вызванной лишними обращениями.
Здравствуйте, Sinclair, Вы писали:
S>И худший он именно из-за того, что быстрое звено (СУБД) вынуждено удерживать блокировки до тех пор, пока медленное звено (веб-сервис) не проснется и не ответит. S>Более того, в предлагаемой схеме временная проблема с веб-сервисом (банальное падение роутера между ним и application tier) иожет привести к откату транзакции резервирования товара. Так делать не надо.
S>Правильный способ, конечно же, в том, чтобы сделать у заказа дополнительное состояние — "передан на упаковку", куда можно перейти только если заказ "зарезервирован".
Ладно, сдаюсь, задолбало меня отвечать на ваше изменение условий. Вы сначала сделайте, что хотите, а потом уже и будет о чем говорить. А ток — одна сплошная риторика.
S>А теперь расскажи нам, как это работает в случае unit of work. Какие блокировки накладываются в какой момент, и в какой они отпускаются. Учти еще, что характерное время ответа от веб-сервиса — это 200мс, а одиночный апдейт в базе выполнится примерно за 10мс.
Я про фому, а ты опять про ерему. В реальной жизни ты не добьешься непересечения под-задач по данным. Хотя бы уже потому, что иначе тебе при каждом изменении нужно будет просматривать все использования изменяемого тобою кода. А с учетом того, что предполагается использовать возможности БД на полную катушку, это еще более усложняется.
Я уже написал. Linq — всего лишь средство доступа к СУБД, а не ее замена.
T>Да вроде смотрел. Ничего особо криминального. Если не учитывать дурацкие алиасы t0, t1, ... вполне себе код как код.
Всё познаётся в сравнении.
S>>Потом можно напустить профайлер на application tier, чтобы посмотреть, насколько "просто" выполнить селект и распихать по свойствам. T>Проблема в том, что сравнивать мне придется с тем, чего еще нет.
Скорее надо сравнивать с тем, чего нет и не будет. В том смысле, что работы, которую ты пронаблюдаешь, в нормальном приложении вовсе быть не должно.
T>Так и работаем.
Ну вот и посмотри на стоимость одного roundtrip до СУБД.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tissot, Вы писали:
T>Ладно, сдаюсь, задолбало меня отвечать на ваше изменение условий. Вы сначала сделайте, что хотите, а потом уже и будет о чем говорить. А ток — одна сплошная риторика.
Я таких систем, в общем-то, написал в ассортименте. И с ORM-подходом тоже наелся по самое не хочу.
S>>А теперь расскажи нам, как это работает в случае unit of work. Какие блокировки накладываются в какой момент, и в какой они отпускаются. Учти еще, что характерное время ответа от веб-сервиса — это 200мс, а одиночный апдейт в базе выполнится примерно за 10мс.
T>Я про фому, а ты опять про ерему. В реальной жизни ты не добьешься непересечения под-задач по данным.
Я не виноват, что ты так плохо придумываешь задачи.
T> Хотя бы уже потому, что иначе тебе при каждом изменении нужно будет просматривать все использования изменяемого тобою кода.
Это иллюзия. Понимаешь, это в случае unit of work и "тру-ООП" подхода у тебя модификации хаотически разбросаны по всему коду. И совершенно непонятно, сколько раз и что апдейтится, и нет ли между апдейтами тяжелой операции с вовлечением внешних ресурсов.
А если ты работаешь в реляционном подходе, то у тебя четко выделены все моменты, когда ты лезешь в базу. И там "просматривать" ничего не надо. Логика будет сильно структурирована: вот мы получаем остатки позиций на складе (с учетом всех политик безопасности и специфических для товарных позиций ограничений), вот мы сравниваем их с позициями заказа; вот мы обрабатываем случаи неполного комплекта и всё такое прочее. А вот собственно результирующий батч поехал в базу, и после его выполнения можно смело переходить к фазе рендера результатов.
T>А с учетом того, что предполагается использовать возможности БД на полную катушку, это еще более усложняется.
Упрощается, и сильно упрощается.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tissot, Вы писали:
T>Можно подкрепить высказывание ссылочкой? Спасибо.
BOL =)
T> ORMapper в конечном итоге говорит и сервером на SQL, а значит все средства остаются в силе.
Классические ORM делают это настолько криво, что плохо становится и сиквелу и разработчику, так как по факту, ничего в силе не остается.
T>Отсутствие ленивой загрузки.
Угу, купи козу — продай козу. А что с остальными косяками делать?
T>Над чем у тебя нет явного контроля в том же LINQ2SQL-е. Он же тупой как пробка.
В этом его и прелесть. Если ты не понял, то L2S — это шаг в правильном направлении, но хочется большего, в этом и был поинт.
Здравствуйте, Tissot, Вы писали:
T>Ку так расскажи, а то все вокруг, да около. Или тоже секретная разработка?
"Лень фаулера цитировать" (с)
T>См. Фаулера, а лучше Evans-а.
Ну вот и смотри лучше в фаулера, даже у него domain model — лишь один из вариантов дизайна, и даже он не настаивает на его универсализме.
T>Ну если другие подходы не выдерживают критики, то приходится ограничиваться "серебрянной пулей"
Так где критика-то? Хотя в принципе, достаточно того, что некоторые другие подходы отлично выдерживают практику.
T>Я так не считаю.
Ну это сугубо твои проблемы.. Де-факто (с), его подавали именно под этим соусом.
T>А это вообще не суть важно. При использовании TransactionScope ты хоть каждый чих оборачивай в транзакцию. Коммит в базу все равно будет только после последнего самомго внешнего TransactionScope-а.
Да, представляю транзакции после такого получаются.. =) Самому не смешно? )
Здравствуйте, Tissot, Вы писали:
T>Ведите себя прилично, не надо переходить на личности.
Не надо фаулером на ровном месте прекрываться, если самому сказать нечего.
Здравствуйте, Tissot, Вы писали:
T>По поводу третьего — думаю, если взять общее число тех, кто знает о hibernte-е (или других мапперах) и имеет возможность его использовать, большинство его использует.
Думаю, что ты ошибаешься.. )
T>Наследование само по себе (без наличия виртуальных методов) ценности не несет.
Во-первых, несет, во-вторых, какие вообще методы ты хочешь видеть в данных и, наконец, в третих, оно таки отлично выражается в ER, что и требовалось доказать.
T>Многие-ко-многим выражается через два отношения один-ко-многим.
Тем не менее выражается.
T>С этим элементарно неудобно работать
Никаких фатальных неудобств с этим нет, а иногда это вообще оборачивается преимуществом.
T>Зато имеет к ООП.
Однако здесь речь идет не об ООП, а об ООП при работе с данными. И в применении к данным, методы и интерфейсы являются большой проблемой.
Дело в том, что срок жизни данных — сильно больше срока жизни типичного ООП-шного объекта, реализующего конкретное поведение в определенном сценарии. Более того, одни и те же данные хорошо бы использовать в разных объектах, но как только к данным прибивается гвоздями определенное поведение и структура с помощью методов и интерфейсов, эта возможность тут же теряется.
Именно по этому, навязать данным методы — дурная затея. Во-первых, меняя в десятый раз поведение данные нужно оставлять неизменными. Во-вторых, добавляя новое поведение, надо его просто добавлять, а не менять старое и не накручивать поверх старого, при этом стараясь оставить данные по прежнему неизменными.
Здравствуйте, IB, Вы писали:
T>>Наследование само по себе (без наличия виртуальных методов) ценности не несет. IB>Во-первых, несет, во-вторых,
Кукую?
IB>какие вообще методы ты хочешь видеть в данных
Например, методы валидации. Или user-friendly ToString.
IB>и, наконец, в третих, оно таки отлично выражается в ER, что и требовалось доказать.
Покажи, как оно отлично выражается. Те способы выражения что я знаю, не очень-то приятные для использования.
T>>Многие-ко-многим выражается через два отношения один-ко-многим. IB>Тем не менее выражается.
T>>С этим элементарно неудобно работать IB>Никаких фатальных неудобств с этим нет, а иногда это вообще оборачивается преимуществом.
Ну это как посмотреть. Кому-то может быть и удобно, мне — не очень.
T>>Зато имеет к ООП. IB>Однако здесь речь идет не об ООП, а об ООП при работе с данными. И в применении к данным, методы и интерфейсы являются большой проблемой. IB>Дело в том, что срок жизни данных — сильно больше срока жизни типичного ООП-шного объекта, реализующего конкретное поведение в определенном сценарии. Более того, одни и те же данные хорошо бы использовать в разных объектах, но как только к данным прибивается гвоздями определенное поведение и структура с помощью методов и интерфейсов, эта возможность тут же теряется.
Пример можно показать, без абстрактных пассов руками в воздухе. По мне так чем объектная модель программы ближе к оной предметной области, тем лучше — проще понимать такой код.
IB>Именно по этому, навязать данным методы — дурная затея. Во-первых, меняя в десятый раз поведение данные нужно оставлять неизменными. Во-вторых, добавляя новое поведение, надо его просто добавлять, а не менять старое и не накручивать поверх старого, при этом стараясь оставить данные по прежнему неизменными.
По поводу неизменности данных я полностью согласен. А вот по поводу "добавлять, а не менять" — не совсем. Если требования поменялись, то код должен быть тоже поменян, зачем хранить в приложении тот код, который уже не актуален? Не понимаю.
Спасибо, что не гугл
А поточнее ссылочку не подкинешь?
T>> ORMapper в конечном итоге говорит и сервером на SQL, а значит все средства остаются в силе. IB>Классические ORM делают это настолько криво, что плохо становится и сиквелу и разработчику, так как по факту, ничего в силе не остается.
Не знаю, смотрел профайлером. Ничего особенно криминального не заметил. Все достаточно просто и понятно.
T>>Отсутствие ленивой загрузки. IB>Угу, купи козу — продай козу. А что с остальными косяками делать?
Для начала сформулировать, что за косяки имеются в виду. Потом — отказаться от EF
T>>Над чем у тебя нет явного контроля в том же LINQ2SQL-е. Он же тупой как пробка. IB>В этом его и прелесть. Если ты не понял, то L2S — это шаг в правильном направлении, но хочется большего, в этом и был поинт.
Здравствуйте, IB, Вы писали:
T>>Ку так расскажи, а то все вокруг, да около. Или тоже секретная разработка? IB>"Лень фаулера цитировать" (с)
А я цитат и не прошу. Ссылочки будет вполне достаточно.
T>>См. Фаулера, а лучше Evans-а. IB>Ну вот и смотри лучше в фаулера, даже у него domain model — лишь один из вариантов дизайна, и даже он не настаивает на его универсализме.
Очень даже настаивает, когда говорит о сложных приложениях.
T>>Ну если другие подходы не выдерживают критики, то приходится ограничиваться "серебрянной пулей" IB>Так где критика-то? Хотя в принципе, достаточно того, что некоторые другие подходы отлично выдерживают практику.
Ладно, проехали. Нет никакой критики. Вы абсолютно правы.
T>>Я так не считаю. IB>Ну это сугубо твои проблемы.. Де-факто (с), его подавали именно под этим соусом.
Это его де-юре таким подавали, а де-факто он был совсем не таким кучерявым, каким хотел казаться.
T>>А это вообще не суть важно. При использовании TransactionScope ты хоть каждый чих оборачивай в транзакцию. Коммит в базу все равно будет только после последнего самомго внешнего TransactionScope-а. IB>Да, представляю транзакции после такого получаются.. =) Самому не смешно? )
Нет, ничуть не смешно. Вложеные TransactionScope-ы реюзают в конечном итоге одну транзакцию, так что множественное число тут не очень уместно.