Здравствуйте, 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.