Архітектурні принципи та методології — це набір правил і рекомендацій, які допомагають розробникам створювати підтримуваний, масштабований і зрозумілий код. За даними дослідження TIOBE Index (2025), проекти, що дотримуються архітектурних принципів, мають на 40% менше критичних дефектів. У цій статті розберемо SOLID, GRASP, DRY, KISS, YAGNI та інші принципи, а також обговоримо технічний борг і Code Smell.
Головне
Архітектурні принципи — це фундамент якісного коду. SOLID — акронім, введений Робертом Мартіном («Дядько Боб»), що описує п'ять принципів об'єктно-орієнтованого проектування. Дотримання SOLID робить код більш гнучким, тестованим і стійким до змін. Порушення архітектурних принципів — одна з головних причин технічного боргу.
Розглянемо кожен принцип. Single Responsibility Principle (SRP) — кожен клас повинен мати лише одну причину для зміни. Open/Closed Principle (OCP) — класи відкриті для розширення, але закриті для модифікації. Liskov Substitution Principle (LSP) — об'єкти підтипів повинні замінювати об'єкти базового типу без порушення логіки. Interface Segregation Principle (ISP) — багато спеціалізованих інтерфейсів краще одного загального. Dependency Inversion Principle (DIP) — залежність від абстракцій, а не від конкретних реалізацій.
За даними аналізу SonarQube (2025), порушення принципів SOLID зустрічається в 68% комерційних проектів. Найчастіші проблеми — порушення SRP (35%) та ISP (22%). В IT Sectr ми впроваджуємо SOLID на етапі архітектурного рев'ю — це допомагає виявити проблеми до того, як вони переростуть у технічний борг.
SRP (Принцип єдиної відповідальності) — найважливіший і одночасно найчастіше порушуваний принцип SOLID. Він говорить: у класу повинна бути лише одна причина для зміни. Якщо клас робить занадто багато — його складно тестувати, змінювати та розуміти.
Типове порушення — клас, який одночасно обробляє дані, зберігає їх у базу та надсилає email-повідомлення. Приклад нижче показує, як виглядає порушення SRP на Kotlin і як його виправити.
// Порушення SRP — клас робить три різні справи
class UserService {
fun registerUser(email: String, name: String) {
// 1. Валідація даних
if (!email.contains("@")) throw IllegalArgumentException("Invalid email")
// 2. Збереження в базу
val user = User(email, name)
database.save(user)
// 3. Відправка сповіщення
emailService.sendWelcomeEmail(email, name)
}
}
// Виправлення — розділення на три класи
class UserRegistrationService {
fun register(email: String, name: String) {
UserValidator().validate(email)
val user = User(email, name)
UserRepository().save(user)
NotificationService().sendWelcome(user)
}
}
У виправленій версії кожен клас відповідає за своє завдання: UserValidator — за валідацію, UserRepository — за збереження, NotificationService — за сповіщення. Це робить код тестованим і перевикористовуваним — можна замінити реалізацію бази даних без зміни логіки валідації.
GRASP (General Responsibility Assignment Software Patterns) — дев'ять архітектурних принципів розподілу відповідальності між об'єктами, описаних Крейгом Ларманом. На відміну від SOLID, GRASP відповідає на питання «який клас повинен містити цей метод?». Ключові шаблони: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations.
Law of Demeter (LoD, принцип мінімальної зв'язаності) — просте правило: об'єкт повинен спілкуватися тільки з безпосередніми сусідами. Не можна писати a.getB().getC().doSomething() — це створює жорсткий зв'язок між класами. LoD покращує перевикористання та спрощує тестування.
В IT Sectr ми перевіряємо дотримання LoD на Code Review. Якщо метод «проходить» через три і більше об'єкти — це сигнал, що архітектуру потрібно спростити. Порушення LoD — один із найпоширеніших Code Smell у великих проектах.
DRY (Don't Repeat Yourself), KISS (Keep It Simple, Stupid) та YAGNI (You Ain't Gonna Need It) — три базових архітектурних принципи, відомих кожному розробнику. Незважаючи на простоту, їх порушення зустрічається постійно.
DRY — не дублюйте код. Якщо одна й та сама логіка зустрічається у двох місцях, винесіть її в загальний метод або клас. Дублювання — головне джерело багів: виправлення в одному місці забувають застосувати в іншому. DRY не означає, що не може бути схожого коду — важливо, щоб бізнес-логіка не повторювалася.
KISS — чим простіше, тим краще. Складні рішення з безліччю абстракцій та наслідувань часто надмірні. Починайте з простого рішення та ускладнюйте тільки за необхідності. YAGNI — не пишіть код для функціональності, яка може знадобитися «колись потім». Це призводить до роздування кодової бази та ускладнення підтримки.
DRY — це не просто відсутність копіпасту. Це принцип, згідно з яким кожна частина знання або логіки повинна мати єдине, однозначне представлення в системі. Дублювання може бути явним (скопійований код) і неявним (однакова логіка в різних шарах).
В IT Sectr ми використовуємо метрики аналізу коду для виявлення дублювання. Інструменти на кшталт SonarQube та Detekt показують відсоток дубльованого коду. Значення вище 5% — привід для рефакторингу. Однак важливо пам'ятати: DRY не повинен досягатися ціною неправильних абстракцій — іноді два схожі шматки коду краще залишити як є, якщо їх об'єднання ускладнить розуміння.
Separation of Concerns (SoC, розділення відповідальності) — архітектурний принцип, при якому система ділиться на незалежні частини (concerns), кожна з яких вирішує своє завдання. Класичний приклад — розділення на шари: presentation, business logic, data access. Кожен шар залежить тільки від нижчого.
Modularity (модульність) — ступінь, в якій система може бути розбита на модулі. Модуль — це логічно пов'язана група класів з чітко визначеним інтерфейсом. Модулі повинні бути слабо зв'язані (low coupling) і сильно зв'язні (high cohesion).
Cohesion (зв'язність) — міра того, наскільки елементи всередині одного модуля пов'язані між собою. Висока зв'язність — це добре: клас робить одну річ і робить її добре. Low coupling (слабка зв'язаність) — міра того, наскільки модулі незалежні один від одного. Низька зв'язаність — це добре: зміна одного модуля не ламає інші.
Ідеальна архітектура — це high cohesion і low coupling. На практиці це означає: клас містить методи, що працюють над одними даними (cohesion), і залежить тільки від абстракцій, а не від конкретних реалізацій (coupling). Порушення балансу призводить до «божественних об'єктів» (God Object) або «спагеті-коду».
Технічний борг (Technical Debt) — це метафора, введена Уордом Каннінгемом, що описує «відсотки», які команда платить за неоптимальні архітектурні рішення та порушення архітектурних принципів. Як і фінансовий борг, технічний борг буває навмисним (вирішили зробити швидко, переробимо потім) і ненавмисним (погана архітектура через брак досвіду).
Code Smell — це поверхневі ознаки глибоких проблем у коді. Термін популяризував Мартін Фаулер у книзі «Refactoring». Типові Code Smell: довгі методи, великі класи, довгі ланцюжки викликів, дублювання коду, надмірне використання коментарів (замість зрозумілого коду).
В IT Sectr технічний борг відстежується в Jira у вигляді окремих задач. Кожен спринт ми виділяємо 20% часу на рефакторинг та погашення боргу. Систематична робота з технічним боргом — єдиний спосіб уникнути ситуації, коли додавання нової фічі займає більше часу, ніж її розробка з нуля.
Часті запитання
Single Responsibility Principle (SRP) — найважливіший, оскільки його порушення автоматично веде до порушення інших принципів. Клас із кількома відповідальностями складно тестувати, розширювати та підтримувати. Почніть з SRP — решта прийде слідом.
Cohesion (зв'язність) — це зв'язок всередині модуля (чим вище, тим краще). Coupling (зв'язаність) — це зв'язок між модулями (чим нижче, тим краще). Хороша архітектура прагне до high cohesion і low coupling.
Ні, принципи — це рекомендації, а не абсолютні закони. У невеликих проектах або прототипах надмірне слідування SOLID може призвести до оверінжинірингу. Важливо знайти баланс між «достатньо хорошою» архітектурою та швидкістю розробки.
Використовуйте статичні аналізатори (SonarQube, Detekt, ESLint), Code Review та метрики коду. Ознаки боргу: код складно тестувати, зміни в одному місці ламають інше, час додавання нової фічі збільшується від спринту до спринту. Регулярний рефакторинг — єдиний спосіб контролювати борг.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.