Як навчитися проектуванню та архітектурі програмного забезпечення - дорожня карта

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

Для мене божевільно вважати той факт, що Facebook колись був порожнім текстовим файлом на чиїмось комп’ютері.

Лол.

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

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

Я розбив його на два артефакти: стек і карту .

Стек

Подібно до моделі OSI у мережі, кожен шар будується поверх основи попереднього.

Стек

Карта

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

Ось це нижче! Щоб розгалужити репо, прочитайте мою докладну запис і завантажте її у високій роздільній здатності, натисніть тут.

Дорожня карта проектування та архітектури програмного забезпечення

Етап 1: Чистий код

Першим кроком до створення довготривалого програмного забезпечення є з’ясування того, як написати чистий код .

Чистий код - це код, який легко зрозуміти та змінити. На низькому рівні це проявляється в декількох варіантах дизайну, таких як:

  • бути послідовним
  • віддаючи перевагу значущим змінам, методам та класам перед написанням коментарів
  • забезпечення коду з відступами та належним інтервалом
  • забезпечення всіх тестів
  • написання чистих функцій без побічних ефектів
  • не передаючи null

Написання чистого коду неймовірно важливо.

Подумайте про це як про гру в дженгу.

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

Найкращий ресурс для вивчення написання чистого коду - книга дядька Боба "Чистий код".

Етап 2: Парадигми програмування

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

У книзі дядька Боба "Чиста архітектура" він звертає увагу на те, що:

  • Об'єктно-орієнтоване програмування - інструмент, який найкраще підходить для визначення того, як ми перетинаємо архітектурні межі за допомогою поліморфізму та плагінів
  • Функціональне програмування - це інструмент, який ми використовуємо для розширення даних до меж наших додатків
  • та Структуроване програмування - це інструмент, який ми використовуємо для написання алгоритмів

Це означає, що ефективне програмне забезпечення використовує гібридні всі 3 стилі парадигм програмування в різний час.

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

Якщо у вас є лише молоток, все здається цвяхом.

Ресурси

Для функціонального програмування перевірте:

  • В основному адекватний посібник професора Фрісбі з функціонального програмування
  • Моделювання доменів зроблено функціональним

Етап 3: Об’єктно-орієнтоване програмування

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

Об’єктно-орієнтоване програмування не тільки дозволяє нам створювати архітектуру плагінів та вбудовувати гнучкість у наші проекти; OOP постачається з 4 принципами ООП (інкапсуляція, успадкування, поліморфізм та абстракція), які допомагають нам створювати багаті моделі доменів .

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

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

Чому це величезна справа?

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

Етап 4: Принципи проектування

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

Але ООП може створити деякі складні завдання.

Коли слід використовувати склад?

Коли слід використовувати спадщину?

Коли слід використовувати абстрактний клас?

Принципи проектування - це справді усталені та перевірені на бої об'єктно-орієнтовані найкращі практики, які ви використовуєте в якості залізничних охоронців.

Ось приклади загальних принципів проектування, з якими вам слід ознайомитись:

  • Склад над спадщиною
  • Інкапсулюйте те, що варіюється
  • Програма проти абстракцій, а не конкрементів
  • Голлівудський принцип: "Не дзвоніть нам, ми зателефонуємо вам"
  • Тверді принципи, особливо принцип єдиної відповідальності
  • СУХИЙ (Не повторюйся)
  • ЯГНІ (тобі це не знадобиться)

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

Етап 5: Шаблони дизайну

Практично кожна проблема в програмному забезпеченні вже класифікована та вирішена. Ми називаємо ці візерунки: насправді шаблони дизайну.

Існує 3 категорії моделей дизайну: креативні , структурні та поведінкові .

Творчі

Творчі зразки - це зразки, що контролюють спосіб створення об’єктів.

Приклади творчих моделей включають:

  • Шаблон Singleton , для забезпечення тільки один екземпляр класу може існувати
  • Шаблон Abstract Factory , для створення екземпляра декількох сімейств класів
  • Моделі прототипу , для початку з екземпляром , який клонований з існуючого

Структурні

Структурні зразки - це зразки, які спрощують спосіб визначення взаємозв'язку між компонентами.

Приклади структурних конструкцій включають:

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

Поведінковий

Поведінкові моделі - це загальноприйняті моделі для полегшення елегантного спілкування між предметами.

Прикладами моделей поведінки є:

  • Шаблон Шаблон для відкладаючи точні кроки алгоритму до підкласу.
  • Шаблон Посередника , для визначення точних каналів зв'язку дозволених між класами.
  • Шаблон Observer , для включення класів , щоб підписатися на що - то інтерес, і отримувати повідомлення , коли відбулася зміна.

Критика дизайну

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

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

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

Ресурси

Гуру рефакторингу - Шаблони дизайну

Етап 6: Архітектурні принципи

Зараз ми перебуваємо на вищому рівні мислення поза класовим.

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

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

Ось те, що я рекомендував би навчитися відразу:

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

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

Етап 7: Архітектурні стилі

Архітектура - це те, що має важливе значення.

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

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

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

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

Структурний

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

Ось кілька прикладів:

  • Архітектури на основі компонентів наголошують на розділенні проблем між окремими компонентами в системі. Подумайте про Google на секунду. Поміркуйте, скільки додатків вони мають у своєму підприємстві (Google Docs, Google Drive, Google Maps тощо). Для платформ з великою кількістю функціональних можливостей архітектури, що базуються на компоненті, розділяють ці проблеми на слабо пов'язані незалежні компоненти. Це горизонтальне розділення.
  • Монолітність означає, що додаток об'єднано в єдину платформу або програму, розгорнуту в цілому. Примітка. Ви можете мати монолітну архітектуру на основі компонентів, якщо правильно розділити свої програми, але все це розгорнути як єдине ціле .
  • Багатошарові архітектури розділяють проблеми вертикально , розрізаючи програмне забезпечення на інфраструктуру, прикладні та доменні рівні.

Чиста архітектура

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

Повідомлення

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

Ось кілька прикладів архітектурних стилів на основі повідомлень:

  • Керовані подіями архітектури розглядають усі значущі зміни стану як події. Наприклад, у додатку для торгівлі вінілами стан пропозиції може змінитися з "очікує на розгляд" на "прийнятий", коли обидві сторони домовляться про торгівлю.
  • Архітектури публікації-передплати будуються на основі шаблону дизайну Observer, роблячи його основним методом зв'язку між самою системою, кінцевими користувачами / клієнтами та іншими системами та компонентами.

Розподілений

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

Кілька прикладів розподілених архітектурних стилів:

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

8 етап: Архітектурні зразки

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

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

  • Управління доменами - це підхід до розробки програмного забезпечення проти дійсно складних проблемних доменів. Щоб DDD був найбільш успішним, нам потрібно застосувати багаторівневу архітектуру , щоб відокремити проблеми доменної моделі від інфраструктурних деталей, які змушують програму насправді працювати, наприклад, бази даних, веб-сервери, кеші тощо.
  • Model-View Controller - це, мабуть, найвідоміший архітектурний шаблон для розробки додатків на основі користувальницького інтерфейсу. Він працює, розділивши додаток на 3 компоненти: модель, вигляд та контролер. MVC неймовірно корисний, коли ви вперше починаєте працювати, і він допомагає вам перекластись на інші архітектури, але є момент, коли ми усвідомлюємо, що MVC недостатньо для проблем з великою кількістю бізнес-логіки.
  • Джерело подій - це функціональний підхід, коли ми зберігаємо лише операції, а ніколи не державу. Якщо нам коли-небудь знадобиться держава, ми можемо застосовувати всі операції з самого початку.

Етап 9: Моделі підприємств

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

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

Де в моделі (М) ми обробляємо ці речі ?:

  • логіка перевірки
  • інваріантні правила
  • доменні події
  • випадки використання
  • складні запити
  • та ділова логіка

Якщо ми просто використовуємо ORM (об'єктно-реляційний маппер), як Sequelize або TypeORM, як модель , все це важливе, що залишається для інтерпретації, куди йому слід йти, і воно опиняється в якомусь невизначеному шарі між (що має бути багатим) ) модель і контролер .

mvc-2

Взято з "3.1 - Тонкі (без логіки) моделі" у Solidbook.io.

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

Для кожної з тих речей, які MVC не вдається вирішити, існують інші моделі підприємств для їх вирішення. Наприклад:

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

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

Структури інтеграції

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

Це, мабуть, найскладніші речі: масштабування, аудит та ефективність .

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

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

Це може бути складно реалізувати, але загальні архітектури в кінцевому підсумку виглядають заснованими на подіях і спираються на широкий спектр концепцій, принципів та практик дизайну програмного забезпечення та систем, таких як Storming Event, DDD, CQRS (сегрегація відповідей командного запиту) та джерело подій .

Сподіваюся, це було вам корисно!

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

На здоров’я!

Розгалужте його на GitHub

Прочитайте книгу про дизайн та архітектуру програмного забезпечення

Прочитайте запис

khalilstemmler.com - я викладаю найкращі практики розширених TypeScript та Node.js для великомасштабних додатків та того, як писати гнучке програмне забезпечення, яке підтримується.