Принцип інверсії залежностей
SOLID |
---|
принципи об'єктно-орієнтованого проєктування |
Принцип інве́рсії зале́жностей (англ. Dependency Inversion Principle, DIP) — один з п'яти SOLID-принципів об'єктно-орієнтованого проєктування програм, суть якого полягає у розриві зв'язності між програмними модулями вищого та нижчого рівнів за допомогою спільних абстракцій.
Принцип формулюється наступним чином:
- Модулі вищого рівня не повинні залежати від модулів нижчого рівня. Обидва типи модулів повинні залежати від абстракцій.
- Абстракції не повинні залежати від деталей реалізації. Деталі реалізації повинні залежати від абстракцій.
Принцип інверсії залежностей вирішує проблеми невдалого проєктування програм.
Щоб уникнути іншої залежності, крім залежності від абстракцій, потрібно:
- Усі змінні-члени класу повинні бути або абстрактними або інтерфейсами;
- Класи не повинні успадковуватись від не абстрактних класів;
- Методи не повинні заміщати методи реалізації;
- Усі модулі класів повинні приєднуватись через модулі інтерфейсів/абстрактних класів;
- Усі об'єкти повинні створюватись через твірні шаблони: фабричний метод чи фабрику чи через бібліотеки впровадження залежностей.
Роберт Мартін у своїй статті The Dependency Inversion Principle[1] навів критерії, за якими, на його думку, можна визначити невдало спроєктовану програму.
Програма, або її частина, яка виконує своє призначення і в той самий час має одну або декілька наступних особливостей, є невдало спроєктованою:
- У програму, або її частину, складно внести зміни, оскільки будь-яка зміна впливає на занадто велику кількість компонентів системи (жорсткість).
- При внесенні змін порушується робота компонентів системи у несподіваних місцях (крихкість).
- Складно використати той самий код у іншій програмі, оскільки його неможливо витягти з даної програми (непорушність).
Програма спроєктована жорстко, якщо у неї не можна легко внести зміни. Така жорсткість обумовлена тим фактом, що одна єдина зміна до тісно взаємозв'язаного коду дає початок послідовності змін в залежних модулях. Якщо дизайнери або розробники не здатні визначити межі тієї послідовності змін, вплив цих змін неможливо спрогнозувати. А отже і наслідки цих змін спрогнозувати неможливо. Керівники проєктів, які стикаються з подібною непередбачуваністю, неохоче погоджуються на впровадження змін. Тому такий дизайн офіційно визнається жорстким.
Крихкість означає схильність програми до виникнення помилок у багатьох місцях після внесення хоча б однієї правки. Часто буває, що проблеми виникають у місцях, які не мають концептуального відношення до місця, якого стосувалась правка. Така крихкість знижує довіру до організації, що займалася проєктуванням та розробкою програми. Користувачі та керівники проєктів не можуть передбачити якість їх продукту. Прості зміни, внесені до однієї частини програми, призводять до збоїв у роботі зовсім не пов'язаних з нею інших частин програми. Спроби виправити це призводять до виникнення ще більших труднощів, і процес підтримки продукту починає нагадувати собаку, що бігає за власним хвостом.
Дизайн програми є непорушним у випадку, коли бажані частини дизайну сильно залежать від небажаних деталей реалізації. Дизайнери, які поставлять собі за мету проєктування такого дизайну, який можна було б використати у інших програмах, можуть здивуватися, як зручно такий дизайн використовувати при створенні нової програми. Але якщо було спроєктовано дизайн, що сильно пов'язаний с деталями реалізації, то такі дизайнери будуть налякані кількістю роботи, необхідної для виокремлення потрібної частини дизайну з-поміж інших непотрібних частин. У багатьох випадках такі проєкти не використовуються повторно, оскільки витрати на виокремлення необхідної частини вищі, ніж витрати на проєктування нового дизайну.
Принцип інверсії залежностей був введений Робертом Мартіном і викладений ним у кількох публікаціях, таких як Object Oriented Design Quality Metrics: an analysis of dependencies,[2] у статті The Dependency Inversion Principle, що була опублікована у 1996 році в журналі C++ Report, а також у книгах «Agile Software Development, Principles, Patterns, and Practices» та «Agile Principles, Patterns, and Practices in C#».
Традиційні методи проєктування програмного забезпечення схиляють до створення програмних структур, у яких модулі вищого рівня залежать від модулів нижчого та у яких абстракції залежать від деталей реалізації. Ці методи, крім всього іншого, мають на меті визначення ієрархії підпрограм, які описують, як модулі вищого рівня здійснюють виклики до модулів нижчого рівня. Тому структура залежностей добре спроєктованої об'єктно-орієнтованої програми «інвертована» по відношенню до структури залежностей, яка є результатом традиційних процедурних методів проєктування.
- ↑ Martin, Robert C. (May 1996). The Dependency Inversion Principle (PDF). C++ Report. Архів оригіналу (PDF) за 14 липня 2011. (англ.)
- ↑ Object Oriented Design Quality Metrics: an analysis of dependencies Robert C. Martin, C++ Report, Sept/Oct 1995 (PDF). Архів оригіналу (PDF) за 13 травня 2019. Процитовано 16 серпня 2014.