Модераторы: LSD
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> IoC: правила применения 
:(
    Опции темы
Vitaly333
Дата 5.8.2011, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 6.11.2006
Где: Volgograd

Репутация: нет
Всего: 2



Хочу отрефакторить ###код в своем проекте. Хочу использовать IoC - паттерн. Никогда его не применял, поэтому есть вопросы:
В каких случаях требуется инжектировать зависимости а в каких нет? Если инжектировать все зависимости в каждом классе то тоже ничего хорошего не выйдет.  Должна быть золотая середина. Есть какое-нибудь правило которым вы пользуетесь? Например, инжектируем только те зависимости которые могут быть изменены (подставлена другая реализация или мок) а те, для которых я точно знаю что они не изменятся я не трогаю.
 
PM MAIL   Вверх
batigoal
Дата 5.8.2011, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: нет
Всего: 151



Цитата(Vitaly333 @  5.8.2011,  23:58 Найти цитируемый пост)
Если инжектировать все зависимости в каждом классе то тоже ничего хорошего не выйдет.  Должна быть золотая середина.

Ну вот золотая середина тут лежит сильно ближе к той стороне, где "инжектятся все зависимости" smile

По большому счету, я стараюсь инжектить всё, кроме создания энтити-экземпляров, да и то - если они создаются напрямую. а не через какую-нибудь фабрику. Даже статические коллекции стараюсь инжектить Спрингом и описывать в XML. 
Если ты будешь использовать IoC-контейнер (Spring, Google Guice, JavaEE-шный движок, etc), то никаких проблем тут нет. Если же его не использовать, тогда попросту слишком много тупого кода нужно будет писать ради инжекта.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Vitaly333
Дата 6.8.2011, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 6.11.2006
Где: Volgograd

Репутация: нет
Всего: 2



Цитата

то никаких проблем тут нет

Представляю какого размера будет конфигурационный-xml в том же Спринге, если у тебя >500 классов и почти каждый описан в нем.

Цитата

Если же его не использовать, тогда попросту слишком много тупого кода нужно будет писать ради инжекта. 

А как можно его не использовать если ты хочешь писать инжектируемый код? И что это будет за "тупой" код? Фабрики ты имеешь ввиду?
PM MAIL   Вверх
Старовъръ
Дата 6.8.2011, 00:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.5.2008

Репутация: 2
Всего: 10



Правильные вопросы задаешь, люблю когда люди сначала идут от теории smile
Как правило следует инжектить все, что кнфигурируется. Например, у нас есть ДАО, который нужно передать в класс бизнес логики. Это пример зависимости, которую следует инжектить. Допустим в уровне сервисов мы трансформируем объекты одного класса в другой, причем конвертер никак не конфигурируется, его просто нужно создать и все. Это пример зависимости, которую нужно не ижектить, а создавать внутри самого класса. Правда затем нужно будет протестировать как-то этот сервис, что значит, что возможность инжектить все-таки должна быть, просто ее не следует использовать в production-коде (можно вместо этого использовать Отражение для установки мока на место поля). 
То есть в большинстве случаев инжектить следует только то, что конфигурируется на глобальном уровне. Иначе будет достаточно сложно как работать с контекстами, так и "бродить" по коду. Ну и объекты, которые нужны нескольким бинам, также логично помещать в контекст.
PM MAIL WWW   Вверх
Stolzen
Дата 6.8.2011, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1041
Регистрация: 17.10.2005

Репутация: 2
Всего: 48



Цитата(batigoal @  6.8.2011,  00:34 Найти цитируемый пост)
Если же его не использовать, тогда попросту слишком много тупого кода нужно будет писать ради инжекта. 

setXXX()  smile 
И выделить отдельный класс-сборщик, который будет создавать, инжектить зависимости и отдавать клиенту интерфейс. 

Инжектить можно тогда, когда встает вопрос о соблюдении SRP (Single responsibility principle). Если класс начинает выполнять более одной работы, то желательно новую функциональность выделить в отдельный класс и делегировать выполнение этих операций новому классу (или интерфейсу + его реализацию инжектить).

Плюсы - код чище, проще покрыть тестами (например мокнуть зависимость и заинжектить ее).

Это сообщение отредактировал(а) Stolzen - 6.8.2011, 08:15


--------------------
datatalks.ru - анализ данных, статистика, машинное обучение
PM MAIL WWW   Вверх
Старовъръ
Дата 6.8.2011, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.5.2008

Репутация: 2
Всего: 10



Цитата
И выделить отдельный класс-сборщик, который будет создавать, инжектить зависимости и отдавать клиенту интерфейс.
В таком случае класс-сборщик и будет IoC-контейнером. 
Кстати, чтоб не было недопониманий: как Фабрики, так и IoC-контейнеры - это все Inversion of Control. Если хочется говорить конкретно об IoC-контейнерах, то лучше применять термин Dependency Injection (DI).
ТС, почитай/посмотри про принципы объектно-ориентированного проектирования (OOD Principles), они смогут помочь когда станет вопрос "а как лучше":
PM MAIL WWW   Вверх
batigoal
Дата 7.8.2011, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: нет
Всего: 151



Цитата(Vitaly333 @  6.8.2011,  01:00 Найти цитируемый пост)
Представляю какого размера будет конфигурационный-xml в том же Спринге, если у тебя >500 классов и почти каждый описан в нем.

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

Цитата(Vitaly333 @  6.8.2011,  01:00 Найти цитируемый пост)
А как можно его не использовать если ты хочешь писать инжектируемый код? И что это будет за "тупой" код? Фабрики ты имеешь ввиду? 

Я имею в виду вот такие цепочки в классах, которые будут заниматься инициализацией всего этого хозяйства:
Код

obj.getA().getB().getC().setD(d);
// либо
C c = new C(d);

то есть прокидывание инжектящихся значений от того, кто о них знает (читай - конструирует) до того, кто их будет использовать. 
Сеттеры - это, конечно, тоже тупой код, но их, по счастью, за нас будут писать IDE. Да и не обойтись без них, независимо от IoC.


Цитата(Старовъръ @  6.8.2011,  01:11 Найти цитируемый пост)
Это пример зависимости, которую нужно не ижектить, а создавать внутри самого класса. Правда затем нужно будет протестировать как-то этот сервис, что значит, что возможность инжектить все-таки должна быть, просто ее не следует использовать в production-коде (можно вместо этого использовать Отражение для установки мока на место поля). 

Не соглашусь. Конвертер этот все равно так или иначе конфигурируется - хотя бы и для уже упомянутых тестов. Затем, стоит подумать о переиспользовании - возможно, один конвертер пригодится нескольким сервисам. Ну и, наконец, если он инжектится, то будет удобно делать апгрейд - заинжектил другой экземпляр, и все. Если инжект объявлен декларативно, то даже перекомпиляция класса сервиса не понадобится.
Ну и, к слову, я против идеи использовать рефлекшн только ради отсечения test-only кода, но это совсем параллельная дискуссия...

Цитата(Stolzen @  6.8.2011,  09:14 Найти цитируемый пост)
И выделить отдельный класс-сборщик, который будет создавать, инжектить зависимости и отдавать клиенту интерфейс. 

Ну так он уже за нас написан, со всеми плюшками типа чтения конфигов из XML, инклюдов и т.п.


Это сообщение отредактировал(а) batigoal - 7.8.2011, 13:31


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Stolzen
Дата 7.8.2011, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1041
Регистрация: 17.10.2005

Репутация: 2
Всего: 48



Цитата(batigoal @  7.8.2011,  14:30 Найти цитируемый пост)
Ну и, к слову, я против идеи использовать рефлекшн только ради отсечения test-only кода, но это совсем параллельная дискуссия...

Кстати, все-таки интересно было бы услышать аргументы против инжектов для тестирования с помощью рефлексии. Почему это плохо и как лучше тогда отсекать test-only код? 


--------------------
datatalks.ru - анализ данных, статистика, машинное обучение
PM MAIL WWW   Вверх
batigoal
Дата 7.8.2011, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: нет
Всего: 151



Цитата(Stolzen @  7.8.2011,  16:42 Найти цитируемый пост)
 Почему это плохо...

Это плохо тем же, чем плоха рефлексия в продакшн-коде. Нет проверок в compile-time, ниже скорость работы, возможность проигнорировать области видимости, etc. Кроме того, есть чисто теоретическое соображение: применяя рефлексию, ты тестируешь не "оригинальный" код, а код, динамически тобой измененный для теста, но это уже демагогия.

Тем не менее, я рефлексию в тестах часто использую, чтобы меньше кода писать (например, чтобы инстанцировать в тесте объект класса, имя которого можно определить по шаблону из имени класса-теста)

Цитата(Stolzen @  7.8.2011,  16:42 Найти цитируемый пост)
...и как лучше тогда отсекать test-only код?  

А зачем? Фактически, тесты вынуждают тебя применять более модульный и "правильный" дизайн. Дополнительные сеттеры - это, фактически, дополнительная гибкость в настройке бина, я не вижу причин её закрывать. 
Другое дело, что нередко приходится расширять область видимости членов класса для адекватного их тестирования. Эта проблема имеет несколько решений: наследование, рефлексия, кладка с прибором smile. Я использую последний вариант, потому что считаю, что это невеликая цена за повышение testability кода. Тестируемость - это всего лишь одна из метрик кода, если инкапслуяция вам дороже - жертвуйте тестируемостью. 



Это сообщение отредактировал(а) batigoal - 7.8.2011, 17:04


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Старовъръ
Дата 7.8.2011, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.5.2008

Репутация: 2
Всего: 10



Цитата
Инклюды спасут отца русской демократии. Если твой код нормально бьется на модули, то будут раздельные конфиги на каждый модуль. Спринг в проектах на 500 классов - это, наоборот, большое подспорье, а не помеха.
Даже инклюды не спасут в достаточно большом проекте, просто будет очень много XML'ей и все (что также не просто поддерживать и читать). 
Цитата
Затем, стоит подумать о переиспользовании - возможно, один конвертер пригодится нескольким сервисам. Ну и, наконец, если он инжектится, то будет удобно делать апгрейд - заинжектил другой экземпляр, и все. Если инжект объявлен декларативно, то даже перекомпиляция класса сервиса не понадобится.
О каком еще переиспользовании? Кто о нем говорил? Его не было и нет. А вот когда появится, тогда и думай о лишних бинах в спрингах. Ибо нечего делать код более гибким, чем это необходимо, это очень усложняет проект (и проекты с излишней гибкостью часто идут на свалку).
Цитата
Это плохо тем же, чем плоха рефлексия в продакшн-коде. Нет проверок в compile-time, ниже скорость работы, возможность проигнорировать области видимости, etc. 
Это все не важно когда ты пишешь тесты, не нужно подгонять тесты под рамки продакшн кода. 
Цитата
Кроме того, есть чисто теоретическое соображение: применяя рефлексию, ты тестируешь не "оригинальный" код, а код, динамически тобой измененный для теста, но это уже демагогия.
В данном случае это не аргумент, ты точно также заменяешь объекты на моки с помощью сеттеров, разница лишь в подходах.
Короче говоря тема переполнена абстрактными мыслями и сферическими конями, дальше ее развивать похоже нет смысла.
PM MAIL WWW   Вверх
Farmazon
Дата 8.8.2011, 06:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Разработчик
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 7.7.2006

Репутация: нет
Всего: 5



Цитата

Даже инклюды не спасут в достаточно большом проекте, просто будет очень много XML'ей и все (что также не просто поддерживать и читать). 


IoC как раз и придумали чтобы хоть как-то управляться с большими проектами. Есть лучше варианты?


--------------------
Таково моё общее мнение.
PM MAIL WWW   Вверх
Старовъръ
Дата 8.8.2011, 08:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.5.2008

Репутация: 2
Всего: 10



Для того, чтоб хоть как-то управляться с большими проектами придумали SOAP & MOM. А IoC придумали для уменьшения связанности (coupling) между классами.
Про варианты по-лучше я писал выше, можно для начала всю тему прочесть перед постингом в ней ;) 
PM MAIL WWW   Вверх
batigoal
Дата 8.8.2011, 08:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: нет
Всего: 151



Старовъръ,  не согласен ни по одному пункту. Вообще говоря, все твои аргументы были когда-то и моими аргументами, пока я не поработал в команде, ратующей за хороший дизайн и уверенно владеющей Spring'ом.

Цитата(Старовъръ @  7.8.2011,  20:50 Найти цитируемый пост)
Даже инклюды не спасут в достаточно большом проекте, просто будет очень много XML'ей и все (что также не просто поддерживать и читать). 

Читать их ни капли не сложнее, чем прямой ява-код. IntelliJ IDEA осуществляет прозрачную навигацию, рефакторинг и поиск по Спринговым конфигам, думаю, другие IDE тоже.

Цитата(Старовъръ @  7.8.2011,  20:50 Найти цитируемый пост)
Ибо нечего делать код более гибким, чем это необходимо, это очень усложняет проект (и проекты с излишней гибкостью часто идут на свалку).

Не нужно смешивать гибкость уровня "а давайте сделаем все поля интерфейса настраиваемыми", т.е. гибкость использования и гибкость на уровне кода - это совершенно ортогональные понятия. Добавление сеттеров в бины никак код не усложняет.

Цитата(Старовъръ @  7.8.2011,  20:50 Найти цитируемый пост)
О каком еще переиспользовании? Кто о нем говорил? Его не было и нет.

Ну естественно, блин - с таким подходом его и не будет. Никто уже и не вспомнит, что где-то там в недрах левого бина уже есть похожий код.

Цитата(Старовъръ @  7.8.2011,  20:50 Найти цитируемый пост)
Это все не важно когда ты пишешь тесты, не нужно подгонять тесты под рамки продакшн кода. 

Надо. Тесты - это такой же код, как и весь остальной. А уж время выполнения - это очень важно. Даже если избирательно отключать длинные тесты в процессе девелопмента, они становятся проблемой при разработке билд-процедур.

Цитата(Старовъръ @  7.8.2011,  20:50 Найти цитируемый пост)
В данном случае это не аргумент, ты точно также заменяешь объекты на моки с помощью сеттеров, разница лишь в подходах.

Э, нет. Я заменяю на моки не тестируемый объект, а его зависимости.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Farmazon
Дата 9.8.2011, 07:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Разработчик
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 7.7.2006

Репутация: нет
Всего: 5



Старовер, ты не прав. MOM и SOAP - не панацея.

Добавлено @ 07:25
Слабая связность и сильное сцепление - признаки хорошо спроектированной системы. IoC - хороший паттерн для достижения этих целей.
И да, правильное разбиение на инклуды очень упрощает чтение конфигурации. Вон, Alfresco взять к примеру... Там много конфигов, но это не значит что нельзя  разобраться со сборкой.

Это сообщение отредактировал(а) Farmazon - 9.8.2011, 12:30


--------------------
Таково моё общее мнение.
PM MAIL WWW   Вверх
Farmazon
Дата 9.8.2011, 07:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Разработчик
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 7.7.2006

Репутация: нет
Всего: 5



Кстати, есть кроме инклудов вариант использовать иерархичные контексты...

SOAP и MOM - у них свои специфичные задачи. SOAP - меж платформенное сетевое взаимодействие, MOM - асинхронный обмен. И они не противоречат IoC и очень хорошо будут работать вместе, этот клей склеит любое приложение.

Добавлено @ 07:45
И какой твой критерий больших проектов?... Вот Eclipse - он большой?


Это сообщение отредактировал(а) Farmazon - 9.8.2011, 07:47


--------------------
Таково моё общее мнение.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Design, Quality, Testing | Следующая тема »


 




[ Время генерации скрипта: 0.0947 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.