![]() |
Модераторы: LSD |
![]() ![]() ![]() |
|
Vitaly333 |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 220 Регистрация: 6.11.2006 Где: Volgograd Репутация: нет Всего: 2 |
Хочу отрефакторить ###код в своем проекте. Хочу использовать IoC - паттерн. Никогда его не применял, поэтому есть вопросы:
В каких случаях требуется инжектировать зависимости а в каких нет? Если инжектировать все зависимости в каждом классе то тоже ничего хорошего не выйдет. Должна быть золотая середина. Есть какое-нибудь правило которым вы пользуетесь? Например, инжектируем только те зависимости которые могут быть изменены (подставлена другая реализация или мок) а те, для которых я точно знаю что они не изменятся я не трогаю. |
|||
|
||||
batigoal |
|
|||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: нет Всего: 151 |
Ну вот золотая середина тут лежит сильно ближе к той стороне, где "инжектятся все зависимости" ![]() По большому счету, я стараюсь инжектить всё, кроме создания энтити-экземпляров, да и то - если они создаются напрямую. а не через какую-нибудь фабрику. Даже статические коллекции стараюсь инжектить Спрингом и описывать в XML. Если ты будешь использовать IoC-контейнер (Spring, Google Guice, JavaEE-шный движок, etc), то никаких проблем тут нет. Если же его не использовать, тогда попросту слишком много тупого кода нужно будет писать ради инжекта. -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
|||
|
||||
Vitaly333 |
|
||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 220 Регистрация: 6.11.2006 Где: Volgograd Репутация: нет Всего: 2 |
Представляю какого размера будет конфигурационный-xml в том же Спринге, если у тебя >500 классов и почти каждый описан в нем.
А как можно его не использовать если ты хочешь писать инжектируемый код? И что это будет за "тупой" код? Фабрики ты имеешь ввиду? |
||||
|
|||||
Старовъръ |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.5.2008 Репутация: 2 Всего: 10 |
Правильные вопросы задаешь, люблю когда люди сначала идут от теории
![]() Как правило следует инжектить все, что кнфигурируется. Например, у нас есть ДАО, который нужно передать в класс бизнес логики. Это пример зависимости, которую следует инжектить. Допустим в уровне сервисов мы трансформируем объекты одного класса в другой, причем конвертер никак не конфигурируется, его просто нужно создать и все. Это пример зависимости, которую нужно не ижектить, а создавать внутри самого класса. Правда затем нужно будет протестировать как-то этот сервис, что значит, что возможность инжектить все-таки должна быть, просто ее не следует использовать в production-коде (можно вместо этого использовать Отражение для установки мока на место поля). То есть в большинстве случаев инжектить следует только то, что конфигурируется на глобальном уровне. Иначе будет достаточно сложно как работать с контекстами, так и "бродить" по коду. Ну и объекты, которые нужны нескольким бинам, также логично помещать в контекст. -------------------- |
|||
|
||||
Stolzen |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1041 Регистрация: 17.10.2005 Репутация: 2 Всего: 48 |
setXXX() ![]() И выделить отдельный класс-сборщик, который будет создавать, инжектить зависимости и отдавать клиенту интерфейс. Инжектить можно тогда, когда встает вопрос о соблюдении SRP (Single responsibility principle). Если класс начинает выполнять более одной работы, то желательно новую функциональность выделить в отдельный класс и делегировать выполнение этих операций новому классу (или интерфейсу + его реализацию инжектить). Плюсы - код чище, проще покрыть тестами (например мокнуть зависимость и заинжектить ее). Это сообщение отредактировал(а) Stolzen - 6.8.2011, 08:15 |
|||
|
||||
Старовъръ |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.5.2008 Репутация: 2 Всего: 10 |
Кстати, чтоб не было недопониманий: как Фабрики, так и IoC-контейнеры - это все Inversion of Control. Если хочется говорить конкретно об IoC-контейнерах, то лучше применять термин Dependency Injection (DI). ТС, почитай/посмотри про принципы объектно-ориентированного проектирования (OOD Principles), они смогут помочь когда станет вопрос "а как лучше": -------------------- |
|||
|
||||
batigoal |
|
||||||||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: нет Всего: 151 |
Инклюды спасут отца русской демократии. Если твой код нормально бьется на модули, то будут раздельные конфиги на каждый модуль. Спринг в проектах на 500 классов - это, наоборот, большое подспорье, а не помеха.
Я имею в виду вот такие цепочки в классах, которые будут заниматься инициализацией всего этого хозяйства:
то есть прокидывание инжектящихся значений от того, кто о них знает (читай - конструирует) до того, кто их будет использовать. Сеттеры - это, конечно, тоже тупой код, но их, по счастью, за нас будут писать IDE. Да и не обойтись без них, независимо от IoC. Не соглашусь. Конвертер этот все равно так или иначе конфигурируется - хотя бы и для уже упомянутых тестов. Затем, стоит подумать о переиспользовании - возможно, один конвертер пригодится нескольким сервисам. Ну и, наконец, если он инжектится, то будет удобно делать апгрейд - заинжектил другой экземпляр, и все. Если инжект объявлен декларативно, то даже перекомпиляция класса сервиса не понадобится. Ну и, к слову, я против идеи использовать рефлекшн только ради отсечения test-only кода, но это совсем параллельная дискуссия...
Ну так он уже за нас написан, со всеми плюшками типа чтения конфигов из XML, инклюдов и т.п. Это сообщение отредактировал(а) batigoal - 7.8.2011, 13:31 -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
||||||||
|
|||||||||
Stolzen |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1041 Регистрация: 17.10.2005 Репутация: 2 Всего: 48 |
Кстати, все-таки интересно было бы услышать аргументы против инжектов для тестирования с помощью рефлексии. Почему это плохо и как лучше тогда отсекать test-only код? |
|||
|
||||
batigoal |
|
|||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: нет Всего: 151 |
Это плохо тем же, чем плоха рефлексия в продакшн-коде. Нет проверок в compile-time, ниже скорость работы, возможность проигнорировать области видимости, etc. Кроме того, есть чисто теоретическое соображение: применяя рефлексию, ты тестируешь не "оригинальный" код, а код, динамически тобой измененный для теста, но это уже демагогия. Тем не менее, я рефлексию в тестах часто использую, чтобы меньше кода писать (например, чтобы инстанцировать в тесте объект класса, имя которого можно определить по шаблону из имени класса-теста) А зачем? Фактически, тесты вынуждают тебя применять более модульный и "правильный" дизайн. Дополнительные сеттеры - это, фактически, дополнительная гибкость в настройке бина, я не вижу причин её закрывать. Другое дело, что нередко приходится расширять область видимости членов класса для адекватного их тестирования. Эта проблема имеет несколько решений: наследование, рефлексия, кладка с прибором ![]() Это сообщение отредактировал(а) batigoal - 7.8.2011, 17:04 -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
|||
|
||||
Старовъръ |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.5.2008 Репутация: 2 Всего: 10 |
Короче говоря тема переполнена абстрактными мыслями и сферическими конями, дальше ее развивать похоже нет смысла. -------------------- |
||||||||
|
|||||||||
Farmazon |
|
|||
![]() Разработчик ![]() ![]() Профиль Группа: Участник Сообщений: 265 Регистрация: 7.7.2006 Репутация: нет Всего: 5 |
IoC как раз и придумали чтобы хоть как-то управляться с большими проектами. Есть лучше варианты? -------------------- Таково моё общее мнение. |
|||
|
||||
Старовъръ |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.5.2008 Репутация: 2 Всего: 10 |
Для того, чтоб хоть как-то управляться с большими проектами придумали SOAP & MOM. А IoC придумали для уменьшения связанности (coupling) между классами.
Про варианты по-лучше я писал выше, можно для начала всю тему прочесть перед постингом в ней ;) -------------------- |
|||
|
||||
batigoal |
|
||||||||||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: нет Всего: 151 |
Старовъръ, не согласен ни по одному пункту. Вообще говоря, все твои аргументы были когда-то и моими аргументами, пока я не поработал в команде, ратующей за хороший дизайн и уверенно владеющей Spring'ом.
Читать их ни капли не сложнее, чем прямой ява-код. IntelliJ IDEA осуществляет прозрачную навигацию, рефакторинг и поиск по Спринговым конфигам, думаю, другие IDE тоже.
Не нужно смешивать гибкость уровня "а давайте сделаем все поля интерфейса настраиваемыми", т.е. гибкость использования и гибкость на уровне кода - это совершенно ортогональные понятия. Добавление сеттеров в бины никак код не усложняет.
Ну естественно, блин - с таким подходом его и не будет. Никто уже и не вспомнит, что где-то там в недрах левого бина уже есть похожий код.
Надо. Тесты - это такой же код, как и весь остальной. А уж время выполнения - это очень важно. Даже если избирательно отключать длинные тесты в процессе девелопмента, они становятся проблемой при разработке билд-процедур.
Э, нет. Я заменяю на моки не тестируемый объект, а его зависимости. -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
||||||||||
|
|||||||||||
Farmazon |
|
|||
![]() Разработчик ![]() ![]() Профиль Группа: Участник Сообщений: 265 Регистрация: 7.7.2006 Репутация: нет Всего: 5 |
Старовер, ты не прав. MOM и SOAP - не панацея.
Добавлено @ 07:25 Слабая связность и сильное сцепление - признаки хорошо спроектированной системы. IoC - хороший паттерн для достижения этих целей. И да, правильное разбиение на инклуды очень упрощает чтение конфигурации. Вон, Alfresco взять к примеру... Там много конфигов, но это не значит что нельзя разобраться со сборкой. Это сообщение отредактировал(а) Farmazon - 9.8.2011, 12:30 -------------------- Таково моё общее мнение. |
|||
|
||||
Farmazon |
|
|||
![]() Разработчик ![]() ![]() Профиль Группа: Участник Сообщений: 265 Регистрация: 7.7.2006 Репутация: нет Всего: 5 |
Кстати, есть кроме инклудов вариант использовать иерархичные контексты...
SOAP и MOM - у них свои специфичные задачи. SOAP - меж платформенное сетевое взаимодействие, MOM - асинхронный обмен. И они не противоречат IoC и очень хорошо будут работать вместе, этот клей склеит любое приложение. Добавлено @ 07:45 И какой твой критерий больших проектов?... Вот Eclipse - он большой? Это сообщение отредактировал(а) Farmazon - 9.8.2011, 07:47 -------------------- Таково моё общее мнение. |
|||
|
||||
![]() ![]() ![]() |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Design, Quality, Testing | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |