Hlavní navigace

Dependency Injection ještě jednou :-)

15. 2. 2023 21:22 (aktualizováno) Mirek Marek

U předešlého článku se nám rozhořela pěkná diskuze :-) Rozhodl jsem se, že napíšu ještě jeden článek čistě na toto téma bez ohledu na PHP Jet. Tentokrát to bude pouze na téma návrh SW. Tak hurá do toho.

DI je super!

Jak jsem uváděl i v minulém článku, tak koncept DI je super věc a používám jí. Ale jako se vším, tak správný koncept se musí použít na správném místě.

Trvám na tom, že je nesmysl nějaký koncept používat všude. Veškerý dogmatismus je velice škodlivá věc. O to jde. Jde o tvrzení, že pro vytvoření „čistého, srozumitelného a udržitelného kódu“ (tedy aplikace) je nutné / dobré používat DI.

Otázka je, co je to ten „čistý kód“, ale držme se raději konkrétních situací.

K čemu je koncept DI dobrý?

Definice říká, že je to princip, kdy jedna komponenta používá druhou, aniž by znala její referenci. Tedy je to koncept pro určitou situaci a pro takovou situaci je to koncept velice užitečný.

Vzdalme se teď ze světa PHP, či jakýchkoliv jiných skriptovacích jazyků a ponořme se do světa jazyků jako je třeba C++.

Skriptovací jazyky nám umožňují tvořit mnohem vice dynamické aplikace (z hlediska jejich vnitřní struktury a chování). Nejsme omezeni překladačem. To je pro dané určení výhoda těchto jazyků a proto jsou tak hojně pro daný typ aplikací používané.

Ovšem já mám rád i staré dobré C (a v praxi jsem v něm pracoval a učí to mého syna) – vlastně nejdůležitější programovací jazyk na planetě, protože v něm je napsané i to PHP samotné a nejen PHP samozřejmě. V tom jazyce je člověk prostě blíž ke stroji. Však to znáte. Na vás je alokace i uvolnění paměti a tak dále. Používá se pointrová aritmetika. Prostě fajn zábava. A ano, vím že čisté C, není OOP jazyk, tak dejme tomu raději uvažujme o C++ – ať neslovíčkaříme. Jde tu o SW architekturu, ne konkrétní technologii.

Zpět tedy k „překládaným jazykům“. Když program překládám, tak jej samozřejmě linkuji s mnoha knihovnami atd. A může se stát, že potřebuji používat služby něčeho, co se mi natáhne dynamicky – třeba z dynamicky nahrávané knihovny na základě konfigurace (není to jediná cesta, pouze příklad).

V době překladu aplikace nemá tušení jaká přesně knihovna se konkrétně postará o danou věc. Např. jaký bude použit kodek na něco, či ovladač. Ale i tak aplikace musí to „cosi“ volat. A od toho může mít právě nějaký kontejner, u kterého je jasné rozhraní a je známo již v době překladu. Aplikace jasně zná kontejner, zná to i překladač a lze tak aplikaci přeložit. A do kontejneru je vložen poskytovatel samotné služby. Poskytovatelem služby – tedy tím co danou operaci opravdu provádí – může být právě dynamická knihovna (například) a kontejner se postará o potřebné náležitosti, nebo kontejner může být inicializován z venčí a tak dále. Ale to není podstata věci. Podstata věci je ta, že kontejner je známá entita a známé rozhraní, které zavolá konkrétní službu, která je však do určitého momentu neznámá.

Proto koncept DI vznikl. Aby bylo možné řešit takovou situaci v prostředí, kde je to vlastně technicky nutné.

A pochopitelně je víc cest, jak problematiku řešit.

Ovšem základní logika je tato:

  • Komponenty aplikace potřebují volat jinou komponentu – nějakou službu.
  • Komponenty aplikace vědí jak onu servisní komponentu / službu volat a jak ji použít.
  • Ovšem komponenty aplikace nemají tušení která konkrétní implementace dané služby (ať je tou službou cokoliv) jim tu službu zabezpečí.
  • Ostatní komponenty tedy použijí / volají kontejner ve kterém je nějak (je teď jedno jak) určeno co přesně je poskytovatel služby a postará se o zabezpečení služby přes konkrétního poskytovatele.

Je to naprosto perfektní koncept a pro některé technologie vlastně nutnost.

K čemu koncept DI není dobrý?

Jednoduše se dá říct, že tento super-užitečný koncept není dobré používat na místech pro které postrádá smysl.

Ano, pokud je modelová situace taková, že aplikace potřebuje něco dělat, ale nemá tušení jak přesně se ta operace vykoná (například logování – krásný příklad), tak je rozhodně dobré tento koncept použít. Je to nejsnadnější cesta k vyřešení daného problému. A nejsnadnější cesta znamená kvalitní aplikaci. To platí pro jakýkoliv jazyk a jakoukoliv technologii.

Ovšem je kontraproduktivní používat tento koncept tam, kde pro něj není místo – tedy v situacích pro které není navržen.

Tam kde řeším jinou situaci použiji jiný koncept pro danou situaci vhodnější. Jednoduché …

A právě to jsou ty „čisté kódy“. Aplikace, které používají správné koncepty na správných místech.

Držet se dogmat nikdy není cesta k efektivitě. To i v lidském životě vede k problémům. Však se koukněte na náboženské a jiné fanatiky. To je vždy zlo. V technice by mělo být dogmatizmu co nejméně.

Proč není dobré používat DI všude?

Pro jistotu opakuji: DI je super a má své nezastupitelné místo. Ale není dobré tento koncept dogmaticky používat všude, zejména tam, kde objektivně nemá své dané uplatnění a neplní svůj účel – aneb matku na šroubu také povolíte kombinačkami, ale není to ono, dá to práci a matka bude pořádně „ožvejkaná“.

Zde jsou důvody:

  • Přináší to do aplikace další složitost, která však není k ničemu reálně užitečná.
  • Zatěžuje to vývojáře a odvádí jej to od řešení podstaty věci. Prostě další věc na kterou musí myslet aniž by to přineslo reálný užitek a potřebnou efektivitu.
  • Pokud používáte framework s nějakými konfigurovatelnými kontejnery a ještě ke všemu v nějakém nestandardním datovém formátu, tak vám to objektivně sníží technickou efektivitu aplikace.

U toho posledního bodu se zastavím. Přemýšleli jsme někdy nad tím kolik paměti, I/O operací a instrukcí procesoru „sežere“ to, že se načítá konfigurace? A nedej bože když se musí nějak parsovat a případně řešit režijní operace s keší? Napadlo vás někdy kolik systémových prostředků „sežere“ registrace rout (mimochodem nedokážu si představit routovací pravidla pro mé projekty), nebo například tzv. služeb, middleware a toho všeho? Však jsem to v jednom ze starších článků ukazoval zcela názorně.

A teď je nutné zdůraznit PHP. PHP má tu výhodu i nevýhodu v tom, že pro každý požadavek aplikace znova nabíhá. Neřešme teď zda je to dobře, nebo špatně. Prostě to tak je. A pro každou prkotinu musí aplikace udělat poměrně dost věcí, „sežrat“ poměrně dost zdrojů systému. To vše je měřitelné. A ano, platí to i pro Jet.

Tak PHP prostě funguje. A s ohledem na to musí být náběh aplikace co nejjednodušší, nejrychlejší a nejoptimalizovanější.

A používání různých DI kontejnerů a dalších věcí, kde s růstem velikosti aplikace úměrně narůstá i náročnost a spotřeba zdrojů systému, jde přímo proti tomu. A to je problém. V online aplikaci dosti podstatný až řekl bych zásadní problém.

Jistě, je různé kešování a tak dále. Ale já říkám: Proč si problémy přidělávat dogmatickým používáním něčeho na to k čemu to není určené. A navíc tak porušovat jiné koncepty OOP.

Závěr

  • DI je super koncept, který má své nezastupitelné místo.
  • Tam kde má koncept DI smysl je vhodné jej použít.
  • Kde ten koncept použít je věcí vývojáře a jeho zkušeností. V žádném případě ne věci dogmatu.
  • Rozhodně neplatí, že tento koncept zajistí „čístý a přehledný kód“. Při nesprávné použití na nesprávném místě udělá pravý opak.
  • Je velice špatné a škodlivé tvrdit, že se určitý koncept má používat všude a že zajistí kvalitní aplikaci. To rozhodně neplatí a něco takové programátory učit je opravdu špatně. Jde to přímo proti podstatě bytí programátora. Programátor / vývojář má znát a chápat jak věci fungují a jak je tedy použít. 
  • Neexistuje jediná správná cesta. Ovšem je zcela legitimní tvrdit, že správná cesta je používat správné nástroje a postupy na správných místech. To je jediné co lze jednoduše považovat za správné. V ostatních případech je to již o posouzení konkrétní situace. A používat něco dogmaticky jde přímo proti tomu.

Tož tak … 

A omlouvám se, že nejsem neustále v diskuzi. Ale např. minulý týden jsem raději se synem blnul na horách. Díky za pochopení. 

Ale čas si určitě zase udělám a do diskuze mrknu ;-)

Díky za přečtení a mějte se krásně!

Sdílet