Принципи розробки сучасних програм від NGINX. Частина 1

Привіт друзі. Напередодні запуску курсу "Backend розробник на PHP", Традиційно ділимося з вами перекладом корисного матеріалу.

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

Принципи розробки сучасних програм від NGINX. Частина 1

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

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

Принципи розробки сучасних програм від NGINX. Частина 1

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

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

Застосувавши ці принципи, ви виявите, що ви користуєтеся останніми тенденціями в розробці програмного забезпечення, включаючи підхід DevOps до розробки та доставки додатків, використання контейнерів (наприклад, Docker) та фреймворків для оркестрації контейнерів (наприклад, Кубернетес), використання мікросервісів (включаючи Мікросервісну Архітектуру NGINX и архітектура мережного зв'язку для мікросервісних програм.

Що таке сучасний додаток?

Сучасні програми? Сучасний стек? Що означає «сучасний»?

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

Сучасна програма підтримує кілька клієнтів, будь то інтерфейс користувача на бібліотеці JavaScript React, мобільний додаток під Android або iOS, або додаток, який з'єднується з іншим за API. Сучасна програма передбачає наявність невизначеної кількості клієнтів, для яких вона надає дані або сервіси.

Сучасна програма надає API для доступу до запитуваних даних та сервісів. API має бути постійним і незмінним, а чи не написаним безпосередньо під специфічний запит з якогось конкретного клієнта. API доступний за HTTP(S) і забезпечує доступ до всього функціонала, який є у GUI або CLI.

Дані мають бути доступними у загальноприйнятому, сумісному форматі, такому як JSON. API надає об'єкти та служби у зрозумілій, організованій формі, наприклад, RESTful API або GraphQL забезпечують гідний інтерфейс.

Сучасні програми будуються на сучасному стеку, а сучасний стек – це той стек, який підтримує такі програми, відповідно. Такий стек дозволяє розробнику з легкістю створювати додаток з інтерфейсом HTTP і чіткими кінцевими точками API. Вибраний підхід дозволить вашому додатку легко приймати та надсилати дані у форматі JSON. Іншими словами, сучасний стек відповідає елементам Дванадцяти-Факторного додатку для мікросервісів.

Популярні версії цього типу стека засновані на Java, Python, вузол, рубін, PHP и Go. Мікросервісна Архітектура NGINX уособлює приклад сучасного стека, реалізованого кожною зі згаданих мов.

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

Принципи

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

Один із принципів звучить як «створюйте маленькі програми», давайте просто назвемо його принципом малості. Існують неймовірно складні програми, які складаються з великої кількості рухомих компонентів. У свою чергу побудова програми з невеликих дискретних компонентів спрощує його проектування, обслуговування та роботу з ним загалом. (Зверніть увагу, ми сказали «спрощує», а не «робить простим»).

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

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

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

Давайте розглянемо ці три принципи детальніше.

Принцип малості

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

Принципи розробки сучасних програм від NGINX. Частина 1

Програми декомпозуються з таких причин:

  • Зниження когнітивного навантаження на розробників;
  • Прискорення та спрощення тестування;
  • Швидка доставка змін у додатку.


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

Отже, три способи знизити когнітивне навантаження:

  1. Зменшити часові рамки, які вони повинні враховувати при розробці нової функції – чим коротший таймфрейм, тим нижчим є когнітивне навантаження.
  2. Зменшити кількість коду над яким ведеться одноразова робота – менше коду – менше навантаження.
  3. Спростити процес внесення інкрементальних змін у додаток.

Зменшення часових рамок розробки

Повернемося у ті часи, коли методологія waterfall був стандартом для процесу розробки, і тимчасові рамки від шести місяців до двох років для розробки або оновлення програми були загальною практикою. Як правило, спочатку інженери читали відповідні документи, такі як вимоги до продукту (PRD), довідковий документ системи (SRD), план архітектури та починали поєднувати всі ці речі разом в одну когнітивну модель, відповідно до якої вони писали код. У міру того, як вимоги та, відповідно, архітектура змінювалися, доводилося докладати серйозних зусиль для інформування всієї команди про оновлення когнітивної моделі. Такий підхід у найгіршому випадку міг просто паралізувати роботу.

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

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

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

Невеликі кодові бази

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

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

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

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

Маленькі інкрементальні зміни

Останній елемент принципу малості – це керування змінами. Особливою спокусою для розробників вважається подивитися на базу коду (навіть, можливо, на свій власний, старіший код) і заявити: "Це лайно, нам потрібно це все переписати". Іноді це правильне рішення, інколи ж ні. Воно покладає на команду розробників тягар глобальної зміни моделі, що, у свою чергу, призводить до масштабного когнітивного навантаження. Краще, щоб інженери зосереджувалися на змінах, які вони можуть зробити протягом спринту, щоб потім своєчасно викотити необхідний функціонал, нехай і поступово. Кінцевий продукт повинен нагадувати попередньо запланований, але з деякими змінами та тестуванням, щоб відповідати потребам клієнта.

При переписуванні великих частин коду іноді швидко здійснити доставку зміни виявляється неможливим, оскільки вступають у гру інші залежності системи. Щоб контролювати потік змін, можна використовувати відключення функціоналу (feature hiding). У принципі, це означає функціонал є на продакшні, але він недоступний за допомогою налаштувань змінних середовища (env-var) або будь-якого іншого механізму конфігурації. Якщо код пройшов усі процеси перевірки якості, то він може опинитися у продакшені у прихованому стані. Однак, ця стратегія працює тільки якщо функція зрештою буде включена. В іншому випадку вона лише захаращуватиме код і додасть когнітивного навантаження, з яким доведеться впоратися розробнику для продуктивної роботи. Управління змінами та інкрементальні зміни власними силами допомагають підтримувати когнітивне навантаження розробників на доступному рівні.

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

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

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

Кінець першої частини.

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

Джерело: habr.com

Додати коментар або відгук