Struktura modulitu

Struktura modulitu

architekturabackend

Headshot Bronislav Klučka, 19. 5. 2025 20:14

Existuje několik způsobů, jak vytvořit modulit, a jeden z nich si dnes ukážeme. Ty důležité části, na které se dnes zaměříme, jsou: aplikační vrstva, business vrstva, fasády a repositáře, event bus/broker, CQ router a utilities.

Pochopení rolí a rozdělení těchto částí je základem pro napsání kódu, který neskončí jako "big ball of mud".

Představení modulitu najdete v předchozím článku.

Aplikační vrstva

Primární rolí aplikační vrstvy je přijímat požadavky. Aplikační vrstva může vystavit jeden nebo více vstupů. Aplikace může být volána pomocí zveřejněného HTTP portu, jiného protokolu nebo z konzole. Může být také napojena na queue a podobně.

Aplikační vrstva překládá požadavky a odpovědi. Překládá požadavky, které přicházejí přes API entry pointy, do interních struktur, které je možné předat do modulů. Stejně tak překládá odpovědi modulů zpět do API entry pointů. Nic mimo aplikační vrstvu by nemělo vědět o tom, jak je aplikace volána.

Aplikační vrstva může obsahovat následující funkcionality:

  • Entry point

  • API validator

  • API translator

  • Middleware

  • Router

  • Nastavení logování

  • apod.

Aplikační vrstva by neměla obsahovat business logiku (business logika je funkcionalita, kterou dodáváme zákazníkům). Middleware může obsahovat autentizaci (authn) a autorizaci (authz), nicméně to není business logika per se.

Business moduly

Moduly mají na starosti funkcionalitu pro zákazníky. Implementují přidanou hodnotu pro zákazníky, jak interní, tak externí. Každý modul má vlastní API/interface a pouze jeden způsob, jak k němu přistoupit. Představte si třídu, která zveřejňuje funkcionalitu modulu. Neměla by existovat jiná možnost, jak do modulu vstoupit.

Cílem je umožnit refaktorování modulu bez obav o to, co všechno se může rozbít. Modul představuje další vrstvu abstrakce. Implementační detaily zůstávají skryté a pouze nezbytná funkcionalita je zveřejněna.

Každý modul vlastní svá data (databázi, object store). Modul, který data vlastní, je zodpovědný za správu dat a definici jejich struktury. Modul může přistoupit k datům jiného modulu pouze přes rozhraní tohoto modulu, nikdy napřímo.

API modulu by mělo používat obecnou terminologii, nikoliv popisovat implementační detaily. Například isUserLoggedIn(token: string) místo tokenExists(token: string).

Fasády a repositáře

Fasáda je implementace API třetí strany (externího nebo jiného modulu), která naplňuje potřeby aplikace.

Přidal jsem sem i repositáře, protože jsou specifickou verzí fasád.

API třetí strany by mělo být oddělené od aplikace a voláno pouze přes fasádu. Fasáda by měla být to jediné, co dané API volá. To snižuje coupling / závislost mezi aplikací (modulem) a specifickým formátem API, nad kterým nemáme nebo bychom neměli mít kontrolu. Ve své podstatě jde o ochranu vaší business-level logiky od všeho, co není vaší business-level logikou.

Jak vidíte na diagramu, business-level logika je chráněna od externího API, storage API, API dalších modulů a aplikační vrstvy (rozhraním modulu samotného). Fasáda absorbuje případné změny v externích částech z pohledu modulu.

Event bus/broker

V této části se věnuji business eventům / doménovým eventům (například UserCreated), nikoli technologickým eventům (například SocketOpened).

Eventy by měly být přirozenou součástí vaší aplikace. Mohou výrazně snížit coupling (propojení) mezi moduly. Zkuste si představit všechny případy, ve kterých chcete sdělit, že se něco stalo, a nějaký další modul na to zareagoval, ale výsledek pro vás není důležitý:

  • Odeslání emailu po registraci uživatele nebo interakci s aplikací.

  • Informování skladu o objednávce.

  • Aktualizace stavu úkolu po jeho ukončení.

  • Informování účetního oddělení o tom, že platba probíhla.

  • Zvýšení počtu zhlédnutí článku.

Všechny tyto subprocesy mohou existovat jako součást většího procesu, který není závislý na tom, jak dopadnou. Je lepší vyvolat event, na který další moduly poslouchají (decoupling), než volat moduly napřímo (coupling).

Event bus/broker je technologické řešení pro komunikaci pomocí eventů. Ideálně by měl existovat pouze jeden, aby moduly nemusely vědět, kam eventy posílat a kde jaké eventy poslouchat (i když existují i use cases pro více).

Event bus/broker by neměl obsahovat business logiku. Osobně preferuji subscription pattern (moduly se přihlásí k poslouchání specifických eventů) před routingem na straně brokeru. To omezuje vliv další části infrastruktury na chování business logiky.

CQ Router

Ale co když chcete zavolat jiný modul a záleží vám na výsledku? K tomu slouží CQ router (command/query router).

I když můžete vytvořit fasádu pro komunikaci s dalšími moduly, CQ router přidává další úroveň abstrakce a decouplingu mezi moduly. Zároveň může sloužit k implementaci drobné business logiky, která vyžaduje spolupráci více modulů (rules engines, scatter/gather, pipelines …).

Funkce CQ routeru by měly být jednoduché a neměly by nahrazovat orchestrátory/joby.

Utilities (Nástroje)

V tomto případě je důležité chápat, co se rozumí pod pojmem utility. Utilita je "rozšíření funkcionality jazyka", které není spojeno s business-level funkcionalitou modulů.

Představte si, že píšete aplikaci na zasílání emailů. Funkcionalita, která spravuje rozesílání kampaní, je business-level logika a patří tedy do modulu. Funkcionalita, která z objektu emailu vytvoří MIME strukturu, je nezávislá na logice aplikace a může být utilitou.

Jelikož jsou utilities "rozšíření jazyka", mohou být volány odkudkoliv, stejně jako nativní funkce jazyka.

Headshot Bronislav Klučka, 19. 5. 2025 20:14

Komentáře

Napište komentář

Komentáře jsou schvalované, než se zobrazí na stránkách.

Nebylo možné přidat komentář.

Váš komentář byl přidán a čeká se na schválení.

Váš komentář je příliš dlouhý.

Používáme cookies a podobné technologie, jako je Google Analytics, pro sběr analytických dat. To nám pomáhá pochopit, jak uživatelé používají naše stránky.

Více info

Stránky používají Google Analytics a analytické služby poskytované společností Google. Google Analytics používá cookies, aby nám pomohla analyzovat, jak uživatelé používají naše stránky. Informace generované cookies, které se týkají vašeho používání stránek (včetně vaší IP adresy), budou přeneseny a uloženy u společnosti Google. Používáme tato data pro vytváření reportů o aktivitě a k poskytování dalších služeb, které se týkají těchto stránek.

Analytická data nám pomáhají vylepšovat naše služby. Nepoužíváme je k marketingovým a reklamním účelům. Tato data nepředáváme ani neprodáváme dál.