SOLID mi pomáhal dávno předtím, než jsem začal při vývoji používat AI. Pomáhal mi rozdělit složité zadání na části, kterým rozumím, rozvíjet je a nemuset se při každé změně znovu zabývat celou aplikací.
Dnes mi dává ještě větší smysl.
Při práci s AI totiž pořád potřebuji vědět, co v systému vzniká, proč to patří právě na dané místo a co od toho můžu očekávat. Potřebuji se v něm vyznat i později. A také ve chvíli, kdy něco přestane fungovat.
Když se proto vracím k SOLIDu, nevybavuje se mi nejdřív pět definic. Vybavují se mi konkrétní situace, ve kterých mi tyto principy pomohly. Postupně jsem si kolem nich vytvořil vlastní způsob práce.
Jedna taková situace mi zůstala v paměti dodnes.
Když si nepamatuji kód, ale rozumím jeho jazyku
Na jednom projektu pracovalo přibližně dvě stě až tři sta lidí. Ve své části jsem měl možnost důsledně držet pravidla pro rozdělení odpovědností a pojmenování.
Asi tři roky po odevzdání určité části přišel kolega a hledal třídu. Myslím, že se týkala předplatného.
Nepamatoval jsem si, kde jsem ji napsal. Vlastně jsem si už nepamatoval ani to, jak jsme tu část přesně poskládali. Požádal jsem ho, aby mi popsal, co řeší.
Z jeho popisu mi vycházel název ve smyslu PaymentCreditBalanceRequest.
Zadali jsme ho do vyhledávání. A přesně pod tím názvem jsme hledanou třídu našli.
Zaujalo mě, že jsem k dohledání nepotřeboval vlastní vzpomínku na implementaci. Stačilo znovu projít způsobem uvažování, podle kterého původně vznikla.
Právě tohle pro mě znamená předvídatelný systém. Nemusím znát každé jeho místo zpaměti. Z toho, čemu už rozumím, dokážu odvodit, kde hledat dál.
Co mi napovídá název
U Single Responsibility mě zajímá, jestli dokážu odpovědnost dané části jasně vymezit. Smyslem není vytvořit co nejmenší třídy, ale oddělit věci, které se mění z různých důvodů. [1]
V každodenní práci si k tomu pomáhám třemi pravidly:
- Co je v názvu funkce, musí být v jejím chování.
- Co funkce dělá, musí být rozpoznatelné z jejího názvu.
- Název funkce se má vejít do dvaceti pěti znaků.
Mluvím o významu funkce, ne o potřebě vypsat do názvu každý její technický krok. A limit se týká funkcí, nikoli všech názvů tříd a zpráv.
Představme si funkci, která vykresluje čtverec. Přijde nový požadavek a já do ní přidám podmínku: někdy má vykreslit ještě trojúhelník.
Kód může být stále krátký. Jenže když se pokusím poctivě pojmenovat, co teď dělá, zjistím, že původní název už nestačí.
To je pro mě užitečný okamžik. Nehledám kratší zkratku, abych se znovu vešel do limitu. Zajímá mě, jestli se změnil účel funkce, nebo jestli se do ní přidala další práce, kterou potřebuji oddělit.
Samotný if pro mě není porušení principu. Zajímá mě změna významu, kterou přinesl.
Pětadvacet znaků není univerzální měřítko kvality. Je to mantinel, který mě nutí zastavit se včas. Často mi ukáže růst odpovědnosti dřív, než ho začnu vnímat jako technický problém.
Jeden význam potřebuji poznat i na jiném místě
Na názvech mi záleží ještě z jednoho důvodu. Potřebuji, abychom používali společný jazyk.
Request končí na Request, event na Event. Pro tutéž věc používáme tentýž pojem. Nechci při přechodu mezi dvěma částmi aplikace zjišťovat, jestli jiný název znamená jinou věc, nebo jen jiného autora.
V tomhle dávám velkou váhu konzistenci. Považuji ji za důležitější než snahu jednotlivce najít při každé úpravě o trochu přesnější slovíčko.
Když je společný pojem zavádějící, potřebuji ho opravit společně. Když si ho každý opraví po svém, přestáváme si rozumět.
Příběh s dohledanou třídou pro mě nebyl výsledkem jednoho dobře zvoleného názvu. Byl výsledkem toho, že jsme stejný způsob pojmenování drželi dlouhodobě.
A tady se pro mě potkává návrh kódu s prací lidí. Pravidlo samo nic neudrží. Potřebuji disciplínu, code review a ochotu vracet se ke společné dohodě.
To, co už funguje, má dál dávat stejný smysl
U veřejných API jsem tuto dohodu začal vnímat ještě výrazněji.
Provozovali jsme více verzí vedle sebe a zákazníkům jsme slíbili jejich podporu. Jenže do jejich implementací jsem neviděl. Nemohl jsem ověřovat správnost změny pouze podle toho, jak se chová náš vlastní klient.
Když přidám nepovinný vstupní parametr a při jeho vynechání zachovám dosavadní chování, může jít o zpětně kompatibilní rozšíření. Když ale z nepovinného údaje udělám povinný, některý zákazník ho vůbec nemusí posílat. Totéž platí pro zpřísnění validace, které začne odmítat dosud platné požadavky. [2]
V kódu se někdy změní velmi málo. Z pohledu zákazníka přestane platit to, na co se spoléhal.
Pravidla těchto změn jsme si stanovili dopředu, také v návaznosti na bezpečnostní analýzu. Díky tomu jsme nemuseli při každém vydání znovu hledat hranici mezi rozšířením a novou verzí.
S Open/Closed se mi tato zkušenost potkává v otázce, co má zůstat stabilní a kde má vzniknout prostor pro nové chování. Samotný princip směřuje k rozšiřování přes vhodně zvolené hranice, aniž bych musel pokaždé měnit stabilní části. [3]
Verzování API není jeho definice. Je to jedna ze situací, ve kterých potřebuji důsledně přemýšlet o tom, co rozšiřuji a co už nahrazuji.
Vyměnit implementaci, zachovat dohodu
Liskov Substitution jsem dlouho používal spíš intuitivně. Vybavovala se mi potřeba dobře testovat nebo vyměnit napojení na externí službu, ne samotný název principu.
Jednou potřebuji produkční implementaci, podruhé testovací implementaci. Později třeba jiného poskytovatele. Chci, aby na tuto výměnu nemusel reagovat každý, kdo službu používá.
Jenže stejné metody ještě neznamenají stejnou dohodu. Implementace musí zachovat to, na co se může uživatel společného rozhraní oprávněně spolehnout. Právě o tuto zaměnitelnost chování u Liskov Substitution jde. [4]
Představme si, že úspěšný výsledek znamená potvrzení o uložení dat. Nová implementace jím ale potvrzuje jen přijetí požadavku, který se má uložit později. Název i návratový typ mohou zůstat stejné, význam výsledku se změnil.
Malé a jasně vymezené části mi pomáhají tuto hranici vidět. Samy o sobě ji ale neověří. Potřebuji vědět, co kontrakt skutečně slibuje, a podle toho posuzovat i své testovací implementace.
Tohle je pro mě důležité i mimo kód: možnost vyměnit způsob provedení není totéž jako možnost potichu změnit očekávaný výsledek.
Celek můžu skládat jinak, než jsem ho složil poprvé
U Interface Segregation pro mě není rozhodující počet metod. Zajímá mě, co konkrétní uživatel rozhraní potřebuje a zda ho nenutím záviset i na něčem dalším. [4]
Poskytovatel času bude přirozeně malý. Potřebuji zjistit čas a v testech ho mít pod kontrolou.
U doručovacího systému je situace jiná. Zprávy připravuji, třídím, někdy seskupuji pro jednoho uživatele a nakonec odesílám. Navenek může být tento proces zastřešený jednou poměrně rozsáhlou fasádou.
Osvědčilo se mi skládat ji z menších rozhraní a komponent. Část, která potřebuje pouze odesílat, pak pracuje jen s odpovídajícím rozhraním. Nemusí kvůli tomu znát celý doručovací proces.
Při stavbě pipeline pro zpracování a odesílání zpráv mi takové rozdělení umožňovalo přeuspořádávat workflow podle požadavků zákazníka. Jednotlivé kroky měly své místo a význam, ale jejich původní uspořádání nebylo něco, co bych musel zachovat navždy.
Právě to mě na kompozici zajímá. Malé části nemusí vést k malému výsledku. Mohu z nich poskládat větší celek a později ho složit jinak.
Kód má být služba businessu, ne socha, do které se nesmí říznout.
Jádro aplikace nemusí znát celé své okolí
Dependency Inversion mi pomáhá podobnou hranici vytvořit mezi business logikou a technickým prostředím. Jádro závisí na abstrakcích vyjadřujících jeho potřeby, nikoli přímo na konkrétních implementacích infrastruktury. [5]
Na projektu pro státní pokladnu jsme na začátku neznali finální provozní prostředí. Potřebovali jsme ale vyvíjet a testovat.
Díky odděleným komponentám a rozhraním jsme mohli vytvořit vlastní prostředí, simulovat potřebné chování okolních služeb a pracovat na business logice. Jak se podoba infrastruktury zpřesňovala, mohli jsme nahrazovat příslušná napojení.
Zajímal mě právě tento rozdíl: měním způsob, jak aplikace komunikuje s okolím, ale nemusím kvůli tomu znovu otevírat business pravidla, která se nezměnila.
Konkrétní implementace při sestavení aplikace zapojuji pomocí Dependency Injection. To je technika zapojení; Dependency Inversion je princip směru závislostí. [6]
Největší hodnotu pro mě nemá samotná možnost vyměnit objekt. Má ji práce, kterou při té výměně nemusím dělat znovu.
Co se pro mě s AI nezměnilo
Když se na tyto zkušenosti podívám dnes, nevidím důvod posunout hranici srozumitelnosti jen proto, že mi s implementací pomáhá AI.
Pořád může přijít chyba. Pořád se mohu dostat do situace, ve které nemám přístup k debuggeru ani k úplným logům a skládám si příčinu z několika indikátorů. Jasně oddělené odpovědnosti mi v takových situacích pomáhaly zúžit hledání. Logování tím nenahrazuji.
Podobně přemýšlím o zadání pro AI agenta. Chci umět říct, která část se má změnit, co má zůstat zachované a podle čeho výsledek ověřím. Když to nedokážu vyjádřit, potřebuji se vrátit k vlastnímu porozumění zadání.
V konzistentních názvech a malých kontraktech vidím také způsob, jak agentovi zpřístupnit záměr, který by jinak zůstal jen v hlavách lidí. Neberu to jako automatickou záruku správného výsledku. Je to důvod, proč mi záleží na tom, co lze ze systému samotného vyčíst.
Možná je právě tohle pro mě dnes na SOLIDu nejdůležitější. Pomáhá mi nejen rozdělit práci, ale také poznat, jestli jí ještě rozumím.
Od pravidel k vlastní zkušenosti
Když tato pravidla probírám s týmem, většinou nepotřebuji hledat další příběh ze své minulosti. Vezmeme kód, na kterém lidé právě pracují.
Zkusíme pojmenovat odpovědnost funkce. Podíváme se, co se změnilo v jejím významu. Projdeme, na co se spoléhá volající a co by se stalo při výměně implementace.
Tady pro mě začíná skutečné učení. Nestačí souhlasit s definicí. Potřebuji ji rozpoznat v situaci, ve které sám rozhoduji.
Nemusím kvůli tomu přestavět celou aplikaci. Můžu začít jedním místem, kde se při změně opakovaně ztrácíme, a sledovat, jestli nám nové rozdělení opravdu pomohlo.
Když se vrátím ke kolegovi, se kterým jsme po třech letech hledali třídu, právě takový výsledek mě zajímá. Abych mohl znovu porozumět tomu, co vzniklo, i když už si nepamatuji okolnosti jeho vzniku.
SOLID mi v tom pomáhal před AI. Při práci s ní o tuto schopnost nechci přijít.
Zdroje a podklady k dalšímu studiu
Příběhy z projektů a pravidla pojmenování vycházejí z mé zkušenosti. Následující texty rozvádějí technické principy, se kterými ji propojuji.
Zdroje ověřeny 14. října 2026.
[1] Robert C. Martin. The Single Responsibility Principle. Odpovědnosti a důvody ke změně.
[2] Google. AIP-180: Backwards compatibility. Zachování chování veřejných API při jejich rozšiřování.
[3] Robert C. Martin. The Open Closed Principle. Stabilní části systému a hranice rozšíření.
[4] Robert C. Martin. Solid Relevance. Zejména Liskov Substitution a Interface Segregation.
[5] Microsoft. Architectural principles. Směr závislostí a oddělení aplikační logiky od infrastruktury.
[6] Martin Fowler. Inversion of Control Containers and the Dependency Injection pattern. Zapojování implementací a oddělení konfigurace od používání služeb.

