Softwarová komplexita 2

Softwarová komplexita 2

architektura

Headshot Bronislav Klučka, 19. 6. 2025 21:12

V návaznosti na předchozí článek budu pokračovat komplexitou škálování, komplexitou podpůrných částí a náhodnou komplexitou – typy, které je možné managovat, redukovat a dokonce i odstranit.

Komplexita škálování

To, čím je big-ball-of-mud tak přitažlivý, je schopnost zavolat repository článků z modelu zákazníka, nebo položit databázový dotaz napřímo na tabulku cen produktů z náhledu faktury.

Je to jednoduché a rychlé, ale je to přesně způsob, jakým je big-ball-of-mud vytvořen, jeden malý coupling za druhým. Řešením tady je high cohesion a low coupling, modularizace a separation of concerns. Nicméně esenciální komplexitu nelze odstranit a tyto postupy zjednodušují řízení business logiky za cenu zvýšení komplexity komunikace.

Pro účely tohoto článku rozdělme komunikaci na 2 typy: když nepotřebujete odpověď (event) a když potřebujete odpověď (query / command). Toto rozdělení je důležité. Kdykoliv nepotřebujete odpověď, použijte eventy, jsou jednodušší na správu; prostě vyvolejte event a pokračujte.

Správa queries vyžaduje vyhodnocení rychlosti získání dat a velikosti dat. Commands představují další vrstvu problému v podobě správy výjimek ve volání mezi moduly. A nakonec síť (distribuovaný systém) je další vrstva potenciálních problémů.

Takže nejdříve: Stojí to za to? Od určité velikosti ano, i když celkově může být systém komplexnější, než je nezbytně nutné, každou separátní část (moduly, komunikace) by mělo být jednodušší pochopit jako separátní entitu.

Jaké vlastnosti by řešení mělo mít?

  • moduly by neměly vědět, jak přistoupit k ostatním modulům. Moduly by měly využívat prostředníky pro komunikaci s ostatními moduly.

  • moduly by neměly být závislé na interním chování dalších modulů a prostředků pro komunikaci.

Možnosti, které máme, jsou:

  • event bus – moduly posílají eventy do event busu, moduly se přihlašují k odběru eventů z event busu (publish / subscribe).

  • Dumb pipes and smart endpoints – prostředky pro komunikaci (intermediaries) by neměly obsahovat business logiku nebo rozumět přesně datům, která se přes ně posílají. Může být nezbytné, aby intermediaries rozuměly typu dat, neměly by řešit obsah.

  • Oddělení interní a externí reprezentace dat. Tvar externích API a DTO, které se používají pro komunikaci, by neměl být závislý na tvaru dat, který se používá pro interní zpracování nebo na jejich reprezentaci v DB (storage). Mělo by být možné měnit tyto reprezentace (interní a externí) bez toho, aby se navzájem ovlivňovaly.

Komplexita podpůrných částí

Prozatím jsme diskutovali komplexitu vyžadovanou business-level požadavky na funkcionalitu. Zbylé dva typy nejsou nezbytné pro to, abychom doručili hodnotu produktu.

Musíme být schopni spravovat a měnit každou část kódu kdykoliv v budoucnosti. Jsme za to zodpovědní. Proč to píšu? Není to zřejmé? Popravdě, občas to tak nevypadá. Čím méně kódu máme, tím jednodušší správa a změna kódu je. Toto není jen otázka kódu, který napíšete sami, toto se týká i 3rd party kódu. Každý framework, každá knihovna, kterou použijete, se stává součástí vašeho kódu a jste za ně zodpovědní.

Nicméně, nejprve se podívejme na to, co to komplexita podpůrných částí je a proč existuje. Komplexita podpůrných částí často slouží k dosažení IoC (inversion of control). Jednoduše řečeno, IoC odděluje aplikační vrstvu (entry pointy, routing, middleware atd.) od business-level logiky (funkcionalita, kterou vaše aplikace poskytuje uživatelům).

Běžně pro IoC používáme frameworky, nicméně často se jejich volba časem ukáže jako problematická. Během několika let začneme pociťovat značné zpomalení nebo dokonce technickou smrt, a to ne kvůli kódu, který jsme napsali, ale kvůli 3rd party kódu. Často to není jen aplikační vrstva, která je závislá na frameworku, ale i business logika. Jakmile se objeví nová nekompatibilní verze, nemůžeme nic dělat. Jakmile se framework přestane vyvíjet, nemůžeme nic dělat. Když se objeví nový a lepší framework, nemůžeme nic dělat.

Dovolte mi být kontroverzní: nepoužívejte běžné frameworky. Angular, React, Vue, Symfony, NextJS, Nuxt atd. Ze začátku možná programování zrychlí na pár týdnů či měsíců, nicméně nakonec vás výrazně zpomalí. Dlouhodobě je cena příliš vysoká. A totéž platí pro ORM (Doctrine, Mongoose, Hibernate atd.). Dříve nebo později začnete spíše framework obcházet a upravovat business-level kód kvůli frameworku, místo toho, aby to bylo naopak.

Tyto obecné frameworky a ORM nezvládnou specifické požadavky vaší aplikace.

Existuje však možnost, jak mít podpůrný kód, který zjednoduší správu aplikace. Jaké jsou tedy strategie?

  • Jasně definovaná separation of concerns: vaše aplikační logika a volba architektonického stylu musí být odděleny od business logiky a naopak.

    • Představte si user service nebo modul, který je self-contained (business logika, repozitář, model atd.). Neměl by být závislý na tom, zda je součástí monolitu s layered architekturou, nebo součástí microservices s event-driven architekturou.

    • Nemělo by záležet na tom, jaký framework použijete, zda to bude framework třetí strany, vlastní, nebo jestli nepoužijete žádný.

  • Doporučují spíše přístup založený na specifických a nezávislých komponentách, které slouží jedinému účelu. Například router, middleware manager, DSL translator, spíše než framework.

  • Kód by měl odpovídat business logice. Nikdy nedovolte, aby vaše business logika byla na něčem závislá; mělo by to být naopak.

  • Nepoužívejte kód třetí strany bez strategie, jak jej nahradit.

Samozřejmě, buďte racionální. Vždy bude potřeba nějaký runtime, nad kterým nemáte kontrolu (programovací jazyk, OS atd.), ale takové závislosti by měly být omezeny pouze na nezbytné.

A co například MIME builder? Komponenta, která vytvoří MIME formát emailu? Pokud nevytváříte mailingovou službu, nedává smysl psát kód, který již byl určitě napsán pro dosažení výsledku, jenž je implementací specifikace. Pokud nepočítáme výkon a bezpečnost, nemůžete dosáhnout 'lepšího' výsledku. Výstup musí mít specifikovaný formát.

Z dlouhodobého pohledu je možnost kontroly kódu, který pohání vaši aplikaci, důležitější než rychlost, kterou můžete mít na začátku.

Náhodná komplexita

Náhodná komplexita neslouží žádnému účelu. Esenciální komplexita a komplexita škálování slouží k implementaci business logiky a její správě. Komplexita podpůrných částí umožňuje oddělení business a aplikační logiky. Náhodná komplexita nepřináší žádný užitek.

Tak proč bychom ji vůbec měli přidávat do aplikace?

  • „To se nám bude hodit v budoucnu.“

  • „Vyřešme rovnou všechny situace, nejen tu jednu.“

  • „Koukejte, jak chytrý programátor jsem! Jak komplikovaný kód umím psát!“

Toto není správná cesta. Řešte problém, který máte, způsobem, který je pro něj vhodný. Neřešte problémy, které nemáte. Neřešte problémy do budoucna, která nikdy nemusí přijít. A k tomu poslednímu bodu... Amatéři píší složitý kód. To není dovednost. Každý umí napsat složitý kód. Co potřebujete, je chytrý kód: jednoduchý, řešící problém, snadno změnitelný.

Existuje přístup založený na agilním softwarovém vývoji: „Dělání rozhodnutí v poslední vhodný moment.“ Tento přístup je někdy kritizován a interpretován jako „nepřemýšlejte dopředu.“ Ale tento přístup znamená něco jiného. Znamená: „Rozhodněte o řešení ve chvíli, kdy na problém narazíte. Nevymýšlejte řešení na problém, který nemáte.“

A co bezpečnost a výkon? To jsou problémy, které řešíte od začátku, jsou měřitelné a vyřešitelné.

A co škálování? Pokud má vaše aplikace 100 uživatelů denně, pak škálování není problém, který byste museli řešit. Proč byste vytvářeli 20 microservices? Vytvořte jednoduchý, modulární monolit. Oddělovat do microservices byste měli až na základě skutečné potřeby, nikoliv na základě předpokladu.


Mimochodem, rozumím tomu. Také mám rád programování, vytváření úžasného kódu a infrastruktury a hraní si s novými, cool technologiemi. Ale "Naší nejvyšší prioritou je vyhovět zákazníkovi časným a průběžným dodáváním hodnotného softwaru."

Headshot Bronislav Klučka, 19. 6. 2025 21:12

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.