Clean Architecture: Як побудувати ідеальну архітектуру для проєктів на Node.js та TypeScript

Поділитися
Вставка
  • Опубліковано 10 лют 2025
  • Хочеш створювати масштабовані та підтримувані застосунки на Node.js та TypeScript?
    У цьому відео розбираємо Clean Architecture: принципи, рівні, залежності та кращі практики на прикладі Node.js + TypeScript.
    Дізнайся, як правильно організувати код, використовувати DDD, Repository Pattern, Dependency Injection та зробити свій застосунок гнучким і зрозумілим.
    Repository with code: github.com/ser...
    🔹 Що ти дізнаєшся у відео?
    ✅ Основи Чистої Архітектури
    ✅ Як правильно розділяти рівні: Domain, Application, Infrastructure, Presentation
    ✅ Патерни Repository, Use Case, Entity, DTO
    ✅ Як зменшити залежності та зробити код тестованим
    ✅ Реальний приклад проєкту на Node.js і TypeScript
    📌 Підписуйся, якщо хочеш більше якісного контенту про архітектуру та розробку! 🚀

КОМЕНТАРІ • 39

  • @durko_o
    @durko_o День тому

    Дуже класна робота, дякую!

  • @rifatismailov
    @rifatismailov 3 дні тому +1

    Дякую. Дякую що Українською. Чудовий курс.

  • @ЖеняЮнчик-н3ь
    @ЖеняЮнчик-н3ь 4 дні тому +1

    Мені подобається, як ти подаєш матеріал і наскільки ретельно підготувався до цього відео - це справді велика робота!

  • @sergeysadovyy7637
    @sergeysadovyy7637 9 днів тому +2

    Дуже дякую за ваші старання

  • @BorysYermokhin
    @BorysYermokhin 7 днів тому +1

    Дякую, дуже корисно нагадати собі такі речі

  • @MrSeredan
    @MrSeredan 5 днів тому

    Дякую. Дуже цікаво і приємно було послухати. Гарно пояснюєте

  • @pinyagoffman
    @pinyagoffman 9 днів тому +2

    Дуже корисно, дякую

  • @nest_ua
    @nest_ua 3 дні тому

    🙌

  • @ThePieceofmeat
    @ThePieceofmeat 3 дні тому

    Дякую, все дуже добре і зрозуміло, особливо з готовим кодом на гітхабі.
    Неочікувано було зустріти інтерфейс до репозиторія в папці domain/repositories, чи не краще його розташувати власне в infrastructure?
    З тем які цікаво було б послухати
    - application VS domain logic на реальних прикладах
    - event bus для послаблення залежностей між модулями та як не перетворити цю взаємодію на dumpster fire
    - сенс розбиття сервісу на окремі use case
    - про транзакції в БД вже вище питали

    • @G0rynych
      @G0rynych 2 дні тому

      >> чи не краще його розташувати власне в infrastructure?
      Якщо ми це зробимо, ми порушимо DIP, бо тоді домен буде залежати від infrastructure (у випадку автора - не домен, а application, але тільки тому, що у нього service лежить не там де треба)

    • @ThePieceofmeat
      @ThePieceofmeat 2 дні тому

      ​​@@G0rynych Чому, все там буде нормально, у автора сервіс залежить не від реалізації, а від інтерфейсу репозиторія, як DIP власне і передбачає.
      import type ... from "infrastructure/repositories" - це не залежність від infrastructure
      Ну або винести всі типи в types. ts або окрему директорію types, щоб не було плутанини

    • @G0rynych
      @G0rynych День тому

      @ Так, формально у нього DIP не порушений, я про не кажу. А порушена Clean Architecture, про яку він і розповідає. Бо коли він з таким підходом буде шось писати далі, то в результаті бізнес-логіка буде розмана тонкім шаром по всьому проєкту.

  • @maxbasov5485
    @maxbasov5485 6 днів тому +1

    Сам зараз замаюсь цією темою-було б цікаво подивитись реалізацію:
    1 взаємодії між модулями
    2 реалізацію db-transactions особливо в цій дебільній прізмі(вибачте це особисте 😂) коли треба наприклад з двох різних модулів зберегти моделі але консистентно, тобто в рамках однієї транзакції

    • @patern_donchenko
      @patern_donchenko  6 днів тому

      Подивіться в сторону патерну "Unit Of Work", де привʼязуючись до концепції DDD на інфраструктурному рівні реалізуємо логіку роботи з різними репозитаріями(використовуються методи-фабрики для створення обʼєктів репок) та транзаціями. Таким чином, не випускаючи деталі PRISMA в доменний рівень, бо тут є величезна спокуса втулити цю логіку в useCase або навіть controller.
      Розширю свій приклад, цією імплементацією згодом.

    • @SheremetRuslan
      @SheremetRuslan 5 днів тому

      ​@@patern_donchenkoдля того, щоб декілька послідовних запитів до бази даних зробити, треба використовувати Query builders з prepared statements, потім вже в певному репозиторії огортати ці об'єднані запити в транзакцію і тільки потім виконувати. Тобто має бути ще розділення коду по формуванню SQL запиту, від колу його виконання!
      А щоб запити були ще чистіше, робити треба stored functions в самій Postgres DB. По факту треба буде в застосунку лише прописати Input/Output параметри без деталей самого SQL.

  • @yuriiovdiienko2126
    @yuriiovdiienko2126 9 днів тому +2

    А якщо ми пишемо проект на несті, то ж виходить що наш application залежний від фреймворку, бо там декоратори всякі використовуємо і тд???

    • @patern_donchenko
      @patern_donchenko  7 днів тому

      Дивіться, мова йде про ізоляцію бізне-логіки від впливу "третіх"-бібліотек, що використовуються в проектові. Декоратори - це мовна конструкція, яка використовуєтьcя широко Nest для своєї роботи. Зрозуміло, що 100 % ізоляція - просто не можлива, але тримати це на контролі потрібно.

  • @lyudmylashumey263
    @lyudmylashumey263 День тому

    Щось постійно читаю шароварна архітектура :)

  • @G0rynych
    @G0rynych 2 дні тому

    О, вже краще )). В цьому відео вже виправлені моменти стосовно залежностей між шарами, але всеж-таки, нажаль, з самою архітектурою недорозібралися (.
    Що не так:
    1) Знову звідкись з'являється історія про data transfer structures між шарами, тобто там, де немає ніякого data transfer. Поясніть мені - нашо, от нашо вони вам там? І ні - вони нічого не захищають, і нема там ніякої оптимізації, і нема ніякої різниці між DTO/SDTO =)
    2) В коді - ProductItemDTO знаходиться на рівні application, а має бути в presentation/controllers
    3) Проблема з розподіленням реалізації - ProductService, який має бути в домені, а на рівні application має бути... якійсь Application. Зараз це не дуже очевидно, бо в прикладі є там два запити та немає жодної команди. А коли ви почнете їх додавати - стикнетесь з проблемкою.

  • @pavlovalor
    @pavlovalor 5 днів тому

    Одразу підписка

  • @D9ID9I
    @D9ID9I 6 днів тому +1

    Domain logic це набір окремих модулів/бібліотек, які живуть у своїх репозиторіях і своїх неймспейсах.
    Не повинно воно бути у одному репозиторії з application. Ще і замішано у одну структуру.

    • @patern_donchenko
      @patern_donchenko  6 днів тому

      Дякую Вам за відповідь, але тут питання до того, що ви написали.
      1. "Domain logic" - цей термін використовується, як "stand-alone" чи в привʼязці до певної концепції типу "DDD"?
      2. "Не повинно воно бути у одному репозиторії з application. Ще і замішано у одну структуру. " . Не зрозумів? А хто казав, що доменна логіка повинна мати один репозиторій, та ще й мішатися в одній структурі?

    • @D9ID9I
      @D9ID9I 6 днів тому

      1. Цей термін використовується у тому вигляді, у якому він реалізовується на практиці.
      2. Це так виглядає виходячи зі структури вашого репозиторія. Що в одному репозиторії з domain роблять папки application та presentation, незрозуміло. Чи давайте по іншому - як у вашій структурі ви створюєте декілька додатків з однією кодовою базою бізнес логіки?

    • @patern_donchenko
      @patern_donchenko  6 днів тому

      @@D9ID9I о, тепер все чітко і зрозуміло, мова йде про код з репки, що. япошарив.
      Код наведений в прикладі - має модульну структуру, де кожен модуль (це абстрактне поняття, не має відношення до модульної системи Node.js) - обʼєднує в собі описану структуру. Доменна логіка - живе в розділі "domain" для кожного модуля. Аналогічно, кожен модуль має розділ "presentation" - де згрупована логіка, що має відношення до презентаційного рівня і так далі.
      Ця структура, ні в якому разі не суперечить жодному зі згаданих принципів.
      Аналогічну структуру (можливо і не дословно) має Nest та інші рішення.
      Сподіваюся, що відповів на Ваше запитання?

  • @GoldFishFAC
    @GoldFishFAC 2 дні тому +1

    Бля какой ты царь
    Благодаря тебе я заработал 150 тыс спасибо ❤

  • @blazheiko777
    @blazheiko777 7 днів тому +1

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

    • @patern_donchenko
      @patern_donchenko  7 днів тому +1

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

    • @blazheiko777
      @blazheiko777 7 днів тому +1

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

    • @patern_donchenko
      @patern_donchenko  7 днів тому +1

      @@blazheiko777 Я Вас зрозумів.
      Приведу простий приклад з життя одного проекту у великій компаній.
      Архітектурний стек, був запропонований клієнтом з величезним акцентом на сервіси AWS. Іншими словами, ДевоПси - закривали лаги архітектури за рахунок ресурсів... (компанія або менеджерський склад - могли собі це дозволити). База, не аналізуючи вимоги бізнес-відділу, була визначена як DynamoDB (one big table). Все рухалося по моделі "write-as-we-go" і приїхали до того моменту, що бізнас-вимоги вже не могли бути адекватно вкладені в проект. З одного боку плоска структура БД цього не давала зробити, з іншого - архітектура проекту, яка не мала ні персістент, ні доменного шару, як таких. Я отримав цей проект на такому етапі.
      Ми переїхали за 4 спрінта на реляційну БД, мігрували дані, побудували відповідні слої та налаштували потоки даних. А головне відділили доменний слой з усіма абстрактними бізнес-моделями, що значно покращило, в кінцевому рахунку моделювання та розширення системи.
      Ціна такої стрільби "по ногах" була висока. Це і кошти, і людський ресурс, який втратився на шляху до дати релізу.

    • @blazheiko777
      @blazheiko777 7 днів тому +1

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

    • @garrywreck4291
      @garrywreck4291 6 днів тому +3

      Для цього існує Repository pattern.
      Він інкапсулює взаємодію з базою даних.
      Ну а сервіс працює вже з Repository.
      Якщо я правильно вас зрозумів...

  • @aleksandrS3894
    @aleksandrS3894 3 дні тому

    Як би круто не робив архітектуру ховаючи все по папочках, я гарантую, що в середньостатистичному сервісі людині яка перший раз його бачить буде набагато легше розібратись в плоскій структурі, де все скопом лежить в папках controller, service, repository, entity чім бродить по модулях і гадать - а куди ж саме відноситься те що мені потрібно знайти...

    • @G0rynych
      @G0rynych 2 дні тому

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

  • @NewChannel-xk6iu
    @NewChannel-xk6iu 5 днів тому

    Вже довго думаю над запитанням організації бізнес логіки, можливо ви підкажете, що думаєте з цього приводу.
    В більшості bekend’ів монолітів, які я бачив використовувалась simple domain model (SDM), де entity - це грубо кажучи, контейнер для даних, а рівень сервісів містить всю бізнес логіку, але з точки зору, Р.Мартіна та М.Фаулера, такий підхід не дуже хороший.
    З іншої сторони є rich domain model (RDM), тобто entity, яка містить дані та певні методи бізнес-логіки для роботи з цими даними, що по логіці ООП є правильніше ніж SDM. Саме таку entity побачив у відео. Але при розробці великих додатків з RDM, де в одного доменного entity може бути велика вкладеність інших entity, агрегатів, value objects і т.д. Відповідно всю бізнес логіку по створенню і редагуванню таких обʼєктів, потрібно помістити в головну entity і вона може бути дуже великою, що не зручно.
    Підкажіть вашу думку стосовно цього і який піхід до організації бізнес логіки ви частіше обираєте ?

    • @G0rynych
      @G0rynych 2 дні тому

      >> в одного доменного entity може бути велика вкладеність інших entity, агрегатів, value objects
      Маленьке уточнення - в такій картинці оця "доменна entity" називається агрегатом, а самі entity агрегатів всередині не мають.
      Відповідь на ваше питання - це організація системи у вигляді окремих модулів (наприклад, мікросервіси для розподілених систем, або бандли для OSGi, або будь-які інші структурні одиниці вашого коду), де кожний з цих модулів отримує свою single responsibility. Таким чином, агрегати всередині цих модулів мать посилання один на одного (типу, ідентифікатор) яке виглядає як один value object заміст цілої вкладеної сутності.