article-spots
article-carousel-spots
programs
Технології

Принципи SOLID. Навіщо вони потрібні програмістам та як з ними працювати

6 лют

Дмитро Колесников, Associate Talent Development Specialist, співпрацює з EPAM вже понад 10 років. У статті Дмитро пояснює, як принципи SOLID сприяють покращенню якості коду, створенню гнучких програмних систем та чому ці принципи варто застосовувати на практиці. 

Що таке SOLID?

SOLID — це акронім, який складається з перших літер назв п'яти принципів, які визначають, як поєднати функціональні елементи в програмні модулі і як ці модулі мають взаємодіяти між собою. Уперше їх узагальнив Роберт Мартін в 2000 році у статті «Design Principles and Design Patterns». Якісь із них вже були відомі раніше.

Практичний досвід показує корисність та ефективність використання принципів SOLID: якщо їх дотримуватися, код виходить більш читабельним, гнучким, таким, що підтримується. Традиційно принципи SOLID відносять до області ООП, але потенційно їх можна застосовувати й поза ним. Розглянемо кожен з них детальніше.

S — Принцип єдиного обов'язку (Single Responsibility Principle, SRP)

«Модуль повинен мати одну і лише одну причину для змін». Іншими словами, модуль має відповідати лише за один аспект функціональності.

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

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

O — Принцип відкритості для розширення, закритості для змін (Open/Closed Principle, OCP)

Принцип відкритості для розширення, закритості для змін (Open/Closed Principle, OCP). Проєктування програмних сутностей повинно дозволяти розширювати їх поведінку без необхідності змінювати вже існуючий код. Для досягнення цього часто застосовують принципи SRP і DIP.

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

L — Принцип підставлення Лісков (Liskov Substitution Principle, LSP)

«Якщо тип S є підтипом T, то будь-які властивості, які задовольняють всі об'єкти типу T, повинні задовольняти всі об'єкти типу S».

Під властивістю слід розуміти певну характеристику функціональності та стан об'єктів. Відношення наслідування між типами — це відношення «бути окремим випадком»: нащадок повинен бути окремим випадком предка.

Принцип LSP посилює вимоги до нащадка. Відомо, що заперечення наслідків призводить до заперечення передумов, тому цей принцип можна переформулювати так: «Якщо можна знайти властивість, яка задовольняє всі об'єкти типа Т і не задовольняє хоча б один об'єкт типу S, то не слід тип S наслідувати від типу Т».

Порушення принципу LSP може привести до порушення поліморфізму, коли об'єкт нащадка не зможе замінити об'єкт предка в певному контексті (програмі). Як приклад, порушенням принципу LSP можна назвати таке: є два класи «Квадрат» та «Прямокутник», якщо ми наслідуємо перший від другого (квадрат є окремим випадком прямокутника), то порушимо LSP тоді, якщо у прямокутника є функціональність зміни ширини без зміни висоти.

I — Принцип розділення інтерфейсу (Interface Segregation Principle, ISP)

«Клієнти не повинні залежати від методів, які вони не використовують». При проєктуванні інтерфейсів перевагу варто надавати створенню невеликих спеціалізованих інтерфейсів.

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

D — Принцип інверсії залежностей (Dependency Inversion Principle, DIP)

«Залежності в вихідному коді повинні бути спрямовані на абстракції, а не на конкретні реалізації». Це принцип, який дозволяє зменшити залежність між компонентами.

Реалізацію принципу можна проілюструвати на прикладі. Якщо клас A залежить від класу B, тоді він залежить від конкретної реалізації. Можна замінити цю залежність двома залежностями від абстракції у вигляді інтерфейсу G:

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

Чому це важливо?

Принципи SOLID взаємозв’язані та дають основу для створення якісних та підтримуваних програмних систем. Їх застосування на практиці прямо впливає на якість програмних систем:

  1. Покращення якості коду: SOLID допомагає створювати більш зрозумілий та підтримуваний код. За допомогою цих принципів можливо покращити читабельність коду, структуру програми, зменшити надмірну складність.
  2. Гнучкість та розширюваність: Використання SOLID дозволяє створювати гнучкі системи, які легко можна розширювати та адаптувати до змін. Програми, побудовані з використанням цих принципів, менше вразливі до майбутніх змін у вимогах.
  3. Зменшення залежностей: SOLID допомагає знижувати залежності між компонентами програми, що полегшує розробку, тестування та підтримку коду.    
55