Здравствуйте, 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>Т.е. фактически такая возможность является документированной дыркой в заборе, через которую можно туда сюда таскать неучтённые данные. Я правильно понимаю?
это зависит только от способов управления и контроля за делами в проекте
ты же понимаешь, что чтобы написать хрень в коде никакую хоть сверхкрутую, хоть простую библиотеку брать не нужно — большинство платформ и так предоставляют достаточное количество встроенных инструментов, чтобы проявить себя во всей красе