Привіт і ласкаво просимо до моєї першої статті тут! Сьогодні я розповім вам свою особисту історію навчання будівництву архітектури та подоланню всіх труднощів, які з цим пов’язані 🙂
Все почалося три роки тому, коли я вирішив створити надійний та підтримуваний додаток на Express.js. Спочатку моя кодова база була хаотичною: контролери, сервіси і навіть бізнес-логіка були розкидані по всьому проекту.
Як це було раніше:
Але після численних спроб, я знайшов структуру папок, яка нарешті принесла порядок у цей хаос:
У папці app
кожна підпапка відповідає за унікальну частину системи:
- Контролери обробляють запити та відповіді, знаходячись на тонкому шарі, що делегує основну роботу іншим частинам.
Як виглядає папка контролерів (модулі)
2.
Маршрути визначають реальні кінцеві точки, групуючи їх за доменами або функціональністю для кращої зрозумілості.
Як виглядає папка з маршрутами (ми маємо папку pulse, але це лише через деякі експерименти там)
3. Сервіси містять основну бізнес-логіку, гарантуючи, що контролери залишаються без зайвого навантаження.
- Допоміжні функції зберігають функції, що повторно використовуються, щоб уникнути дублювання коду.
- Моделі відображають структури бази даних, допомагаючи підтримувати послідовний підхід до даних.
- DTO (Об'єкти передачі даних) гарантують цілісність даних при їх передачі між шарами.
- Скрипти автоматизують задачі, такі як насіння бази даних чи міграції, зберігаючи ці процеси організованими.
- Типи централізують всі визначення TypeScript для повторного використання та надійності.
6.
Утиліти містять утилітарні класи або спеціалізовану функціональність, яка не зовсім підходить до інших папок.
Тим часом папка tests
стоїть окремо, щоб тримати всю логіку тестування подалі від продакшн-коду. Усередині можна знайти підпапку unit
для тестування маленьких, ізольованих частин функціональності, а також, можливо, підпапку integration
для тестування того, як різні модулі працюють разом.
На початку я змішував тести в тих самих директоріях, що й мої контролери та сервіси, але їх розділення допомогло чіткіше зрозуміти, що де має бути.
Пам’ятаю приклад з одного з моїх перших великих рефакторингів: я перемістив заплутану логіку кінцевої точки входу для логіну з контролера в окремий AuthService
. Раптом код контролера зменшився до кількох рядків, а відлагодження стало набагато легшим. Крім того, я створив LoginDTO
для обробки вхідних запитів на логін, гарантуючи, що мій сервіс отримує правильні дані.
Це не лише покращило зручність читання коду, але й дозволило TypeScript виявляти помилки на ранніх етапах, рятуючи мене від сороміцьких багів у продакшн-коді.
Зрештою, справа була не лише в акуратності — мова йшла про зменшення технічного боргу та спрощення життя для всіх учасників. Коли ми залучали нових розробників, встановлена структура папок служила своєрідною картою, яка вела їх через контролери, маршрути та сервіси без плутанини. Вони розуміли потік даних від запиту, що потрапляє в маршрут (route), проходить через контролер (controller), обробляється сервісом (service) і використовує модель (model) для взаємодії з базою даних.
З кожною новою функцією розподіл обов'язків зробив перегляд коду швидшим і дозволив розвивати проект модульно. Така архітектура також дозволила нам повторно використовувати код у різних доменах через хелпери (helpers), утиліти (utilities) та DTO (Data Transfer Objects), замість того, щоб щоразу переписувати однакові функції.
Невдовзі ми почали спостерігати менше багів, простіші злиття та швидший випуск нових функцій.
Оглядаючись на цей шлях, я можу з упевненістю сказати, що добре спроектована папка app
, в парі з окремою папкою tests
, є основою чистого, масштабованого проекту на Express.js. Кожного разу, коли я розпочинаю новий проєкт, я починаю з цих папок, готуючи їх для контролерів (controllers), маршрутів (routes), сервісів (services), хелперів (helpers), моделей (models), DTO (Data Transfer Objects), скриптів (scripts), типів (types) і утиліт (utils). Потім я налаштовую свої тести, щоб кожна частина коду була ретельно перевірена.
Ця структура папок, разом із статичним типізуванням TypeScript, сприяє порядку та надійності коду. Вона допомагає всім у команді бути на одній хвилі, значно знижує головний біль від налагодження та дозволяє додатку без проблем розвиватися. Ось така історія про те, як я знайшов архітектуру, яка не тільки виглядає акуратно ззовні, але й дає мені впевненість у тому, щоб братися за будь-яку функцію або масштабувати проект до нових висот.
А якщо ви на подібному шляху,
Сподіваюся, що ці уроки допоможуть вам досягти більш акуратного та підтримуваного майбутнього з Express.js.
Перекладено з: The Most Efficient Architecture for Your Express.js Project: A Story of Lessons Learned