Kdy DDD nepoužívat – upřímně
Sedm situací, kdy DDD nepoužít, s alternativami, ukázkami kódu a rozhodovacím stromem. Pro vývojáře, kteří nechtějí do projektu zanášet zbytečnou složitost.
Obsah kapitoly
Tato kapitola je rozhodovací rámec: kdy DDD nasadit a kdy ne. Chyby v kódu, když už DDD nasazené je, katalogizuje kapitola Anti-vzory a typické chyby. Provozní třenice s Doctrine, Messengerem a Symfony, kdy je DDD nasazené správně, ale infrastruktura bolí, rozebírá DDD v praxi – kde to bolí.
DDD není architektura pro každý projekt. Nasazené na nesprávném místě přidává vrstvy abstrakce, zpomaluje vývoj a frustruje tým, aniž by cokoli přineslo. Kapitola říká přímo, kdy DDD vynechat a co místo toho použít.
22.01 Rozhodovací strom: kolik DDD dát které části systému?#
Otázka „mám použít DDD?“ je špatně položená. Jeden systém běžně obsahuje část, která rozhoduje o konkurenceschopnosti, část, bez které to nejede, ale nikoho nezajímá, a část, která se dá koupit. Každá si zaslouží jinou odpověď. Strom níže se proto ptá na jednu subdoménu, ne na projekt, a prochází se za každou zvlášť.
Postupuje ve třech krocích:
- Dá se subdoména pořídit hotová? Účetnictví, rozesílání e-mailů, platební brána. Pokud ano, je to Generic. Kupte ji. DDD tu řeší jen integraci, typicky Anti-Corruption Layer na hranici.
- Odlišuje vás od konkurence? Pokud ne, je to Supporting. Plný taktický návrh se vyplatí jen
při splnění tří podmínek (autorský test této knihy): tým ho zvládá, model je inovativní
a má vydržet roky. Jinak stačí lehký model nebo rovnou CRUD. Tým to ale musí
říct nahlas a adresář
Domain/nevydávat za doménový model. - Je to Core Domain? Pak zbývají dvě brány, které rozhodují o načasování, ne o vhodnosti: přístup k doménovým expertům a stabilita domény.
Klasifikaci subdomén rozvádí kapitola o subdoménách, hybridní přístup uvnitř jednoho systému pak sekce 22.09.
V celé kapitole platí ještě jedno rozlišení. „Nepoužít DDD“ znamená v praxi téměř vždy „nesahat po taktických vzorech“: agregátech, doménových událostech, repozitářích. Ubiquitous Language, hranice kontextů a mapování domény se vyplatí i tam, kde se plný doménový model nevyplatí. Sedm situací níže mluví o taktické vrstvě, pokud není řečeno jinak.
22.02 1. CRUD admin a jednoduchý backoffice#
Aplikace, kde uživatel vytvoří záznam, upraví ho a smaže. Formulář mapuje 1:1 na tabulku. Žádná doménová logika, jen persistence.
DDD zde přidá agregáty, repozitáře, doménové události a hodnotové objekty pro věci, které jsou přirozeně jen řádky v databázi. Ukázka níže to vyčísluje: šest tříd místo jedné a žádná přidaná hodnota.
Eric Evans to u vzoru Core Domain říká bez obalu: The harsh reality is that not all parts of the design are going to be equally refined. Priorities must be set. Propracovaný model patří tam, kde je komplexní doménová logika. CRUD operace ji nemají. Jsou to čtení a zápisy dat bez doménových pravidel.
22.03 2. Startup – doména se mění každý sprint#
Hledáte product-market fit. Co dnes je objednávka, zítra je subscription. Zákazník se přes noc změní v partnera. Pojmy se teprve hledají a ustálený model, který by taktické vzory zachytily, zatím neexistuje.
DDD předpokládá, že doméně rozumíte dost dobře na to, abyste ji modelovali. Ve fázi hledání to neplatí. Každý refaktoring agregátů a Bounded Contextů vás zpomaluje a vývojové iterace se soustředí na architekturu místo na hodnotu pro zákazníka.
Ve fázi hledání naopak pomáhají strategické nástroje DDD, zejména Event Storming a Context Mapping. Dávají jména tomu, čemu ještě nerozumíte. Nevyplatí se taktické DDD (agregáty, doménové události, repozitáře) pro model, který se příští týden změní od základů.
22.04 3. Malý tým bez doménových expertů#
DDD stojí na spolupráci vývojářů se zákazníky, produktovými manažery a analytiky, tedy s lidmi, kteří doméně rozumí. Bez nich modelujete doménu sami, z hlavy, bez zpětné vazby.
Vznikne model podle vývojářovy představy, ne podle toho, jak byznys skutečně běží, tedy opak toho, k čemu DDD slouží. Vaughn Vernon v Implementing Domain-Driven Design zdůrazňuje, že bez spolupráce s doménovými experty se Ubiquitous Language stává jen technickým žargonem.
Zásadní rozdíl oproti bodu 7: Zde doménové experty nemáte v týmu (malý tým = vývojáři dělají všechno). V bodě 7 experti existují, ale doména samotná je nejasná a nikdo neví, co modelovat. Řešení je odlišné: zde potřebujete lidi, tam potřebujete znalosti.
22.05 4. Data pipeline, ETL a reportovací systémy#
Systém načítá data z externích zdrojů, transformuje je a ukládá nebo z nich skládá reporty. Doménová pravidla ani invarianty nemá. Data přesouvá, doménu nemodeluje.
Agregáty chrání invarianty. Pokud žádné nemáte, zbude z agregátu prázdný obal a režie navíc. Evans definuje agregát jako cluster of associated objects that we treat as a unit for the purpose of data changes. V DDD Reference k tomu doplňuje, že vlastnosti a invarianty se definují pro celek a jejich vynucení patří kořeni. Pipeline nemá co vynucovat: pravidla žijí v transformačním kroku, ne ve stavu objektu.
22.06 5. Projekt s životností kratší než rok#
Interní nástroj, landing page, jednorázová migrace, prototyp pro demo zákazníkovi. Kód napíšete, použijete a zahodíte.
DDD investice se vrátí na projektech, které žijí roky a rostou. Na krátkodobých projektech tým zaplatí cenu DDD (čas, komplexita, učební křivka), aniž by kdy sklidil výhody (udržovatelnost, schopnost rozvíjet se).
Proč zrovna rok? DDD vyžaduje počáteční investici: modelování domény, budování Ubiquitous Language, návrh agregátů a Bounded Contextů. Ta se typicky začíná vracet ve chvíli, kdy projekt povyroste a tým začne těžit z čistých doménových hranic. U projektů, které skončí do roka, se to nestihne.
Rok je autorský odhad, ne měřená veličina. Fowler klade v Design Stamina Hypothesis hranici návratnosti návrhu podstatně níž, spíš týdny než měsíce. Sám k tomu dodává, že jde o hypotézu: produktivitu ani kvalitu návrhu měřit neumíme. Rozdíl je v předmětu. Fowler mluví o návrhu obecně, zde jde o plný taktický aparát DDD, který má vyšší učební křivku i vyšší vstupní režii.
Vernon v Domain-Driven Design Distilled to obrací k volbě, kam úsilí namířit: žádná organizace nemůže vynikat ve všem, takže si musí pečlivě vybrat, v čem vyniknout chce. Kde tahle volba na váš projekt nepadne, plný taktický návrh se do něj nevyplatí.
22.07 6. Tým DDD nezná a čas na učení není#
DDD vyžaduje, aby tým rozuměl konceptům, jako jsou agregáty, Bounded Contexty, doménové události a repozitáře. Špatně pochopené DDD je horší než žádné DDD: produkuje pseudo-DDD kód, který má přidanou komplexitu bez architektonických výhod. Jak takový kód vypadá v detailu, ukazuje katalog Anti-vzory.
„Naučíme se za pochodu“ na produkčním projektu s deadlinem je recept na technický dluh, který bude bolet roky.
22.08 7. Doména je nejasná, experti nejsou k dispozici#
Zákazník neví, co chce. Požadavky jsou vágní. Doménový expert buď neexistuje, nebo nemá čas spolupracovat. Modelujete pak bez pevného základu.
Zásadní rozdíl oproti bodu 3: V bodě 3 chybí lidé. Máte malý tým bez přístupu k expertům, ale doména může být jasná (pojišťovnictví, e-commerce…). Zde doménu nikdo nechápe, ani potenciální experti. Požadavky se teprve formují, pojmy nejsou ustálené, doménová pravidla se mění s každou schůzkou.
DDD bez znalosti domény je jen přejmenování tříd. „Order“, „Customer“, „Product“ – vypadá to jako DDD, ale model neodráží skutečnou doménu. Za rok, až doménu pochopíte, přepíšete stejně všechno.
22.09 Hybrid podle typu subdomény – DDD tam, kde dává smysl#
Volba „celé DDD ano, nebo celé ne“ málokdy odpovídá realitě projektu. Khononov v Learning DDD (2021) volí vzor pro byznys logiku podle její složitosti a typ subdomény mu slouží jako vodítko. Jednoduchá logika podpůrných a generických subdomén vede na Transaction Script, nebo na Active Record, když jsou datové struktury složité. Složitá logika, typicky v Core Domain, dostane Domain Model, a pokud jde o peníze nebo auditní stopu, jeho event-sourced podobu.
Tabulka tuto heuristiku přenáší do Symfony: každý Bounded Context dostane tolik DDD, kolik odpovídá jeho kategorii subdomény. „Lehké DDD“ v ní je zjednodušení této knihy, ne Khononovův termín:
| Typ subdomény | Architektonický styl | Důvod |
|---|---|---|
| Core Domain | Plné DDD (taktické + strategické vzory, agregáty, eventy) | Konkurenční výhoda, komplexní pravidla, vysoký ROI investice do modelu |
| Supporting Subdomain | Transaction Script nebo Active Record; v Doctrine lehké DDD (entita + repozitář, bez agregátních hranic) | Pravidla existují, ale nejsou diferenciační. Plné DDD je over-engineering. |
| Generic Subdomain | CRUD nebo SaaS (auth, notifikace) | Nepřináší konkurenční výhodu, kupuje se nebo se použije hotové řešení. |
Active Record v tabulce pochází z prostředí, kde ho framework nabízí. Doctrine ORM 3 je Data Mapper a Active Record nemá. Praktickým ekvivalentem je Doctrine entita s veřejnými settery, kterou obsluhuje tenká servisní třída. Nejde o anemický model ve Fowlerově smyslu, protože doménový model se tu vůbec nestaví: logika vědomě žije v servisní třídě jako Transaction Script. Volbě stylu podle kontextu se věnuje kapitola Architektonické styly.
Konkrétně: pojišťovna má Core Underwriting (DDD ano), Supporting Customer Management (lehké DDD), Generic Notifikace (CRUD nebo SaaS jako Twilio). Plné DDD ve všech třech kontextech znamená trojnásobnou režii. Ve dvou ze tří se ta investice nevrátí.
V Symfony projektu se to projevuje strukturou monolitu. src/Underwriting/ má plnou
DDD strukturu: Domain, Application, Infrastructure, agregáty a eventy.
src/Customer/ vystačí s rozdělením Entity + Repository. A src/Notification/
je čistý EasyAdmin nad Doctrine entitami, nebo rovnou externí služba.
Pět otázek na složitost domény
Typ subdomény se nepozná z organigramu. Khononov k tomu nabízí otázky, které se dají položit přímo na sezení s doménovým expertem:
- Popisují experti systém v CRUD termínech („založíme zákazníka, upravíme objednávku“)? Pak je logika nejspíš jednoduchá.
- Točí se pravidla hlavně kolem validace vstupu? Také jednoduché.
- Jsou v doméně netriviální výpočty a algoritmy? Složité.
- Existují invarianty, které musí platit vždy a napříč několika objekty? Složité.
- Kolik scénářů má jedna operace a jak vysoká by byla cyklomatická složitost jejího zápisu?
Hraniční případ má vlastní pravidlo: pokud je Supporting subdoména složitá a ta složitost má obchodní důvod, jde nejspíš o Core subdoménu v přestrojení. Přípustný je i opačný extrém. Projekt nemusí mít žádnou Core subdoménu, a pak se plný doménový model nevyplatí nikde.
Pseudo-DDD – varování před cargo cultem
Nejhorší výsledek není „nepoužít DDD“. Je to pseudo-DDD: tým má adresářovou
strukturu DDD (Domain/, Application/, Infrastructure/), používá slovník
DDD ve standupech, ale doménový model je anemický CRUD. Symptomy:
- Agregáty mají gettery, settery a žádné chování.
- Doménové události se publikují, ale žádný handler na ně neposlouchá ve smyslu doménové logiky, jen logování nebo audit.
- Bounded Contexts existují jako adresáře, ale tým je přejmenoval z původního
technického dělení (
UserModule/→UserBoundedContext/). - Code review diskuse jsou o „je toto správné DDD“ místo „chrání tato změna invariant“.
Pseudo-DDD má všechny náklady DDD (víc kódu, učební křivka) a žádný přínos (invarianty nejsou chráněné, doména není modelovaná). Tutéž bilanci popsal Fowler už u anemického modelu a pseudo-DDD je jeho ceremoniální varianta. V tomto stavu je přiznaný CRUD lepší volba. Náprava: přiznat si, že doména komplexní logiku nemá, a zjednodušit.
Evans má pro otázku „kde uvnitř systému nemodelovat“ vlastní pojmenované odpovědi. Big Ball of Mud říká, že kolem nepořádku se nakreslí hranice, pojmenuje se a sofistikované modelování se dovnitř nepouští. Separate Ways řeší druhý případ: integrace stojí víc, než kolik přinese, takže kontexty zůstanou nepropojené a každý si najde vlastní jednoduché řešení. Obojí je strategické rozhodnutí, ne rezignace.
Podrobnosti rozebírá kapitola o anti-vzorech.
22.10 Kdy DDD naopak smysl má#
Podmínky níže jsou druhou stranou bran rozhodovacího stromu. Plné taktické DDD na úrovni celého projektu se vyplatí tehdy, když platí všechny:
| Podmínka | Proč záleží | Příklad z praxe |
|---|---|---|
| Komplexní doménová logika (ne jen CRUD) | DDD chrání invarianty a modeluje pravidla – bez pravidel nemá co chránit | Pojistné smlouvy s 50+ doménovými pravidly pro schválení, pojistné události s workflow |
| Projekt bude žít a růst roky | Investice do architektury se vrátí jen při dostatečném horizontu | Core banking systém, ERP, zdravotnický informační systém |
| Přístup k doménovým expertům | Ubiquitous Language a model se tvoří ve spolupráci – ne ze vzduchoprázdna | Pojistný matematik, zkušený účetní, vedoucí skladu – lidé, kteří žijí doménou denně |
| Tým rozumí DDD nebo má čas se učit | Špatně implementované DDD je horší než žádné DDD | Tým prošel školením, má za sebou alespoň jeden DDD projekt, nebo má 2–3 měsíce na rozjezd |
| Více Bounded Contextů nebo microservices | DDD dává přirozené hranice pro dekompozici systému | E-commerce s oddělenými kontexty: katalog, objednávky, platby, logistika |
Neplatnost jedné podmínky neznamená automatické „ne“. Plné DDD pak jen nepatří do celého systému a rozhodnutí se přesouvá na jednotlivé kontexty podle typu subdomény. Tam, kde neplatí ani většina z pěti podmínek, je jednodušší architektura levnější i poctivější volba.
Z kapitoly se dá vyčíst i opak, proto na závěr: „ne DDD“ neznamená „ne návrh“. Vernon v Domain-Driven Design Distilled cituje Douglase Martina: alternativou dobrého návrhu je špatný návrh, ne žádný návrh. Flat MVC, prostý controller i EasyAdmin potřebují moduly, hranice, pojmenování a testy. Fowler totéž říká o architektuře, kterou plánujete jednou zahodit: dobrá modularita zůstává součástí zdravé kódové základny i tam.
Implementaci DDD v Symfony rozebírá implementační kapitola, problémy při jeho zavádění kapitola DDD v praxi – kde to bolí. Kdo DDD zavádí postupně v existujícím projektu, začne migrací z CRUD.
Časté otázky
Vyplatí se DDD pro jednoduchý CRUD admin?
Ne. CRUD administrace, která pouze mapuje formulář na databázovou tabulku, postrádá doménovou logiku, kterou by DDD mohlo chránit. Nasazení agregátů, hodnotových objektů a repozitářů nad prostým „create/update/delete“ přináší komplexitu bez odpovídající hodnoty. V této situaci je lepší volbou přímá CRUD implementace, například přes EasyAdmin nebo Sonata Admin. Podrobněji v sekci CRUD admin a jednoduchý backoffice.
Má smysl DDD ve startupu, kde se doména rychle mění?
Spíše ne, dokud startup hledá product-market fit. DDD investuje do přesného modelování domény. Když se doména s každým sprintem překopává, tato investice se odepisuje dřív, než přinese hodnotu. Pragmatičtější je začít s jednoduchou architekturou a DDD zavádět selektivně, až se jádro produktu stabilizuje a stejná doménová pravidla začne sdílet víc případů užití. Rozbor situace v sekci Startup – doména se mění každý sprint.
Co když tým nemá s DDD zkušenosti?
Bez zkušenosti s DDD tým typicky produkuje anemický model: taktické vzory (agregáty, repozitáře, události) se používají jako prázdné obaly kolem CRUD logiky, zatímco strategický design schází. Výsledkem je komplikovaná architektura bez reálných přínosů. Pokud chybí čas na učení, lepší je začít čistou, dobře strukturovanou CRUD architekturou a DDD prvky přidávat postupně, až s rostoucí doménovou složitostí. Detailní rozbor v sekci Tým DDD nezná a čas na učení není.
Kdy DDD naopak smysl má?
DDD se vyplatí tam, kde se sejde několik podmínek současně. Patří mezi ně komplexní doménová logika s mnoha invarianty, dlouhodobý horizont projektu (roky, ne měsíce), přístup k doménovým expertům a tým s dostatečnými zkušenostmi nebo časem na učení. Typické domény, kde DDD dlouhodobě vyhrává, jsou core banking, pojišťovnictví, zdravotnictví, logistika nebo regulovaná odvětví s bohatými pravidly. Rozhodnutí by nemělo stát na popularitě DDD, ale na konkrétní povaze projektu a týmu. Rozhodovací kritéria a domény v sekci Kdy DDD naopak smysl má.