LINUX.ORG.RU

Java, IoC, Spring

 , ,


1

1

Всем привет, очередной вопрос назрел.
Начал изучать паттерны javaEE, делаю тестовый проект на Spring/Hibernate. Как я понимаю - основная фишка Спринга это именно IoC, то бишь избавление от зависимости на конкретную реализацию доступа к модели - DAO (верно?).
Также вводится понятие сервиса, которые работают с реализацией DAO..

Вобщем, у меня взрывается моск от таких дел, ведь получается, на одну модель Device имеем ещё 5 классов:

DeviceDAO
DeviceDaoImpl
DeviceService
DeviceServiceImpl
DeviceViewModel

Не жирно ли? Или я чего-то не допонимаю, но зачем еще и интерфейс для сервиса, есть ведь уже для DAO? Вообще, в каких случаях стоит всё это городить, если не предвидится нужды менять способ доступа к модели?

Короче, не могу разложить по полочкам.. Спасибо.

★★

Ну просто считается, что если огородить приложение интерфейсами, то оно будет гибкое и удобное (и это правда). Не хочешь - не делай интерфейсы.
Что касается IoC - он по сути никак не связан с DAO'шками и т.п. Это просто design pattern. А уж где и как его применять - это уже твое дело.

kovrik ★★★★★ ()

Тут же enterprise во все поля.
Логика какая: есть некая сущность. Чтобы привязать ее (модель) к базе - нужна DAOшка. Чтобы эта штука была гибкой - делаем отдельный интерфейс.
Отдельно есть бизнес-логика. Для ее реализации нужна работа с моделями. Но не напрямую, а через сервисы (Модель - это просто модель. Бизнес логику она не должна содержать. Мухи отдельно, котлеты отдельно). Ну, а сервисам для гибкости тоже добавляется интерфейс.

Т.е. получается что-то вроде:

[DB] <--> [DAO] <--> [Service] <--> [Business logic]

А прослойками служат интерфейсы.

kovrik ★★★★★ ()

Сам Device забыл )

Часть того что ты написал - интерфейсы. Сейчас, это подход, который становится более популярным, люди просто меньше парятся с интерфейсами. Вместо изоляции за интерфейсом, люди напрямую инжектят класс. Ведь с помощью public/private у тебя уже есть нечто похожее на интерфейс, зачем дублировать? В целом более убежденные в этом подходе люди считают наличие *Impl классов - антипаттерном.

Например хорошо:

1) class DeviceDao

2) interface DeviceDao, class BlockDeviceDao, class StreamDeviceDao

Плохо:

1) interface DeviceDao, class DeviceDaoImpl

2) interface DeviceDao, class DefaultDeviceDao

Проблем с неинтерфейсным кодингом особенно нет.

1) Мокинг будет работать генерацией подкласса этого класса, сейчас фреймворки это умеют

2) Средства разработки сильны в рефакторинге, потому ввести интерфейс будет очень просто, буквально по всему коду проекта.

Интерфейсы нужены для публичного стабильного API, на него будут зависеть бинарно пользователи, и тут ничего не придумаешь. Если будет торчать класс - будет плохо

vertexua ★★★☆☆ ()
Ответ на: комментарий от vertexua

Интерфейсы нужены для публичного стабильного API, на него будут зависеть бинарно пользователи, и тут ничего не придумаешь. Если будет торчать класс - будет плохо

+1
все зависит от твоего приложения.
Если куча модулей и/или плотно взаимодействует с другими частями системы/другими системами, то юзай интерфейсы.
Если у тебя приложение само в себе, то тут думай по ситуации. Если смысла в интерфейсе не видишь - не делай.

kovrik ★★★★★ ()

Спасибо всем, очень грамотно разъяснили :)
Так я и представлял это, но казалось как-то дико столько интерфейсов городить. В моём случае чисто веб-приложение, вроде как само в себе, так что постараюсь интерфейсов по минимуму.

POLTER ★★ ()

Если у интерфейса планируется ровно одна реализация (DeviceService/DeviceServiceImpl), то никакого смысла в интерфейсе нет, это лишний код.

DAO работает с базой на уровне отдельных запросов. В случае использования Hibernate по сути весь DAO в нём реализован и делать отдельный класс, каждый метод в котором будет однострочным методом-редиректом в хибернейт смыла нет. Если JDBC используешь, то смысл имеет.

Service работает на уровне транзакций и вызывает некоторое множество DAO операций как одну транзакцию. На этом уровне пишутся @Transactional. Для несложных приложений в этом уровне тоже большого смысла нет, т.к. там все методы будут однострочные, просто пиши этот код в контролере и не парься.

Но при большом желании можно создать по 5 классов на каждый чих, с помощью IDE это не сложно и ничего страшного в этом в общем то не будет, только кучка читабельного синтаксического мусора.

Legioner ★★★★★ ()
Ответ на: комментарий от Legioner

Ясно, ну примерно так и обстоит дело, интерфейсы не нужны. А вообще нужно ли тогда заморачиваться со Spring ну и вообще с IoC? Сейчас я для теста на чистом Hibernate + zk Framework сделал небольшое приложение, ну и вроде все ок.. Но потом почитал про все эти паттерны и задумался)

POLTER ★★ ()
Ответ на: комментарий от POLTER

IoC это очень правильный принцип. Использовать его надо, я не знаю вменяемых альтернатив.

Конкретно Spring - на вкус и цвет. Если от него кроме IoC больше ничего не нужно, есть легковесные альтернативы, Google Guice например. В Spring очень много полезного помимо IoC - Spring MVC, например.

Legioner ★★★★★ ()
Ответ на: комментарий от POLTER

Если приложение гарантированно не будет расти - то можно и не заморачиваться со спрингом. Если возможно развитие и усложнение логики, то учше сразу делать более-менее правильно с точки зрения архитектуры. Ну и да, спринг это дажеко не только IoC. Там и mvc/rest есть и security и AOP и spring-data-repository и дофига чего еще (типа тех=же оберток над jms или jmx, позволяющих в разы легче все это барахло использовать). Причем все это гарантированно друг с другом интегрированно и нормально взаимодействует.

Nagwal ★★★★ ()
Ответ на: комментарий от Legioner

это с помощью какой IDE и как именно несложно генерить этот шлак? Генерить надо.

stevejobs ★★★☆☆ ()
Ответ на: комментарий от stevejobs

Ну накидал интерфейс. Создал класс, написал «implements Bla», дал команду «implement methods», ОК. Заготовки для методов готовы, пиши реализацию. Eclipse и Idea такое умеют, думаю всё остальное тоже умеет.

Legioner ★★★★★ ()
Ответ на: комментарий от Legioner

Эхъ, я пишу не от архитектуры, а наоборот - от тестов/консоли/репла, архитектура сама выводится. Если выводится. Но иногда не выводится, и поэтому нужно сгенерить тонну архитектурного буллшита по готовому компактному работающему коду. Метода быстрой автоматизации этого я пока не придумал :( Есть тот же extract interface / supercalass, но это долго и много думать, т.к. кода, который не следует ни из чего оно вывести не может.

stevejobs ★★★☆☆ ()

Интерфейсы нужны как минимум для самодокументирования. Иметь отдельно описание контракта довольно удобно. В типичных сервисах обычно с десяток методов, обьем самого сервиса довольно большой. А когда нужно изучить код сервиса, очень удобно начать с изучения интерфейса - все методы перед глазами в одном месте, сгруппированные по смыслу и откомментированные по надобности.

Что касается количества слоев, то я придерживаюсь не строгого layering. Если я могу сделать все что мне нужно через DAO, то городить сервис, который только и делает, что проксирует запросы к DAO я не буду.

dizza ★★★★★ ()
Ответ на: комментарий от Legioner

В случае использования Hibernate по сути весь DAO

Юзать напрямую хибернейт не айс - API там сырой. Нужен некий GenericDao, который имеет хелперные методы. Что-то врде HibernateTemplate из спринга.

dizza ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.