Здравствуйте, Lucker, Вы писали:
L>Кто какие способы предпочитает и почему?
наконец-то я понял в чём был твой вопрос ....
если можно, то я задам встречный: а зачем вообще DAO?
манипуляции данными обычно не так тривиальны, чтобы заморачиваться на dao, для простых операций типа получения по id достаточно возможностей, которые даёт hibernate-сессия, для сложных типа запросить сджойненные данные с хитрой фильтрацией — dao не помогает.
я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо
Здравствуйте, C0s, Вы писали:
C0s>наконец-то я понял в чём был твой вопрос .... C0s>если можно, то я задам встречный: а зачем вообще DAO?
С такими вопросами в архитектуру надо. Обычное такое введение дополнительного слоя. Даже если вроде бы и видимой пользы от него мало, то как минимум читать и разбирать такой код проще.
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Lucker, Вы писали:
L>>Кто какие способы предпочитает и почему?
C0s>наконец-то я понял в чём был твой вопрос ....
C0s>если можно, то я задам встречный: а зачем вообще DAO?
Если вдруг захочешь перейти с Hibernate на другую ORM технологию или реализовать отдельные запросы вообще на уровне JDBC без изменения классов бизнес-логики. В этом случае DAO и пригодится, бизнес логика в идеале вообще не должна зависить от деталей реализации механизма сохранения/загрузки данных. Но все имеет свою цену и смотреть надо по ситуации, стоит с DAO заморачиваться или нет.
C0s>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо
Ну если не использовать DAO, то таже тонна кода будет размазана по всей бизнес-логике, только и всего.
Здравствуйте, C0s, Вы писали:
C0s>наконец-то я понял в чём был твой вопрос ....
C0s>если можно, то я задам встречный: а зачем вообще DAO?
"На у как же без кокошника, без кокошника нельзя, а то батюшка вые...т"
C0s>манипуляции данными обычно не так тривиальны, чтобы заморачиваться на dao, для простых операций типа получения по id достаточно возможностей, которые даёт hibernate-сессия, для сложных типа запросить сджойненные данные с хитрой фильтрацией — dao не помогает.
по большому счету у нас есть два типа дао
1) простой. тупо объявлен интерфейс с get/save/dele/find методами. Реализация генерится javassist-ом, на основе GenericDAO реализации + генерятся finder методы, которые тупо вызывают именнованые запросы по имени метода, и передавая туда параметры. Тут можно было бы поизголяться с аннотациями, типа для указания имен запросов, сопоставления параметров и се такое, но простой вариант пока работает.
2) сложные, по сути расширяют простой случай + реализуют сложные запросы через CriteriaAPI.
есть еще plain JDBC DAO для сбора больших объемов статистики (где нужен быстрый нативный доступ к ResulSet)
C0s>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо
на самом деле кода получается совсем мало, некторые ДАО объявлены только интерфейсно, классы для них генерятся на лету.
Здравствуйте, Trean, Вы писали:
T>Если вдруг захочешь перейти с Hibernate на другую ORM технологию
ИМХО, это миф. Когда соискателей спрашиваешь про MVC они тоже зачастую говорят, чтобы можно было легко разные реализации View использовать. На практике замена таких слоев как View или DAO встречается очень редко.
T>или реализовать отдельные запросы вообще на уровне JDBC без изменения классов бизнес-логики. В этом случае DAO и пригодится, бизнес логика в идеале вообще не должна зависить от деталей реализации механизма сохранения/загрузки данных. Но все имеет свою цену и смотреть надо по ситуации, стоит с DAO заморачиваться или нет.
А вот это уже дело. Такое при использовании ORM сплошь и рядом. Когда в критических местах обнаруживается оверхед из-за специфики ORM, тогда в DAO и дописываются оптимизированые методы.
C0s>>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо T>Ну если не использовать DAO, то таже тонна кода будет размазана по всей бизнес-логике, только и всего.
Ну, зачастую и DAO можно реализовать через Ж. Но ведь это никак не говорит о том что от него стоит отказыватся.
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, Trean, Вы писали:
T>>Если вдруг захочешь перейти с Hibernate на другую ORM технологию B>ИМХО, это миф. Когда соискателей спрашиваешь про MVC они тоже зачастую говорят, чтобы можно было легко разные реализации View использовать. На практике замена таких слоев как View или DAO встречается очень редко.
Технологии приходят и уходят (Entity Beans), а проекты остаются , всякое бывает (особенно в долгоживущих проектах)
C0s>>>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо T>>Ну если не использовать DAO, то таже тонна кода будет размазана по всей бизнес-логике, только и всего.
B>Ну, зачастую и DAO можно реализовать через Ж. Но ведь это никак не говорит о том что от него стоит отказыватся.
Ну и я том же, кстати ни где не встречал статеек вида "DAO pattern considered useless/harmful", только реализация меняется (появление к примеру Generic DAO). Наоборот призывают использовать настоятельно.
Здравствуйте, Trean, Вы писали:
T>Ну если не использовать DAO, то таже тонна кода будет размазана по всей бизнес-логике, только и всего.
предлагаю оттолкнуться от простого, но наиболее часто встречающегося кода (загрузки по id):
1) как это у меня без DAO:
final SomeObjectInDB o = (SomeObjectInDB) getSession().load(SomeObjectInDB.class, id);
2) как это выглядит с DAO (подсмотрел в проекте, к которому сейчас прикручиваю функциональность):
final SomeObjectInDB o = SomeObjectInDBDAO.getInstance().get(id);
и там, и там — одна строка. и там, и там, смею утверждать, абсолютно одинаковая понятность (при условии, что читает человек, для которого hibernate-сессия и её API не пустой звук).
спрашивается, зачем городить целый отдельный класс SomeObjectInDBDAO, если наиболее общеупотребительный случай с одинаковым успехом реализуется и без него?!
при этом, специфические запросы, чаще всего, используются в одном месте, т.е. их повторная используемость стремится к нулю. а, скажем, DAO-методы общего назначения типа execQuery(String query) ничего не упрощают
Здравствуйте, Trean, Вы писали:
T>Ну и я том же, кстати ни где не встречал статеек вида "DAO pattern considered useless/harmful", только реализация меняется (появление к примеру Generic DAO). Наоборот призывают использовать настоятельно.
для меня этот уровень выглядит уже неплохо реализованным в виде объекта hibernate-сессии, с помощью которого легко получить доступ к первым объектам, из которых по графу вложенности далее работает уже объекто-ориентированная навигация (геттеры)
Здравствуйте, C0s, Вы писали:
C0s>при этом, специфические запросы, чаще всего, используются в одном месте, т.е. их повторная используемость стремится к нулю. а, скажем, DAO-методы общего назначения типа execQuery(String query) ничего не упрощают
Угу, абсолютно согласен. DAO и DTO — два достаточно бесполезных паттерна, ИМХО. В своих проектах просто использую явный session.get(...), а для повторящихся запросов делаю класс типа <EntityNames>Utils в который добавляю статические методы с кодом запросов.
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, C0s, Вы писали:
C0s>>при этом, специфические запросы, чаще всего, используются в одном месте, т.е. их повторная используемость стремится к нулю. а, скажем, DAO-методы общего назначения типа execQuery(String query) ничего не упрощают C>Угу, абсолютно согласен. DAO и DTO — два достаточно бесполезных паттерна, ИМХО. В своих проектах просто использую явный session.get(...), а для повторящихся запросов делаю класс типа <EntityNames>Utils в который добавляю статические методы с кодом запросов.
Насчет DTO соглашусь, он вообще "вынужденный" шаблон и актуален только для распределенных систем, где необходимо избежать слишком частых вызовов по сети и соответственно больших задержек.
А проблема утилитных статических методов <EntityNames>Utils в усложнении тестируемости (Mock объекты), кроме того если захочется, например в целях оптимизации, подменить реализацию обращения к базе, придется работать с файлами через vcs (ну или коментить в коде), а с DAO достаточно в каком-нибудь spring-conf.xml заменить один бин на другой и вообще не придется трогать код с бизнес-логикой. Такое вот мое имхо.
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Lucker, Вы писали:
L>>Кто какие способы предпочитает и почему?
C0s>наконец-то я понял в чём был твой вопрос ....
C0s>если можно, то я задам встречный: а зачем вообще DAO? C0s>манипуляции данными обычно не так тривиальны, чтобы заморачиваться на dao, для простых операций типа получения по id достаточно возможностей, которые даёт hibernate-сессия, для сложных типа запросить сджойненные данные с хитрой фильтрацией — dao не помогает.
C0s>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо
1. Для удобной замены реального DAO на MockDAO для автомтаических тестов. При условии, что сами DAO продуцируются некой фаббрикой. Тгода просто — для тестов и для реального приложения просто 2 раных конфига...
2. Session managment — важная штука. Как сесию лучше вести? для трэда или для сессии?
Дальше больше... В общем случае, база данных — не единственный storage для данных домена. Например, подсистема классификаторов может быть реализована вообще в виде черного ящика, который вам "корпоративный стандарт" выдал... Но в приложении удобно работать с объектами классификаторов, как с обычными персистентными классами... вот и будут DAO для классификаторов потроха иные иметь.
Или ситуация, когда какие-то сущности "живут" на каком-то удаленном компе с доступом по веб-сервису или еще как. Например, список юзеров в домене... Но удобно было бы "интегрировать" эту сущность в модель домена для единообразности подхода моделирования бизнес-логики... Ну значит будет у вас класс DomainUser и какой-нить DAO к нему, который будет в ActiveDirectory лезть...
ВСе это примеры из реальной жизни.
Ну а вообще, тут дело такое... Если не чувствуете необходимость исопльзования какого-то комопнента сейчас — не используйте. А уж тем более, когда вы скорее бесполезность чувствуете... Нафиг тогда разрывать себя противоречиями?
Здравствуйте, Cyberax, Вы писали:
C>Угу, абсолютно согласен. DAO и DTO — два достаточно бесполезных паттерна, ИМХО. В своих проектах просто использую явный session.get(...), а для повторящихся запросов делаю класс типа <EntityNames>Utils в который добавляю статические методы с кодом запросов.
как ни странно, DTO я не считаю бесполезным. причины этого я как-то уже два-три раза в форуме по java писал
основных, действительно, две:
1) необходимость передачи данных по сети,
2) транзакции — максимально короткие, а данные нужны бывают дольше (пока завершаем обработку запроса), скажем, мне не нравится, если уровень презентации будет неявно обращаться к DB. так вот контейнеры этой информации — очень похожи на DTO, я их у себя обычно так и называю
в остальном же я придерживаюсь схожего подхода (т.е. выделение кода для поддержки только тех запросов, которые повторно используюися, при этом делается это каждый раз наиболее подходящим для конкретного случая способом)
Здравствуйте, noetic, Вы писали:
N>1. Для удобной замены реального DAO на MockDAO для автомтаических тестов. При условии, что сами DAO продуцируются некой фаббрикой. Тгода просто — для тестов и для реального приложения просто 2 раных конфига...
здравая мысль, как только моей головы перестанет хватать на другие способы контроля качества, так и перейду на DAO с двумя реализациями и автотестами
N>2. Session managment — важная штука. Как сесию лучше вести? для трэда или для сессии?
в-общем случае, конечно, можно сказать, что надо смотреть. на практике, однако, я пока сталкиваюсь с необходимостью укорачивать транзакции. т.е. сессия живёт ровно столько, сколько нужно для обработки конкретного запроса. это даже меньше, чем тред.
N>Дальше больше... В общем случае, база данных — не единственный storage для данных домена. Например, подсистема классификаторов может быть реализована вообще в виде черного ящика, который вам "корпоративный стандарт" выдал... Но в приложении удобно работать с объектами классификаторов, как с обычными персистентными классами... вот и будут DAO для классификаторов потроха иные иметь. N>Или ситуация, когда какие-то сущности "живут" на каком-то удаленном компе с доступом по веб-сервису или еще как. Например, список юзеров в домене... Но удобно было бы "интегрировать" эту сущность в модель домена для единообразности подхода моделирования бизнес-логики... Ну значит будет у вас класс DomainUser и какой-нить DAO к нему, который будет в ActiveDirectory лезть...
в ситуации с разными источниками данных унификация такого рода (когда в тексте программы обращения выглядят одинаковыми) мне кажется вредной, т.к. поощряет программистов-пользователей такого уровня DAO не задумываться, откуда данные. следствием этого будут ошибки, которые исправить будет нелегко.
я предпочитаю, когда вещи называются своими именами, т.е. в конкретном случае часть вызовов будет к сессии hibernate (и тем самым в тексте метода будет явно отражено, какие объекты являются хранимыми в БД), а другая — к web-сервису (и тем самым будет видно, какая информация получается за счёт коммуникации по http).
видеть эту разницу в тексте — фундаментально для адекватной обработки ошибочных и полуошибочных ситуаций и для правильной расстановки вызовов, например, когда часть данных можно получить перед транзакцией БД, тем самым, не удлиняя её.
N>Нафиг тогда разрывать себя противоречиями?
да эта ветка была выделена из обсуждения, у меня-то противоречий нет, просто интересно, откуда у народа появляется желание писать лишний код (лишний код — источник ошибок, а не путь к исправлению имеющихся)
C0s> final SomeObjectInDB o = (SomeObjectInDB) getSession().load(SomeObjectInDB.class, id);
C0s>
C0s>2) как это выглядит с DAO (подсмотрел в проекте, к которому сейчас прикручиваю функциональность): C0s>
C0s> final SomeObjectInDB o = SomeObjectInDBDAO.getInstance().get(id);
C0s>
C0s>и там, и там — одна строка. и там, и там, смею утверждать, абсолютно одинаковая понятность
Понятность может и одинаковая, а вот как захочется поменять реализацию этого геттера... добавить туда маленький общий фильтрик например...
В каком-то смысле второй вариант более абстрактен, а лишний уровень абстракции хорош не тольео тем, что можно поменять способ реализации нижнего уровня, но и саму семантику, без изменения интерфейса.
Здравствуйте, noetic, Вы писали:
N>1. Для удобной замены реального DAO на MockDAO для автомтаических тестов. При условии, что сами DAO продуцируются некой фаббрикой. Тгода просто — для тестов и для реального приложения просто 2 раных конфига...
ИМХО, это абсолютная фантастика. Кроме DAO есть еще взаимодействие с сессией, включая всякие сохранения идентичности объектов и проксиков. Кроме того, объем кода моков для получается просто астрономический — проще использовать базу данных.
В общем, не видел я пока ни одного реального проекта, где было бы тестирование c помощью замены DAO.
N>2. Session managment — важная штука. Как сесию лучше вести? для трэда или для сессии?
А это вообще не забота DAO. По-хорошему, методы DAO типа "loadByPrimaryKey(long key)" в нормальной архитектуре нужно искоренять и заменять на явную передачу сессии в качестве параметра (я у себя так и делаю в статических хэлперах).
N>Или ситуация, когда какие-то сущности "живут" на каком-то удаленном компе с доступом по веб-сервису или еще как. Например, список юзеров в домене... Но удобно было бы "интегрировать" эту сущность в модель домена для единообразности подхода моделирования бизнес-логики... Ну значит будет у вас класс DomainUser и какой-нить DAO к нему, который будет в ActiveDirectory лезть...
А вот так делать точно не надо. AD и web-сервисы часто имеют совершенно отличные от БД характеристики по скорости, взаимодействию с транзакциями и т.п. Лучше такие места отделять явно.
Здравствуйте, C0s, Вы писали:
C0s>как ни странно, DTO я не считаю бесполезным. причины этого я как-то уже два-три раза в форуме по java писал C0s>основных, действительно, две: C0s>1) необходимость передачи данных по сети, C0s>2) транзакции — максимально короткие, а данные нужны бывают дольше (пока завершаем обработку запроса), скажем, мне не нравится, если уровень презентации будет неявно обращаться к DB. так вот контейнеры этой информации — очень похожи на DTO, я их у себя обычно так и называю
Мне в DTO не нравится его параллельность с моделью доменных объектов. Видел несколько проектов, где DTO фактически повторяли модель объектов. Кроме того, появляются проблемы со сложными графами объектов.
Не вижу я особого смысла в DTO, особенно учитывая, что сейчас для persistance'а используют не тяжеловесные entity-бины, а вполне обычные POJO.
Здравствуйте, Igor Trofimov, Вы писали:
iT>Понятность может и одинаковая, а вот как захочется поменять реализацию этого геттера... добавить туда маленький общий фильтрик например...
Фильтрик можно и в Hibernate добавить. Причем он действовать будет на все варианты загрузки, в том числе и через всякие select'ы.
Здравствуйте, Cyberax, Вы писали:
C>Мне в DTO не нравится его параллельность с моделью доменных объектов. Видел несколько проектов, где DTO фактически повторяли модель объектов. Кроме того, появляются проблемы со сложными графами объектов.
я понимаю, у каждого свой опыт у меня DTO не совпадают, в них всегда присутствует интеллектуализм по отношению к некоторым данным, в т.ч. синтетическим,
C>Не вижу я особого смысла в DTO, особенно учитывая, что сейчас для persistance'а используют не тяжеловесные entity-бины, а вполне обычные POJO.
у меня есть явное различие: hibernate-бины — modifable, а DTO — нет, что позволяет писать намного более строгий код, поддающийся верификации на уровне code-review, а не бесконечным ночным автотестированием
Здравствуйте, C0s, Вы писали:
C>>Мне в DTO не нравится его параллельность с моделью доменных объектов. Видел несколько проектов, где DTO фактически повторяли модель объектов. Кроме того, появляются проблемы со сложными графами объектов. C0s>я понимаю, у каждого свой опыт у меня DTO не совпадают, в них всегда присутствует интеллектуализм по отношению к некоторым данным, в т.ч. синтетическим,
А можно подробнее? Просто интересно, а я расскажу как я организовал распределенную систему из Hibernate'овских бинов.
C>>Не вижу я особого смысла в DTO, особенно учитывая, что сейчас для persistance'а используют не тяжеловесные entity-бины, а вполне обычные POJO. C0s>у меня есть явное различие: hibernate-бины — modifable, а DTO — нет, что позволяет писать намного более строгий код, поддающийся верификации на уровне code-review, а не бесконечным ночным автотестированием
А кто мешает так же делать с Hibernate'овскими бинами? Выделяешь у них иммутабельный интерфейс и бьешь по пальцам молотком за использование в клиентском коде мутебельных объектов.
Здравствуйте, C0s, Вы писали:
C0s>спрашивается, зачем городить целый отдельный класс SomeObjectInDBDAO, если наиболее общеупотребительный случай с одинаковым успехом реализуется и без него?!
Проблема в том, что при таком подходе весь код оказывается гвоздями прибит к Гибернейту. По сути гибернейт диктует и архитектуру приложения и реализацию и все остальное. Получается уже программирование на гибернейте, а не на языке программирования...
Вынесение же работы с БД в отдельный класс позволяет держать подобный код в резервации, что положительно сказывается на поддержке и понятности.
Здравствуйте, C0s, Вы писали:
C0s>в ситуации с разными источниками данных унификация такого рода (когда в тексте программы обращения выглядят одинаковыми) мне кажется вредной, т.к. поощряет программистов-пользователей такого уровня DAO не задумываться, откуда данные. следствием этого будут ошибки, которые исправить будет нелегко.
Скорее наоборот. Лишние раздумывание над ненужными подробностями и вытягивание этих подробностей на более высокий слои как раз и ведет к ошибкам.
Логика того как в какой последовательности и что вызывать как раз и должна быть сосредоточена в DAL, собственно, это одна из его основных задач. Код который вызывает DAL это заботить не должно.
C0s>видеть эту разницу в тексте — фундаментально для адекватной обработки ошибочных и полуошибочных ситуаций и для правильной расстановки вызовов, например, когда часть данных можно получить перед транзакцией БД, тем самым, не удлиняя её.
Пусть этим DAL занимается, это как раз его забота. Именно для этого служит класс, о необходимости которого ты спрашивал в первом сообщении топика.
Здравствуйте, IB, Вы писали:
C0s>>в ситуации с разными источниками данных унификация такого рода (когда в тексте программы обращения выглядят одинаковыми) мне кажется вредной, т.к. поощряет программистов-пользователей такого уровня DAO не задумываться, откуда данные. следствием этого будут ошибки, которые исправить будет нелегко. IB>Скорее наоборот. Лишние раздумывание над ненужными подробностями и вытягивание этих подробностей на более высокий слои как раз и ведет к ошибкам. IB>Логика того как в какой последовательности и что вызывать как раз и должна быть сосредоточена в DAL, собственно, это одна из его основных задач. Код который вызывает DAL это заботить не должно.
не соглашусь. к примеру, пусть по факту обработки use-case "обращение клиента", надо сначала дёрнуть legacy-систему, потом поковыряться в своей БД, после чего вызвать web-service отсылки e-mail.
для меня в такой ситуации API legacy-системы будет отделено во всех смыслах от DAL к собственной БД, и уж тем более оба будут отделены от API почтового web-сервиса. и располагаться на одном уровне доступных сервисов и внешних систем.
а вот на уровне бизнес-логики обработки use-case'а будет явно прописано, что и в каком порядке вызывается и как это сочетается с транзакциями, например, в зависимости от того, поддерживает ли API к legacy-системе интеграцию с глобальными транзакциями или нет.
IB>Пусть этим DAL занимается, это как раз его забота. Именно для этого служит класс, о необходимости которого ты спрашивал в первом сообщении топика.
вот в приведенном примере это как раз забота алгоритма реализации use-case'а, но никак не DAL
Здравствуйте, IB, Вы писали:
IB>Проблема в том, что при таком подходе весь код оказывается гвоздями прибит к Гибернейту.
в моих приложения гвоздями прибивается к hibernate'у не весь код, а только реализации тех use cases, которые взаимодействуют с БД, причём это не касается уровня презентации, который hibernate и прочие внешние системы у меня никогда не видит.
при этом абстрагироваться в реализации use-cases от hibernate, который как тул работы с БД меня полностью устраивает, я не вижу смысла. т.е. причина могла бы быть одна — ожидаемое появление через N месяцев brandNewHibernate, помноженное на необходимость развивать проект в течение долгих лет.
IB>По сути гибернейт диктует и архитектуру приложения и реализацию и все остальное. Получается уже программирование на гибернейте, а не на языке программирования...
только в реализации use cases, большой уровень презентации и прочего ничего про это не знает
IB>Вынесение же работы с БД в отдельный класс позволяет держать подобный код в резервации, что положительно сказывается на поддержке и понятности.
лишний код далеко не всегда положительно сказывается на здоровье проекта
Здравствуйте, C0s, Вы писали:
C0s>в моих приложения гвоздями прибивается к hibernate'у не весь код, а только реализации тех use cases, которые взаимодействуют с БД, причём это не касается уровня презентации, который hibernate и прочие внешние системы у меня никогда не видит.
Отлично, а что видит уровень презентации и БЛ?
C0s>при этом абстрагироваться в реализации use-cases от hibernate, который как тул работы с БД меня полностью устраивает, я не вижу смысла.
DAL — это не только БД.
C0s>только в реализации use cases, большой уровень презентации и прочего ничего про это не знает
И как это отделено друг от друга?
C0s>лишний код далеко не всегда положительно сказывается на здоровье проекта
Это если он лишний. А если для дела, то как правило положительно.
Здравствуйте, C0s, Вы писали:
C0s>к примеру, пусть по факту обработки use-case "обращение клиента", надо сначала дёрнуть legacy-систему, потом поковыряться в своей БД, после чего вызвать web-service отсылки e-mail.
Ключевой вопрос — это бизнес-процесс такой или это реализация DAL?
C0s>для меня в такой ситуации API legacy-системы будет отделено во всех смыслах от DAL к собственной БД, и уж тем более оба будут отделены от API почтового web-сервиса.
В каких всех смыслах?
Если это такой бизнес-процесс, то у нас есь ServiceLayer, который там же где и DAL и спроектирован таким же образом. И опять-таки вызывающий код совршенно не парит, к какой-такой Legacy сестеме он обращается и что он вообще опращается к legacy — это не его головная боль, равно как и особенности реализации этого обращения. Просто есть некий метод, а уж легаси он там или не очень — дело десятое.
Так же его не парит, как именно реализован сервис рассылок, веб-сервис ли это, очередь или еще что, это просто некая конструкция оборудованная соответствующим API. То же самое относится и к БД/DAL, я знать не знаю гибернейт там или еще что и знать не хочу — это особенность реализации, которая не должна влиять на публичный контракт какого-то ни было слоя.
Далее, в бизнес-слое просто отрабатывается соответствующий сценарий обработки клиентского запроса не заморачиваясь вопросами эффективности вызовов и прочей низкоуровневой требухи. Забота бизнес слоя — исключительно правильность логики.
Если же обращение к легаси системе часть механизма хранения данных, то это все закатываетсяв DAL (естествнно, каждый аспект в свою часть), а наружу торчит единственный метод "сохранить запрос клиента", с соответствующим набором параметров. И внешний код не заботит как это будет сделано, что там пойдет через легаси, а что нет.
Отправка мыла — это всегда отдельный сервис, единственное что может сделать DAL — это выставить соответствующие признаки в БД, куда и что отправлять.
C0s>а вот на уровне бизнес-логики обработки use-case'а будет явно прописано, что и в каком порядке вызывается и как это сочетается с транзакциями, например, в зависимости от того, поддерживает ли API к legacy-системе интеграцию с глобальными транзакциями или нет.
Разбираться кто там поддерживает транзакции, а кто нет — это не забота бизнес-логики. Забота BL — это только сама логика и ничего кроме логики. Если легаси система транзакций не поддерживает, а в БЛ это надо, значит DAL должен реализовать соответствующую обертку чтобы все заработало.
C0s>вот в приведенном примере это как раз забота алгоритма реализации use-case'а, но никак не DAL
Это зависит от задач которые решает данный пример.
Здравствуйте, IB, Вы писали:
C0s>>в моих приложения гвоздями прибивается к hibernate'у не весь код, а только реализации тех use cases, которые взаимодействуют с БД, причём это не касается уровня презентации, который hibernate и прочие внешние системы у меня никогда не видит.
IB>Отлично, а что видит уровень презентации и БЛ? IB>И как это отделено друг от друга?
реализация usecases — это и есть БЛ. естественно, что уровень презентации видит БЛ-api, и оба зависят от структур данных, с помощью которых производится обмен информацией между ними. эти структуры можно назвать POJO, можно DTO, суть не меняется. просто эти структуры не обязаны повторять структуры DAL с одной стороны, с другой стороны они могут помогать переносить информацию между узлами по сети в ситуации удалённых вызовов.
Здравствуйте, C0s, Вы писали:
C0s>лишний код далеко не всегда положительно сказывается на здоровье проекта
а не сказывается ли такое вот размазывание Hibernate-вызовов на появление того самого лишнего кода? Ведь что такое DAO? Абстракция, призваная инкапсулировать в себя детали работы с DAL. А в больших системах наблюдаются некторые шаблонные подходы к этим деталям, которые вполне могуть быть выделены в базовые классы и использоваться повсеместно. Пример этому — тот самый GenericDAO, в котором могут быть обобщены наиболее часто используемые запросы. Если этого не делать, то по любому появятся всякие статик-хелперы, реализующие те самые детали, причем завязываеющие БЛ на себя уже статически. К тому же при использовании GenericDAO получается еще один бонус — проверка типов на этапе компилирования, без необходимости каста в местах вызова.
Здравствуйте, IB, Вы писали:
C0s>>к примеру, пусть по факту обработки use-case "обращение клиента", надо сначала дёрнуть legacy-систему, потом поковыряться в своей БД, после чего вызвать web-service отсылки e-mail. IB>Ключевой вопрос — это бизнес-процесс такой или это реализация DAL?
возможно, имеет место терминологическая путаница, ибо я это называю слоем БЛ, и никак уж не DAL.
для меня слой БЛ — это слой, где реализуются use cases.
C0s>>для меня в такой ситуации API legacy-системы будет отделено во всех смыслах от DAL к собственной БД, и уж тем более оба будут отделены от API почтового web-сервиса. IB>В каких всех смыслах?
они друг от друга не зависят, их использует вышестоящий уровень — уровень реализации use cases, по требованиям к которому в приведённом абстракном примере пришлось проинтегрироваться с legacy-системой, и реализованным студентом Пупкиным набором web-сервисов.
C0s>>а вот на уровне бизнес-логики обработки use-case'а будет явно прописано, что и в каком порядке вызывается и как это сочетается с транзакциями, например, в зависимости от того, поддерживает ли API к legacy-системе интеграцию с глобальными транзакциями или нет.
IB>Разбираться кто там поддерживает транзакции, а кто нет — это не забота бизнес-логики. Забота BL — это только сама логика и ничего кроме логики.
я не согласен именно с пренебрежением относительно забот насчет транзакций. где-то ведь возникает демаркация транзакций, явная или декларативная. реализация каждого use case, по моим представлениям, идеальный кандидат на работу в рамках транзакции, но с поправками на то, какие нетранзакционные сервисы ему приходится дёргать.
IB>Если легаси система транзакций не поддерживает, а в БЛ это надо, значит DAL должен реализовать соответствующую обертку чтобы все заработало.
если она не поддерживает транзакций, то ни в коем случае этот факт не должен быть скрыт от определенного уровня. я так понял, ты этот уровень не называешь БЛ, а для меня он в любом случае выше, чем DAL.
попробую опять пояснить, пусть пример с "обращением клиента" и абстрактен:
я подразумевал, что это — бизнес use case, т.е. на презентационном уровне была форма, которую пользователь заполнил и нажал кнопку. по этой кнопке данные валидируются и передаются обсуждаемой реализации этого use case. и требование интегрироваться с legacy — не прихоть программера, а одно из дебильных бизнес-требований к реализации большей части use cases проекта.
вот это обилие слов "бизнес" ну никак мне не дает возможности назвать этот уровень DAL или high-level DAL. для меня это БЛ.
Здравствуйте, Lucker, Вы писали:
L>а не сказывается ли такое вот размазывание Hibernate-вызовов на появление того самого лишнего кода? Ведь что такое DAO? Абстракция, призваная инкапсулировать в себя детали работы с DAL.
я не могу сказать, что у меня что-то размазывалось. как правило, у меня это выглядит как набор интерфейсов по одному на каждую часть предметной области (разбиение на части делается по каким-то признакам группировки use-cases и призвано для упрощения работы с сущностями системы).
еще я начинаю думать, что то, что у меня называется низко- и среднеуровневой логикой, ты (и IB, если я правильно понял) называешь DAL. просто некоторые простые манипуляции типа создания объекта или его обновления уже могут реализовывать самостоятельные бизнес-use cases.
при этом сложная БЛ у меня базируется на упомянутой низко- и среднеуровневой логике, и в ней hibernate (или DAO) не упоминается вообще — работа ведётся через API, предоставленное с более низких уровней реализации БЛ
L>А в больших системах наблюдаются некторые шаблонные подходы к этим деталям, которые вполне могуть быть выделены в базовые классы и использоваться повсеместно. Пример этому — тот самый GenericDAO, в котором могут быть обобщены наиболее часто используемые запросы.
видимо, я пока пишу маленькие системы, т.к. я не вижу путей к обоющению.
простой пример: реализация постраничных фильтрованных запросов. разные сущности — разные фильтры, принципиально разные запросы и никакого обобщения.
Здравствуйте, C0s, Вы писали:
C0s> эти структуры можно назвать POJO, можно DTO, суть не меняется. просто эти структуры не обязаны повторять структуры DAL с одной стороны, с другой стороны они могут помогать переносить информацию между узлами по сети в ситуации удалённых вызовов.
Угу. Только как правило оказывается, что DTO практически один в один таки повторяют объекты DAL. Вот у нас и получается некая бизнес-сущность, с которой удобно работатьи БД, и БЛ и презеннтационному слою, и по сети ее пулять.
Очень удобно и никаких лишних преобразований, но это уже другой вопрос...
Я собственно к тому, что слой бизнес-логики у тебя помимо собственно обработки use-case'ов занимается еще и преобразованием объектов DAL в объекты для презентационного слоя и работает с гибернейтом.. Так?
Здравствуйте, IB, Вы писали:
C0s>> эти структуры можно назвать POJO, можно DTO, суть не меняется. просто эти структуры не обязаны повторять структуры DAL с одной стороны, с другой стороны они могут помогать переносить информацию между узлами по сети в ситуации удалённых вызовов.
IB>Угу. Только как правило оказывается, что DTO практически один в один таки повторяют объекты DAL. Вот у нас и получается некая бизнес-сущность, с которой удобно работатьи БД, и БЛ и презеннтационному слою, и по сети ее пулять.
я тут выше уже писал — у меня они разные. похожие, но разные =)
IB>Очень удобно и никаких лишних преобразований, но это уже другой вопрос...
я не боюсь этих лишних преобразований, т.к. более строгие DTO позволяют минимизировать всякие ошибки в коде более высокого уровня. потом, те объекты, которые имеют очень сильное сходство я просто поднимаю выше, но всегда через урезающую обёртку — всё для той же строгости.
т.е. для меня кажется нормальным, что объекты, использующиеся в деталях реализации одного уровня не экспозируются на вышестоящий.
IB>Я собственно к тому, что слой бизнес-логики у тебя помимо собственно обработки use-case'ов занимается еще и преобразованием объектов DAL в объекты для презентационного слоя и работает с гибернейтом.. Так?
простые методы БЛ — да,
сложные же методы БЛ являются либо композицией простых, т.е. сами по себе не работают уже с hibernate'ом etc
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Lucker, Вы писали:
L>>А в больших системах наблюдаются некторые шаблонные подходы к этим деталям, которые вполне могуть быть выделены в базовые классы и использоваться повсеместно. Пример этому — тот самый GenericDAO, в котором могут быть обобщены наиболее часто используемые запросы.
C0s>видимо, я пока пишу маленькие системы, т.к. я не вижу путей к обоющению. C0s>простой пример: реализация постраничных фильтрованных запросов. разные сущности — разные фильтры, принципиально разные запросы и никакого обобщения.
вот как раз из попытки обобщить реализацию такого примера первоначальный вопрос и появился. Вроде, неплохо обобщилось.
Все сущности в системе унаследованы от общего класса Entity, с Integer id полем. Значит, сущности уже можно искать по id, или набору id. Далее, в системе есть пользователи (User), каждый из которых может принадлежать некоторому региону. Значит пользователей уже можем искать по id и по региону. Далее, пользователи делятся на два типа: StaffUser, каждый из которых выполняет свою роль (можем искать по id, региону и роли), и Client, имеющие дополнительный классификатор Type(можем искать по id, региону и типу). Ну и так далее. Для каждой сущности есть интерфей EntityQueryParameters
public interface EntitiesQueryParameters {
Collection<? extends Integer> getIds();
}
public interface UserQueryParameters extends EntitiesQueryParameters {
Region getRegion();
}
public interface ClientsQueryParameters extends UserQueryParameters {
Type getType();
}
public interface StaffQueryParameters extends UserQueryParameters {
Role getRole();
}
Ну и теперь ДАО:
public abstract class AbstractEntitiesQuerySupportDAO<E extends Entity, T extends EntitiesQueryParameters>{
public List<? extends E> findEntities(final T queryParameters, final int startFrom, final int count, final SortDefinition... sortDefinitions) {
return getHibernateTemplateEx().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
final Criteria[] criteria = createCriteria(session, queryParameters);
if (criteria == null) {
return Collections.emptyList();
}
if (startFrom != 0) {
criteria[0].setFirstResult(startFrom);
}
if (count >= 0) {
criteria[0].setMaxResults(count);
}
return setupOrder(criteria[0], sortDefinitions).list();
}
});
}
protected Criteria[] createCriteria(final Session session, final T filter) {
final Criteria[] criteria = new Criteria[]{session.createCriteria(getEntityName())};
if (filter.getIds() != null) {
if (filter.getIds().size() == 0) {
return null;
}
criteria[0].add(Restrictions.in("id", filter.getIds()));
}
return criteria;
}
}
что делают остальные ДАО, так это переопределяют createCriteria, добавляя в него свои критерии
public abstract class UserDAOImpl<A extends User, P extends UserQueryParameters>
extends AbstractEntitiesQuerySupportDAO<A, P> implements UserDAO<A, P> {
@Override
protected Criteria[] createCriteria(final Session session, final P filter) {
final Criteria[] criteria = createCriteria(session, filter);
if (criteria == null) {
return null;
}
if (filter.getRegion() != null) {
criteria[0].add(Restrictions.eq("region", filter.getRegion()));
}
return criteria;
}
}
public class StaffDAOImpl extends UserDAOImpl<StaffUser, StaffQueryParameters> implements StaffDAO {
@Override
protected Criteria[] createCriteria(final Session session, final StaffQueryParameters filter) {
final Criteria[] criteria = super.createCriteria(session, filter);
if (criteria == null) {
return null;
}
if (filter.getRole() != null) {
criteria[0].add(Restrictions.eq("role", filter.getRole()));
}
return criteria;
}
}
public class ClientDAOImpl extends UserDAOImpl<Client, ClientsQueryParameters> implements ClientDAO {
@Override
protected Criteria[] createCriteria(final Session session, final ClientsQueryParameters filter) {
final Criteria[] criteria = super.createCriteria(session, filter);
if (criteria == null) {
return null;
}
if (filter.getType() != null) {
criteria[0].add(Restrictions.eq("type", filter.getType()));
}
return criteria;
}
}
И так далее. Для клиента есть другие интерфейсы,
public interface EntitiesQuery<T extends EntitiesQuery, E extends Entity> {
T withId(Integer id);
T withIds(Collection<? extends Integer> id);
List<? extends E> find(final SortDefinition ... definitions);
List<? extends E> find(int startFrom, int count, final SortDefinition ... definitions);
}
public interface UserQuery<T extends UserQuery, A extends User> extends EntitiesQuery<T, A> {
T inRegion(Region region);
}
public interface StaffQuery extends UserQuery<StaffQuery, StaffUser> {
StaffQuery whithRole(Role role);
}
public interface ClietnQuery extends UserQuery<ClietnQuery, Client> {
ClietnQuery whithType(Type type);
}
createStaffQuery() — псевдовызов, возвращающий нужный запрос в виде интерфейса.
Все детали выполения запросов сосредоточены в DAO, Query — тупо собирают параметры, и передают их в ДАО, а клиент работает с жестко типизироваными методами.
Здравствуйте, C0s, Вы писали:
C0s>я не согласен именно с пренебрежением относительно забот насчет транзакций. где-то ведь возникает демаркация транзакций, явная или декларативная. реализация каждого use case, по моим представлениям, идеальный кандидат на работу в рамках транзакции, но с поправками на то, какие нетранзакционные сервисы ему приходится дёргать.
use-case не должно заботить поддерживает нижележащий уровень транзакцию или нет. Если транзакция нужна, значит этот уровень обязан ее поддержать. Не надо при реализации логики заморачиваться на особенности реализации нижележащего кода.
C0s>я подразумевал, что это — бизнес use case, т.е. на презентационном уровне была форма, которую пользователь заполнил и нажал кнопку. по этой кнопке данные валидируются и передаются обсуждаемой реализации этого use case. и требование интегрироваться с legacy — не прихоть программера, а одно из дебильных бизнес-требований к реализации большей части use cases проекта.
У нас есть в DAL два метода Native и Legacy. use-case обработки запроса заключается в последовательном вызове методов Legacy и Native.
Так вот БЛ вызывает просто Method1 и Method2 — какой из них легаси и что он там поддерживает — не его забота. Главное что он реализовывает соответствующую функциональность, а уж как он это делает у него голова болеть не должна, хоть голубиной почтой.
Здравствуйте, C0s, Вы писали:
C0s>я тут выше уже писал — у меня они разные. похожие, но разные =)
Зря. Когда одинаковые — жить проще.
C0s>я не боюсь этих лишних преобразований, т.к. более строгие DTO позволяют минимизировать всякие ошибки в коде более высокого уровня.
И внести новые на этапе преобразований. Хрен редьки....
Здравствуйте, IB, Вы писали:
C0s>>я не боюсь этих лишних преобразований, т.к. более строгие DTO позволяют минимизировать всякие ошибки в коде более высокого уровня. IB>И внести новые на этапе преобразований. Хрен редьки....
не совсем,
1) эти объекты не так сложны в устройстве.
2) каждый объект используется в N местах. я предпочитаю контролировать M имплементаций объектов (инстанцирование которых собрано в небольшом количестве фабричных классов) вместо усиления контроля за M*N(m) мест их использования
Здравствуйте, IB, Вы писали:
IB>use-case не должно заботить поддерживает нижележащий уровень транзакцию или нет.
возможно, ты еще не видел, как при таком подходе делаются ошибки, приводящие к рассогласованности данных, о которой не идет правильной диагностики "наверх"
IB>Если транзакция нужна, значит этот уровень обязан ее поддержать. Не надо при реализации логики заморачиваться на особенности реализации нижележащего кода.
если транзакция нужна, но нижележащий код не может ее поддержать, это должно быть явно учтено (на текущем уровне), а не проигнорировано путём заглушек (на нижележащем уровне), имитирующих поддержку транзакции
IB>У нас есть в DAL два метода Native и Legacy. use-case обработки запроса заключается в последовательном вызове методов Legacy и Native. IB>Так вот БЛ вызывает просто Method1 и Method2 — какой из них легаси и что он там поддерживает — не его забота. Главное что он реализовывает соответствующую функциональность, а уж как он это делает у него голова болеть не должна, хоть голубиной почтой.
где объявлены и как реализованы Method1 и Method2?
Здравствуйте, C0s, Вы писали:
C0s>1) эти объекты не так сложны в устройстве.
Так зачем их тогда вообще трогать?
C0s>2) каждый объект используется в N местах. C0s> я предпочитаю контролировать M имплементаций объектов (инстанцирование которых собрано в небольшом количестве фабричных классов) вместо усиления контроля за M*N(m) мест их использования
Каждый объект содается ровно в одном месте и нигде не модифицируется. Сами объекты крайне просты, значит и контролировать их не надо, ни в N, ни в M случаях.
Здравствуйте, C0s, Вы писали:
C0s>возможно, ты еще не видел, как при таком подходе делаются ошибки, приводящие к рассогласованности данных, о которой не идет правильной диагностики "наверх"
Ага и вообще пороху не нюхал.. =)
Как описанная схема мешает правильной диагностике?
C0s>если транзакция нужна, но нижележащий код не может ее поддержать, это должно быть явно учтено (на текущем уровне),
Нет. Это означает что вышележащий код начинает лезть в особенности реализации нижележащего и при изменении кода DAL тебе придется перетряхивать весь проект и следить не рухнуло ли что.
C0s> а не проигнорировано путём заглушек (на нижележащем уровне), имитирующих поддержку транзакции
Имитируют они или нет — дело десятое.
C0s>где объявлены и как реализованы Method1 и Method2?
Объявлены — хоть в интерфейсе. Реализованы в DAL.
Здравствуйте, IB, Вы писали:
C0s>>спрашивается, зачем городить целый отдельный класс SomeObjectInDBDAO, если наиболее общеупотребительный случай с одинаковым успехом реализуется и без него?! IB>Проблема в том, что при таком подходе весь код оказывается гвоздями прибит к Гибернейту. По сути гибернейт диктует и архитектуру приложения и реализацию и все остальное. Получается уже программирование на гибернейте, а не на языке программирования...
То что ты ORMофоб мы уже и так знаем
IB>Вынесение же работы с БД в отдельный класс позволяет держать подобный код в резервации, что положительно сказывается на поддержке и понятности.
Зачем ее выносить в слое, который непосредственно с данными работает? Обычно у нас все равно появляются неявные связи с используемой системой ORM/DAL. Вот в интерфейсе слоя бизнес-логики и клиентского кода — деталей DALа не должно быть.
Здравствуйте, IB, Вы писали:
C0s>>1) эти объекты не так сложны в устройстве. IB>Так зачем их тогда вообще трогать?
что значит "трогать"?! я пишу про DTO, ты же утверждаешь, что их вообще использовать не надо
C0s>>2) каждый объект используется в N местах. C0s>> я предпочитаю контролировать M имплементаций объектов (инстанцирование которых собрано в небольшом количестве фабричных классов) вместо усиления контроля за M*N(m) мест их использования IB>Каждый объект содается ровно в одном месте и нигде не модифицируется. Сами объекты крайне просты, значит и контролировать их не надо, ни в N, ни в M случаях.
если это ORM-pojo, то он создаётся в большинстве случаев в недрах ORM и является модифицируемым (mutable)
именно поэтому я и пишу про DTO, которые у меня создаются мной там, где надо, оторваны от ORM и объектов, жизненным циклом котороых управляет ORM, и я являются настолько простыми, насколько это позволяет задача уровня презентации или что там еще бывает при работе с извлекаемыми данными.
Здравствуйте, IB, Вы писали:
C0s>>возможно, ты еще не видел, как при таком подходе делаются ошибки, приводящие к рассогласованности данных, о которой не идет правильной диагностики "наверх"
IB>Ага и вообще пороху не нюхал.. =)
да не измерений ради...
C0s>>где объявлены и как реализованы Method1 и Method2? IB>Объявлены — хоть в интерфейсе. Реализованы в DAL.
C0s>> а не проигнорировано путём заглушек (на нижележащем уровне), имитирующих поддержку транзакции IB>Имитируют они или нет — дело десятое.
итого твою картину ситуации я представляю так (если что — поправь):
и вот здесь мы старательно закрываем глаза на то, как эти методы ведут себя в отношении транзакций:
BL {
MyUseCaseImpl() throws BusinessException {
transaction.start;
try DAL.Method1(); on SomeProblemException transaction.rollback() and throw BusinessException("problem in legacy");
try DAL.Method2(); on AnotherProblemException transaction.rollback() and throw BusinessException("problem in native");
try transaction.commit(); on CommitFailed transaction.rollback and throw BusinessException("commit failed");
}
}
в этом коде не обеспечена целостность данных при проблемах на уровне legacy только из-за того, что уровень BL закрывает глаза на разнородность сервисов нижележащего уровня
Здравствуйте, C0s, Вы писали:
C0s>если можно, то я задам встречный: а зачем вообще DAO? C0s>манипуляции данными обычно не так тривиальны, чтобы заморачиваться на dao, для простых операций типа получения по id достаточно возможностей, которые даёт hibernate-сессия, для сложных типа запросить сджойненные данные с хитрой фильтрацией — dao не помогает.
Вот это я не понял. Можно пояснить на примере? Если тебе встретилась сложная логика, то здравый смысл должен подсказать тебе изолировать эту логику от другого кода, а это, для твоего случая, прямой путь к написанию dao.
C0s>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо
Если тебе плохо от тонны кода dao, то это проблема не dao, а того кто его писал.
Первая и главная цель, для которой вводиться отдельный слой для работы с данными — это уменьшения сложности кода. Все остальные аргументы, то как: легко прикрутить новую базу, удобство тестирования, параллельная разработка и т.д. — вторичны и, как правило, являются дополнительным бонусом при стремлении к этой цели. Что значит уменьшение сложности? Упрощенно, чем меньшим количеством абстракций/сущностей мне нужно оперировать при вычитывании некоторого фрагмента кода, тем ниже сложность этого кода. Если читая метод бизнес логики для расчета заработной платы сотрудника я должен думать о базе данных — это плохо. Это значит, что программист, который написал этот метод не смог изолировать логику работы с базой в отдельном методе(классе, слое). Это значит, что этот код больше подвержен ошибкам, т.к. жонглировать тремя апельсинами сложнее, чем двумя.
Как изолировать логику работу с данными? Когда проект состоит из пары классов, достаточно логику работы с источниками данных вынести в отдельные методы. Когда проект состоит из пары десятков классов — имеет смысл вынести эту логику в отдельные классы. Когда проект состоит из сотен классов — вводите отдельный слой для работы с базой, даже если вы используете hibernate. Несмотря на все прелести hibernate-а и иже с ними, он не достаточно хорошо изолирует логику работы с базой данных и является, скорее, помощником в написании dao, чем полноценным его заменителем.
Здравствуйте, C0s, Вы писали:
C0s>в этом коде не обеспечена целостность данных при проблемах на уровне legacy только из-за того, что уровень BL закрывает глаза на разнородность сервисов нижележащего уровня
Из этого только следует, что не надо скрывать от уровня бизнес логики, что Method1 не поддерживает транзакцию. Вытаскивать всю логику работы с легаси системой и базой только с целью сообщить вызывающему коду о поддержке или неподдержке транзакций — как минимум очень странно. Самое простое решение для данного примера — сделать передачу транзакции явной.
Здравствуйте, IB, Вы писали:
IB>Проблема в том, что при таком подходе весь код оказывается гвоздями прибит к Гибернейту.
Это как раз не проблема. Люди сознательно выбирают хибернейт и привязываются к нему. Вот выйдет link2sql люди сознательно будут выбирать его.
IB>По сути гибернейт диктует и архитектуру приложения и реализацию и все остальное. Получается уже программирование на гибернейте, а не на языке программирования...
Вот это другое дело. Проблема в навязывании своей архитектуры и проектированию фактически от хибернейт, а не от БД.
IB>Вынесение же работы с БД в отдельный класс позволяет держать подобный код в резервации, что положительно сказывается на поддержке и понятности.
Этот подход тоже имеет проблемы. Надеюсь, подход линка окажется более совершенным.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, C0s, Вы писали:
C0s>что значит "трогать"?!
Трогать — это значит урезать и городить на их основе другие — более простые/сложные объекты
C0s> я пишу про DTO, ты же утверждаешь, что их вообще использовать не надо
Не, я утверждаю что в идеале то что ты называешь DTO это эквивалент BizEntity.
C0s>если это ORM-pojo, то он создаётся в большинстве случаев в недрах ORM и является модифицируемым (mutable)
Модифицируемым — не в смысле Mutable, а в смысле урезать/добавить при переходе из слоя в слой.
Хотя и сделать большинство из них immutable тоже не помешало бы.
C0s>именно поэтому я и пишу про DTO, которые у меня создаются мной там, где надо, оторваны от ORM и объектов, жизненным циклом котороых управляет ORM, C0s> и я являются настолько простыми, насколько это позволяет задача уровня презентации или что там еще бывает при работе с извлекаемыми данными.
Во. А я пишу про то, что объекты изначально должны быть простыми и никакая ORM не имеет право управлять их жизненным циклом или еще что-то с ними делать. (За что собственно и не люблю ORM)
Здравствуйте, Cyberax, Вы писали:
C>То что ты ORMофоб мы уже и так знаем
Не лишним будет в очередной раз напомнить.. )
C>Зачем ее выносить в слое, который непосредственно с данными работает?
Чтобы слой который работает со слоем, который работает непосредственно с данными ничего об интимных подробностях конкретной ORM не знал.
C>Обычно у нас все равно появляются неявные связи с используемой системой ORM/DAL.
Где?
C>Вот в интерфейсе слоя бизнес-логики и клиентского кода — деталей DALа не должно быть.
Это само собой. Речь о том что в интерфейсе BL-DAL не должно быть подробностей конкретной реализации DAL.
Здравствуйте, C0s, Вы писали:
C0s>да не измерений ради...
Ну надеюсь..
C0s>в этом коде не обеспечена целостность данных при проблемах на уровне legacy только из-за того, что уровень BL закрывает глаза на разнородность сервисов нижележащего уровня
Внимание вопрос. Что мешает сделать поддержку транзакций в Method1, поверх вызова Legacy? Хотя бы тем способом, что предложил MaximVK?
И зачем эту, явно низкоуровневую логику тащить наверх?
Здравствуйте, IT, Вы писали:
IT>Это как раз не проблема. Люди сознательно выбирают хибернейт и привязываются к нему.
Ну собственно в этом-то и проблема.. =)
IT>Вот выйдет link2sql люди сознательно будут выбирать его.
Ну, у линка подход другой, он не должен так жестко руки связывать.
IT>Этот подход тоже имеет проблемы. Надеюсь, подход линка окажется более совершенным.
Посмотрим..
Здравствуйте, IB, Вы писали:
C>>Зачем ее выносить в слое, который непосредственно с данными работает? IB>Чтобы слой который работает со слоем, который работает непосредственно с данными ничего об интимных подробностях конкретной ORM не знал.
Нереально. Точнее, непрактично.
Детали ORM могут косвенно влиять на использование объектов. Например, есть ORM в которых не поддерживается identity mapping — значит многие алгоритмы с такой ORM, рассчитаные на правильную идентичность, будут падать.
Другой пример, Hibernate автоматически генерирует методы equals и hashCode для проксиков (заменяя их на сравнение и взятие хэшкода главного ключа объекта), так что неинициализированые проксики можно быстро класть в hash-коллекции. Таким образом, если мы в наших классах добавим equals+hashCode, то можем вдруг получить неприятные сюрпризы по скорости из-за того, что при попытке положить такие объекты в HashSet у нас они будут загружаться из базы.
Да, с ленивой загрузкой тоже могут быть оооочень интересные сюрпризы.
C>>Обычно у нас все равно появляются неявные связи с используемой системой ORM/DAL. IB>Где?
См. предидущий параграф
C>>Вот в интерфейсе слоя бизнес-логики и клиентского кода — деталей DALа не должно быть. IB>Это само собой. Речь о том что в интерфейсе BL-DAL не должно быть подробностей конкретной реализации DAL.
Не согласен. Детали доступа к данным могут сильно влиять на BL.
Здравствуйте, IB, Вы писали:
C0s>>в этом коде не обеспечена целостность данных при проблемах на уровне legacy только из-за того, что уровень BL закрывает глаза на разнородность сервисов нижележащего уровня IB>Внимание вопрос. Что мешает сделать поддержку транзакций в Method1, поверх вызова Legacy? Хотя бы тем способом, что предложил MaximVK?
Кстати, я у себя примерно так и делаю — все нужные параметры передаю явно.
Кроме того, такой метод все равно не подходит для обобщенного DAL, который по легенде можно одной строчкой в конфиге поменять с БД на использование файловой системы на марсоходе Spirit через систему космической связи NASA.
IB>И зачем эту, явно низкоуровневую логику тащить наверх?
Так передача транзакции — это уже низкоуровневая логика.
Здравствуйте, IB, Вы писали:
IT>>Это как раз не проблема. Люди сознательно выбирают хибернейт и привязываются к нему. IB>Ну собственно в этом-то и проблема.. =)
Не проблема это. Иначе так можно договориться до того, что использование любой библиотеки — это проблема. Даже .NET FW.
IT>>Вот выйдет link2sql люди сознательно будут выбирать его. IB>Ну, у линка подход другой, он не должен так жестко руки связывать.
Вот с руками действительно проблема. А прибото приложение гвоздями к линку или хибернейту — это не важно. Любое решение всегда к чему-нибудь прибивается.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Не проблема это. Иначе так можно договориться до того, что использование любой библиотеки — это проблема. Даже .NET FW.
Смотря какая библиотека... Мне не нравится идея программировать на библиотеке, не для этого их пишут.
IT> Любое решение всегда к чему-нибудь прибивается.
Вопрос в какой степени и какой частью. Если по уму, то шурупчики можно аккуратно вывернуть и что-нибудь другое прикрутить, и изменение в одном кусочке не вылиывается в перелопачивание всего кода.
Здравствуйте, Cyberax, Вы писали:
C>Нереально.
Реально.
C> Точнее, непрактично.
Очень практично, на практике проверено.
C>Детали ORM могут косвенно влиять на использование объектов.
А не надо чтобы влияли. Точнее надо чтобы не влияли.
C> Например, есть ORM в которых не поддерживается identity mapping — значит многие алгоритмы с такой ORM, рассчитаные на правильную идентичность, будут падать.
На кой байт, слою реализующиму логику знать об identity mapping? если нужна правильная идентичность — пусть DAL ее обеспечивает, а уж с помощю ORM он это сделает или нет — дело десятое.
C>Другой пример, Hibernate автоматически генерирует методы equals и hashCode для проксиков (заменяя их на сравнение и взятие хэшкода главного ключа объекта), так что неинициализированые проксики можно быстро класть в hash-коллекции. Таким образом, если мы в наших классах добавим equals+hashCode, то можем вдруг получить неприятные сюрпризы по скорости из-за того, что при попытке положить такие объекты в HashSet у нас они будут загружаться из базы.
Угу. Это к вопросу о том, что не надо использовать ORM типа гибернейта, которые пытаются все решить за нас.
Эти нюансы не должны заботить слой занимающийся логикой — его задача обслуживание use-case'ов и ничего более, а тут получается, что этот слой еще и обслуживанием ORM занимается.
C>Да, с ленивой загрузкой тоже могут быть оооочень интересные сюрпризы.
Какие?
C>См. предидущий параграф
Во-во. Вот не надо нам неявных связей, проще надо быть.
C>Не согласен. Детали доступа к данным могут сильно влиять на BL.
Ну как писать. Могут-то конечно могут, но надо писать чтобы не влияли.
Здравствуйте, Cyberax, Вы писали:
C>Кроме того, такой метод все равно не подходит для обобщенного DAL,
Что мешает?
C>Так передача транзакции — это уже низкоуровневая логика.
Это смотря какой транзакции. Если БД транзакции, то низкоуровневая, но здесь речь идет о бизнес-транзакции, а это уровень повыше будет.
Здравствуйте, IB, Вы писали:
IT>>Не проблема это. Иначе так можно договориться до того, что использование любой библиотеки — это проблема. Даже .NET FW. IB>Смотря какая библиотека... Мне не нравится идея программировать на библиотеке, не для этого их пишут.
Ваня, это теория. Красивая сказка. Реализация напрямую зависит от выбранных средств. И чем сложнее средства, тем большими гвоздями к ней прибивается реализация. Единственное что ты можешь сделать — это написать всё сам, но, надеюсь ты понимаешь, что при текущем состоянии дел в индустрии для более менее сложных задач это не реально.
IT>> Любое решение всегда к чему-нибудь прибивается. IB>Вопрос в какой степени и какой частью. Если по уму, то шурупчики можно аккуратно вывернуть и что-нибудь другое прикрутить, и изменение в одном кусочке не вылиывается в перелопачивание всего кода.
Давай для примера возьмём не DAL, а UI. Как ты думаешь насколько реально выбрать в качестве UI библиотеки сначала Syncfusion, а потом передумать, открутить шурупчики и прикрутить Infragistic? Если у тебя есть сомнения, что абсолютно весь код, касающийся логики UI будет переписан, то можешь сам попробовать на досуге.
Так что проблема не в том, используются какие-либо библиотеки или нет. Проблема в том, как они влияют на архитектуру приложения. В частности, хибернейт не просто влияет, он её диктует, а это значит, что отход от предложенного подхода будет немедленно караться. Проблема именно в этом.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IB, Вы писали:
C>> Точнее, непрактично. IB>Очень практично, на практике проверено.
Можно список проектов, желательно OpenSource?
Я утверждаю, что если DAL заранее не проектировался для работы с несколькими видами источников данных, то DAO фиг чем помогут. Могу привести пример, когда источник RDF-данных пытались (очень плохоуспешно) синтегрировать с реляционными данными.
C>> Например, есть ORM в которых не поддерживается identity mapping — значит многие алгоритмы с такой ORM, рассчитаные на правильную идентичность, будут падать. IB>На кой байт, слою реализующиму логику знать об identity mapping? если нужна правильная идентичность — пусть DAL ее обеспечивает, а уж с помощю ORM он это сделает или нет — дело десятое.
А безопасность тоже он обеспечивать будет? И транзакционные уровни изоляции?
C>>Другой пример, Hibernate автоматически генерирует методы equals и hashCode для проксиков (заменяя их на сравнение и взятие хэшкода главного ключа объекта), так что неинициализированые проксики можно быстро класть в hash-коллекции. Таким образом, если мы в наших классах добавим equals+hashCode, то можем вдруг получить неприятные сюрпризы по скорости из-за того, что при попытке положить такие объекты в HashSet у нас они будут загружаться из базы. IB>Угу. Это к вопросу о том, что не надо использовать ORM типа гибернейта, которые пытаются все решить за нас.
А без разницы. Самодельный ORM точно так же может [не] страдать этим.
IB>Эти нюансы не должны заботить слой занимающийся логикой — его задача обслуживание use-case'ов и ничего более, а тут получается, что этот слой еще и обслуживанием ORM занимается.
Хочешь расскажу тайну? Нету такой вещи в природе как слой чистой бизнес-логики (достаточно развитой, естественно, о "hello, world!" не говорим), незамутненной деталями реализации нижележащих слоев.
C>>Да, с ленивой загрузкой тоже могут быть оооочень интересные сюрпризы. IB>Какие?
Ооооо... Тут ТАКОЙ список...
Например, взаимодействие с версированием объектов, с транзакциями, с конкуррентным использованием, безопасностью, возможностью нелокальной работы.
C>>См. предидущий параграф IB>Во-во. Вот не надо нам неявных связей, проще надо быть.
Так эти неявные связи все равно будут. Если ты сегодня напишешь простой рабоче-крестьянский CRUDовый DAL, а завтра решишь использовать Hinernate — то скорее всего возникнут сюрпризы. Могу рассказать по своему опыту, если интересно.
C>>Не согласен. Детали доступа к данным могут сильно влиять на BL. IB>Ну как писать. Могут-то конечно могут, но надо писать чтобы не влияли.
Например, мы делаем так:
List<User> users=UserDAO.getInstance().getUsersByPattern("Vasja*"); //В списке всего 10 объектов.
Collections.sort(users); //Но объекты достаются через CORBA...
В результате, для сортировки этого списка тебе может потребоваться примерно 30 удаленных вызовов. Так как для сравнения на равенство CORBA-объектов потребуется удаленный вызов.
В то же время, если объекты передаются по значению — то сортировка будет мгновенной. Вместо сортировки можно, например, взять валидацию email.
Здравствуйте, IB, Вы писали:
C>>Кроме того, такой метод все равно не подходит для обобщенного DAL, IB>Что мешает?
Отсутствие у него параметра с транзакцией
C>>Так передача транзакции — это уже низкоуровневая логика. IB>Это смотря какой транзакции. Если БД транзакции, то низкоуровневая, но здесь речь идет о бизнес-транзакции, а это уровень повыше будет.
А чем тебе объект с бизнес-транзакцией поможет в DAO, если через него нельзя получить DB-транзакцию?
Здравствуйте, IT, Вы писали:
IT>Так что проблема не в том, используются какие-либо библиотеки или нет. Проблема в том, как они влияют на архитектуру приложения. В частности, хибернейт не просто влияет, он её диктует, а это значит, что отход от предложенного подхода будет немедленно караться. Проблема именно в этом.
Насчет "диктует" — абсолютно не согласен. Hibernate может быть адаптирован почти под любую архитектуру в своих рамках применимости (т.е. не совсем brain-damaged-схемы, не OLAP и т.п.), хотя он при этом, естественно, будет влиять на конкретные решения в коде.
Здравствуйте, IT, Вы писали:
IT>Ваня, это теория. Красивая сказка.
Угу, мне она нравится...
IT> Единственное что ты можешь сделать — это написать всё сам, но, надеюсь ты понимаешь, что при текущем состоянии дел в индустрии для более менее сложных задач это не реально.
Тут есть тонкий момент. Как раз для действительно сложных задачь это может быть и оправдано и реально. Не все конечно, но вещи типа ORM уж точно.
IT>Давай для примера возьмём не DAL, а UI. Как ты думаешь насколько реально выбрать в качестве UI библиотеки сначала Syncfusion, а потом передумать, открутить шурупчики и прикрутить Infragistic?
В принципе реально.
IT>Если у тебя есть сомнения, что абсолютно весь код, касающийся логики UI будет переписан, то можешь сам попробовать на досуге.
Логики UI — да, байндинг там всякий непосредственно к UI объектам и прочую муть.. Но вот всю остальную логику, в частности BL, можно попробовать оставить в непркосновенности, собственно об этом и речь. С Syncfusion и Infragistic не игрался, а вот WebForms и WinForms для одного приложения реализовать удалось.
IT>Так что проблема не в том, используются какие-либо библиотеки или нет. Проблема в том, как они влияют на архитектуру приложения.
Именно.
IT> В частности, хибернейт не просто влияет, он её диктует, а это значит, что отход от предложенного подхода будет немедленно караться. Проблема именно в этом.
Я об этом и говорю...
Здравствуйте, Cyberax, Вы писали:
C>Можно список проектов, желательно OpenSource?
Я опенсорсом не занимаюсь.. )
C>Я утверждаю, что если DAL заранее не проектировался для работы с несколькими видами источников данных, то DAO фиг чем помогут.
Причем здесь виды источников данных? Это уже другой вопрос...
Если же вернуться к теме обсждения то таки-да, DAL действительно надо проектировать так, чтобы его детали реализации наружу не торчали, собственно об этом я и толкую.
C>А безопасность тоже он обеспечивать будет? И транзакционные уровни изоляции?
Именно. Только он и никто иной. Еще мне транзакционные IL на бизнес-слое под ногами мешаться будут.
C>А без разницы.
Об чем и речь.
C>Например, взаимодействие с версированием объектов, с транзакциями, с конкуррентным использованием, безопасностью, возможностью нелокальной работы.
И что мешает убрать всю эту муть в DAL?
C>Так эти неявные связи все равно будут.
"Что я деляю не так?" =)
C> Если ты сегодня напишешь простой рабоче-крестьянский CRUDовый DAL, а завтра решишь использовать Hinernate — то скорее всего возникнут сюрпризы. Могу рассказать по своему опыту, если интересно.
Совершенно не интересно.. ) Во первых я не пишу CRUDовый DAL, во-вторых я не пользую гибернейт.. =)
C>В результате, для сортировки этого списка тебе может потребоваться примерно 30 удаленных вызовов. Так как для сравнения на равенство CORBA-объектов потребуется удаленный вызов.
Когда я вызываю Collection.Sort — там уже не CORBA, там обычные объекты, мои, простые и незатейливые. Они просто не умеют делать удаленных вызовов.
Здравствуйте, Cyberax, Вы писали:
C>Отсутствие у него параметра с транзакцией
Ну ты задачку-то под ответ не подгоняй, я тожетак умею.. )
C>А чем тебе объект с бизнес-транзакцией поможет в DAO, если через него нельзя получить DB-транзакцию?
Наоборот. На основе бизнес-транзакции я построю обычную.
Здравствуйте, Cyberax, Вы писали:
C>Насчет "диктует" — абсолютно не согласен. Hibernate может быть адаптирован почти под любую архитектуру в своих рамках применимости (т.е. не совсем brain-damaged-схемы, не OLAP и т.п.), хотя он при этом, естественно, будет влиять на конкретные решения в коде.
Хранилища объектов уже достаточно, чтобы до конца жизненного цикла приложения плясать под хибернейтовскую дудку.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
C>>Насчет "диктует" — абсолютно не согласен. Hibernate может быть адаптирован почти под любую архитектуру в своих рамках применимости (т.е. не совсем brain-damaged-схемы, не OLAP и т.п.), хотя он при этом, естественно, будет влиять на конкретные решения в коде. IT>Хранилища объектов уже достаточно, чтобы до конца жизненного цикла приложения плясать под хибернейтовскую дудку.
Эээ... А кто мешает тебе использтвать SQL вместе с Hibernate?
Например, у нас интерфейс с базой сделан на Hibernate, а аналитика и построение отчетов написана на SP + голый SQL.
Здравствуйте, IB, Вы писали:
IT>>Ваня, это теория. Красивая сказка. IB>Угу, мне она нравится...
Что-бы воплотить её в жизнь, нужно стараться, тратить на это время и ресурсы, специально подбирать инструменты и затачивать архитектуру. Бесплатно такая сказка не даётся.
IT>> Единственное что ты можешь сделать — это написать всё сам, но, надеюсь ты понимаешь, что при текущем состоянии дел в индустрии для более менее сложных задач это не реально. IB>Тут есть тонкий момент. Как раз для действительно сложных задачь это может быть и оправдано и реально. Не все конечно, но вещи типа ORM уж точно.
ORM сегодня уже вообще никого не должен волновать. Всё уже мильён раз жёвано пережёвано. А завтра, с выходом линка должен умереть прикладной DAL. А послезавтра за ним должен последовать и pass-through BL.
IT>>Давай для примера возьмём не DAL, а UI. Как ты думаешь насколько реально выбрать в качестве UI библиотеки сначала Syncfusion, а потом передумать, открутить шурупчики и прикрутить Infragistic? IB>В принципе реально.
В принципе нет. У этих библиотек абсолютно разный API.
IT>>Если у тебя есть сомнения, что абсолютно весь код, касающийся логики UI будет переписан, то можешь сам попробовать на досуге. IB>Логики UI — да, байндинг там всякий непосредственно к UI объектам и прочую муть..
Баиндинг как раз работать будет. Хотя, например, в том же вебовском GridView криворукие инудсы из майкрософт умудрились так напортачить, что без специальных подпорок кастомный баиндинг не работает.
IB>Но вот всю остальную логику, в частности BL, можно попробовать оставить в непркосновенности, собственно об этом и речь.
BL в большинстве приложений на 90% вообще должен умереть. Должна остаться модель данных, отображённая на БД и запросы к этой модели. В общем, что-то похожее на хибернейт, только развернуть эту избушку надо к лесу задом, а не так как сейчас.
IB>С Syncfusion и Infragistic не игрался, а вот WebForms и WinForms для одного приложения реализовать удалось.
Ты попробуй сначала, потом обсудим. Например, можно реализовать несколько связанных редактируемых гридов, с подсветкой некоторых ячеек в зависимости от данных в других полях.
IT>> В частности, хибернейт не просто влияет, он её диктует, а это значит, что отход от предложенного подхода будет немедленно караться. Проблема именно в этом. IB>Я об этом и говорю...
Это я понял. Я не согласен с тобой в том, что гвозди и библиотеки — это зло. От этого никуда не денешься.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Cyberax, Вы писали:
IT>>Хранилища объектов уже достаточно, чтобы до конца жизненного цикла приложения плясать под хибернейтовскую дудку. C>Эээ... А кто мешает тебе использтвать SQL вместе с Hibernate?
Боюсь, мы с тобой о разных вещах говорим. Тут кто-то упоминал то, что в хибернейт управлением жизнью объектов занимается он сам. Я говорю об этом.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
C>>Эээ... А кто мешает тебе использтвать SQL вместе с Hibernate? IT>Боюсь, мы с тобой о разных вещах говорим. Тут кто-то упоминал то, что в хибернейт управлением жизнью объектов занимается он сам. Я говорю об этом.
да, те объекты, которые вынимаются через hibernate query language, создаются самим hibernate'ом, и lazy-приколы оттуда и растут, что навигацию по графу привязанных объектов тоже обеспечивает hibernate, досоздавая при необходимости на лету объекты
а при прямом SQL, выдаваемом через hibernate можно как пользоваться custom-мэппингом на объекты (и тогда всё сводится к описанному), а можно самому брать сырые intы, stringи и иже с ними, не накладывая на hibernate никаких обязательств.
ps. ессно, наличие такой фичи имхо следует воспринимать как наличие спецподушки безопасности, что если вдруг так сложится, что что-то не ляжет по каким-то критериям (быстродействия, быстроприкручивания и т.п.) в стройную картину hibernate-подхода, то всегда остаётся возможность низкоуровневого доступа к данным (на свой риск получить трудноподдерживаемый код)
Здравствуйте, IT, Вы писали:
IT>>>Хранилища объектов уже достаточно, чтобы до конца жизненного цикла приложения плясать под хибернейтовскую дудку. C>>Эээ... А кто мешает тебе использтвать SQL вместе с Hibernate? IT>Боюсь, мы с тобой о разных вещах говорим. Тут кто-то упоминал то, что в хибернейт управлением жизнью объектов занимается он сам. Я говорю об этом.
Что ты понимаешь под "жизнью объектов"?
В Hibernate можно кастомизировать все этапы жизни — ты можешь загрузить объект руками через SQL и воткнуть его в сессию при желании, можешь выдирать объекты из сессии, обновлять и т.п.
Здравствуйте, IT, Вы писали:
IB>>Но вот всю остальную логику, в частности BL, можно попробовать оставить в непркосновенности, собственно об этом и речь. IT>BL в большинстве приложений на 90% вообще должен умереть. Должна остаться модель данных, отображённая на БД и запросы к этой модели. В общем, что-то похожее на хибернейт, только развернуть эту избушку надо к лесу задом, а не так как сейчас.
У меня примерно так большая часть приложения построена — толстый клиент работает почти непосредственно с моделью данных (естественно, учитывая ограничения безопасности) через мою библиотеку (которая позволяет использовать сами же Hibernate'овские бины в качестве DTO). На клиенте хранится рабочий граф объектов, который поддерживается в актуальном состоянии с помощью сообщений с сервера.
Причем 90% приложения построено на навигационном доступе, а так как у клиента свой локальный кэш — то обращений к серверу получается очень немного. Так что можно спокойно держать на одном не очень сильном сервере сотни клиентов.
Однако, слой бизнес-логики все равно в нормальном приложении присутствует. Так как приложения, которые просто работают интерфейсами к таблицам в базе, я вообще серьезными приложениями не считаю.
Здравствуйте, IB, Вы писали:
C>>Можно список проектов, желательно OpenSource? IB>Я опенсорсом не занимаюсь.. )
Сразу видно плохое влияние MS
C>>Я утверждаю, что если DAL заранее не проектировался для работы с несколькими видами источников данных, то DAO фиг чем помогут. IB>Причем здесь виды источников данных? Это уже другой вопрос...
Эээ... Как одним из доводов за использование DAO была возможность прозрачно использовать разные виды источники данных. Или я чего-то не понимаю?
IB>Если же вернуться к теме обсждения то таки-да, DAL действительно надо проектировать так, чтобы его детали реализации наружу не торчали, собственно об этом я и толкую.
"Наружу" это куда? На клиент — несомененно (кроме особых случаев). В вот бизнес-логику, ИМХО, смысла нет изолировать.
C>>А безопасность тоже он обеспечивать будет? И транзакционные уровни изоляции? IB>Именно. Только он и никто иной. Еще мне транзакционные IL на бизнес-слое под ногами мешаться будут.
?? То есть тебе в бизнес-слое пофиг на транзакции? А если для определенного алгоритма потребуется особый уровень изоляции?
C>>Например, взаимодействие с версированием объектов, с транзакциями, с конкуррентным использованием, безопасностью, возможностью нелокальной работы. IB>И что мешает убрать всю эту муть в DAL?
Так как в анекдоте — Hibernate получается.
C>>Так эти неявные связи все равно будут. IB>"Что я деляю не так?" =)
Не достаточно сильноразные источники используешь, видимо.
C>> Если ты сегодня напишешь простой рабоче-крестьянский CRUDовый DAL, а завтра решишь использовать Hinernate — то скорее всего возникнут сюрпризы. Могу рассказать по своему опыту, если интересно. IB>Совершенно не интересно.. ) Во первых я не пишу CRUDовый DAL, во-вторых я не пользую гибернейт.. =)
А что делаешь вместо CRUDа?
C>>В результате, для сортировки этого списка тебе может потребоваться примерно 30 удаленных вызовов. Так как для сравнения на равенство CORBA-объектов потребуется удаленный вызов. IB>Когда я вызываю Collection.Sort — там уже не CORBA, там обычные объекты, мои, простые и незатейливые. Они просто не умеют делать удаленных вызовов.
Почему уже обычные? DAO нам возвращает проксики на удаленные объекты. Или ты все переоборачиваешь в свои объекты? И что ты собираешься делать с зависимыми объектами?
Здравствуйте, IB, Вы писали:
C>>Отсутствие у него параметра с транзакцией IB>Ну ты задачку-то под ответ не подгоняй, я тожетак умею.. )
Ну так годы опыта во флеймах...
C>>А чем тебе объект с бизнес-транзакцией поможет в DAO, если через него нельзя получить DB-транзакцию? IB>Наоборот. На основе бизнес-транзакции я построю обычную.
То есть у тебя-таки бизнес-слой будет адаптирован для нетранзакционного DALа?
Здравствуйте, MaximVK, Вы писали:
C0s>>манипуляции данными обычно не так тривиальны, чтобы заморачиваться на dao, для простых операций типа получения по id достаточно возможностей, которые даёт hibernate-сессия, для сложных типа запросить сджойненные данные с хитрой фильтрацией — dao не помогает. MVK>Вот это я не понял. Можно пояснить на примере? Если тебе встретилась сложная логика, то здравый смысл должен подсказать тебе изолировать эту логику от другого кода, а это, для твоего случая, прямой путь к написанию dao.
да я бы сказал так, что если это метод БЛ, который просто реализует use-case фильтрованного просмотра группы каких-то объектов с целью нахождения нужного, то мне не интересно создать два метода, один их которых состоит из одной строки вызова другого
а если-таки возникает речь о локально повторно используемых запросах, то я скорее обойдусь выделением нескольких приватных методов. называть это уровнем у меня язык не поворачивается (см. пример ниже)
а если это будет какая-то супер сложная БЛ, то она будет базироваться на методах среднего уровня БЛ. к примеру, метод БЛ, реализующий use-case получения данных о клиенте getClientData напрямую используется из уровня представления для вывода детальной информации о клиенте, но также — в БЛ регистрации контракта для этого клиента и т.п.
C0s>>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо MVK>Если тебе плохо от тонны кода dao, то это проблема не dao, а того кто его писал.
сейчас из-за того, что это "типа модно — DAO-слоями программать", то уже есть поддержка визардами со стороны ide-писателей... вот то, что я видел — визардами сгенерено.
MVK> Первая и главная цель, для которой вводиться отдельный слой для работы с данными — это уменьшения сложности кода. Все остальные аргументы, то как: легко прикрутить новую базу, удобство тестирования, параллельная разработка и т.д. — вторичны и, как правило, являются дополнительным бонусом при стремлении к этой цели.
Что значит уменьшение сложности? Упрощенно, чем меньшим количеством абстракций/сущностей мне нужно оперировать при вычитывании некоторого фрагмента кода, тем ниже сложность этого кода. Если читая метод бизнес логики для расчета заработной платы сотрудника я должен думать о базе данных — это плохо. Это значит, что программист, который написал этот метод не смог изолировать логику работы с базой в отдельном методе(классе, слое). Это значит, что этот код больше подвержен ошибкам, т.к. жонглировать тремя апельсинами сложнее, чем двумя.
там нечего изолировать, т.к. скорее всего это будет выглядеть схематически (опуская try-catch и проч) так:
// метод среднеуровневой бизнес-логики, неявная демаркация транзакций (если еще не в контексте), скрытая инъекция ORM-сессии
public calcEmpSalary(empId : ID, date : timestamp) : numeric {
Emp emp = getSession().load(empId, Emp.class); // явный вызов ORM API
FinData finData = emp.getFinData(); // неявная работа ORM при навигации по графу
int normalWorkhoursCount = getWorkhoursCount(emp, date, false);
int extraWorkhoursCount = getWorkhoursCount(emp, date, true);
return calcSalary(finData, normalWorkhoursCount, extraWorkhoursCount); // вызов математического алгоритма
}
// вспомогательный метод, который по моему мнению не особо достоин отдельного класса, т.к. используется только в вышеприведенном методе
private getWorkhours(emp : Emp, date : timestamp, isExtra : boolean) : int {
String hql = // здесь построение текста запроса к данным о посещаемости за последний месяц до date
// с фильтром по обычным рабочим часам и по выходным (пример, как я бы обошёлся с повторно используемым запросом,
// который используется локально всего два раза)
return getSession().createFilter(emp.getPresenceData(), hql).bindParameter("date", date).bindParameter("isExtra", isExtra).exec();
}
вот непонятно мне, зачем реализовывая БЛ-метод calcEmpSalary что-то выделять еще куда-то. и так более-менее просто
Здравствуйте, MaximVK, Вы писали:
MVK>Из этого только следует, что не надо скрывать от уровня бизнес логики, что Method1 не поддерживает транзакцию.
и я говорю — не надо этого скрывать. но тому, кто вызывает этот метод и надо думать, что делать в ситуации сбоя. кто вызвал, тот и отвечает, а систем, где всё "само собой" разруливается, потому что внутри много хоттабычей я еще не видел
MVK>Вытаскивать всю логику работы с легаси системой и базой только с целью сообщить вызывающему коду о поддержке или неподдержке транзакций — как минимум очень странно.
я не говорил вытаскивать "много" или "всё". я лишь клоню к тому, что в руках у пишущего метод БЛ должны быть все инструменты для разруливания ситуации сбоя бизнес-транзакции
MVK>Самое простое решение для данного примера — сделать передачу транзакции явной.
явно или неявно — вообще не важно. в CORBA/JEE это делается неявно по вполне понятно работающим механизмам. на уровне чистой java это легко реализуется через threadLocal-переменные
важно как раз не заниматься написанием непомогающих обёрток Method1/Method2, а нормально в методе БЛ предусмотреть что-то типа
Legacy(); // что-то изменили в legacy-системе, знаем, что если остальные действия не выполнятся, нам надо постараться откатить и это
try {
globalTransaction.start();
try {
Native(); // присоединяет свою локальную транзакцию в глобальную, т.к. всё, что надо для транзакционности метод поддерживает
commit;
}
catch (SomethingStrange) {
globalTransaction.rollback();
}
finally {
// понятно, что от всех видов сбоев мы не уберегаемся, но хотя бы предохраняемся от самых мейнстримовых
if (globalTransaction.isRolledBack()) LegacyRollback();
}
я считаю, что лучше так, чем объяснять заказчику, что "мы не стали бороться со сбоями вообще, в угоду нашим представлениям о программировании, а также из-за общего пофигизма в ситуации, когда API к Legacy-системе не поддерживает транзакции"
Здравствуйте, IB, Вы писали:
C0s>> я пишу про DTO, ты же утверждаешь, что их вообще использовать не надо IB>Не, я утверждаю что в идеале то что ты называешь DTO это эквивалент BizEntity.
попробую погуглить насчёт этого термина, хотя в конечном итоге, не так важно, как назвать
IB>Хотя и сделать большинство из них immutable тоже не помешало бы.
если это типичные данные в таблицах, то далеко не по каждому полю можно сделать только getter.
при этом при извлечении данных для демонстрации на уровне презентации (не важно, будь то read-only page или форма для доплнения/изменения), должны передаваться данные только immutable, потому что их только визуализируют (вставляют в поля формы)
IB>Во. А я пишу про то, что объекты изначально должны быть простыми и никакая ORM не имеет право управлять их жизненным циклом или еще что-то с ними делать. (За что собственно и не люблю ORM)
моими DTO никакой ORM не управляет, они рождаются на уровне БЛ
Здравствуйте, IB, Вы писали:
IB>Внимание вопрос. Что мешает сделать поддержку транзакций в Method1, поверх вызова Legacy? Хотя бы тем способом, что предложил MaximVK? IB>И зачем эту, явно низкоуровневую логику тащить наверх?
см. ответ, который я дал на тот пост с предложением Maxim'аVK
Здравствуйте, IT, Вы писали:
IT>Так что проблема не в том, используются какие-либо библиотеки или нет. Проблема в том, как они влияют на архитектуру приложения. В частности, хибернейт не просто влияет, он её диктует, а это значит, что отход от предложенного подхода будет немедленно караться. Проблема именно в этом.
странно, что у меня такой проблемы нет. для меня hibernate — это инструмент реализации БЛ, связанной с необходимостью манипулировать и извлекать данные в БД.
выше БЛ (презентационному уровню, комманд-лайн утилитам выполнения ночных задач, методам интеграции с внешними системами) наличие hibernate не видно в принципе. все эти субстанции видят только БЛ-API и связаны с ним только через структуры данных, под это API написанные
Здравствуйте, C0s, Вы писали:
C0s>ps. ессно, наличие такой фичи имхо следует воспринимать как наличие спецподушки безопасности, что если вдруг так сложится, что что-то не ляжет по каким-то критериям (быстродействия, быстроприкручивания и т.п.) в стройную картину hibernate-подхода, то всегда остаётся возможность низкоуровневого доступа к данным (на свой риск получить трудноподдерживаемый код)
Т.е. фактически такая возможность является документированной дыркой в заборе, через которую можно туда сюда таскать неучтённые данные. Я правильно понимаю?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Cyberax, Вы писали:
C>В Hibernate можно кастомизировать все этапы жизни — ты можешь загрузить объект руками через SQL и воткнуть его в сессию при желании, можешь выдирать объекты из сессии, обновлять и т.п.
Дело в том, что мне вообще сессия не нужна. Я без неё прекрасно обхожусь. При этом что касается быстродействия, расширяемости, гибкости и простоты кода, то любой хибернейт уплачется самыми горючими слезами.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Cyberax, Вы писали:
C>Однако, слой бизнес-логики все равно в нормальном приложении присутствует. Так как приложения, которые просто работают интерфейсами к таблицам в базе, я вообще серьезными приложениями не считаю.
Это уже пенисометрия пошла. А если так, то я, например, считаю, что 80% логики в 80% "серьёзных" приложений являются результатом кривого дизайна, жестокого хардкода и затычек, необходимых для выкривления кривизны первого и второго.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Т.е. фактически такая возможность является документированной дыркой в заборе, через которую можно туда сюда таскать неучтённые данные. Я правильно понимаю?
это зависит только от способов управления и контроля за делами в проекте
ты же понимаешь, что чтобы написать хрень в коде никакую хоть сверхкрутую, хоть простую библиотеку брать не нужно — большинство платформ и так предоставляют достаточное количество встроенных инструментов, чтобы проявить себя во всей красе
Здравствуйте, C0s, Вы писали:
C0s>странно, что у меня такой проблемы нет. для меня hibernate — это инструмент реализации БЛ, связанной с необходимостью манипулировать и извлекать данные в БД. C0s>выше БЛ (презентационному уровню, комманд-лайн утилитам выполнения ночных задач, методам интеграции с внешними системами) наличие hibernate не видно в принципе. все эти субстанции видят только БЛ-API и связаны с ним только через структуры данных, под это API написанные
Это легко обоъясняется. Скорее всего ты хорошо знаком с хибернейтом и чётко следуешь его правилам при построении своей архитектуры. В резултате у вас получается полная идилия
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
C0s>>странно, что у меня такой проблемы нет. для меня hibernate — это инструмент реализации БЛ, связанной с необходимостью манипулировать и извлекать данные в БД. C0s>>выше БЛ (презентационному уровню, комманд-лайн утилитам выполнения ночных задач, методам интеграции с внешними системами) наличие hibernate не видно в принципе. все эти субстанции видят только БЛ-API и связаны с ним только через структуры данных, под это API написанные
IT>Это легко обоъясняется. Скорее всего ты хорошо знаком с хибернейтом и чётко следуешь его правилам при построении своей архитектуры. В резултате у вас получается полная идилия
если дать крен в философию, то можно сравнить с машиной. с одной стороны, чтобы ехать надо чётко понимать и следовать определенным законам, но с другой стороны — это всего лишь инструмент перемещения...
если же продолжать рассуждать о технической стороне подхода, то для меня гораздо менее важно, насколько я буду отвязан снизу уровня БЛ от ORM/БД/DAO/всё-что-угодно, и, наоборот, более важно зафиксировать интерфейсы и структуры данных БЛ, которые видны вышележащему слою.
Здравствуйте, IT, Вы писали:
C0s>>ps. ессно, наличие такой фичи имхо следует воспринимать как наличие спецподушки безопасности, что если вдруг так сложится, что что-то не ляжет по каким-то критериям (быстродействия, быстроприкручивания и т.п.) в стройную картину hibernate-подхода, то всегда остаётся возможность низкоуровневого доступа к данным (на свой риск получить трудноподдерживаемый код) IT>Т.е. фактически такая возможность является документированной дыркой в заборе, через которую можно туда сюда таскать неучтённые данные. Я правильно понимаю?
В Hibernate при желании можно вообще почти все переписать — там внутри архитектура построена на событиях. В частности, Google так и сделал для добавления поддержки горизонтального разделения данных.
Здравствуйте, IT, Вы писали:
C>>В Hibernate можно кастомизировать все этапы жизни — ты можешь загрузить объект руками через SQL и воткнуть его в сессию при желании, можешь выдирать объекты из сессии, обновлять и т.п. IT>Дело в том, что мне вообще сессия не нужна.
Эээ... А откуда у тебя будет соединение с БД браться? А сохранение идентичности у тебя поддерживается?
Кстати, в Hibernate есть легковесная сессия, которая фактически просто оборачивает соединение с БД и вообще не делает ничего лишнего.
IT>Я без неё прекрасно обхожусь. При этом что касается быстродействия, расширяемости, гибкости и простоты кода, то любой хибернейт уплачется самыми горючими слезами.
По сравнению с BL Toolkit? Прости, но Hibernate удобнее.
Здравствуйте, IT, Вы писали:
C>>Однако, слой бизнес-логики все равно в нормальном приложении присутствует. Так как приложения, которые просто работают интерфейсами к таблицам в базе, я вообще серьезными приложениями не считаю. IT>Это уже пенисометрия пошла.
Почему? Ну не считаю я простые интерфейсы к БД чем-то заслуживающим внимания. Да, они нужны, но мне абсолютно неинтересны — со времен Delphi тут уже все осовено.
IT>А если так, то я, например, считаю, что 80% логики в 80% "серьёзных" приложений являются результатом кривого дизайна, жестокого хардкода и затычек, необходимых для выкривления кривизны первого и второго.
Например, для бухгалтерии теперь вычисление зарплаты (с учетом overtime, праздников, отпусков, больничных) — это следствие кривизны, так как на модель данных плохо отображается?
Здравствуйте, Cyberax, Вы писали:
C>Эээ... А откуда у тебя будет соединение с БД браться?
Из кеша ADO.NET.
C>А сохранение идентичности у тебя поддерживается?
Это когда два разных запроса одних и тех же данных возвращают один и тот же объект? Я этими глупостями уже не занимаюсь. Такой дипазал, что в нём больше проблем, чем преимуществ.
C>Кстати, в Hibernate есть легковесная сессия, которая фактически просто оборачивает соединение с БД и вообще не делает ничего лишнего.
Ещё одна дырка в заборе?
IT>>Я без неё прекрасно обхожусь. При этом что касается быстродействия, расширяемости, гибкости и простоты кода, то любой хибернейт уплачется самыми горючими слезами. C>По сравнению с BL Toolkit? Прости, но Hibernate удобнее.
Да ради бога, я разве против Нравится, пользуйся. Не нравится, не пользуйся. По мне так ни то, ни другое не является идеалом. Cегодня вообще смотреть нужно в сторону dsl'ей.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Cyberax, Вы писали:
IT>>Это уже пенисометрия пошла. C>Почему?
Потому что при желании большинство задач можно свести к интерфейсу к БД, а можно любую самую простую реализовать кучей непонятно что и зачем делающего кода.
C>Ну не считаю я простые интерфейсы к БД чем-то заслуживающим внимания. Да, они нужны, но мне абсолютно неинтересны — со времен Delphi тут уже все осовено.
IT>>А если так, то я, например, считаю, что 80% логики в 80% "серьёзных" приложений являются результатом кривого дизайна, жестокого хардкода и затычек, необходимых для выкривления кривизны первого и второго. C>Например, для бухгалтерии теперь вычисление зарплаты (с учетом overtime, праздников, отпусков, больничных) — это следствие кривизны, так как на модель данных плохо отображается?
Есть много путей решения, всё зависит от требований. А вот ответь ты мне. Что насчёт ввода табеля, ввода праздников, отпусков и больничных, новых работников и изменения их параметров. Это уже не зарплата, или здесь у тебя тоже супер навороченная бизнес логика? А может это всё-таки те самые 80% любой задачи?
C>А еще есть BPM-системы — это тоже кривость?
К моему стыду, не знаю что это такое.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>>>Это уже пенисометрия пошла. C>>Почему? IT>Потому что при желании большинство задач можно свести к интерфейсу к БД, а можно любую самую простую реализовать кучей непонятно что и зачем делающего кода.
Я бы сказал, что при желании большинство задач можно на 80%-90% свести к интерфейсу с БД.
C>>Например, для бухгалтерии теперь вычисление зарплаты (с учетом overtime, праздников, отпусков, больничных) — это следствие кривизны, так как на модель данных плохо отображается? IT>Есть много путей решения, всё зависит от требований. А вот ответь ты мне. Что насчёт ввода табеля, ввода праздников, отпусков и больничных, новых работников и изменения их параметров. Это уже не зарплата, или здесь у тебя тоже супер навороченная бизнес логика? А может это всё-таки те самые 80% любой задачи?
Так я не возражаю. Я только говорю, что обычно эта часть не представляет особого интереса. Там все по большей части достаточно просто и вполне хватает средств, которые существуют уже лет 10.
C>>А еще есть BPM-системы — это тоже кривость? IT>К моему стыду, не знаю что это такое. http://en.wikipedia.org/wiki/Business_Process_Management
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>Здравствуйте, IT, Вы писали:
IT>>Cегодня вообще смотреть нужно в сторону dsl'ей.
ДГ>Можно ссылочку на "что это такое?" ДГ>Спасибо.
Здравствуйте, C0s, Вы писали:
C0s>моими DTO никакой ORM не управляет, они рождаются на уровне БЛ
Во. А я толкую о том, что рождаться они должны на уровне DAL ибольше ни во что не трансформироваться.
Здравствуйте, Cyberax, Вы писали:
C>Сразу видно плохое влияние MS
Что же в нем плохого?
C>Эээ... Как одним из доводов за использование DAO была возможность прозрачно использовать разные виды источники данных. Или я чего-то не понимаю?
Это не цель, это то, что получается само.
C>"Наружу" это куда? На клиент — несомененно (кроме особых случаев). В вот бизнес-логику, ИМХО, смысла нет изолировать.
Именно бизнес-логику и есть смысл изолировать. Собственно об этом и речь.
C>?? То есть тебе в бизнес-слое пофиг на транзакции?
На транзакции в терминах БД? Конечно пофиг.
C> А если для определенного алгоритма потребуется особый уровень изоляции?
Уровень изоляции — это забота DAL, для бизнес-слоя транзакция всегда должа быть Serializable, никаких особых уровней там быть не должно.
C>Так как в анекдоте — Hibernate получается.
Не получается, гибернейт все равно заставляет думать об источнике конкретного объекта и его зависимостях.
C>Не достаточно сильноразные источники используешь, видимо.
Мне хватает.. (
C>А что делаешь вместо CRUDа?
Пишу свой DAL под мои задачи.
C>Почему уже обычные?
Потому что я их такими сделал.
C>И что ты собираешься делать с зависимыми объектами?
Зависимыми от чего?
Здравствуйте, IT, Вы писали:
IT>Что-бы воплотить её в жизнь, нужно стараться, тратить на это время и ресурсы, специально подбирать инструменты и затачивать архитектуру. Бесплатно такая сказка не даётся.
Угу, но это уже другой вопрос.
IT>ORM сегодня уже вообще никого не должен волновать. Всё уже мильён раз жёвано пережёвано.
Меня-то он уже давно не волнует.. )
IT>В принципе нет. У этих библиотек абсолютно разный API.
Но мой-то код будет работать не с этим API, а с моим собственным, который будет транслировать все вызовы в API конкретной системы.
IT>BL в большинстве приложений на 90% вообще должен умереть. Должна остаться модель данных, отображённая на БД и запросы к этой модели. В общем, что-то похожее на хибернейт, только развернуть эту избушку надо к лесу задом, а не так как сейчас.
Велкам то Entity Framework и LINQ 2 Entity.. =)
IT>Ты попробуй сначала, потом обсудим.
Ну яж говорю, для веб и вин пробовал, тоже малопохожие конструкции, но получилось довольно не плохо...
IT>Это я понял. Я не согласен с тобой в том, что гвозди и библиотеки — это зло. От этого никуда не денешься.
Хорошо. Если ближе к теме — мне конкретно не нравятся гвозди гибернейта.
Здравствуйте, C0s, Вы писали:
C0s>я считаю, что лучше так, чем объяснять заказчику, что "мы не стали бороться со сбоями вообще, в угоду нашим представлениям о программировании, а также из-за общего пофигизма в ситуации, когда API к Legacy-системе не поддерживает транзакции"
Ну что опять за демагогия?
Разница в том, что в моем случае BL выглядит так:
begin_tran
Method1()
Method2()
commit
А в твоем :
if (Legacy1())
обрабатываем ситуацию с тем что L1 транзакцию не поддерживает
else if (Legacy2())
обрабатываем ситуацию с тем что L2 транзакцию поддерживает
но ни так как нам надо
else if (Native())
делаем просто вызов Native(), но опят-таки в явной транзакции
else — еще что-нибудь...
Я даже не буду подкалывать, что твой код якобы не заработает. Допустим, что и в том и в другом случае работать все будет одинаково... Только вот понять, чем собственно система занимается в конкретном случае и выкинуть обращение к легаси коду, когда он будет переписан, в первом случае, сдается мне, будет существенно проще.
Здравствуйте, Cyberax, Вы писали:
C>То есть у тебя-таки бизнес-слой будет адаптирован для нетранзакционного DALа?
Да ну нет же. Связь в обратную сторону развернута — DAL будет адаптироваться под нужды BL.
Здравствуйте, IB, Вы писали:
IT>>BL в большинстве приложений на 90% вообще должен умереть. Должна остаться модель данных, отображённая на БД и запросы к этой модели. В общем, что-то похожее на хибернейт, только развернуть эту избушку надо к лесу задом, а не так как сейчас. IB>Велкам то Entity Framework и LINQ 2 Entity.. =)
Ну да. Монстрик похлеще хибернейта.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Cyberax, Вы писали:
IT>>Потому что при желании большинство задач можно свести к интерфейсу к БД, а можно любую самую простую реализовать кучей непонятно что и зачем делающего кода. C>Я бы сказал, что при желании большинство задач можно на 80%-90% свести к интерфейсу с БД.
Можно и так.
C>Так я не возражаю. Я только говорю, что обычно эта часть не представляет особого интереса. Там все по большей части достаточно просто и вполне хватает средств, которые существуют уже лет 10.
Здравствуйте, IT, Вы писали:
C>>Так я не возражаю. Я только говорю, что обычно эта часть не представляет особого интереса. Там все по большей части достаточно просто и вполне хватает средств, которые существуют уже лет 10. IT>10 лет назад немеряно рулили двузвенки. Предлагаешь назад в будущее?
Вообще говоря, для непосредственного показа данных "псевдодвухзвенки" и сейчас рулят.
C>>http://en.wikipedia.org/wiki/Business_Process_Management IT>И какие у нас тут особенные проблемы?
Скажу так — без выделения сущностей (что-то тита ORM) там все очень плохо. Но это уже другой флейм.
Здравствуйте, C0s, Вы писали:
C0s>и я говорю — не надо этого скрывать. но тому, кто вызывает этот метод и надо думать, что делать в ситуации сбоя. кто вызвал, тот и отвечает, а систем, где всё "само собой" разруливается, потому что внутри много хоттабычей я еще не видел
Транзакции в базе данных — это "хоттабычи"? Ведь посуди сам, ты просто сказал rollback, а у тебя в базе "хоттабычи" автоматически удалили все записи, которые ты там вставлял в рамках транзакции.
C0s>я не говорил вытаскивать "много" или "всё". я лишь клоню к тому, что в руках у пишущего метод БЛ должны быть все инструменты для разруливания ситуации сбоя бизнес-транзакции
Эти инструменты и есть DAO классы. А что там внутри этих классов — ему знать не надо. В идеальном вариатне, DAO должен так изолировать legacy систему, что бизнес логика не должна заменить, когда, например, весь легаси перепишут в нэйтив.
C0s>явно или неявно — вообще не важно. в CORBA/JEE это делается неявно по вполне понятно работающим механизмам. на уровне чистой java это легко реализуется через threadLocal-переменные
Конечно можно через threadlocal. Я о другом говорю. Цель передачи транзакции явно — дать информацию коду бизнес логики, поддерживает ли этот метод транзакции. Это, конечно, "решение в лоб" и приведено исключительно в демонстративных целях. Тоже самое можно сделать через паттерн Command и методы DoMethod и UndoMethod. Можно использовать аннотации. Важно следующее, если одновременно есть методы, которые поддерживают транзакции и методы которые не поддерживают, то нужно придумать способ донести эту информацию до программистов, которые будут эти методы использовать. А если все методы поддерживают транзакции (например, весь DAL работает с только базой), то такой необходимости нет, это, так сказать, их свойство по умолчанию.
C0s>важно как раз не заниматься написанием непомогающих обёрток Method1/Method2, а нормально в методе БЛ предусмотреть что-то типа
Я посмотрел этот код. Очень запутанно. Собственно говоря Иван уже привел пример корректного кода. Замечу только, что метод LegacyRollback из твоего кода должен переместиться в DAO и там вызываться при откате транзакции. Задача бизнес логики сказать "Откатить!", а вот как откатить — это уже задача DAO. Кто-то скажет dbTransaction.Rollback(), а кто-то вызовет веб-серсис DeleteOrder(), т.к. это единственный способ "откатить" вызов сервиса CreateOrder(). Главное, что детали будут сокрыты в классах, которые знают все нюансы об источнике данных и изолировал эти знания от бизнес логики, предоставив ей простую и понятную абстракцию транзакционного метода.
Спасибо. Но ведь это какого размера и популярности должен быть Domain, чтобы для него Specific Language стали ваять? Да и помог бы тебе DSL упростить закачку многомегабайтных текстовых файлов в телекомовские базы? (Хех, и как именно, если не секрет? )
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>Спасибо. Но ведь это какого размера и популярности должен быть Domain, чтобы для него Specific Language стали ваять? Да и помог бы тебе DSL упростить закачку многомегабайтных текстовых файлов в телекомовские базы? (Хех, и как именно, если не секрет? )
Имхо у тебя изначальный предпосыл неверный — что кто-то за тебя должен этот DSL ваять. Подход, насколько я это понимаю, в основном следующий: работаешь в какой-то области, делаешь похожие вещи, но т.к. на универсальном языке, то слишком много там деталей, не относящихся к конкретной задаче, которые одинаковые в довольно большом классе задач. А DSL как раз и удаляет такие подробности, позволяет теме решать саму задачу.
Для загрузки есть ETL-решения, особо в них не разбираюсь. Но вроде как те же гуёвые тулзы, что там используются, есть некое подобие DSL.
(Кстати DSL не обязательно должен быть текстовым, хотя текст много гибче, конечно)
Здравствуйте, Курилка, Вы писали:
К>Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>>Спасибо. Но ведь это какого размера и популярности должен быть Domain, чтобы для него Specific Language стали ваять? Да и помог бы тебе DSL упростить закачку многомегабайтных текстовых файлов в телекомовские базы? (Хех, и как именно, если не секрет? )
К>Имхо у тебя изначальный предпосыл неверный — что кто-то за тебя должен этот DSL ваять.
Неправда! Я имел в виду, что далеко не всякую задачу можно упростить введением специального языка. Приведённый в вики пример BNF (yacc/bison) весьма специфичен, и под ним строгая математическая база. И вообще любой интерпретатор специального языка можно рассматривать как банальный data-driven код. Мне кажется, на таком уровне сложности управляющих данных data-driven подход имеет весьма ограниченное применение.
К>Подход, насколько я это понимаю, в основном следующий: работаешь в какой-то области, делаешь похожие вещи, но т.к. на универсальном языке, то слишком много там деталей, не относящихся к конкретной задаче, которые одинаковые в довольно большом классе задач. А DSL как раз и удаляет такие подробности, позволяет теме решать саму задачу.
В подавляющем большинстве случаев достаточно сделать абстрактный слой с соответствующим API. Вот например, IT упоминал DSL как альтернативу идеологии Hibernate (насколько я понял). Ну и где здесь, спрашивается, выгода? Быстродействие? Оно зависит от потрохов реализации, а не от выбора синтаксиса. Удобство? Что мешает прикрутить нужный синтаксический сахар к Хибернейту? В общем пока непонятно, где здесь концептуальный рывок.
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>В подавляющем большинстве случаев достаточно сделать абстрактный слой с соответствующим API. Вот например, IT упоминал DSL как альтернативу идеологии Hibernate (насколько я понял). Ну и где здесь, спрашивается, выгода? Быстродействие? Оно зависит от потрохов реализации, а не от выбора синтаксиса. Удобство? Что мешает прикрутить нужный синтаксический сахар к Хибернейту? В общем пока непонятно, где здесь концептуальный рывок.
По сути — API и есть DSL, правда как правило очень ограниченный, т.к. всёж ты продолжаешь работать в рамках того же самого языка и уровень абстракции получается несколько ниже.
По поводу хибернета и DSL — эт к IT, я лично не готов обсуждать разницу, если не понимаю толком, что сравнивается (если честно — не знаю соотв. DSL).
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>Спасибо. Но ведь это какого размера и популярности должен быть Domain, чтобы для него Specific Language стали ваять?
Хейлсберг с Боксом придумали целый Linq и встроили его в C#. Как ты думаешь, он будет популярным или нет?
ДГ>Да и помог бы тебе DSL упростить закачку многомегабайтных текстовых файлов в телекомовские базы? (Хех, и как именно, если не секрет? )
Мегобайты — фигня. Для закачки гигибайтных текстовых данных в телекомовские базы я в своё делал dsl на xml для описания структуры этих самых данных.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
ДГ>>Спасибо. Но ведь это какого размера и популярности должен быть Domain, чтобы для него Specific Language стали ваять?
IT>Хейлсберг с Боксом придумали целый Linq и встроили его в C#. Как ты думаешь, он будет популярным или нет?
На заметку я себе взял, посмотреть пока времени нет. Как-то не верится, что это Domain Specific. Или под Domain-ом имеется в виду persistence?
Здравствуйте, Дм.Григорьев, Вы писали:
ДГ>На заметку я себе взял, посмотреть пока времени нет. Как-то не верится, что это Domain Specific. Или под Domain-ом имеется в виду persistence?
Говоря о DSL я имел ввиду что не исключено, что для многих задач будет гораздо эффективнее сначала заточить под них инструмент, а уже потом быстренько наклепать на нём бизнес логику.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, MaximVK, Вы писали:
C0s>>и я говорю — не надо этого скрывать. но тому, кто вызывает этот метод и надо думать, что делать в ситуации сбоя. кто вызвал, тот и отвечает, а систем, где всё "само собой" разруливается, потому что внутри много хоттабычей я еще не видел MVK>Транзакции в базе данных — это "хоттабычи"? Ведь посуди сам, ты просто сказал rollback, а у тебя в базе "хоттабычи" автоматически удалили все записи, которые ты там вставлял в рамках транзакции.
когда речь идёт всего лишь об одной БД в рамках транзакции — да.
однако, обсуждается пример, когда транзакционных ресурсов несколько + один нетранзакционный (т.е. который по тем или иным причинам не встроен в механизм прозрачных глобальных транзакций)
C0s>>я не говорил вытаскивать "много" или "всё". я лишь клоню к тому, что в руках у пишущего метод БЛ должны быть все инструменты для разруливания ситуации сбоя бизнес-транзакции MVK>Эти инструменты и есть DAO классы. А что там внутри этих классов — ему знать не надо. В идеальном вариатне, DAO должен так изолировать legacy систему, что бизнес логика не должна заменить, когда, например, весь легаси перепишут в нэйтив.
в идеале это должен делать совсем не DAO.
в идеальном варианте должен быть написан некий адаптер (в терминах JEE, например, это был бы коннектор по спеке JSR-112), встраивающий систему в общий транзакционный механизм. тогда и код её использования будет простым и прозрачным, равно как и замена этой системы на другую, но работающую через аналогичный адаптер будет безболезненной. подчеркну, этот адаптер — совсем не DAO, а уровнем ниже.
C0s>>важно как раз не заниматься написанием непомогающих обёрток Method1/Method2, а нормально в методе БЛ предусмотреть что-то типа MVK>Я посмотрел этот код. Очень запутанно. Собственно говоря Иван уже привел пример корректного кода. Замечу только, что метод LegacyRollback из твоего кода должен переместиться в DAO и там вызываться при откате транзакции. Задача бизнес логики сказать "Откатить!", а вот как откатить — это уже задача DAO. Кто-то скажет dbTransaction.Rollback(), а кто-то вызовет веб-серсис DeleteOrder(), т.к. это единственный способ "откатить" вызов сервиса CreateOrder(). Главное, что детали будут сокрыты в классах, которые знают все нюансы об источнике данных и изолировал эти знания от бизнес логики, предоставив ей простую и понятную абстракцию транзакционного метода.
в неидеальном мире, однако, без поддержки на стороне самой легаси-системы встроить её нормально в транзакционный механизм не удастся.
опять же в идеальном мире, глобальные транзакции начинаются и заканчиваются неявно, в обсуждаемом примере явное управление транзакцией возникло только из-за того, что одна из систем не встраивается в транзакционный механизм. моё мнение в том, что слой DAO не уменьшает в таком случае непонятность, а, наоборот, размазывает непростой код по двум местам вместо одного
Здравствуйте, C0s, Вы писали:
C0s>если можно, то я задам встречный: а зачем вообще DAO? C0s>манипуляции данными обычно не так тривиальны, чтобы заморачиваться на dao, для простых операций типа получения по id достаточно возможностей, которые даёт hibernate-сессия, для сложных типа запросить сджойненные данные с хитрой фильтрацией — dao не помогает.
C0s>я в своих проектах dao не использую, сейчас для одного проекта попросили дописать фичу, я гляжу на тонну кода dao и мне становится плохо
Если вы не используете дао, то у вас вероятно достаточно маленькие проекты. Посмотрел бы я на вас, если бы вам пришлось мигрировать проект с хибернейта 2 на 3 в проекте без ДАО, в котором пару сотен персистент классов и несколько сотет различных запросов. Ну и до кучи в параллельном бранче, с которым вам потом нужно будет мерджиться, колбясят бизнес-логику. Был опыт...
Здравствуйте, Ушастый Ёж, Вы писали:
УЁ>Если вы не используете дао, то у вас вероятно достаточно маленькие проекты. Посмотрел бы я на вас, если бы вам пришлось мигрировать проект с хибернейта 2 на 3 в проекте без ДАО, в котором пару сотен персистент классов и несколько сотет различных запросов. Ну и до кучи в параллельном бранче, с которым вам потом нужно будет мерджиться, колбясят бизнес-логику. Был опыт...
Здравствуйте, Ушастый Ёж, Вы писали:
УЁ>Если вы не используете дао, то у вас вероятно достаточно маленькие проекты. Посмотрел бы я на вас, если бы вам пришлось мигрировать проект с хибернейта 2 на 3 в проекте без ДАО, в котором пару сотен персистент классов и несколько сотет различных запросов. Ну и до кучи в параллельном бранче, с которым вам потом нужно будет мерджиться, колбясят бизнес-логику. Был опыт...
не исключено, что и маленькие... в последнем хранимых данных наскреблось на десяток, т.к. там суть была не в данных БД
в другом сейчас посмотрел ради интереса — 102 хранимых класса, около 8 тыс. строк мэппинга (1700 тыс. xml-элементов) (написано было ещё на hibernate2), и при этом я до сих пор достаточно неплохо себе представляю, как именно я бы это мигрировал, если бы сейчас этим занялся бы
а в чём именно возникли проблемы у тебя при миграции?
мне вот кажется, что достаточно поменять имена пакетов и перепроверить реализацию custom types (на hibernate 3 мне с ними ещё не довелось работать, и я просто не знаю, что именно там могло изменится), а новые фичи меня ведь никто не заставит в мигрируемый код сразу забивать...
странный текст
автор начинает с неправильно сделанного примера, и демонстрирует как можно усложнить картину, не улучшив её... правильно мысль начинает работать только в конце:
In the next part, I will have a look at the Repository implementations while using an ORM framework like Hibernate. We do not need DAOs there, since the object graph will have transparent persistence functionality backed up by the ORM engine
Странно вы читали текст. Автор именно показал как улучшить неправильный пример.
C0s>странный текст C0s>автор начинает с неправильно сделанного примера, и демонстрирует как можно усложнить картину, не улучшив её... правильно мысль начинает работать только в конце: C0s>
C0s>In the next part, I will have a look at the Repository implementations while using an ORM framework like Hibernate. We do not need DAOs there, since the object graph will have transparent persistence functionality backed up by the ORM engine
А если читать внимательно, то в первом абзаце можно найти строки:
In the absence of an ORM framework, the DAO handles the impedance mismatch that a relational database has with OO techniques
Но к сожалению отсюда не следует, что при наличии ORM надо лепить работу с сессией в бизнес объектах. Очень часто, как заметил автор, репозиторий и дао сливаются в одно целое. И именно смесь дао и репозитория можно чаще всего встретить в проектах. И эта смесь лучше чем ничего, поскольку это первый шаг к разделению котлет от мух, к тому же шаг очень большой и вполне достаточный для решения массы проблем (я уже приводил примеры).
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Ушастый Ёж, Вы писали:
УЁ>>Если вы не используете дао, то у вас вероятно достаточно маленькие проекты. Посмотрел бы я на вас, если бы вам пришлось мигрировать проект с хибернейта 2 на 3 в проекте без ДАО, в котором пару сотен персистент классов и несколько сотет различных запросов. Ну и до кучи в параллельном бранче, с которым вам потом нужно будет мерджиться, колбясят бизнес-логику. Был опыт...
C0s>не исключено, что и маленькие... в последнем хранимых данных наскреблось на десяток, т.к. там суть была не в данных БД C0s>в другом сейчас посмотрел ради интереса — 102 хранимых класса, около 8 тыс. строк мэппинга (1700 тыс. xml-элементов) (написано было ещё на hibernate2), и при этом я до сих пор достаточно неплохо себе представляю, как именно я бы это мигрировал, если бы сейчас этим занялся бы
Ты работаешь в проекте один? Сколько еще времени ты будешь помнить что и как в персистенс-классах относится к работе с хибернейтом, а что в бизнес-логике? А что будет если в проекте работает 10 человек, или к тебе присоединится кто то еще?
C0s>а в чём именно возникли проблемы у тебя при миграции? C0s>мне вот кажется, что достаточно поменять имена пакетов и перепроверить реализацию custom types (на hibernate 3 мне с ними ещё не довелось работать, и я просто не знаю, что именно там могло изменится), а новые фичи меня ведь никто не заставит в мигрируемый код сразу забивать...
Все что теоретически нужно сделать описано в migration guide на официальном сайте хибернейта. Но на практике код оказывается неготовым к таким изменениям из-за множества side-effects, которые становятся актуальными из-за кривости существующего кода, работающего с хибернейт API. Описывать конкретные примеры мало интересно, поскольку они имеют смысл только в контексте общей архитектуры определнного проекта, но есть сильное чувство, что в любой архитектуре окажется масса своих косяков при миграции. Если конечно не нужны новые фичи, то миграция минимальна, но в этом случае и сама миграци нафиг не нужна...
Здравствуйте, Ушастый Ёж, Вы писали:
УЁ>Но к сожалению отсюда не следует, что при наличии ORM надо лепить работу с сессией в бизнес объектах. Очень часто, как заметил автор, репозиторий и дао сливаются в одно целое. И именно смесь дао и репозитория можно чаще всего встретить в проектах. И эта смесь лучше чем ничего, поскольку это первый шаг к разделению котлет от мух, к тому же шаг очень большой и вполне достаточный для решения массы проблем (я уже приводил примеры).
скажу проще, статья меня не убедила, т.к. в ней выбран плохой пример. сам факт того, что автор отталкивается от такого примера (а именно в доменной модели допускает манипуляции, т.е. смешивает данные и алгоритмы), для меня характеризует автора не с лучшей стороны.
а прячет он манипуляции в другой класс или нет — не важно, это второстепенный момент
Здравствуйте, Ушастый Ёж, Вы писали:
C0s>>не исключено, что и маленькие... в последнем хранимых данных наскреблось на десяток, т.к. там суть была не в данных БД C0s>>в другом сейчас посмотрел ради интереса — 102 хранимых класса, около 8 тыс. строк мэппинга (1700 тыс. xml-элементов) (написано было ещё на hibernate2), и при этом я до сих пор достаточно неплохо себе представляю, как именно я бы это мигрировал, если бы сейчас этим занялся бы
УЁ>Ты работаешь в проекте один? Сколько еще времени ты будешь помнить что и как в персистенс-классах относится к работе с хибернейтом, а что в бизнес-логике? А что будет если в проекте работает 10 человек, или к тебе присоединится кто то еще?
я помню детали проектов, в которых учавствовал 7 — 10 лет назад, что с того?
все последние проекты были больше, чем на одного, и я их делал не в одиночку
достаточно того, что просто никогда не допускался разброд, похожие вещи во каждом проекте либо удостаивались выделения в отдельные повторно используемые классы, либо за невозможностью оного просто делались одинаковым способом. это уже вопрос управления, как минимизировать вхождение нового человека, а не DAO/hibernate/другой библиотеки
УЁ>Все что теоретически нужно сделать описано в migration guide на официальном сайте хибернейта. Но на практике код оказывается неготовым к таким изменениям из-за множества side-effects, которые становятся актуальными из-за кривости существующего кода, работающего с хибернейт API. Описывать конкретные примеры мало интересно, поскольку они имеют смысл только в контексте общей архитектуры определнного проекта, но есть сильное чувство, что в любой архитектуре окажется масса своих косяков при миграции. Если конечно не нужны новые фичи, то миграция минимальна, но в этом случае и сама миграци нафиг не нужна...
с выделенным словом не совсем согласен, а вот с тем, что миграция ради миграции не нужна — да... и именно поэтому я не полезу проверять мигрируемость того, к чему я уже отношения имею мало... могу только добавить, что там не пришлось бы сначала долго мигрировать, а потом тестировать — всё было разбито по компонентам, и на первых двух-трёх компонентах удалось бы как набить возможных шишек, так и убедиться в отсутствии серьёзных препятствий, после чего остаток работы просто сводился бы к внимательности мигратора, а не хождению по граблям
Здравствуйте, Cyberax, Вы писали:
C>ИМХО, это абсолютная фантастика. Кроме DAO есть еще взаимодействие с сессией, включая всякие сохранения идентичности объектов и проксиков. Кроме того, объем кода моков для получается просто астрономический — проще использовать базу данных.
Почему же фантастика. Точно такая же схема используется и в нашем проекте для автоматического тестирование ServiceLayer. Все зависит от выбранных вами решений. BL\SL реалиизует бизнес логику обращаясь к различным DAO для получения данных причем как тут выше писали от BL скрыто где и как эти данные получается это могет быть DB, WebService, JMS итд. При таком подходе инстанциируется класс сервиса, вызывается соответствующий метод бизнес логики, при этом
мочатся(mock) все вызовы DAO нужными значениями. Манипулирую возвращаемыми значениями мы создаем нужное нам покрытие при автом. тестировании.
Здравствуйте, Ушастый Ёж, Вы писали:
УЁ>Все что теоретически нужно сделать описано в migration guide на официальном сайте хибернейта. Но на практике код оказывается неготовым к таким изменениям из-за множества side-effects, которые становятся актуальными из-за кривости существующего кода, работающего с хибернейт API. Описывать конкретные примеры мало интересно, поскольку они имеют смысл только в контексте общей архитектуры определнного проекта, но есть сильное чувство, что в любой архитектуре окажется масса своих косяков при миграции. Если конечно не нужны новые фичи, то миграция минимальна, но в этом случае и сама миграци нафиг не нужна...
Поддерживаю, был опыт миграции с Hibernate 2 на 3. И как обычно у нас бывает проект достался по наследству. Слава богу весь код работы с Hibernate был собран в DAO, 2\3 классов получилось модифицировать автозаменой. Там где использовались критерии и сложные условия — в ручную. Опять таки оценить объем работы легче, распределить по разработчикам — привсем при этом не в зуб ного в BL.
Ну и статейка Ни очем кроме пеара... Уж лучше на википедию ходить, там хоть без этого мусора...
Идеологом DSL является один из ведущих мировых экспертов в UML — Jochen Seeman. Рекомендую его блог: http://blogs.msdn.com/jochens/default.aspx. Там же вы найдете ссылки на блоги других членов команды разработки DSL.