Джерело
Принципи S.O.L.I.D., які є основними для розробки надійних та довговічних додатків, є базовими принципами програмування, які повинен знати кожен розробник програмного забезпечення.
У процесі розробки програмного забезпечення дуже важливо забезпечити читаність коду, зручність для обслуговування (maintenance) та розширюваність (extension). У цьому контексті, принципи SOLID є основою для створення добре спроектованих програмних систем і складаються з п’яти важливих принципів. Ці принципи спрямовані на запобігання помилок під час розробки архітектури програмного забезпечення та надання можливості робити код більш гнучким, стійким та легким у підтримці. У цій статті ми розглянемо, що таке принципи SOLID, чому вони важливі і як їх можна застосовувати на практиці.
Ці принципи були розроблені Робертом С. Мартіном (Robert C. Martin, або Uncle Bob) на початку 2000-х років і базуються на принципах об'єктно-орієнтованого програмування (OOP). Вони були створені для мінімізації проблем, з якими стикаються розробники під час розробки програмного забезпечення.
- Легкість адаптації нашого коду до змін та доповнень, коли це необхідно,
- Можливість додавати нові функціональності без необхідності змінювати вже написаний код,
- Створення модульного, тестованого, стійкого та повторно використовуваного коду.
Принципи, сформульовані Робертом С. Мартіном, позначаються абревіатурою з перших літер п'яти основних принципів:
- Принцип єдиного обов'язку (Single Responsibility Principle, SRP)
- Принцип відкритості/закритості (Open/Closed Principle, OCP)
- Принцип підстановки Ліскова (Liskov Substitution Principle, LSP)
- Принцип сегрегації інтерфейсів (Interface Segregation Principle, ISP)
- Принцип інверсії залежностей (Dependency Inversion Principle, DIP)
Принцип єдиного обов'язку (Single Responsibility Principle)
Цей принцип, який можна перекласти як "Принцип єдиного обов'язку", вимагає, щоб кожен клас (class) мав лише одну відповідальність. Необхідно розділяти код на частини, кожна з яких буде відповідати за виконання однієї конкретної функції.
Принцип єдиного обов'язку означає, що у кожного класу повинна бути чітко визначена єдина відповідальність. Клас (об'єкт) можна змінювати тільки для виконання однієї мети, і ця мета є основною відповідальністю класу. Іншими словами, клас повинен виконувати лише одну задачу.
Джерело: coderized
Якщо у нас є великий клас із незалежними функціями, то для того, щоб дотримуватись принципу єдиного обов'язку, потрібно ці функції розподілити по окремих класах.
Джерело: coderized
Це може призвести до збільшення кількості коду, але робить роль кожного класу чіткішою та більш зрозумілою. Це також полегшує тестування та дозволяє використовувати ці функціональності в інших частинах проєкту.
Принцип відкритості/закритості (Open/Closed Principle)
Клас або функція повинні зберігати свої наявні характеристики, тобто не повинні змінювати свою поведінку, але при цьому мають бути здатні отримувати нові можливості.
Програмні компоненти (класи, модулі) повинні бути відкритими для розширення, але закритими для змін. Це означає, що нові функціональності повинні додаватися до існуючого коду без необхідності змінювати його. Таким чином, програмне забезпечення стає більш стійким до помилок і простішим у підтримці.
Джерело: coderized
Ми повинні додавати функціональність до модуля через його розширення, а не змінювати сам модуль. Модуль має бути закритим для змін, але відкритим для розширень.
Так ви зможете значно знизити ймовірність помилок при додаванні нових можливостей до вашого коду.
Принцип підстановки Ліскова (Liskov Substitution Principle)
Ми повинні мати можливість використовувати підкласи замість їх батьківських класів без необхідності вносити зміни в код.
Türeyen sınıf yani alt sınıflar ana(üst) sınıfın tüm özelliklerini ve metotlarını aynı işlevi gösterecek şekilde kullanabilmeli ve kendine ait yeni özellikler barındırabilmelidir.
Тут клас-нащадок (derived class), тобто підклас, має використовувати всі властивості та методи батьківського класу (parent class) і виконувати їх аналогічно, при цьому має мати свої власні властивості. Це означає, що підклас може бути використаний замість батьківського класу, не порушуючи його поведінки. Цей принцип допомагає забезпечити узгодженість коду під час використання поліморфізму (polymorphism) та наследування (inheritance).
Нижче клас-нащадок, але він все одно залишається шістикутником за своєю суттю.
Цей принцип вказує, що клас-нащадок має зберігати основні властивості свого батьківського класу. Якщо клас-нащадок не зберігає цих властивостей, то або він має наслідувати ці властивості з іншого класу, або бути визначений як окремий клас.
Принцип сегрегації інтерфейсів (Interface Segregation Principle)
Цей принцип говорить, що замість того, щоб зібрати всі обов'язки в одному інтерфейсі, слід створювати кілька більш спеціалізованих інтерфейсів.
Замість великих, універсальних інтерфейсів, слід використовувати більш малі та специфічні інтерфейси. Таким чином, класи реалізують тільки ті методи, які їм необхідні, і ми уникаємо непотрібних залежностей.
Багато інтерфейсів, орієнтованих на клієнта, краще, ніж один універсальний інтерфейс.
- Роберт С. Мартін (Robert C. Martin)
Джерело: coderized
Модулі не повинні знати про функціональність, яку вони не використовують. Розділяючи модулі на більш дрібні абстракції (через інтерфейси), ми надаємо кожному модулю лише ті функції, які йому потрібні.
Цей принцип також значно полегшує тестування. Завдяки модульній структурі коду, ми можемо легко передавати необхідні mock дані в модуль для тестування.
Принцип інверсії залежностей (Dependency Inversion Principle)
Залежності між класами повинні бути мінімальними, особливо високорівневі класи не повинні залежати від низькорівневих класів.
Високорівневі модулі не повинні залежати від низькорівневих. Натомість, обидва модулі повинні залежати від інтерфейсів. Цей принцип підвищує гнучкість коду та зменшує залежності між компонентами.
Частини коду не повинні взаємодіяти безпосередньо, а повинні використовувати інтерфейси для зв'язку. Джерело: coderized
Коли змінюється поведінка високорівневого класу, низькорівневі класи повинні адаптуватися до цієї зміни. Але коли змінюється поведінка низькорівневих класів, це не повинно порушувати поведінку високорівневих класів.
Принцип інверсії залежностей усуває прямі зв'язки в нашому коді, дозволяючи кожній частині коду бути ізольованою. Ізольовані частини коду взаємодіють через інтерфейси і не потребують знань про те, як інші класи реалізують свої функціональності. Вони лише мають приймати вхідні дані та повертати очікуваний результат.
Результат
Декомпозиція (Decoupling)
Коли ми використовуємо принципи SOLID разом, результатом є застосування деякої декомпозиції до нашого коду. Декомпозиція дозволяє зменшити залежності в коді, що робить його гнучким, підтримуваним, масштабованим, розширюваним, повторно використовуваним та тестованим.
Застосування принципів SOLID приносить значні переваги як для індивідуальних розробників, так і для команд розробників в довгостроковій перспективі.
Дякую за прочитання! Сподіваюся, що це було корисно.
Також настійно рекомендую подивитися це відео від Coderized, яке я використовував як джерело.
Перекладено з: SOLID Prensipleri Kısa ve Öz