Nette Documentation Preview

syntax
Gyakran ismételt kérdések a DI-ről (FAQ)
****************************************


A DI az IoC másik neve? .[#toc-is-di-another-name-for-ioc]
----------------------------------------------------------

Az *Inversion of Control* (IoC) egy olyan elv, amely a kód végrehajtásának módjára összpontosít - arra, hogy a kódod külső kódot kezdeményez, vagy a kódod integrálódik külső kódba, amely aztán meghívja azt.
Az IoC egy tág fogalom, amely magában foglalja az [eseményeket |nette:glossary#Events], az úgynevezett [hollywoodi elvet |application:components#Hollywood style] és más szempontokat.
A gyárak, amelyek a [3. szabály: Let the Factory Handle It |introduction#Rule #3: Let the Factory Handle It] részét képezik, és a `new` operátor inverzióját jelentik, szintén e koncepció összetevői.

A *Dependency Injection* (DI) arról szól, hogy egy objektum hogyan tud egy másik objektumról, azaz függőségről. Ez egy olyan tervezési minta, amely megköveteli a függőségek explicit átadását az objektumok között.

Így a DI az IoC egy sajátos formájának mondható. Az IoC nem minden formája alkalmas azonban a kódtisztaság szempontjából. Például az anti-minták közé soroljuk az összes olyan technikát, amely [globális állapottal |global state] vagy az úgynevezett [Service Locatorral |#What is a Service Locator] dolgozik.


Mi az a Service Locator? .[#toc-what-is-a-service-locator]
----------------------------------------------------------

A Service Locator a Dependency Injection alternatívája. Úgy működik, hogy létrehoz egy központi tárolót, ahol az összes elérhető szolgáltatás vagy függőség regisztrálva van. Amikor egy objektumnak szüksége van egy függőségre, akkor azt a Service Locatorból kéri.

A Dependency Injectionhoz képest azonban veszít az átláthatóságból: a függőségek nem kerülnek közvetlenül az objektumokhoz, ezért nem könnyen azonosíthatók, ami a kód vizsgálatát igényli az összes kapcsolat feltárásához és megértéséhez. A tesztelés is bonyolultabb, mivel nem adhatunk át egyszerűen mock objektumokat a tesztelt objektumoknak, hanem a Service Locatoron keresztül kell haladnunk. Továbbá a Service Locator megzavarja a kód tervezését, mivel az egyes objektumoknak tisztában kell lenniük a létezésével, ami eltér a Dependency Injectiontől, ahol az objektumok nem tudnak a DI konténerről.


Mikor jobb, ha nem használjuk a DI-t? .[#toc-when-is-it-better-not-to-use-di]
-----------------------------------------------------------------------------

A Dependency Injection tervezési minta használatával kapcsolatban nincsenek ismert nehézségek. Ellenkezőleg, a függőségek globálisan elérhető helyekről való megszerzése [számos bonyodalomhoz |global-state] vezet, akárcsak a Service Locator használata.
Ezért tanácsos mindig a DI használata. Ez nem dogmatikus megközelítés, de egyszerűen nem találtunk jobb alternatívát.

Vannak azonban olyan helyzetek, amikor nem adunk át objektumokat egymásnak, és a globális térből szerezzük meg őket. Például, amikor kódot hibakeresünk, és a program egy adott pontján ki kell dobnunk egy változó értékét, meg kell mérnünk a program egy bizonyos részének időtartamát, vagy naplóznunk kell egy üzenetet.
Ilyen esetekben, amikor olyan ideiglenes műveletekről van szó, amelyek később eltávolításra kerülnek a kódból, jogos egy globálisan elérhető dumper, stopperóra vagy logger használata. Ezek az eszközök végül is nem tartoznak a kód tervezéséhez.


Vannak-e hátrányai a DI használatának? .[#toc-does-using-di-have-its-drawbacks]
-------------------------------------------------------------------------------

A Dependency Injection használata jár-e hátrányokkal, például a kódírás bonyolultabbá válásával vagy rosszabb teljesítménnyel? Mit veszítünk, ha a DI-vel összhangban kezdünk kódot írni?

A DI nincs hatással az alkalmazás teljesítményére vagy memóriaigényére. A DI konténer teljesítménye szerepet játszhat, de a [Nette DI | nette-container] esetében a konténer tiszta PHP-be van fordítva, így az alkalmazás futási ideje alatt a többletköltsége lényegében nulla.

A kód írásakor olyan konstruktorokat kell létrehozni, amelyek elfogadják a függőségeket. Régebben ez időigényes lehetett, de a modern IDE-knek és a [konstruktorok tulajdonságainak promóciójának |https://blog.nette.org/hu/php-8-0-teljes-attekintes-az-ujdonsagokrol#toc-constructor-property-promotion] köszönhetően ez ma már néhány másodperc kérdése. A Nette DI és egy PhpStorm plugin segítségével néhány kattintással könnyedén létrehozhatók a konstruktorok.
Másrészt nincs szükség singletonok és statikus hozzáférési pontok írására.

Megállapítható, hogy egy megfelelően megtervezett, DI-t használó alkalmazás nem rövidebb és nem hosszabb a singletonokat használó alkalmazáshoz képest. A függőségekkel dolgozó kódrészek egyszerűen kivonásra kerülnek az egyes osztályokból, és új helyekre, azaz a DI konténerbe és a gyárakba kerülnek.


Hogyan írjunk át egy régi alkalmazást DI-re? .[#toc-how-to-rewrite-a-legacy-application-to-di]
----------------------------------------------------------------------------------------------

A régebbi alkalmazásról a Dependency Injectionra való áttérés kihívást jelentő folyamat lehet, különösen a nagy és összetett alkalmazások esetében. Fontos, hogy szisztematikusan közelítsük meg ezt a folyamatot.

- A Dependency Injectionra való áttérés során fontos, hogy a csapat minden tagja megértse az alkalmazott elveket és gyakorlatokat.
- Először is végezze el a meglévő alkalmazás elemzését a kulcsfontosságú összetevők és függőségük azonosítása érdekében. Készítsen tervet arra vonatkozóan, hogy mely részeket és milyen sorrendben fogja refaktorálni.
- Implementáljon egy DI-konténert, vagy még jobb, ha egy meglévő könyvtárat használ, például a Nette DI-t.
- Fokozatosan alakítsa át az alkalmazás minden egyes részét a Dependency Injection használatára. Ez magában foglalhatja a konstruktorok vagy metódusok módosítását, hogy paraméterként elfogadják a függőségeket.
- Módosítsa a kód azon helyeit, ahol függőségi objektumok jönnek létre, hogy a függőségeket a konténer injektálja. Ez magában foglalhatja a gyárak használatát.

Ne feledje, hogy a függőségi injektálásra való áttérés a kód minőségébe és az alkalmazás hosszú távú fenntarthatóságába való befektetés. Bár kihívást jelenthet ezeknek a változtatásoknak a végrehajtása, az eredménynek tisztább, modulárisabb és könnyen tesztelhető kódnak kell lennie, amely készen áll a jövőbeli bővítésekre és karbantartásra.


Miért előnyösebb a kompozíció az örökléssel szemben? .[#toc-why-composition-is-preferred-over-inheritance]
----------------------------------------------------------------------------------------------------------
Az [öröklés |nette:introduction-to-object-oriented-programming#inheritance] helyett előnyösebb a [kompozíciót |nette:introduction-to-object-oriented-programming#composition] használni, mert ez a kód újrafelhasználását szolgálja anélkül, hogy aggódnunk kellene a változások következményei miatt. Így lazább csatolást biztosít, ahol nem kell aggódnunk amiatt, hogy bizonyos kódok megváltoztatása más függő kódok megváltoztatásának szükségességét eredményezi. Tipikus példa erre a [konstruktorpokolnak |passing-dependencies#Constructor hell] nevezett helyzet.


Használható-e a Nette DI Container a Nette rendszeren kívül is? .[#toc-can-nette-di-container-be-used-outside-of-nette]
-----------------------------------------------------------------------------------------------------------------------

Természetesen. A Nette DI Container része a Nette-nek, de önálló könyvtárként van kialakítva, amely a keretrendszer más részeitől függetlenül használható. Csak telepítse a Composer segítségével, hozzon létre egy konfigurációs fájlt, amely meghatározza a szolgáltatásait, majd néhány sor PHP kóddal hozza létre a DI konténert.
És máris elkezdheti kihasználni a Dependency Injection előnyeit a projektjeiben.

A [Nette DI Container |nette-container] fejezetben leírja, hogyan néz ki egy konkrét felhasználási eset, a kóddal együtt.


Miért van a konfiguráció NEON fájlokban? .[#toc-why-is-the-configuration-in-neon-files]
---------------------------------------------------------------------------------------

A NEON egy egyszerű és könnyen olvasható konfigurációs nyelv, amelyet a Nette-en belül fejlesztettek ki az alkalmazások, szolgáltatások és függőségeik beállítására. A JSON-hoz vagy a YAML-hez képest sokkal intuitívabb és rugalmasabb lehetőségeket kínál erre a célra. A NEON-ban természetesen leírhatók olyan kötöttségek, amelyeket Symfony & YAML-ben egyáltalán nem vagy csak bonyolult leírással lehetne megírni.


Lassítja a NEON fájlok elemzése az alkalmazást? .[#toc-does-parsing-neon-files-slow-down-the-application]
---------------------------------------------------------------------------------------------------------

Bár a NEON fájlok elemzése nagyon gyorsan történik, ez a szempont nem igazán számít. Ennek oka az, hogy a fájlok elemzése csak egyszer történik meg az alkalmazás első indítása során. Ezt követően a DI-konténer kódja generálódik, a lemezen tárolódik, és minden további kérésnél további elemzés nélkül végrehajtódik.

Ez így működik a termelési környezetben. A fejlesztés során a NEON-fájlok minden alkalommal elemzése megtörténik, amikor tartalmuk megváltozik, így biztosítva, hogy a fejlesztő mindig naprakész DI-konténerrel rendelkezzen. Mint korábban említettük, a tényleges elemzés egy pillanat alatt megtörténik.


Hogyan férhetek hozzá a konfigurációs fájl paramétereihez az osztályomban? .[#toc-how-do-i-access-the-parameters-from-the-configuration-file-in-my-class]
---------------------------------------------------------------------------------------------------------------------------------------------------------

Tartsd szem előtt az [1. szabályt: Hagyd, hogy átadják n |introduction#Rule #1: Let It Be Passed to You]eked. Ha egy osztálynak szüksége van egy konfigurációs fájlból származó információra, nem kell kitalálnunk, hogyan érhetjük el az információt, hanem egyszerűen kérdezzük meg - például az osztály konstruktorán keresztül. Az átadást pedig a konfigurációs fájlban végezzük el.

Ebben a példában a `%myParameter%` a `myParameter` paraméter értékének helyőrzője, amelyet a `MyClass` konstruktornak adunk át:

```php
# config.neon
parameters:
	myParameter: Some value

services:
	- MyClass(%myParameter%)
```

Ha több paramétert akar átadni, vagy automatikus kapcsolást szeretne használni, hasznos, ha [a paramétereket egy objektumba csomagolja |best-practices:passing-settings-to-presenters].


Támogatja a Nette a PSR-11 konténer interfészt? .[#toc-does-nette-support-psr-11-container-interface]
-----------------------------------------------------------------------------------------------------

A Nette DI Container nem támogatja közvetlenül a PSR-11-et. Ha azonban interoperabilitásra van szüksége a Nette DI Container és a PSR-11 Container interfészt elváró könyvtárak vagy keretrendszerek között, létrehozhat egy [egyszerű adaptert |https://gist.github.com/dg/7f02403bd36d9d1c73802a6268a4361f], amely hídként szolgál a Nette DI Container és a PSR-11 között.

Gyakran ismételt kérdések a DI-ről (FAQ)

A DI az IoC másik neve?

Az Inversion of Control (IoC) egy olyan elv, amely a kód végrehajtásának módjára összpontosít – arra, hogy a kódod külső kódot kezdeményez, vagy a kódod integrálódik külső kódba, amely aztán meghívja azt. Az IoC egy tág fogalom, amely magában foglalja az eseményeket, az úgynevezett hollywoodi elvet és más szempontokat. A gyárak, amelyek a 3. szabály: Let the Factory Handle It részét képezik, és a new operátor inverzióját jelentik, szintén e koncepció összetevői.

Dependency Injection (DI) arról szól, hogy egy objektum hogyan tud egy másik objektumról, azaz függőségről. Ez egy olyan tervezési minta, amely megköveteli a függőségek explicit átadását az objektumok között.

Így a DI az IoC egy sajátos formájának mondható. Az IoC nem minden formája alkalmas azonban a kódtisztaság szempontjából. Például az anti-minták közé soroljuk az összes olyan technikát, amely globális állapottal vagy az úgynevezett Service Locatorral dolgozik.

Mi az a Service Locator?

A Service Locator a Dependency Injection alternatívája. Úgy működik, hogy létrehoz egy központi tárolót, ahol az összes elérhető szolgáltatás vagy függőség regisztrálva van. Amikor egy objektumnak szüksége van egy függőségre, akkor azt a Service Locatorból kéri.

A Dependency Injectionhoz képest azonban veszít az átláthatóságból: a függőségek nem kerülnek közvetlenül az objektumokhoz, ezért nem könnyen azonosíthatók, ami a kód vizsgálatát igényli az összes kapcsolat feltárásához és megértéséhez. A tesztelés is bonyolultabb, mivel nem adhatunk át egyszerűen mock objektumokat a tesztelt objektumoknak, hanem a Service Locatoron keresztül kell haladnunk. Továbbá a Service Locator megzavarja a kód tervezését, mivel az egyes objektumoknak tisztában kell lenniük a létezésével, ami eltér a Dependency Injectiontől, ahol az objektumok nem tudnak a DI konténerről.

Mikor jobb, ha nem használjuk a DI-t?

A Dependency Injection tervezési minta használatával kapcsolatban nincsenek ismert nehézségek. Ellenkezőleg, a függőségek globálisan elérhető helyekről való megszerzése számos bonyodalomhoz vezet, akárcsak a Service Locator használata. Ezért tanácsos mindig a DI használata. Ez nem dogmatikus megközelítés, de egyszerűen nem találtunk jobb alternatívát.

Vannak azonban olyan helyzetek, amikor nem adunk át objektumokat egymásnak, és a globális térből szerezzük meg őket. Például, amikor kódot hibakeresünk, és a program egy adott pontján ki kell dobnunk egy változó értékét, meg kell mérnünk a program egy bizonyos részének időtartamát, vagy naplóznunk kell egy üzenetet. Ilyen esetekben, amikor olyan ideiglenes műveletekről van szó, amelyek később eltávolításra kerülnek a kódból, jogos egy globálisan elérhető dumper, stopperóra vagy logger használata. Ezek az eszközök végül is nem tartoznak a kód tervezéséhez.

Vannak-e hátrányai a DI használatának?

A Dependency Injection használata jár-e hátrányokkal, például a kódírás bonyolultabbá válásával vagy rosszabb teljesítménnyel? Mit veszítünk, ha a DI-vel összhangban kezdünk kódot írni?

A DI nincs hatással az alkalmazás teljesítményére vagy memóriaigényére. A DI konténer teljesítménye szerepet játszhat, de a Nette DI esetében a konténer tiszta PHP-be van fordítva, így az alkalmazás futási ideje alatt a többletköltsége lényegében nulla.

A kód írásakor olyan konstruktorokat kell létrehozni, amelyek elfogadják a függőségeket. Régebben ez időigényes lehetett, de a modern IDE-knek és a konstruktorok tulajdonságainak promóciójának köszönhetően ez ma már néhány másodperc kérdése. A Nette DI és egy PhpStorm plugin segítségével néhány kattintással könnyedén létrehozhatók a konstruktorok. Másrészt nincs szükség singletonok és statikus hozzáférési pontok írására.

Megállapítható, hogy egy megfelelően megtervezett, DI-t használó alkalmazás nem rövidebb és nem hosszabb a singletonokat használó alkalmazáshoz képest. A függőségekkel dolgozó kódrészek egyszerűen kivonásra kerülnek az egyes osztályokból, és új helyekre, azaz a DI konténerbe és a gyárakba kerülnek.

Hogyan írjunk át egy régi alkalmazást DI-re?

A régebbi alkalmazásról a Dependency Injectionra való áttérés kihívást jelentő folyamat lehet, különösen a nagy és összetett alkalmazások esetében. Fontos, hogy szisztematikusan közelítsük meg ezt a folyamatot.

  • A Dependency Injectionra való áttérés során fontos, hogy a csapat minden tagja megértse az alkalmazott elveket és gyakorlatokat.
  • Először is végezze el a meglévő alkalmazás elemzését a kulcsfontosságú összetevők és függőségük azonosítása érdekében. Készítsen tervet arra vonatkozóan, hogy mely részeket és milyen sorrendben fogja refaktorálni.
  • Implementáljon egy DI-konténert, vagy még jobb, ha egy meglévő könyvtárat használ, például a Nette DI-t.
  • Fokozatosan alakítsa át az alkalmazás minden egyes részét a Dependency Injection használatára. Ez magában foglalhatja a konstruktorok vagy metódusok módosítását, hogy paraméterként elfogadják a függőségeket.
  • Módosítsa a kód azon helyeit, ahol függőségi objektumok jönnek létre, hogy a függőségeket a konténer injektálja. Ez magában foglalhatja a gyárak használatát.

Ne feledje, hogy a függőségi injektálásra való áttérés a kód minőségébe és az alkalmazás hosszú távú fenntarthatóságába való befektetés. Bár kihívást jelenthet ezeknek a változtatásoknak a végrehajtása, az eredménynek tisztább, modulárisabb és könnyen tesztelhető kódnak kell lennie, amely készen áll a jövőbeli bővítésekre és karbantartásra.

Miért előnyösebb a kompozíció az örökléssel szemben?

Az öröklés helyett előnyösebb a kompozíciót használni, mert ez a kód újrafelhasználását szolgálja anélkül, hogy aggódnunk kellene a változások következményei miatt. Így lazább csatolást biztosít, ahol nem kell aggódnunk amiatt, hogy bizonyos kódok megváltoztatása más függő kódok megváltoztatásának szükségességét eredményezi. Tipikus példa erre a konstruktorpokolnak nevezett helyzet.

Használható-e a Nette DI Container a Nette rendszeren kívül is?

Természetesen. A Nette DI Container része a Nette-nek, de önálló könyvtárként van kialakítva, amely a keretrendszer más részeitől függetlenül használható. Csak telepítse a Composer segítségével, hozzon létre egy konfigurációs fájlt, amely meghatározza a szolgáltatásait, majd néhány sor PHP kóddal hozza létre a DI konténert. És máris elkezdheti kihasználni a Dependency Injection előnyeit a projektjeiben.

Nette DI Container fejezetben leírja, hogyan néz ki egy konkrét felhasználási eset, a kóddal együtt.

Miért van a konfiguráció NEON fájlokban?

A NEON egy egyszerű és könnyen olvasható konfigurációs nyelv, amelyet a Nette-en belül fejlesztettek ki az alkalmazások, szolgáltatások és függőségeik beállítására. A JSON-hoz vagy a YAML-hez képest sokkal intuitívabb és rugalmasabb lehetőségeket kínál erre a célra. A NEON-ban természetesen leírhatók olyan kötöttségek, amelyeket Symfony & YAML-ben egyáltalán nem vagy csak bonyolult leírással lehetne megírni.

Lassítja a NEON fájlok elemzése az alkalmazást?

Bár a NEON fájlok elemzése nagyon gyorsan történik, ez a szempont nem igazán számít. Ennek oka az, hogy a fájlok elemzése csak egyszer történik meg az alkalmazás első indítása során. Ezt követően a DI-konténer kódja generálódik, a lemezen tárolódik, és minden további kérésnél további elemzés nélkül végrehajtódik.

Ez így működik a termelési környezetben. A fejlesztés során a NEON-fájlok minden alkalommal elemzése megtörténik, amikor tartalmuk megváltozik, így biztosítva, hogy a fejlesztő mindig naprakész DI-konténerrel rendelkezzen. Mint korábban említettük, a tényleges elemzés egy pillanat alatt megtörténik.

Hogyan férhetek hozzá a konfigurációs fájl paramétereihez az osztályomban?

Tartsd szem előtt az 1. szabályt: Hagyd, hogy átadják neked. Ha egy osztálynak szüksége van egy konfigurációs fájlból származó információra, nem kell kitalálnunk, hogyan érhetjük el az információt, hanem egyszerűen kérdezzük meg – például az osztály konstruktorán keresztül. Az átadást pedig a konfigurációs fájlban végezzük el.

Ebben a példában a %myParameter% a myParameter paraméter értékének helyőrzője, amelyet a MyClass konstruktornak adunk át:

# config.neon
parameters:
	myParameter: Some value

services:
	- MyClass(%myParameter%)

Ha több paramétert akar átadni, vagy automatikus kapcsolást szeretne használni, hasznos, ha a paramétereket egy objektumba csomagolja.

Támogatja a Nette a PSR-11 konténer interfészt?

A Nette DI Container nem támogatja közvetlenül a PSR-11-et. Ha azonban interoperabilitásra van szüksége a Nette DI Container és a PSR-11 Container interfészt elváró könyvtárak vagy keretrendszerek között, létrehozhat egy egyszerű adaptert, amely hídként szolgál a Nette DI Container és a PSR-11 között.