Softwarová komplexita 2

Softwarová komplexita 2

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

V návaznosti na předchozí článek budu pokračovat k komplexitě škálování, komplexita podpůrných částí a náhodné komplexitě, typech, 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 and low coupling, modularizace a separation of concerns. Nicméně esenciální komplexitu nelze odstranit a tyto postupy zjednodušují managing 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ěla mít?

  • moduly be neměly vědět, jak přistoupit k ostatním modulům. Moduly by měli 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ěli by 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 ovlivňovali navzájem.

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 IoC (inversion of control). Jednoduše řečeno, IoC odděluje aplikační vrstvu (entry pointy, routing, middleware, apod.) 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 čase ukáže jako problematická. Během pár let začneme pociťovat značné zpomalení nebo dokonce technickou smrt, 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, business logika je také. Jakmile se objeví nová, nekompatibilní verze, nemůžeme nic dělat. Jakmile se framework přestane rozví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, apod. Ze začátku možná programování zrychlí na pár týdnů, měsíců, nicméně nakonec vás výrazně zpomalí. Dlouhodobě je cena příliš velká. A to samé platí pro ORM (Doctrine, Mongoose, Hibernate, apod.). 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/ORM nezvládnou specifické požadavky vaší aplikace.

Existuje ale možnost, jak mít podpůrný kód, který zjednoduší management aplikace. Jaké jsou zde strategie?

  • Jasně definované separation of concerns: vaše aplikační logika a volba architektonického stylu musí být oddělena od business logiky a naopak.
    • Představte si user service nebo modul, který je self-contained (business logika, repositář, model, apod.). Neměl by být závislý na tom, jestli 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, jestli to bude framework 3. 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ží jednomu účelu. Např. 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 3. 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 formu emailu? Pokud nevytváříte mailingovou službu, nedává smysl psát kód, který už byl určitě napsán pro docílení výsledku, který je implementací specifikace. Pokud nepočítám výkon a bezpečnost, nemůžete docílit "lepšího" výsledku. Výstup musí mít specifický formát.

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

Náhodná komplexita

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

Tak proč bychom ji vůbec přidávali do aplikace?

  • "To se nám bude hodit v budoucnosti"
  • "Vyřešme rovnou všechny situace, nejen to jednu"
  • "Koukejte, jak chytrej programátor jsem! Jak komplikovanej kód umím psát!"

Toto není 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 budoucnosti, která nikdy nemusí přijít. A k tomu poslednímu bodu? Amatéři píší komplikovaný kód. To není skill. Každý umí napsat komplikovaný kód. Co potřebujete je chytrý kód: jednoduchý, řešící problém, snadný změnit.

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 ř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, které jsou měřitelné a vyřešitelné.

A škálování? Pokud má vaše aplikace 100 uživatelů denně, potom š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 předpokladu.


Mimochodem rozumím tomu. Také mám rád programování, vytváření úžasného kódu a infrastruktury a hraní s si 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."

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.