Кожен день, кожну мить протягом нашої інженерної кар'єри ми стикаємося з багатьма різними проблемами різної складності та ситуаціями, коли нам потрібно прийняти рішення або відкласти його через брак даних. Щоразу, коли ми будуємо нові сервіси, будуємо інфраструктуру чи навіть формуємо процеси розробки, ми торкаємося величезного світу різноманітних викликів.
Перелічити всі проблеми складно, а можливо, навіть неможливо. Ви зіткнетеся з деякими з цих проблем, лише якщо працюєте в певній ніші. З іншого боку, є багато проблем, які ми всі повинні розуміти, як вирішити, оскільки вони мають вирішальне значення для створення ІТ-систем. З високою ймовірністю ви зустрінете їх у всіх проектах.
У цій статті я поділюся своїм досвідом щодо деяких проблем, з якими зіткнувся під час створення програмного забезпечення.
Якщо ми заглянемо у Вікіпедію, то знайдемо таке визначення
У аспектно-орієнтованій розробці програмного забезпечення наскрізні проблеми — це аспекти програми, які впливають на декілька модулів, без можливості бути інкапсульованими в будь-якому з них. Ці проблеми часто неможливо чітко відокремити від решти системи як при проектуванні, так і при реалізації, і це може призвести до розпорошення (дублювання коду), заплутування (значних залежностей між системами) або обох.
Це детально описує, що це таке, але я хочу трохи розширити та спростити це:
Наскрізне занепокоєння – це концепція або компонент системи/організації, який впливає (або «перетинає») багато інших частин.
Найкращими прикладами таких проблем є архітектура системи, журналювання, безпека, керування транзакціями, телеметрія, дизайн бази даних та багато інших. Далі в цій статті ми розглянемо багато з них.
На рівні коду наскрізні проблеми часто реалізуються за допомогою таких методів, як аспектно-орієнтоване програмування (AOP) , де ці проблеми поділяються на окремі компоненти, які можна застосовувати в усій програмі. Це зберігає бізнес-логіку ізольованою від цих проблем, роблячи код більш читабельним і зручним для обслуговування.
Існує багато можливих способів класифікації аспектів шляхом їх сегментації за різними властивостями, такими як обсяг, розмір, функціональність, важливість, ціль та інші, але в цій статті я використовуватиму просту класифікацію обсягу. Під цим я маю на увазі, куди спрямований цей конкретний аспект, незалежно від того, чи це вся організація, окрема система чи окремий елемент цієї системи.
Отже, я збираюся розділити аспекти на макро та мікро .
Під макроаспектом я маю на увазі в основному міркування, яких ми дотримуємося для всієї системи, як-от обрана архітектура системи та її дизайн (монолітна, мікросервіси, сервіс-орієнтована архітектура), технологічний стек, організаційна структура тощо. Макроаспекти пов’язані в основному зі стратегічним і високорівневим рішення.
Між тим, мікроаспект набагато ближчий до рівня коду та розробки. Наприклад, який фреймворк використовується для взаємодії з базою даних, структура проекту папок і класів або навіть шаблони проектування конкретних об’єктів.
Хоча ця класифікація не є ідеальною, вона допомагає структурувати розуміння можливих проблем, а також важливості та впливу рішень, які ми застосовуємо до них.
У цій статті моя основна увага буде зосереджена на макроаспектах.
Коли я тільки почав вивчати архітектуру програмного забезпечення, я прочитав багато цікавих статей про закон Конвея та його вплив на організаційну структуру. Особливо цей . Отже, цей закон говорить про це
Будь-яка організація, яка розробляє систему (у широкому значенні), створить проект, структура якого є копією комунікаційної структури організації.
Я завжди вважав, що ця концепція справді дуже універсальна і представляє золоте правило.
Тоді я почав вивчати підхід Еріка Еванса до моделювання систем, орієнтований на домен (DDD). Ерік Еванс підкреслює важливість ідентифікації обмеженого контексту. Ця концепція передбачає поділ складної моделі предметної області на менші, більш керовані секції, кожна з яких має власний обмежений набір знань. Цей підхід сприяє ефективній командній комунікації, оскільки зменшує потребу в глибоких знаннях усієї області та мінімізує перемикання контексту, що робить розмови ефективнішими. Перемикання контексту — це найгірша і найбільш ресурсозатратна річ. Навіть комп'ютери борються з цим. Хоча навряд чи вдасться досягти повної відсутності перемикання контексту, я вважаю, що це те, до чого ми повинні прагнути.
Повертаючись до закону Конвея, я знайшов у ньому кілька проблем.
Перша проблема, з якою я зіткнувся у зв’язку із законом Конвея, який припускає, що дизайн системи відображає організаційну структуру, — це потенціал для формування складних і всеохоплюючих обмежених контекстів. Ця складність виникає, коли організаційна структура не узгоджується з межами домену, що призводить до обмежених контекстів, які сильно взаємозалежні та завантажені інформацією. Це призводить до частого перемикання контексту для команди розробників.
Інша проблема полягає в тому, що організаційна термінологія просочується на рівень коду. Коли організаційні структури змінюються, це вимагає модифікації кодової бази, споживаючи цінні ресурси.
Таким чином, дотримання інверсного маневру Конвея допомагає побудувати систему та організацію, які заохочують бажану архітектуру програмного забезпечення. Однак варто зазначити, що цей підхід не дуже добре працюватиме у вже сформованій архітектурі та структурах, оскільки зміни на цьому етапі тривають, але він винятково ефективний у стартапах, оскільки вони швидко вносять будь-які зміни.
Цей шаблон або «антишаблон» створює систему без будь-якої архітектури. Немає ні правил, ні меж, ні стратегії, як контролювати неминучу зростаючу складність. Складність є найстрашнішим ворогом на шляху створення програмних систем.
Щоб уникнути побудови такого типу системи, нам потрібно дотримуватися певних правил і обмежень.
Існує безліч визначень архітектури програмного забезпечення. Мені подобається багато з них, оскільки вони охоплюють різні його аспекти. Однак, щоб мати можливість міркувати про архітектуру, нам потрібно природно сформувати деякі з них у своїй свідомості. І варто зазначити, що це визначення може розвиватися. Тож, принаймні на даний момент, я маю для себе такий опис.
Архітектура програмного забезпечення — це рішення та вибір, які ви робите щодня, які впливають на побудовану систему.
Щоб приймати рішення, необхідно мати в «сумці» принципи та шаблони для вирішення виникаючих проблем, також важливо зазначити, що розуміння вимог є ключовим для побудови того, що потрібно бізнесу. Однак інколи вимоги є непрозорими або навіть невизначеними, у цьому випадку краще почекати з отриманням додаткових роз’яснень або покладатися на свій досвід і довіряти своїй інтуїції. Але в будь-якому випадку ви не можете правильно приймати рішення, якщо у вас немає принципів і шаблонів, на які можна спиратися. Ось де я підходжу до визначення стилю архітектури програмного забезпечення.
Стиль архітектури програмного забезпечення — це набір принципів і шаблонів, які визначають, як створювати програмне забезпечення.
Існує багато різних архітектурних стилів, орієнтованих на різні сторони запланованої архітектури, і застосування декількох з них одночасно є нормальною ситуацією.
Наприклад, такі як:
Монолітна архітектура
Дизайн, орієнтований на домен
На основі компонентів
Мікросервіси
Труба і фільтри
Керований подіями
Мікроядро
Сервісно-орієнтований
і так далі...
Звичайно, вони мають свої переваги та недоліки, але найголовніше, що я дізнався, це те, що архітектура розвивається поступово, залежно від реальних проблем. Початок роботи з монолітної архітектури є чудовим вибором для зменшення операційних складнощів, дуже ймовірно, що ця архітектура відповідатиме вашим потребам навіть після досягнення етапу відповідності продукту ринку (PMI) створення продукту. У масштабі ви можете розглянути можливість переходу до підходу, керованого подіями, і мікросервісів для досягнення незалежного розгортання, гетерогенного середовища стеку технологій і менш зв’язаної архітектури (і тим часом менш прозорого через характер підходів, керованих подіями та pub-sub, якщо вони прийняті). Простота і ефективність близькі і мають великий вплив один на одного. Зазвичай складні архітектури впливають на швидкість розробки нових функцій, підтримку та підтримку існуючих і викликають природну еволюцію системи.
Однак складні системи часто вимагають складної та комплексної архітектури, що є неминучим.
Чесно кажучи, це дуже широка тема, і є багато чудових ідей про те, як структурувати та будувати системи для природної еволюції. На основі свого досвіду я виробив такий підхід:
Також важливо розуміти цифри та показники, такі як DAU (активні користувачі за день), MAU (активні користувачі за місяць), RPC (запит за секунду) і TPC (транзакція за секунду), оскільки це може допомогти вам зробити вибір, оскільки архітектура для 100 активних користувачів і 100 мільйонів активних користувачів різні.
Наостанок я б сказав, що архітектура має значний вплив на успіх продукту. Для масштабування потрібна погано розроблена архітектура для продуктів, що, швидше за все, призведе до невдачі, оскільки клієнти не чекатимуть, поки ви масштабуєте систему, вони виберуть конкурента, тому ми повинні випереджати потенційне масштабування. Хоча я визнаю, що іноді це не може бути економним підходом, ідея полягає в тому, щоб мати масштабовану, але ще не масштабовану систему. З іншого боку, маючи дуже складну та вже масштабовану систему без клієнтів або планів отримати багато з них, ви даремно коштуватимете грошей на свій бізнес.
Вибір стека технологій також є рішенням на макрорівні, оскільки воно впливає на наймання, перспективи природного розвитку системи, масштабованість і продуктивність системи.
Ось список основних міркувань для вибору технологічного стека:
Як наявність кількох стеків технологій може вплинути на розвиток бізнесу?
З одного боку, запровадження ще одного стека може збільшити ваші найми, але з іншого боку, це принесе додаткові витрати на обслуговування, оскільки вам потрібно підтримувати обидва стеки. Отже, як я вже казав раніше, з моєї точки зору, тільки додаткова потреба повинна бути аргументом для включення більшої кількості стеків технологій.
Але як щодо принципу вибору найкращого засобу для конкретної проблеми?
Іноді у вас немає іншого вибору, окрім як запровадити нові інструменти для вирішення конкретної проблеми на основі тих самих міркувань, які згадані вище, у таких випадках має сенс вибрати найкраще рішення.
Створення систем без високого зв'язку з конкретною технологією може бути проблемою. Тим не менш, корисно прагнути до умов, коли система не буде тісно пов’язана з технологіями, і вона не помре, якщо завтра певний фреймворк або інструмент стане вразливим або навіть застарілим.
Ще один важливий аспект пов’язаний із залежностями програмного забезпечення з відкритим кодом і пропрієтарного програмного забезпечення. Власне програмне забезпечення дає вам меншу гнучкість і можливість налаштування. І все ж найнебезпечнішим фактором є прив’язка до постачальника, коли ви стаєте залежними від продуктів, цін, умов і плану постачальника. Це може бути ризиковано, якщо постачальник змінить напрямок, підвищить ціни або припинить випуск продукту. Програмне забезпечення з відкритим кодом зменшує цей ризик, оскільки окрема організація не контролює його. Усунення єдиної точки відмови на всіх рівнях є ключем до створення надійних систем для зростання.
Єдина точка відмови (SPOF) відноситься до будь-якої частини системи, яка, якщо виходить з ладу, призведе до припинення функціонування всієї системи. Усунення SPOF на всіх рівнях має вирішальне значення для будь-якої системи, яка вимагає високої доступності. Все, включаючи знання, персонал, системні компоненти, хмарні провайдери та інтернет-кабелі, може вийти з ладу.
Є кілька основних методів, які ми можемо застосувати для усунення окремих точок відмови:
У цій статті ми розглянули кілька ключових макроаспектів і те, як ми можемо впоратися з їх складністю.
Дякую за читання! До зустрічі наступного разу!