Стоит ли отказываться от слоя DAO?

 
 
 
Сообщения:9894
Товарищ samolisov в своем блоге О спорном паттерне DAO считает что этот слой является пережитком прошлого и на самом деле практической ценности не несет. Предлагаю прочитать блог и обсудить этот вопрос здесь.
Изменен:28 сен 2014 06:36
 
 
Сообщения:7990
Имхо это вопрос субъективный.

Слой дао психологически ограничивает буйство пользователя в дёрганье базы из сервисов. Физически-то ничего не мешает сделать дао таким огромным и разветвлённым что мигрировать его на новую базу будет мучительно.

Плюс в статье про тестирование мало сказано. Когда я сервисы тестирую, я вызовы дао мокаю. А если я в жирном сервисном методе активно юзаю ентити-манажер... в общем неясно.

Кроме того находятся и люди которые чтоб не строить таких обёрточных сервисов дёргают дао из контроллеров (так что дао сами сервисами становятся как бы). Это то же самое в принципе что дёргать EntityManager из сервиса, только сервис будет называться DAO :)

Так что ответ по-моему "зависит от проекта, того как его пишут и личных предпочтений".

www.codeabbey.com - programming problems for novice coders (+ certificates)
 
 
Сообщения:586
Про тестирование согласен, этот момент не рассмотрел, но все аргументы в пользу DAO вконце концов и свелись к тестированию. Поэтому разумно задать два вопроса: есть ли в ваших приложениях сложная логика доступа к данным (только доступа к данным, может быть какие-то запросы навороченные) и как часто вы пишите модульные тесты для ее проверки?
 
 
Сообщения:7990
Дао я вообще предпочитаю не тестировать, хотя любители есть, да :)

Главное что, имхо, в том или ином виде этот слой формируется само собой обычно в проектах - между бизнес-логикой и базой - никто ж не хочет SQL/JPQL в логике видеть... Но необязательно при этом называется DAO.

Так что для меня главный вопрос скорее в том нужен ли дополнительный слой для простых методов (типа getById или save).

www.codeabbey.com - programming problems for novice coders (+ certificates)
 
 
Сообщения:586
RodionGork:
нужен ли дополнительный слой для простых методов (типа getById или save).

Разработчики Spring Framework еще в своих древних книгах (2002-й год) советовали при ненужности транзакции вызывать из контроллера сразу соответствующий метод DAO, т.е. делать в сервисе дубль getById() не нужно, можно в контроллере обратиться сразу к DAO, а вот для save() придется написать метод в сервисе, как минимум оборачивающий вызов в транзакцию. Но это в каком-то смысле отход от слоистой архитектуры, т.к. теперь слой представления может обращаться к слою хранения, минуя слой бизнес-логики.
Изменен:25 сен 2014 11:36
 
 
Сообщения:189
samolisov:
RodionGork:
нужен ли дополнительный слой для простых методов (типа getById или save).

Разработчики Spring Framework еще в своих древних книгах (2002-й год) советовали при ненужности транзакции вызывать из контроллера сразу соответствующий метод DAO, т.е. делать в сервисе дубль getById() не нужно, можно в контроллере обратиться сразу к DAO, а вот для save() придется написать метод в сервисе, как минимум оборачивающий вызов в транзакцию. Но это в каком-то смысле отход от слоистой архитектуры, т.к. теперь слой представления может обращаться к слою хранения, минуя слой бизнес-логики.
А как поступать с транзакциями, если убрать слой сервисов? Делать в DAO, два метода сохранить с транзакцией и без?
 
 
Сообщения:586
oleg_v_:
А как поступать с транзакциями, если убрать слой сервисов?

Мы обсуждаем удаление слоя DAO, а не сервисов. На слой сервисов не покушаемся :)

Впрочем, если у вас в приложении только CRUD без какой-то сложной логики, то тогда DAO и может стать таким "сервисом", нужно только правильно аннотировать его методы таким образом, чтобы часть выполнялась в транзакциях (save, update, delete), а часть - вне транзакций (get***).
 
 
Сообщения:2398
Мы вроде уже обсуждали тут эту проблему год назад.
Кому как, но мне со слоем DAO проще
- тестировать бизнес-слой,
- добавлять слой кеширования
- добавлять репликации (распределение данных по кластеру, оптимизация хранения по нодам и т.п.)
В моей практике было несколько случаев, когда наличие слоя неплохо упростило работы по замене JPA на обычный JDBC (увы, но у JPA есть свои лимиты по оптимизации).

samolisov:
Про тестирование согласен, этот момент не рассмотрел, но все аргументы в пользу DAO вконце концов и свелись к тестированию. Поэтому разумно задать два вопроса: есть ли в ваших приложениях сложная логика доступа к данным (только доступа к данным, может быть какие-то запросы навороченные) и как часто вы пишите модульные тесты для ее проверки?

1) сложная логика доступа к данным начинается уже когда надо сохранить объекты, раскиданные по 2-3 таблицам и необходимо применять каскадирование дочерних коллекций. Метод save() сразу же становится нетривиальным, а JPA начинает ругаться на попытки сохранить detached instance.
2) Всегда. Пишешь раз и забываешь про этот слой навсегда (в идеале). Или не пишешь и потом ловишь баги по всему приложению :)

Изменен:26 сен 2014 02:10
 
 
Сообщения:9894
Я полагаю что мы не рассматриваем случай когда у нас одновременно две реализаций DAO потому как в таком случае необходимость в DAO трудно отрицать. Соответственно сводим наш случай до одной реализации DAO с гипотетической возможностью перевести приложение на другую реализацию.
Из статьи:
Поддержка конструкции "интерфейс сервиса - сервис - интерфейс DAO - одна или несколько реализаций DAO" довольно утомительна. Чтобы добавить новую операцию в сервис, в общем случае необходимо сделать следующее:
Добавить метод в интерфейс сервиса.
Добавить метод в реализацию сервиса.
Добавить метод в интерфейс DAO.
Добавить метод в одну или несколько реализаций DAO.
Добавлять в этот список интерфейс для сервисов - неправильно, он ведь будет (или его не будет) независимо от DAO. На самом деле и интерфейс для DAO совсем не обязательно заводить сразу. Мы бы могли его создавать только тогда когда/если необходим непосредственный переход с одной реализации на другую. С современными возможностями рефакторинга в IDE это не составит больших проблем. Будем следовать KISS/YAGNI, за сим предлагаю список сократить до:
- Добавить метод в реализацию сервиса.
- Добавить метод в реализацию DAO.
Т.е. в случае DAO у нас +1 одно место обновляется. Что уже не так плохо.

RodionGork:
никто ж не хочет SQL/JPQL в логике видеть
Если помещаем SQL в отдельные методы специально для SQL, то он и не будет фигурировать. Т.е. хотя бы на уровне методов можно избежать перемешки. Тем не менее на уровне класса будет непонятно где метод с sql, а где с предметной логикой. Что не так уж и критично на самом деле.

Но в общем-то все равно с DAO будет удобней - сервисы и так часто переполнены логикой, не хватало там еще работы с БД.
samolisov:
есть ли в ваших приложениях сложная логика доступа к данным (только доступа к данным, может быть какие-то запросы навороченные) и как часто вы пишите модульные тесты для ее проверки?
Сервис можно не протестировать, контроллер можно не покрыть, но уровень доступа к БД оставить без внимания нельзя. Это наверно самые полезные в плане нахождения багов и ускорения работы тесты.
Из статьи:
Переключение между ORM и JDBC. ORM-фреймворки, в отличие от JDBC реализуют прозрачное хранение (т.н. transparent persistence). Если после загрузки объекта в сессию обратиться к его сеттерам, то после синхронизации сессии с базой данных эти изменения будут отражены в ней. При использовании же JDBC такой прозрачности нет, поэтому любые изменения необходимо явно синхронизировать с базой данных посредством вызова соответствующих методов DAO, а значит требуется добавить обращение к этим методами в слой бизнес-логики, т.к. ранее, при использовании ORM, они отсутствовали.
Еще один повод делать прозрачное сохранение данных даже в случае с ORM. На одно отличие с JDBC меньше.

Плюс - вариант перехода с ORM на JDBC более вероятен (а он намного проще), потому как недостатки ORM на первых порах не являются критичными в отличие от его плюсов (скорости разработки). А потооом, когда будем больше работать над NFR, тогда уже и может понадобиться переход на JDBC - при этом JDBC & ORM будут очень долго сосуществовать.

Поэтому я тоже пока не нахожу плюсов в том чтоб отказываться от DAO. В начале разработки конечно можно быть и по-проще, хоть в контроллерах все оставлять, главное - по-быстрей иметь что-то работоспособное. Но если проект будет продолжать развиваться долго, то выделение Services/DAO как-то само собой подразумевается. Просто легче станет понимать код, все будет по полочкам - логика тут, БД там, веб сям.
Изменен:25 сен 2014 22:28
 
 
Сообщения:586
Quote:
Еще один повод делать прозрачное сохранение данных даже в случае с ORM. На одно отличие с JDBC меньше.

Наверное имелось ввиду не делать прозрачное сохранение данных в случае с ORM, потому что jdbc его не умеет, а orm - наоборот умеет.

На мой взгляд это нелогичный подход - отказываться от основного преимущества orm из-за гипотетической ситуации "ну а вдруг захотим изменить". В принципе это вопрос построения архитектуры приложения и компетенций архитектора: мы думали бомба будет мощностью 5 килотонн, а она как ...ла - это как-то неправильно. Есть требования к нагрузке, есть ограничения по железу и срокам - твори нетленку, а если промахнулся и выбрал неверную технологию, то конечно это мудро с точки зрения карьеры подложить себе соломку в виде "откажусь от основных возможностей, зато потом на jdbc перейду легко", но с точки зрения подставы компании на трудозатраты на разработку это как-то непрофессионально что-ли. В конце концов, если есть понимание, что вот здесь узкое место, то почему бы его сразу на jdbc не реализовать? Впрочем, оверхед, вносимый орм, зачастую преувеличивается, уверен, что многие, говорящие о "сейчас тут дао перепишу на jdbc и у меня все залетает" даже планы запросов не смотрели, просто есть стереотип - орм - медленно, jdbc - быстро. У нас коллеги мигрировали мощный банковский портал на zEnterprise EC12 (мейнфрейм), связка Open JPA + DB2 + JSF (!) держит 8000 конкурентных сессий, приложение - что-то вроде онлайн-банка.
 
 
Сообщения:9894
samolisov:
На мой взгляд это нелогичный подход - отказываться от основного преимущества orm из-за гипотетической ситуации "ну а вдруг захотим изменить".
Просто заканчивай каждую транзакцию на XxxDao#saveOrUpdate() - никаких затрат на реализацию. И уж считать само-сохранение сущностей главной фичей ORM я бы постеснялся. Я бы ее даже важной фичей не назвал, это больше даже побочный эффект. Есть вон ORM'ы попроще типа MyBatis которые не управляют жизненным циклом сущностей, так что я бы трагедию из этого не делал.
samolisov:
Впрочем, оверхед, вносимый орм, зачастую преувеличивается, уверен, что многие, говорящие о "сейчас тут дао перепишу на jdbc и у меня все залетает" даже планы запросов не смотрели, просто есть стереотип - орм - медленно, jdbc - быстро
Дык никто и не говорит что каждое приложение переписывается с ORM на JDBC. Просто вероятность того что это произойдет выше, чем переписывание с JDBC на ORM (вот такой переход был бы скорей всего страшным геморроем).
 
 
Сообщения:586
Вопрос скорее в отношении, на мой взгляд понимание прозрачного сохранения (transparent persistence) - ключ к эффективному и грамотному использованию ORM. Причем под ORM я понимаю прежде всего провайдеры JPA, образец - Hibernate, не потому что он самый лучший, скорее - самый распространенный. Да и в большинстве проектов под ORM понимают прежде всего Hibernate нежели MyBatis. Можем провести опрос. Переписать что-то с MyBatis на JDBC действительно просто, но зачем?
 
 
Сообщения:284
прочитал статью.

Мои 5 копеек. С DAO код понимается проще и вход в рабочий проект ниже. Дается большее чувство свободы по управлению данными, хотя зачастую и ложное.
+ То же тестирование на уровне DAO убережет от разбора ошибок БД в тестах в сервисном слое.
И если затрагивать spring, то его разработчики предложили неплохой компромисс - spring data.

С другой стороны согласен с Павлом, что для большинства проектов смысла в DAO нет никакого, избыточный код и новый слой будут лишними.
 
 
Сообщения:43
Вот не понимаю почему нельзя запилить какой-нибудь мега редактор по типу 1с который бы генерил 99% дао?
 
 
Сообщения:586
В продукте конкурентов такой есть. В Oracle SOA Suite/Oracle Service Bus есть DBAdapter, который настраивается с помощью мастера, несколько кликов мышки и вы получаете веб-сервис, который может делать insert/upset/update/delete/select одной или нескольких, связанных или нет записей. Так же можно настроить полинг и наоборт, ваш сервис будет вызываться при добавлении записи в БД. В основе лежит JPA, работает на WebLogic и WebSphere AS. Остается только отправлять или принимать XML, схему которого данный мастер вам сгенерирует.
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет