Slovník pojmů
Clean Architecture
Technologie mají sloužit pravidlům aplikace. Architektura pomáhá, když dokáže udržet jejich směr závislostí čitelný i při změnách.
Stručná definice
Business pravidla nejsou detail frameworku ani databáze.
Clean Architecture popisuje systém přes soustředné oblasti odpovědností. Blíže středu jsou pravidla, která mají nejdelší životnost: enterprise business rules neboli entity a pravidla konkrétní aplikace vyjádřená případy použití. Na okraji jsou HTTP controller, databáze, ORM, fronta zpráv, framework a klienti externích služeb.
Základní pravidlo, dependency rule, říká, že zdrojový kód vnitřní části nemá znát názvy ani konkrétní implementace vnější části. Vnitřek tedy může definovat kontrakt, který potřebuje, a adaptér na okraji jej implementuje. Neznamená to, že aplikace nemá používat framework; znamená to, že framework nemá určovat podobu jejích podstatných pravidel.
Jaký problém řeší
Změny technických detailů nemají přepisovat rozhodování aplikace.
Přístup je užitečný tam, kde se kód rozvíjí déle než jedna drobná funkce a kde více vstupů nebo integrací sdílí stejná pravidla.
- oddělení pravidel objednávky od konkrétního ORM a databázového schématu
- spuštění stejného případu použití z HTTP controlleru, CLI příkazu i consumeru fronty
- testování rozhodování bez skutečného marketplace API nebo databázového připojení
- výměna poskytovatele externí služby bez proniknutí jeho SDK do aplikační logiky
- čitelné místo pro transakci, autorizaci a převod vstupních dat na model případu použití
- postupné zpřehlednění dlouhodobě udržovaného modulu bez nutnosti přepsat celý systém najednou
Praktický příklad
Import objednávky z marketplace
HTTP controller přijme identifikátor objednávky a předá vstupní model případu použití ImportMarketplaceOrder. Tento use case rozhodne, zda lze objednávku založit, převede externí položky na interní model a požádá o uložení. Pravidla objednávky, například zakázaný přechod stavu nebo práce s částkou, patří do doménové části.
Use case nevolá přímo SDK marketplace ani databázový klient. Místo toho pracuje s kontrakty pro načtení objednávky a její uložení. HTTP adaptér marketplace a databázový adaptér tyto kontrakty implementují na okraji. Test může dodat řízené náhrady a ověřit, že se při neplatné měně objednávka neuloží. Stejný use case lze později spustit z příkazu pro zpětný import bez duplikace rozhodování.
Textový diagram
HTTP controller
→ ImportMarketplaceOrder (application use case)
→ Order a pravidla objednávky (domain)
→ MarketplaceOrderSource (výstupní kontrakt)
→ HTTP adaptér marketplace
→ OrderStore (výstupní kontrakt)
→ databázový adaptér
Jak funguje
Od vstupu k detailu bez obrácení závislostí
Textový diagram popisuje směr spolupráce. Šipka při běhu může směřovat ven, ale závislost zdrojového kódu zůstává řízena kontraktem ve vnitřní části.
- Vstupní adaptér Controller, CLI příkaz nebo handler zprávy převede technický vstup na jednoduchý vstupní model. Nemá v sobě držet obchodní rozhodování ani databázové dotazy.
- Případ použití Aplikační vrstva koordinuje jeden cíl uživatele či systému: načte potřebná data, vyvolá doménová pravidla, určí hranici transakce a připraví výstup.
- Doménová pravidla Entity a další doménové objekty chrání význam a platný stav. Nejsou automaticky kopiemi tabulek ani místem pro odesílání HTTP požadavků.
- Výstupní kontrakt Vnitřní část definuje, jakou schopnost potřebuje, například načíst objednávku nebo uložit změnu. Kontrakt mluví jazykem případu použití, ne nutně jazykem konkrétní knihovny.
- Adaptér a framework Databázový, HTTP nebo frameworkový kód implementuje potřebnou schopnost. Jeho konkrétní typ se zvolí při sestavení aplikace a lze jej testovat i měnit samostatně.
Hlavní části
Kruhy jsou pomůcka pro odpovědnosti, ne povinná adresářová mapa.
Původní model používá čtyři oblasti. Reálný modul je může spojit nebo pojmenovat jinak, pokud zachová srozumitelný směr závislostí.
Entity a enterprise business rules
V původním významu jde o obecnější pravidla podniku, která nejsou vázaná na jeden způsob doručení aplikace. V menším systému může jít jednoduše o objekt, jenž chrání platnost objednávky nebo ceny.
Use cases
Pravidla konkrétní aplikace skládají kroky jednoho scénáře. Rozhodují, kdy pracovat s daty a jaký výsledek vrátit, ale nemají být pevně svázaná s HTTP requestem nebo ORM entitou.
Interface adapters
Převádějí data mezi vnějším světem a případy použití. Patří sem například controller, presenter, mapper nebo implementace výstupního kontraktu; nejde o předem daný počet tříd.
Frameworks and drivers
Framework, databáze, webový server a SDK jsou technické volby na okraji. Mohou být velmi užitečné, jen jejich API nemá bez důvodu prostupovat do pravidel, která mají přežít jejich změnu.
Vstupní a výstupní modely
Use case může pracovat s malými datovými modely nezávislými na transportu. Není nutné vytvářet DTO, mapper a interface pro každé pole; hranice má odpovídat skutečnému překladu významu nebo riziku změny.
Vztah k podobným přístupům
Stejný cíl neznamená stejný vzor.
Tyto pojmy se často kombinují, ale každý odpovídá na jinou otázku návrhu.
- Clean a hexagonální architektura
- Oba přístupy chrání aplikační jádro před technickým okolím. Hexagonální architektura zdůrazňuje porty a adaptéry pro vstupy i výstupy; Clean Architecture popisuje především pravidlo směru závislostí a oblasti odpovědností. Nejde o dvě povinné vrstvy jednoho vzoru.
- Clean Architecture a DDD
- Clean Architecture řeší uspořádání závislostí. Domain-Driven Design pracuje s porozuměním problémové doméně, jazykem týmu a hranicemi modelů. Doménový model může Clean Architecture využít, ale jeden přístup z druhého automaticky neplyne.
- Dependency inversion a dependency injection
- Dependency inversion je návrhové pravidlo: vyšší politika nemá záviset na nízkoúrovňovém detailu, oba mohou záviset na abstrakci. Dependency injection je způsob, jak při vytváření objektů předat zvolenou implementaci. DI může princip podporovat, ale není jeho synonymem.
- Architektura a adresáře
- Názvy složek samy nic nevynucují. Architektura je vidět ve směru použitých typů, kontraktech, testech a místech, kde se skládá aplikace. Adresáře jsou jen jedna z organizačních pomůcek.
Výhody a omezení
Hranice chrání změnu, ale také stojí kód a pozornost.
Přínosy
- kritická pravidla nejsou přímo závislá na jedné databázi, transportu nebo frameworku
- stejný use case může obsloužit více vstupních bodů
- testy mohou rychle ověřovat rozhodování bez vzdálené infrastruktury
- technické integrace mají jasnější místo a výměna jejich detailu má menší dopad
Omezení a časté chyby
- přidat vrstvy, DTO, interface a mapper ke každé drobné operaci bez skutečné hranice
- zaměnit doménový objekt za ORM entitu nebo naopak vynucovat jejich oddělení i tam, kde nic nepřináší
- předpokládat, že framework je nepřítel místo toho, aby byl rozumně omezeným nástrojem
- považovat diagram nebo název složky za důkaz správné architektury bez kontroly závislostí a chování
Pragmatičnost
Struktura má odpovídat složitosti, kterou opravdu chrání.
U malého formuláře, jednorázového importu nebo jednoduché administrační obrazovky může být přímá frameworková služba čitelnější než plný model se čtyřmi kruhy. Základní otázka není, zda lze vytvořit další abstrakci, ale zda se očekává změna technologie, více vstupů, obtížná pravidla nebo potřeba nezávislých testů.
Naopak objednávky, platby, skladové rezervace a integrace se často mění z různých důvodů. Tam se vyplatí nejdřív vymezit jednu skutečně bolestivou hranici a udržet ji. Pokud se počet výjimek, průchozích mapperů a prázdných kontraktů rychle zvětšuje, je to signál k zjednodušení, ne k přidání další vrstvy.
Na co myslet
Architektura má být ověřitelná v každé změně.
Nejužitečnější pravidla lze vysvětlit konkrétním scénářem a ověřit při code review i automaticky.
- začít jedním kritickým případem použití a jednou skutečnou integrační hranicí
- držet frameworkový a databázový kód na okraji, pokud by jeho změna neměla měnit pravidla
- pojmenovat kontrakty podle potřeb aplikace, ne podle implementace dodavatele
- testovat doménová rozhodnutí i integrační adaptéry na jejich vlastních hranicích
- kontrolovat směr závislostí v review nebo automatizovaným pravidlem, pokud je hranice důležitá
Časté otázky
Clean Architecture v praxi
Vyžaduje Clean Architecture přesně čtyři vrstvy?
Ne. Kruhy jsou model odpovědností. Konkrétní modul může některé části spojit, rozdělit nebo pojmenovat jinak, pokud technické detaily nezačnou určovat pravidla, která mají zůstat stabilní.
Musí doménová část nikdy nepoužívat žádnou knihovnu?
Neexistuje univerzální zákaz. Závislost je problém hlavně tehdy, když zatahuje technický detail do pravidel, která by na něm neměla být svázaná. Malá stabilní knihovna může být přijatelnější než vlastní a hůře udržovaný kód.
Je Clean Architecture jen jiný název pro dependency injection?
Ne. Dependency injection předává objektům jejich závislosti. Clean Architecture řeší širší rozdělení odpovědností a pravidlo směru závislostí; DI je jedním z praktických způsobů, jak aplikaci sestavit.
Kdy je řešení zbytečně složité?
Když většina tříd jen převádí data mezi dalšími vrstvami, kontrakty nemají reálné konzumenty a změna jednoduchého pravidla vyžaduje průchod mnoha prázdnými abstrakcemi. V takovém případě je vhodné hranice zmenšit.
Jak architekturu používám v praxi
Hranice volím podle změn, které má aplikace bezpečně unést.
U složitějších částí odděluji pravidla aplikace od databáze, HTTP a externích služeb. Cílem není počet vrstev, ale srozumitelná odpovědnost a bezpečné změny.