Рекомендації щодо інтеграції контейнера DI / IoC у існуючу програму


10

Зараз я стикаюся з інтеграцією контейнера інверсії керування (IoC) у існуючий додаток, і я шукаю деякі рекомендації щодо того, як це можна найпростіше здійснити з кінцевою метою зменшення зчеплення, тим самим підвищити простежуваність. Хоча я, як правило, не класифікую більшість класів як об'єкти бога , кожен має занадто багато обов'язків та прихованих залежностей через статику, синглтон та відсутність інтерфейсів.

Ось трохи підсумків деяких проблем, з якими потрібно зіткнутися:

  • Ін'єкційну залежність застосовують нечасто
  • Статичних методів багато - як фабричні, так і допоміжні методи
  • Синглтони досить поширені
  • Інтерфейси при їх використанні не надто детальні
  • Об'єкти часто втягують непотрібні залежності через базові класи

Наша мета полягає в тому, що наступного разу, коли нам потрібно внести зміни в певну область, ми намагатимемося дражнити залежності, які насправді існують, але ховаються за глобалами, такими як одиночні та статичні.

Я вважаю, що це робить контейнер IoC вторинним для впровадження ін'єкцій залежностей, але я би сподівався, що існує певний набір практик та рекомендацій, які можна дотримуватися чи розглянути, які допоможуть нам вирвати ці залежності.


3
Я повинен запитати про причину цього робити зараз ... що сприяє цій зміні? Технічне обслуговування? Масштабованість, оскільки вона буде рости експоненціально? Розробникам нудно?
Аарон Маківер

1
Я нещодавно приєднався до компанії і намагаюся запровадити деякі "найкращі практики". Моя головна мета - підвищити довіреність і зменшити зв'язок. Ми можемо легко використовувати DI / IoC для нового коду і не збираємось намагатися змінити весь існуючий код одразу, але я хотів би отримати рекомендації щодо того, як ми можемо змінити існуючий код на краще наступного разу, коли ми робимо зміни в цій області. Поки що єдине, що я знайшов в Інтернеті, це: code.google.com/p/autofac/wiki/ExistingApplications
Калеб Педерсон

3
Якщо на місці не існує великої кількості автоматизованих тестів для блоку / інтеграції; модифікація існуючої інфраструктури, якщо проблема не існує заради кращих практик, не вимагає проблем. Навіть якщо ваш комплект модульних / інтеграційних тестувань був надійним, я все ще вагаюся.
Аарон Маківер

1
@Aaron Я сподіваюся, що це не звучало так, як ми робимо це заради найкращих практик. Ми вносимо зміни, тому що важко і повільно працювати з існуючим кодом і робимо це поодиноко, коли ми працюємо в цій конкретній області. З радістю, у нас є набір розумних інтеграційних тестів та декілька одиничних тестів для підтримки внесення змін.
Калеб Педерсон

Відповіді:


8

Для того, щоб витягнути щось подібне, вам доведеться працювати поетапно, кожен з них не є дрібницею, але їх можна виконати. Перш ніж почати, ви повинні зрозуміти, що не можете поспішати з цим процесом.

  1. Визначте основні підсистеми програми та а interfaceдля кожної з них. Цей інтерфейс повинен тільки визначити методи , що і інші частини системи будуть використовувати для розмови з ним. ПРИМІТКА. Можливо, вам доведеться зробити більше одного проходу.
  2. Забезпечте реалізацію оболонки цього інтерфейсу, який делегує існуючому коду. Мета цієї вправи - уникнути масового перезапису , але перефактурувати код для використання нових інтерфейсів - тобто зменшити з'єднання у вашій системі.
  3. Налаштуйте контейнер IoC для створення системи за допомогою створених інтерфейсів та реалізацій. На цьому етапі ви хочете подбати про інстанцію контейнера IoC, щоб він міг виводити додаток. Тобто, якщо ви перебуваєте в сервлет-середовищі, переконайтеся, що ви можете отримати / створити контейнер init()методом сервлетів .
  4. Знову зробіть те саме в кожній підсистемі, на цей раз, коли ви рефактор, ви перетворюєте свою заглушку на справжню річ, яка в свою чергу використовує інтерфейси для спілкування з її компонентами.
  5. Повторіть по мірі необхідності, поки ви не забезпечите гарний баланс розміру компонента та функціональності.

Коли ви закінчите, єдиними статичними методами у вашій системі є ті, які є справді функціями - наприклад, подивіться на Collectionsклас чи Mathклас. Жоден статичний метод не повинен намагатися отримати прямий доступ до інших компонентів.

Це те, що займе багато часу, сплануйте відповідно. Переконайтеся, що, виконуючи рефакторинг, ви стаєте більш твердими у своєму дизайнерському підході. На початку це буде боляче. Ви різко змінюєте дизайн своєї програми ітеративно.


Гарні пропозиції. Я також посилаюся на інші пропозиції тут, вносячи такі зміни: code.google.com/p/autofac/wiki/ExistingApplications
Kaleb Pederson

7

Підберіть ефективну роботу зі спадковим кодом та дотримуйтесь його порад. Почніть зі створення островів з прихованим кодом і поступово рухайтесь до більш добре структурованої програми. Намагання масово змінитись - це рецепт катастрофи.


Любіть цю книгу !!
Martijn Verburg

Гарна рекомендація. Хоча я прочитав половину його років тому, я уявляю, що отримаю набагато більше від цього зараз, коли заглиблююся в ситуацію.
Калеб Педерсон

Це смішно, обрана відповідь в основному підсумовує книгу;) Звичайно, пір’я йде детальніше.
Майкл Браун

5

Основна причина введення IoC - роз'єднання модулів. Проблема особливо Java - надзвичайно сильна прив'язка, яку newнадає оператор, у поєднанні з тим, що код виклику точно знає, який модуль він буде використовувати.

Фабрики були введені для переміщення цих знань на центральне місце, але врешті-решт ви все-таки або за допомогою модуля new/ singleton, який зберігає жорстку зв'язок, або ви навантажуєте модулі , або ви читаєте у конфігураційному файлі та використовуєте відбиток / Class.forName, який є крихким при рефакторингу .

Якщо у вас немає цільової модуляції, то IoC нічого не дасть вам.

Введення тестів Unit, швидше за все, змінить це, оскільки вам потрібно буде знущатися з модулів, які не перевіряються, і найпростіший спосіб впоратися з цим, а також фактичні виробничі модулі з тим же кодом - використовувати рамку IoC для введення відповідних модулі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.