Struktura modulitu

Struktura modulitu

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

Existuje několik způsobů, jak vytvořit modulit a jeden z nich si dneska ukážeme. Ty důležité části, na které se dneska 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, či více vstupů. Aplikace může být volána pomocí zveřejněného HTTP portu, či pomocí jiného protokolu, nebo z konzole. Aplikace může být napojena na queue, apod.

Aplikační vrstva překládá požadavky a odpovědi. Překládá požadavky, které přicházejí přes API entry pointu 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 auhtn a 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, interní i externí. Každý modul má vlastní API/interface a jenom jeden způsob, jak k němu přistoupit. Představte si třídu, které zveřejní funkcionalitu modulu. Neměla by existovat jiná možnost, jak do modulu vstoupit.

Cílem je možnost refaktorovat modul bez starosti o to, co všechno se může rozbít. Modul reprezentuje další vrstvu abstrakce. Implementační detaily zůstávají schované a pouze nezbytná funkcionalita je zveřejněna.

Každý modul vlastní svoje data (databázi, object store). Modul, který data vlastní, je zodpovědný za správu dat a definici struktury dat. 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ř. isUserLoggedIn(token: string) na místo tokenExists(token: string).

Fasády a repositáře

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

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

API 3. strany by mělo 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á. Toto snižuje coupling / závislost mezi aplikací (modulem) a specifickým formátem API na kterým nemáme / neměli bychom 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 (UserCreated), ne technologickým eventům (SocketOpened).

Eventy by měli být přirozenou součástí vaší aplikace. Eventy 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
  • update stavu úkolu po jeho ukončení
  • informování účetního oddělení o tom, že platba proběhla
  • zvýšení počtu shlé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ém 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, ať moduly nemusí 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. Omezuje to 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 vytváří další úroveň abstrakce a decouplingu mezi moduly. Zároveň může sloužit k implementaci drobné business logiky, ke které potřebujete i více modulů (rules engines, scatter/gather, pipelines …)

Funkce CQ routeru by měli být jednoduché a neměli by nahrazovat orchestratory/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í spojená 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 volně volané odkudkoliv, stejně jako nativní funkce jazyka.

Používáme cookies a podobné technologie, jako 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 tato služba 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. Poží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.