Vertikální slice architektura vs. Tradiční DDD

Tradiční přístup k DDD

Tradiční přístup k DDD, často označovaný jako "vrstvený" (layered), organizuje kód do vrstev podle technické odpovědnosti [1]. Typické vrstvy v tradičním DDD jsou:

  • Prezentační vrstva (Presentation Layer) - Zodpovědná za interakci s uživatelem.
  • Aplikační vrstva (Application Layer) - Koordinuje aplikační aktivity a deleguje práci doménové vrstvě.
  • Doménová vrstva (Domain Layer) - Obsahuje doménový model a doménovou logiku.
  • Infrastrukturní vrstva (Infrastructure Layer) - Poskytuje technické služby pro ostatní vrstvy.

Příklad: Tradiční struktura DDD projektu

src/
├── Presentation/                # Prezentační vrstva
│   └── Controller/
│       └── UserController.php
├── Application/                 # Aplikační vrstva
│   ├── Service/
│   │   └── UserService.php
│   └── DTO/
│       └── UserDTO.php
├── Domain/                      # Doménová vrstva
│   ├── Model/
│   │   └── User.php
│   ├── Repository/
│   │   └── UserRepository.php
│   └── Service/
│       └── DomainUserService.php
└── Infrastructure/              # Infrastrukturní vrstva
    ├── Repository/
    │   └── DoctrineUserRepository.php
    └── Persistence/
        └── Doctrine/
            └── Mapping/
                └── User.orm.xml

V tradičním přístupu jsou vrstvy organizovány horizontálně, což znamená, že každá vrstva poskytuje služby vrstvě nad ní. Tento přístup je často znázorňován jako "cibulová" nebo "hexagonální" architektura [2].

Vertikální slice architektura (Vertical Slice Architecture)

Vertikální slice architektura (někdy nepřesně označovaná jako "horizontální DDD") organizuje kód podle funkcí (feature slices) místo technických vrstev [3]. Každá funkce (feature) obsahuje všechny vrstvy potřebné pro její implementaci, což umožňuje lepší modularitu a nezávislost jednotlivých částí aplikace.

Příklad: Struktura projektu s vertikální slice architekturou

src/
├── UserManagement/             # Bounded Context: Správa uživatelů
│   ├── Registration/           # Feature: Registrace uživatelů
│   │   ├── Domain/             # Doménová logika pro registraci
│   │   ├── Application/       # Aplikační logika pro registraci
│   │   │   ├── Command/
│   │   │   │   ├── RegisterUser.php
│   │   │   │   └── RegisterUserHandler.php
│   │   │   └── Service/
│   │   │       └── RegistrationService.php
│   │   └── Presentation/      # Prezentační vrstva pro registraci
│   │       ├── Controller/
│   │       │   └── UserRegistrationController.php
│   │       └── Form/
│   │           └── UserRegistrationForm.php
│   ├── Profile/                # Feature: Profil uživatele
│   │   ├── Application/       # Aplikační logika pro profil
│   │   │   ├── Query/
│   │   │   │   ├── GetUserProfile.php
│   │   │   │   └── GetUserProfileHandler.php
│   │   └── Presentation/      # Prezentační vrstva pro profil
│   │       ├── Controller/
│   │       │   └── UserProfileController.php
│   │       └── ViewModel/
│   │           └── UserProfileViewModel.php
│   ├── Domain/                # Sdílená doménová logika pro celý kontext
│   │   ├── Model/
│   │   │   └── User.php       # Entita (Aggregate Root)
│   │   ├── ValueObject/
│   │   │   ├── UserId.php
│   │   │   └── Email.php
│   │   └── Repository/
│   │       └── UserRepository.php  # Rozhraní
│   └── Infrastructure/       # Infrastruktura pro celý kontext
│       └── Repository/
│           └── DoctrineUserRepository.php
├── OrderManagement/           # Bounded Context: Správa objednávek
│   ├── Checkout/              # Feature: Pokladna
│   │   ├── Application/
│   │   │   ├── Command/
│   │   │   │   ├── CreateOrder.php
│   │   │   │   └── CreateOrderHandler.php
│   │   └── Presentation/
│   │       ├── Controller/
│   │       │   └── CheckoutController.php
│   │       └── Form/
│   │           └── CheckoutForm.php
│   └── ... (podobná struktura jako u UserManagement)
└── Shared/                    # Sdílené komponenty pro celý systém
    └── Domain/
        └── Exception/
            └── DomainException.php

Ve vertikální slice architektuře jsou funkce (features) organizovány jako vertikální řezy (slices) přes všechny vrstvy, přičemž každá funkce obsahuje všechny vrstvy potřebné pro její implementaci. Tento přístup minimalizuje vazby mezi jednotlivými funkcemi a maximalizuje vazby uvnitř funkce [4]. Zároveň zachovává principy DDD tím, že respektuje bounded contexts a doménový model.

Porovnání přístupů

Aspekt Tradiční (vertikální) DDD Vertikální slice architektura
Organizace kódu Podle technických vrstev Podle funkcí (features)
Vazby Silné vazby mezi vrstvami Silné vazby uvnitř funkce, slabé vazby mezi funkcemi
Změny Změna často vyžaduje úpravy ve více vrstvách Změna je obvykle omezena na jednu funkci
Testovatelnost Často vyžaduje mnoho mocků pro testování Snazší testování, méně mocků
Škálovatelnost Může být obtížné škálovat při růstu aplikace Snazší škálování, funkce mohou být rozděleny do mikroslužeb
Složitost Jednodušší pro pochopení na začátku Může být složitější pro pochopení na začátku
Vhodnost pro CQRS Vyžaduje dodatečnou práci pro implementaci CQRS Přirozeně podporuje CQRS [5]

Kdy použít který přístup

Kdy použít tradiční DDD:

  • Když je tým zvyklý na tradiční architekturu.
  • Pro menší aplikace s jasně definovanými vrstvami.
  • Když je důležitá jasná separace technických vrstev.
  • Pro aplikace s jednodušší doménovou logikou.

Kdy použít vertikální slice architekturu:

  • Pro větší a složitější aplikace [6].
  • Když je důležitá modularita a nezávislost funkcí.
  • Pro aplikace, které budou v budoucnu rozděleny do mikroslužeb.
  • Když chcete implementovat CQRS.
  • Pro týmy, které jsou zvyklé na agilní vývoj a časté změny.

Implementace v Symfony 7

Symfony 7 poskytuje mnoho nástrojů a komponent, které usnadňují implementaci obou přístupů k DDD [7].

Implementace tradičního DDD v Symfony 7:

Pro implementaci tradičního DDD v Symfony 7 můžete použít standardní adresářovou strukturu Symfony a rozdělit kód do vrstev:

src/
├── UserManagement/             # Bounded Context: Správa uživatelů
│   ├── Presentation/            # Prezentační vrstva
│   │   ├── Controller/
│   │   │   ├── UserController.php
│   │   │   └── RegistrationController.php
│   │   └── ViewModel/
│   │       └── UserViewModel.php
│   ├── Application/            # Aplikační vrstva
│   │   ├── Command/
│   │   │   ├── RegisterUser.php
│   │   │   └── RegisterUserHandler.php
│   │   ├── Query/
│   │   │   ├── GetUser.php
│   │   │   └── GetUserHandler.php
│   │   └── Service/
│   │       └── UserApplicationService.php
│   ├── Domain/                 # Doménová vrstva
│   │   ├── Model/
│   │   │   └── User.php         # Entita (Aggregate Root)
│   │   ├── ValueObject/
│   │   │   ├── UserId.php
│   │   │   └── Email.php
│   │   ├── Event/
│   │   │   └── UserRegistered.php
│   │   ├── Repository/
│   │   │   └── UserRepository.php  # Rozhraní
│   │   └── Service/
│   │       └── UserDomainService.php
│   └── Infrastructure/         # Infrastrukturní vrstva
│       ├── Repository/
│       │   └── DoctrineUserRepository.php
│       └── Persistence/
│           └── Doctrine/
│               └── Mapping/
│                   └── User.orm.xml
├── OrderManagement/           # Bounded Context: Správa objednávek
│   ├── Presentation/            # Prezentační vrstva
│   ├── Application/            # Aplikační vrstva
│   ├── Domain/                 # Doménová vrstva
│   └── Infrastructure/         # Infrastrukturní vrstva
└── Shared/                    # Sdílené komponenty
    └── Domain/                 # Sdílená doménová logika
        └── Exception/
            └── DomainException.php

Implementace vertikální slice architektury v Symfony 7:

Pro implementaci vertikální slice architektury v Symfony 7 můžete organizovat kód podle funkcí (features) [8]:

src/
├── UserManagement/             # Bounded Context: Správa uživatelů
│   ├── Registration/           # Feature: Registrace uživatelů
│   │   ├── Domain/             # Doménová logika pro registraci
│   │   │   ├── Event/
│   │   │   │   └── UserRegistered.php
│   │   │   └── Service/
│   │   │       └── RegistrationDomainService.php
│   │   ├── Application/       # Aplikační logika pro registraci
│   │   │   ├── Command/
│   │   │   │   ├── RegisterUser.php
│   │   │   │   └── RegisterUserHandler.php
│   │   │   └── Service/
│   │   │       └── RegistrationService.php
│   │   └── Presentation/      # Prezentační vrstva pro registraci
│   │       ├── Controller/
│   │       │   └── UserRegistrationController.php
│   │       └── Form/
│   │           └── UserRegistrationForm.php
│   ├── Profile/                # Feature: Profil uživatele
│   │   ├── Application/       # Aplikační logika pro profil
│   │   │   ├── Query/
│   │   │   │   ├── GetUserProfile.php
│   │   │   │   └── GetUserProfileHandler.php
│   │   │   └── Service/
│   │   │       └── ProfileService.php
│   │   └── Presentation/      # Prezentační vrstva pro profil
│   │       ├── Controller/
│   │       │   └── UserProfileController.php
│   │       └── ViewModel/
│   │           └── UserProfileViewModel.php
│   ├── Domain/                # Sdílená doménová logika pro celý kontext
│   │   ├── Model/
│   │   │   └── User.php       # Entita (Aggregate Root)
│   │   ├── ValueObject/
│   │   │   ├── UserId.php
│   │   │   └── Email.php
│   │   └── Repository/
│   │       └── UserRepository.php  # Rozhraní
│   └── Infrastructure/       # Infrastruktura pro celý kontext
│       └── Repository/
│           └── DoctrineUserRepository.php
├── OrderManagement/           # Bounded Context: Správa objednávek
│   ├── Checkout/              # Feature: Pokladna
│   │   ├── Domain/
│   │   ├── Application/
│   │   └── Presentation/
│   └── ... (podobná struktura jako u UserManagement)
└── Shared/                    # Sdílené komponenty pro celý systém
    └── Domain/
        └── Exception/
            └── DomainException.php

Symfony 7 poskytuje mnoho komponent, které jsou užitečné pro implementaci vertikální slice architektury [9]:

  • Messenger komponenta - Pro implementaci CQRS a asynchronní zpracování [10].
  • Validator komponenta - Pro validaci doménových objektů.
  • Form komponenta - Pro zpracování vstupů od uživatele.
  • Security komponenta - Pro autentizaci a autorizaci.
  • Doctrine ORM - Pro persistenci doménových objektů.

Důležité poznámky

Při implementaci vertikální slice architektury v Symfony 7 je důležité:

  • Minimalizovat vazby mezi jednotlivými funkcemi (features).
  • Používat CQRS pro oddělení čtení a zápisu [11].
  • Používat doménové události pro komunikaci mezi funkcemi.
  • Definovat jasné hranice mezi funkcemi.

V další kapitole se podíváme na základní koncepty DDD a jak je implementovat v Symfony 7.