25.08.2026

Архітектура програмного забезпечення: компроміси, не шаблони

0
arkhitektura-prohramnoho-zabezpechennia-kompromisy-ne-shablony-2747

Архітектура програмного забезпечення — це не «гарні прямокутники зі стрілками» і не обов’язково мікросервіси. Це набір фундаментальних рішень про те, з яких частин складається система, як вони обмінюються даними і за якими правилами змінюватимуться наступні роки. Саме ці рішення дорого переглядати пізніше: змінити ORM можна за спринт, змінити спосіб розгортання чи межі модулів — уже проєкт на квартал.

Більшість провалів виглядають однаково. Команда копіює чужий шаблон, ігнорує атрибути якості й отримує або моноліт без внутрішніх меж, або розподілений моноліт із десятка сервісів, які не можна випускати окремо. У 2025–2026 роках індустрія якраз відходить від цієї релігійної війни: модульний моноліт знову вважають дорослим вибором, а мікросервіси — інструментом під конкретні обмеження, а не статусом.

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

Архітектура — це не діаграма, а набір обмежень

Стандарт ISO/IEC/IEEE 42010:2022 визначає архітектуру як фундаментальні поняття й властивості системи в її середовищі, втілені в елементах, зв’язках і принципах проєктування та еволюції. Формулювання сухе, але точне: архітектура живе не в файлі architecture.drawio, а в тому, що система може й не може зробити без болю.

Класичне визначення Лена Басса, Пола Клементса і Ріка Казмана з Software Architecture in Practice близьке за змістом: архітектура — це набір структур, потрібних, щоб міркувати про систему. Структури складаються з елементів, відношень між ними та властивостей і тих, і інших. Звідси практичний наслідок. Якщо рішення не змінює структури, відношення чи властивості на рівні системи — це дизайн або реалізація, а не архітектура.

Різниця важлива, бо її постійно змішують. Вибір між PostgreSQL і MySQL при однаковій моделі даних рідко архітектурний. Рішення «кожен сервіс має власну базу, синхронізація лише через події» — архітектурне: воно фіксує автономію, ціну узгодженості й спосіб відмови. Винести валідацію форми в окремий клас — дизайн. Дозволити клієнту ходити безпосередньо в базу аналітики — архітектура, бо ламає межі й безпекову модель.

Історично дисципліна виросла з простої ідеї, що структура програми важлива не менше за алгоритми. Едсгер Дейкстра в 1968 році й Девід Парнас на початку 1970-х показали: правильне приховування інформації зменшує вартість змін. У 1990-х з’явилися мови опису архітектури, стилі як першокласні об’єкти й модель «4+1» Філіпа Крухтена: логічний, процесний, фізичний і «розробницький» вигляди плюс сценарії. Перший стандарт опису — IEEE 1471-2000, пізніше ISO/IEC 42010, чинна редакція — 2022 рік. Він не нав’язує мікросервіси чи шари. Він вимагає іншого: назвати зацікавлених, їхні занепокоєння й показати систему кількома узгодженими виглядами, а не однією «правдивою» схемою.

Архітектура завжди відповідає на обмеження середовища: регуляція, командна структура, бюджет інфраструктури, gravitas легасі, час до ринку. Тому дві системи з однаковим функціоналом можуть і мусять мати різну архітектуру. Форма підпорядковується не «кращому патерну з блогу», а функції й контексту.

Які рішення справді архітектурні

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

Атрибути якості — справжні драйвери, не список фіч. Модель ISO/IEC 25010 групує їх у функційну придатність, продуктивність, сумісність, зручність, надійність, безпеку, супроводжуваність і переносимість. Для архітектора важливі не назви, а сценарії. «Система має бути швидкою» — порожня фраза. «Сторінка каталогу для 95% запитів відкривається менш ніж за 300 мс при 5 000 RPS, навіть якщо пошуковий індекс відстає на 10 секунд» — уже контракт, під який можна обрати кеш, асинхронну індексацію й допустиму застарілість даних.

Типові драйвери, які реально змінюють структуру:

  • Час зміни. Скільки днів потрібно, щоб випустити нову знижку, не чіпаючи кошик і оплату.
  • Ізоляція відмов. Чи падає оформлення замовлення, якщо «рекомендації» не відповідають.
  • Масштаб однієї осі. Чи треба масштабувати лише обробку зображень, а не всю систему.
  • Командна автономія. Чи можуть дві команди деплоїти в різні дні без спільного реліз-поїзда.
  • Дані й відповідність. Де лежать персональні дані, хто має право їх читати, як виглядає право на видалення.
  • Спостережуваність. Чи можна за 15 хвилин зрозуміти, який крок сценарію зламався в продакшені.

Кожен драйвер тягне компроміс. Сильна ізоляція відмов майже завжди збільшує складність комунікації. Сильна консистентність даних б’є по доступності під час мережевих збоїв — це не «помилка мікросервісів», а наслідок теореми CAP у розподіленому середовищі. Архітектор не «вибирає найкращий стиль». Він явно фіксує, чим жертвує.

Окремий, часто пропущений драйвер — закон Конвея (1968): система відтворює комунікаційні межі організації. Якщо продуктова аналітика, бекенд і мобільна команда не мають спільного каналу рішень, «єдина» архітектура розпадеться на три неофіційні. З практики це видно одразу: дубльовані довідники статусів замовлення, різні визначення «активного користувача», інтеграції через Excel «на час». Архітектура, яка ігнорує оргструктуру, програє оргструктурі.

Стилі, які працюють: порівняння без гасел

Стиль — це обмежений словник елементів і правил їх з’єднання. Шарована архітектура, клієнт-сервер, пайпи й фільтри, подієва, мікросервіси, serverless — усе це різні словники. Помилка конкурентних оглядів у тому, що вони ставлять в один ряд MVC, фабричний метод і мікросервіси. Перші два — патерни проєктування. Мікросервіси — стиль розгортання й володіння межами.

Для більшості продуктових команд у 2020-х релеванні п’ять робочих конфігурацій. Вони часто співіснують в одній системі: оплата — окремий сервіс, кабінет — модульний моноліт, генерація звітів — черги й воркери.

Стиль Коли доречний Головна ціна Типовий провал
Класичний моноліт MVP, 2–8 людей, одна предметна область, неясний продукт Важко масштабувати окрему вісь і паралелити релізи «Велика купа бруду»: немає модулів, усе тягне спільну базу й спільний стан
Модульний моноліт Стабільний продукт, одна-три команди, межі доменів ще рухаються Потрібна дисципліна меж і автоматичні перевірки залежностей Модулі існують лише в назвах папок, транзакції й імпорти ходять навпростець
Мікросервіси Чіткі bounded context, незалежне масштабування, кілька команд із власним деплоєм Мережа, спостережуваність, узгодженість даних, платформна зрілість Розподілений моноліт: сервіси не автономні, спільна БД, синхронний ланцюг з 8 викликів
Подієво-орієнтована Піки навантаження, слабко зв’язані процеси, інтеграція кількох систем Eventual consistency, складне трасування, ідемпотентність Ніхто не може відповісти, хто опублікував подію і що має статися при повторі
Serverless / FaaS Нерівномірне навантаження, швидкі експерименти, події від хмарних сервісів Ліміти платформи, холодний старт, vendor lock-in, розмите володіння кодом Бізнес-логіка розмазана по десятках функцій без спільного домену

Джерело: узагальнення практик SEI, моделі C4 і хмарно-нативних оглядів 2025–2026 років, зокрема зсуву до модульних монолітів.

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

Мікросервіси виграють, коли незалежність розгортання уже є бізнес-вимогою: різні SLO, різні команди, різна частота релізів, різна модель відмови. Netflix і подібні кейси тут погані вчителі для команди з дванадцяти людей. Вони розв’язували організаційну проблему сотень команд, а не «чистоту архітектури».

Подієва модель добре лягає на доставку, білінг, нотифікації, оновлення пошуку. Погано — на «натиснув “оплатити” і одразу побачив результат», якщо ви не продумали сагу, компенсації й ідемпотентність ключів. Serverless доречний для обробки зображень, вебхуків, рідкісних звітів. Якщо на ньому зібрати ядро домену інтернет-магазину, через рік ви матимете не архітектуру, а розсип функцій із спільною таблицею в DynamoDB.

Хмарно-нативний звіт CNCF 2025 фіксує іншу реальність інфраструктури: понад 80% користувачів контейнерів уже запускають Kubernetes у продакшені. Це означає, що оркестрація більше не експеримент. Це не означає, що кожен модуль має стати окремим сервісом. Платформа зріла. Стиль усе одно обирають за драйверами, а не за наявністю кластера.

Як зібрати робочу архітектуру з нуля

Починати зі стеку — найшвидший спосіб отримати випадкову структуру. Порядок інший.

1. Зібрати драйвери, а не wishlist технологій

Сідаєте з продактом, експлуатацією й одним сильним розробником і записуєте 6–10 сценаріїв якості. Для кожного: стимул, середовище, реакція, вимірювана відповідь. Приклад для маркетплейсу: «Чорна п’ятниця, 8× звичайного трафіку, каталог і пошук деградують до 1,5 с, оформлення замовлення лишається в межах 500 мс, оплата не втрачає callback від провайдера». Уже цей рядок відсікає ідею «все в одному синхронному запиті».

Паралельно фіксуєте обмеження: розмір команди, хто чергує вночі, чи є DBA, чи потрібен аудит НБУ або GDPR, який бюджет на хмару в перші пів року. Архітектура без обмежень — фантазія.

2. Нарізати систему за зміною, а не за шарами

Шари UI → application → domain → infrastructure корисні всередині модуля. На рівні системи вони провокують «наскрізні» фічі: нова знижка чіпає всі шари одразу. Кращий розріз — за предметними межами, які змінюються разом: Каталог, Кошик і ціноутворення, Замовлення, Оплата, Доставка, Ідентичність, Нотифікації.

Перевірка меж проста. Якщо щоб змінити правило безкоштовної доставки, треба чіпати чотири репозиторії й узгоджувати реліз — межі фальшиві. Якщо правило живе в модулі «Доставка», а «Замовлення» лише читає опубліковану політику — межа жива.

3. Показати систему чотирма висотами, не одним «бог-схемою»

Модель C4 Саймона Брауна закриває типову діру документації. Context — хто користується системою і з якими зовнішніми сервісами вона говорить. Container — застосунки, бази, черги, воркери як одиниці розгортання. Component — основні модулі всередині контейнера. Code малюють лише там, де без цього не зрозуміти нетривіальний механізм, наприклад сагу оплати. Нотація неважлива. Важливо, щоб нова людина за 20 хвилин зрозуміла, куди деплоїти зміну й кого вона зачіпає.

Діаграма показує що вийшло. Вона не пояснює чому. Для «чому» потрібні Architecture Decision Records. Формат Майкла Найгарда досі найпрактичніший: контекст, рішення, статус, наслідки. Один ADR — одне рішення. «Переходимо на мікросервіси» — поганий ADR, бо там сховано двадцять виборів. «Платежі виносимо в окремий сервіс зі своєю БД, каталог лишаємо в моноліті» — хороший.

4. Закласти перевірки, поки дисципліна ще не втомилась

Модульний моноліт без автоматичного контролю залежностей за пів року стане звичайним монолітом. ArchUnit, залежності Gradle/Maven, правила import у лінтері, контрактні тести на межах модулів — це й є архітектура в репозиторії. Те, чого немає в перевірках CI, існує лише в презентації.

Для розподілених частин обов’язковий мінімум інший: трасування запиту (trace id), ідемпотентність входів, таймаути й повторні спроби з джитером, деградація, а не каскадне падіння. Якщо цього немає, «мікросервісна архітектура» — лише мережевий виклик замість виклику функції.

Міфи, які коштують місяців

У реальних кейсах одні й ті самі історії повторюються незалежно від стеку. Нижче — не теорія, а типові самообмани.

«Спочатку зробимо швидко, архітектуру додамо потім». Архітектура з’являється все одно — як випадковий осад від перших рішень. Ви не уникаєте її, ви втрачаєте керування. Для MVP достатньо свідомого моноліта з двома-трьома модулями й одним способом логінування помилок. Це вже архітектура, просто дешева.

«Мікросервіси масштабують систему». Масштабують конкретну вісь навантаження і командну автономію. Якщо вузьке місце — одна таблиця замовлень і синхронний виклик платіжки, розпил на 15 репозиторіїв додасть latency і інциденти, а не RPS. Горизонтальне масштабування моноліта за stateless-сесією часто закриває перші два порядки росту.

«Шарована архітектура = правильна архітектура». Шари впорядковують напрямок залежностей. Вони не дають модульності. Можна мати ідеальні шари й усе одно змінювати дванадцять пакетів заради однієї бізнес-правила.

«Єдина база — спрощення». Спільна БД — це прихована шина інтеграції. Сервіси, які «незалежні», але пишуть у ті самі таблиці, не незалежні. Транзакція через межі команд повертає вас до монолітного реліз-циклу, тільки з мережею посередині.

«Документація застаріває, тому її не пишемо». Застаріває детальний опис класів. Не застарівають ADR і C4-контекст, якщо їх оновлюють у тому ж PR, що й зміну. Діаграма контейнерів на 12 боксів дешевша за онбординг, який триває місяць усно.

«Архітектор — людина, яка малює і зникає». Рішення, яке не доведене до репозиторію, пайплайна й чергування, не існує. Найдорожчий розрив — між «цільовою архітектурою» в Confluence і кодом, який команда пише під дедлайн.

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

Коли система вже «попливла»: план порятунку

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

Перший крок — зупинити розширення хаосу. Нові фічі не кладуть «куди зручно». Вводите правило: зміна живе в модулі-власнику або створює явний публічний інтерфейс. Це неприємно і рятує більше, ніж новий фреймворк.

Далі — карта фактичної архітектури, не бажаної. C4 рівня контейнерів плюс список баз, черг і «тіньових» інтеграцій (спільні таблиці, крос-схеми, файли на FTP, таблиці Google). У реальних кейсах саме тіньові зв’язки пояснюють, чому «незалежний» сервіс падає разом із легасі.

Нарізка йде від болю, не від підручника DDD. Обираєте один потік з високою частотою змін або високою ціною інциденту — наприклад, перерахунок кошика чи callback оплати — і витягуєте його за патерном strangler fig, описаним Мартіном Фаулером: фасад перехоплює виклики, нові сценарії йдуть у новий модуль або сервіс, старі лишаються, поки трафік не переїде. Не чіпаєте все ядро одночасно.

Якщо у вас уже мікросервісний розподілений моноліт, консолідація — нормальний хід, а не капітуляція. Кілька сервісів з однією командою, однією базою й одним ритмом релізів збирають назад у модульний застосунок. Межі лишають у коді. Операційну складність прибирають. Це не «повернення в 2012-й». Це визнання, що стиль має відповідати розміру організації.

Окремий рятівний прийом — архітектурні фітнес-функції: автоматичні перевірки інваріантів. «Модуль Оплата не імпортує Каталог», «сервіс X не ходить у БД Y», «p95 кошика < 400 мс на стейджингу». Вони дешевші за квартальні «архітектурні комітети», які затверджують слайди й не бачать pull request.

Чого не робити під час порятунку: не міняти одночасно стиль, хмару, мову й процес. Не оголошувати «заморозку фіч на пів року заради платформи» без видимих проміжних поставок. Бізнес вимкне такий проєкт раніше, ніж ви доберетесь до красивої цільової схеми.

Коли варто кликати архітектора — і чим він відрізняється від синьйора

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

В українському ринку роль добре оплачувана саме тому, що дефіцитна. За літнім зарплатним звітом DOU 2026 медіана System Architect — 7000, третій квартиль —8375; після зимового просідання група знову серед лідерів. Цифра не доводить якість рішень. Вона показує попит на людей, які вміють не лише малювати, а доводити структуру до продакшену.

Кликати зовнішнього або внутрішнього архітектора варто в кількох ситуаціях, а не «з першого рядка коду».

  • З’являється друга команда, і вже неясно, хто володіє даними користувача.
  • Готуєтесь до пікового сезону, регуляторної перевірки або публічного API для партнерів.
  • Інциденти почали перетинати модулі, яких «ніхто не чіпав».
  • Обговорюєте розпил моноліта або, навпаки, злиття сервісів — обидва рішення важко відкотити.
  • Онбординг нового розробника триває довше за два тижні лише через відсутність карти системи.
  • Бізнес хоче «зробити як у Netflix / як у банківського ядра», не називаючи драйверів.

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

Короткий чек-лист перед стартом розробки або великим рефакторингом:

  • Є 6–10 сценаріїв якості з числами, не прикметниками.
  • Намальовано контекст і контейнери (C4), і вони збігаються з репозиторіями.
  • Межі модулів перевіряються в CI, а не «домовленостями».
  • Кожне дороге рішення має ADR зі статусом і наслідками.
  • Відомо, що деградує першим при відмомі залежності.
  • Є власник кожного критичного потоку даних.
  • Спостережуваність закладена в стиль, а не обіцяна «після релізу».
  • Стиль відповідає розміру команди, а не моді.

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

Ключові інсайти

Архітектура програмного забезпечення — це дисципліна компромісів під атрибути якості, а не каталог модних стилів. Діаграма без драйверів і перевірок у CI нічого не гарантує. Моноліт із живими модулями часто чесніший за мікросервіси зі спільною базою. Документуйте «чому» в ADR і «що» в C4; решту код розкаже сам. Коли система вже болить, рятують межі, фасад і поступове витіснення легасі, а не великий вибух. І найнезручніше: хороша архітектура повторює те, як люди насправді приймають рішення в компанії. Якщо це ігнорувати, код усе одно підлаштується — тільки проти вас.

Leave a Reply

Your email address will not be published. Required fields are marked *