10 принципів програмування, які варто знати розробнику програмного забезпечення
Tags: programming, tutorial, career
Published: 2023-08-16 16:39:14

Написання коду - це не просто змусити щось працювати, це також створення чистого, ефективного та зручного для обслуговування коду. Щоб досягти цього, розробники програмного забезпечення повинні ознайомитися з набором фундаментальних принципів програмування. Ці принципи діють як дороговкази, допомагаючи розробникам писати код, який є надійним, масштабованим і легким для розуміння. У цій статті ми розглянемо 10 основних принципів програмування, які повинен знати кожен розробник програмного забезпечення. Розуміння і застосування цих концепцій у ваших підходах до кодування дозволить вам створювати код, який буде не тільки функціональним, але й чистим і керованим.

## 1. DRY (Не повторюйся)

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

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

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

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

Пам'ятайте, що дотримання принципу DRY не тільки допомагає писати чистіший та організованіший код, але й економить час та зусилля у довгостроковій перспективі.

## 2. KISS (Не ускладнюй, дурню)

KISS підкреслює важливість простоти в розробці програмного забезпечення. Він передбачає, що ми повинні прагнути до того, щоб **код і рішення були якомога простішими**. Спрощення коду полегшує його розуміння, підтримку та налагодження, зменшуючи ймовірність помилок або проблем.

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

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

Спрощення коду допомагає підвищити його зрозумілість та адаптивність як для вас, так і для інших розробників у майбутньому. Крім того, це зменшує ймовірність виникнення помилок.

## 3. YAGNI (Тобі це не знадобиться)

YAGNI - це корисне керівництво для розробників програмного забезпечення. Він нагадує нам **уникати додавання непотрібних функцій або можливостей до нашого коду**. Іншими словами, не пишіть код для речей, які вам не потрібні зараз або не очікується, що знадобляться в майбутньому. Цей принцип сприяє простоті та ефективності розробки програмного забезпечення.

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

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

## 4. Розподіл турбот (SoC)

Принцип розподілу обов'язків (англ. Separation of Concerns, SoC) - це фундаментальна концепція в розробці програмного забезпечення, яка сприяє розбиттю програми на окремі незалежні частини, кожна з яких відповідає за певну задачу або сферу відповідальності.

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

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

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

## 5. Зробіть найпростішу річ, яка може спрацювати

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

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

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

## 6. Код для супровідника

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

Один із способів досягти зручності супроводу коду - це дотримуватися встановлених конвенцій кодування та найкращих практик. Наприклад, використання описових змінних та імен функцій може значно покращити читабельність. Замість того, щоб використовувати загадкові імена на кшталт `a`, `b` або `x`, обирайте змістовні імена, які чітко описують призначення та функціональність коду.

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

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

## 7. Уникайте передчасної оптимізації

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

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

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

## 8. Правило бойскаута

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

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

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

## 9. Закон Деметри

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

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

Уявімо ситуацію, коли у нас є об'єкт під назвою `Person`, який має різні властивості та поведінку. Відповідно до закону Деметри, якщо ми хочемо отримати доступ до властивості адреси особи, замість того, щоб звертатися до неї напряму, наприклад, `person.address.street`, ми повинні використовувати метод, наданий самим об'єктом person, наприклад, `person.getStreet()`. Таким чином, об'єкт `Person` інкапсулює деталі власної адреси і надає інтерфейс вищого рівня для взаємодії з іншими компонентами.

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

## 10. Принципи SOLID

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

**Принцип єдиної відповідальності (SRP)**
Цей принцип стверджує, що **клас або модуль повинен мати лише одну причину для змін**, тобто він повинен мати єдину відповідальність. Класи, які зосереджені на одній меті, легше зрозуміти, протестувати та адаптувати. Наприклад, розглянемо клас під назвою `EmailSender`. Він має відповідати за надсилання електронних листів і не виконувати жодних інших завдань, не пов'язаних з цим, таких як створення звітів або аналіз даних. Дотримуючись SRP, ми робимо кодову базу більш легкою в обслуговуванні та модульною.

**Принцип відкритості/закритості (OCP)**
Принцип OCP підкреслює, що **програмні об'єкти (класи, модулі, функції) повинні бути відкритими для розширення, але закритими для модифікації**. Це означає, що ми повинні мати можливість додавати нові функції або поведінку, не змінюючи існуючий код. Одним із способів досягти цього є використання успадкування або інтерфейсів. Наприклад, уявіть собі клас `Shape` з різними підкласами, такими як `Rectangle` і `Circle`. Якщо ми хочемо додати нову фігуру, ми можемо створити новий підклас, не змінюючи існуючий клас `Shape`. Цей принцип сприяє повторному використанню коду і зменшує ризик внесення помилок у вже працюючий код.

**Принцип підстановки Ліскова (LSP)**
LSP стверджує, що об'єкти суперкласу повинні бути замінені об'єктами його підкласів без впливу на коректність роботи програми. Простіше кажучи, **будь-який екземпляр класу можна використовувати замість його батьківського класу, не викликаючи при цьому неочікуваної поведінки**. Наприклад, припустимо, у нас є базовий клас `Animal` з методом `makeSound()`. Підкласи, такі як `Cat` і `Dog`, повинні мати можливість замінити клас `Animal` і все одно виробляти очікувану поведінку, не спричиняючи жодних помилок чи невідповідностей.

**Принцип розділення інтерфейсів (ISP)**
ISP радить **не змушувати клієнтів залежати від інтерфейсів, якими вони не користуються**. Він заохочує створення специфічних інтерфейсів, пристосованих до потреб клієнтів, а не великих, монолітних інтерфейсів. Це позбавляє класи від необхідності реалізовувати методи, які не мають до них відношення. Наприклад, уявіть собі інтерфейс з назвою `Printer` з методами `print()`, `scan()` та `fax()`. Замість того, щоб мати один інтерфейс, краще розбити його на менші інтерфейси, такі як `Printable`, `Scanable` і `Faxable`. Таким чином, класи можуть реалізовувати лише ті інтерфейси, які їм потрібні, зберігаючи кодову базу чистішою та сфокусованішою.

**Принцип інверсії залежностей (DIP)**
DIP передбачає, що **високорівневі модулі не повинні залежати від низькорівневих модулів**; обидва повинні залежати від абстракцій. Це сприяє вільному зв'язку і дозволяє легше модифікувати і тестувати. На практиці це означає, що класи повинні залежати від інтерфейсів або абстрактних класів, а не від конкретних реалізацій. Наприклад, розглянемо клас з назвою `Logger`, який має записувати журнали у файл. Замість того, щоб безпосередньо залежати від конкретної реалізації файлової системи, він повинен залежати від інтерфейсу типу `FileSystem`, який може мати декілька реалізацій (наприклад, `LocalFileSystem`, `CloudFileSystem`). Таким чином, ми можемо переключатися між реалізаціями без модифікації класу `Logger`.

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

## Підбиваємо підсумки

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