Abstrakt: Hexagonální architektura, známá také jako Ports and Adapters, definovaná Alistairem Cockburnem, představuje princip oddělení doménové logiky od technických detailů. Článek vysvětluje základní stavební bloky, popisuje praktické zásady implementace, dopady na testování a typické chyby. Text je určen architektům, technickým vedoucím a vývojářům, kteří uvažují o zavedení tohoto vzoru do enterprise prostředí.
Motivace
Tradiční vrstvená architektura propojuje doménovou logiku s konkrétní databází, webovým frameworkem a externími API. Dokud se technologie nemění, řešení funguje. Jakmile dojde k záměně databáze, přidání mobilního klienta nebo migraci na jiný framework, dopad zasáhne celou aplikaci.
Hexagonální architektura tento problém řeší inverzí závislostí. Doména je v centru a definuje rozhraní, která okolní svět implementuje. Technologie se stávají vyměnitelným adaptérem, doména zůstává nedotčena.
Základní stavební bloky
Doménové jádro obsahuje entity, hodnotové objekty, doménové služby a obchodní pravidla. Jádro nezná webový framework, ORM ani externí klienty. Pracuje pouze s vlastními typy a rozhraními, která si samo definuje.
Primární porty jsou rozhraní, přes která vnější svět zadává jádru úkoly. Vyjadřují záměr v jazyce domény, nikoli technické operace. Příkladem je rozhraní OrderService s metodami placeOrder nebo cancelOrder, namísto handleHttpPostRequest.
Primární adaptéry překládají vnější protokoly na volání primárních portů. Patří sem REST kontrolery, CLI rozhraní, posluchače front zpráv nebo plánovače úloh. Adaptér se stará o serializaci, validaci formátu a převod chyb.
Sekundární porty definují potřeby jádra vůči okolí. Typicky jde o repozitáře, klienty externích služeb, publikátory událostí nebo službu pro odesílání e-mailů. Důležité je, že rozhraní vlastní doména, nikoli infrastruktura.
Sekundární adaptéry implementují tato rozhraní pomocí konkrétních technologií. Stejný port může mít několik implementací, například paměťovou pro testy a postgresovou pro produkci.
Struktura projektu
V praxi se osvědčilo organizovat zdrojový kód podle vrstev odpovědnosti:
domain— entity, hodnotové objekty, doménové služby, definice portůapplication— případy užití, orchestrace doménových objektůadapters/primary— webové, CLI a další vstupní bodyadapters/secondary— implementace persistence, integrací a externích služebconfiguration— propojení komponent, dependency injection
Toto rozložení činí závislosti viditelnými již ve struktuře souborů. Pravidlo je jednoduché: doména a aplikace nesmí importovat nic z adaptérů ani konfigurace.
Tok dat
Příchozí požadavek prochází primárním adaptérem, který jej převede na doménový objekt nebo příkaz a předá aplikační službě přes primární port. Ta orchestruje doménové entity, případně volá sekundární porty pro získání dat nebo odeslání zprávy. Sekundární adaptéry vyřizují technické detaily a vrací doméně její vlastní typy.
Klíčové je, že doména nikdy nepracuje s objekty z infrastruktury. Pokud repozitář vrací entitu, je to doménová entita, nikoli ORM třída. Konverzi mezi technologickými typy a doménou provádí výhradně adaptér.
Testování
Hexagonální architektura zásadně zjednodušuje testování. Doménové jádro lze pokrýt jednotkovými testy bez frameworku, databáze i sítě. Testy běží v řádu milisekund a poskytují okamžitou zpětnou vazbu.
Pro aplikační vrstvu se používají falešné implementace sekundárních portů. V paměti uložená verze repozitáře umožňuje ověřit chování případu užití bez startu databáze. Pro chybové scénáře stačí připravit implementaci, která vyhazuje příslušné výjimky.
Integrační testy ověřují adaptéry proti reálným technologiím. Knihovny typu Testcontainers umožňují spustit databázi nebo frontu zpráv v rámci testu a ověřit, že adaptér správně mapuje data. End-to-end testy pak prověří celý tok přes HTTP nebo jiné rozhraní.
Časté chyby
Nejčastějším problémem je únik infrastruktury do domény. Doménová entita anotovaná JPA anotacemi nebo serializačními značkami již nepatří do jádra. Stejně tak metoda portu přijímající HttpRequest porušuje princip oddělení.
Druhým úskalím je nadměrné mapování. Pokud DTO, doménová entita a databázová entita obsahují totožná data, vznikají tři téměř identické třídy a tři vrstvy mapování. V jednoduchých případech postačí menší počet vrstev. Architektura má sloužit potřebám, ne ideologii.
Třetí chybou je aplikování vzoru tam, kde nemá smysl. Pro jednoduché CRUD aplikace s jednou databází a jedním rozhraním přináší hexagonální architektura více režie než užitku. Vhodná je pro středně velké až velké systémy s více vstupy, dlouhou životností a vyvíjejícími se požadavky.
Migrace existujícího kódu
Zavedení vzoru do běžící aplikace nelze provést přes noc. Doporučuje se postupovat po jednotlivých modulech, typicky podle ohraničených kontextů z doménově orientovaného návrhu. Pro každý modul se nejprve identifikuje doménové jádro, vyčlení do samostatného balíčku a postupně se odřízne od infrastruktury pomocí nově definovaných portů.
V průběhu migrace pomáhá vzor strangler fig. Nový kód se vytváří podle hexagonálního modelu, starý kód zůstává a postupně se nahrazuje. Vrstva proti znečištění chrání čistou doménu před koncepty z legacy systémů.
Dopady na tým
Hexagonální architektura klade vyšší nároky na disciplínu týmu. Každý nový vývojář potřebuje pochopit princip inverze závislostí a roli portů. Bez společného porozumění vznikají kompromisy, které časem rozmělňují přínos.
Osvědčuje se zavést pravidla pro revize kódu zaměřená na dodržování vrstev. Nástroje jako ArchUnit pro Javu nebo NetArchTest pro .NET dokážou strojově ověřit, že doména neimportuje infrastrukturu. Architektonické rozhodnutí se zaznamenává formou ADR (Architecture Decision Record), aby budoucí členové týmu rozuměli kontextu.
Návaznost na další vzory
Hexagonální architektura se přirozeně doplňuje s dalšími přístupy. CQRS odděluje operace zápisu a čtení do samostatných portů s vlastními modely. Event sourcing využívá doménové události jako primární zdroj pravdy a sklad událostí jako sekundární adaptér. V mikroslužbách představuje každá služba vlastní hexagon s jasnými kontrakty směrem ven.
Tyto kombinace nejsou povinné. Hexagonální architektura sama o sobě poskytuje dostatek hodnoty pro většinu enterprise aplikací. Další vzory přidávají pouze tehdy, pokud řeší konkrétní problém.
Závěr
Hexagonální architektura není samoúčelnou elegancí, ale praktickým nástrojem pro budování dlouhodobě udržitelných aplikací. Investice do správného návrhu se vrací v podobě nižších nákladů na změny, rychlejších testů a srozumitelnějšího kódu pro nové vývojáře.
Klíčem k úspěchu je vědomá volba. Pro jednoduché aplikace zůstává vrstvená architektura dobrým řešením. Pro středně velké a velké systémy s nároky na evoluci a testovatelnost představuje hexagonální architektura ověřený základ. Cílem není dokonalá technická čistota, ale obchodní hodnota a schopnost reagovat na změny.
Doporučené zdroje
- Alistair Cockburn: původní článek o hexagonální architektuře
- Robert C. Martin: Clean Architecture
- Vaughn Vernon: Implementing Domain-Driven Design
- ArchUnit a NetArchTest pro automatickou kontrolu architektonických pravidel
- Architecture Decision Records (ADR) pro dokumentaci rozhodnutí