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.

  1. 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.
  2. 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.
  3. 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ů.
  4. 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.
  5. 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.

Zavolejte mi

Zavolám vám následující pracovní den mezi 9:00 a 17:00.

Můžete mi také zavolat rovnou.

+420 605 181 728

Nechte mi telefonní číslo a pošlete žádost o zpětné zavolání.

Odesláním souhlasíte se zpracováním údajů pro vyřízení žádosti.