Context Mapping: vztahy mezi Bounded Contexty
Context Map a vztahy mezi kontexty: Partnership, Shared Kernel, Customer/Supplier a Separate Ways. Kdo komu dodává model, kdo rozhoduje a co to znamená v Symfony.
Přehrávač YouTube se načte až po kliknutí · otevřít na YouTube (nové okno) ↗
Přepis dílu komentář tak, jak zazní ve videu
Kdo vlastní kontrakt mezi kontexty?
Modelový e-shop. Ordering volá Catalog a v týmu to ví každý. Jenže kdo vlastní ten kontrakt? A co se stane, když ho Catalog v úterý jednostranně změní?
Tyhle odpovědi zapisuje Context Map. Bez ní zůstane jen implicitní vztah a jeho pravidla se tým dozví až z chyby v integraci.
Co je Context Map a proč ji nakreslit
Context Map popsal Eric Evans v roce 2003. Je to přehled všech modelů na projektu. U každého místa, kde se dva modely potkávají, mapa popisuje překlad, co se sdílí a kdo má na koho jaký vliv.
Zachycuje skutečný stav. Evans radí napřed zmapovat terén tak, jak doopravdy vypadá, a změny řešit až potom.
S diagramem tříd nemá nic společného. Je to organizační a politická mapa, tedy kdo s kým mluví, jakým jazykem a kdo rozhoduje, když se jazyk musí změnit.
Má dvě složky. Diagram s kontexty a šipkami a k němu krátký textový popis každého vztahu. V popisu stojí, kdo za vztah odpovídá, jaký je kontrakt a na koho se obrátit při sporu. Text váží víc. Obrázek zastará rychleji, než ho stihnete aktualizovat.
A bacha na oblíbenou zkratku, že co Bounded Context, to mikroslužba. Kontext je logická hranice modelu. Modul ji promítá do kódu a nasazení je provozní rozhodnutí. Modulární monolit klidně nasadí deset kontextů jako jednu aplikaci a hranice mezi nimi platí dál.
Osm vztahů a rolí – přehled
Pojmenovaných vzorů je osm. Sedm popsal Evans v roce 2003, Partnership doplnil až v DDD Reference.
Neleží ale na jedné úrovni. Čtyři popisují vztah dvou kontextů, tedy Partnership, Shared Kernel, Customer Supplier a Separate Ways.
Zbylé čtyři jsou role na jednom konci vztahu. Na straně upstreamu Open Host Service a Published Language, na straně downstreamu Conformist nebo Anti-Corruption Layer.
Nevybírá se tedy jedna možnost z osmi. Vybírá se vztah a k němu role na obou koncích.
Evans v DDD Reference zmiňuje ještě devátý vzor, Big Ball of Mud. Ten se nenavrhuje. Vznikne sám, když žádná volba nepadne.
Partnership a Shared Kernel
Partnership je vztah dvou týmů, které společně uspějí, nebo společně padnou. Koordinují plánování a typicky nasazují společně.
Od stolu se obvykle nevolí. Spolupráce vznikne sama a mapa ji pojmenuje a dá jí pravidla, tedy společné plánování a řízení integrace.
Horší je Partnership, ke kterému se nikdo vědomě nepřihlásil. Agregáty jednoho kontextu začnou číst tabulky druhého, protože je to rychlejší. Po roce nikdo neví, kde končí Catalog a začíná Pricing.
Shared Kernel je malý kus doménového modelu, který kontexty fyzicky sdílí. Jednostranně ho nesmí změnit nikdo. Každá změna potřebuje souhlas všech týmů, které na něm stojí.
Proto musí zůstat malý. Typicky jde o elementární hodnotové objekty jako Money nebo Currency. Kniha jako vodítko uvádí méně než deset stabilních tříd.
Nejčastěji selže tím, že roste. K Money přibude adresa, vždyť je všude stejná. Pak telefon, zákazník a objednávka. Najednou má kernel dvě stě tříd a každá změna trvá týdny.
Do kernelu patří jen doménový model, třeba tahle třída Money. Logger nebo HTTP klient jsou běžné technické závislosti a tam nemají co dělat. Obecná DomainException je vědomá zkratka, protože pojmenovaná výjimka by znamenala další sdílený typ.
Customer/Supplier
Customer Supplier je asymetrický vztah. Upstream dodává data nebo službu a downstream je konzumuje. Na rozdíl od Conformistu ale konzument má hlas a může si říct o nové funkce.
Ordering tým třeba řekne: potřebujeme v produktu i dostupnost skladem. Catalog to neudělá hned. Nejdřív posoudí, jestli to do jeho modelu patří.
Stav skladu vlastní Warehouse. Catalog z něj ale přebírá odvozenou dostupnost pro výpis produktů, takže pole přidat může. Naplánuje ho do dalšího sprintu. O tom, kdy a jak, rozhoduje supplier.
V Symfony se to typicky staví na asynchronních událostech. Catalog publikuje ProductPriceChanged do AMQP exchange a Ordering si ho bere přes vlastní Messenger transport. Cizí zprávy ale výchozí serializér Messengeru nepřečte, transport proto potřebuje vlastní.
Handler pak aktualizuje lokální kopii ceny. Ta je eventually consistent, takže může chvíli zaostávat za Catalogem.
Evans k tomu přidává technickou pojistku. Týmy spolu napíšou akceptační testy a ty běží v CI upstreamu. Rozbitý kontrakt tak shodí build u Catalogu, a ne až produkci. Dnes se tomu říká consumer-driven contracts.
Separate Ways
A pak je tu Separate Ways, vědomé rozhodnutí kontexty vůbec neintegrovat. Evans připomíná, že integrace je vždycky drahá a přínos někdy malý.
Modelový příklad z knihy. Marketing posílá kampaně přes vlastní SendGrid. Integrace s Identity by stála dvě stě hodin vývoje a osm hodin údržby měsíčně, a riziko rozjetého souhlasu by stejně nezmizelo.
Souhlas s obchodními sděleními se proto uděluje i odvolává jen v SendGridu. Identity o něm neví. Celé rozhodnutí stojí na jediné podmínce: souhlas žije na jednom místě.
Kdyby se zákazník mohl odhlásit i v Identity, marketing by se to nedozvěděl a každá další kampaň by porušovala zákon.
Když tým jen prohlásí, že integrace je moc složitá, a nic nespočítá, o Separate Ways nejde. Je to skrytý technický dluh.
Otázky a shrnutí
Krátká otázka na rozmyšlenou. Ordering nemůže změnit kontrakt Catalogu, ale může o změnu požádat a Catalog ji naplánuje. Který vztah to je?
Customer Supplier. Kdyby Ordering hlas neměl a jen se přizpůsoboval, skončil by v roli Conformistu.
A jedna otázka z prvního dílu. Co je DDD-Lite?
Taktické vzory bez strategické části. Výsledkem bývá jeden model pro celou firmu, jen obalený vzory.
Takže v kostce. Context Map zachycuje, kdo s kým mluví a kdo rozhoduje o kontraktu.
Vybírá se vztah a k němu role na koncích. Shared Kernel má smysl jen malý a Separate Ways jen spočítané.
Příští díl je o rolích na hranici, tedy o Conformistu, Anti-Corruption Layer, Open Host Service a Published Language. Kapitolu najdete v knize na ddd-v-symfony.katuscak.cz.