Întrebări frecvente despre DI (FAQ)
- Este DI un alt nume pentru IoC?
- Ce este un Service Locator?
- Când este mai bine să nu folosiți DI?
- Utilizarea DI are dezavantajele sale?
- Cum să rescrieți o aplicație moștenită în DI?
- De ce este preferată compoziția în locul moștenirii?
- Poate fi utilizat Nette DI Container în afara Nette?
- De ce este configurația în fișiere NEON?
- Analiza fișierelor NEON încetinește aplicația?
- Cum pot accesa parametrii din fișierul de configurare în clasa mea?
- Nette acceptă interfața PSR-11 Container?
Este DI un alt nume pentru IoC?
Inversion of Control (IoC) este un principiu care se concentrează asupra modului în care este executat codul –
dacă codul dumneavoastră inițiază codul extern sau dacă codul dumneavoastră este integrat în codul extern, care îl
apelează. IoC este un concept larg care include evenimente,
așa-numitul principiu Hollywood și alte
aspecte. Fabricile, care fac parte din Regula nr. 3: Lasă fabrica
să se ocupe, și reprezintă inversiunea pentru operatorul new
, sunt, de asemenea, componente ale acestui
concept.
Dependency Injection (DI) se referă la modul în care un obiect știe despre un alt obiect, adică la dependență. Este un model de proiectare care necesită transmiterea explicită a dependențelor între obiecte.
Astfel, se poate spune că DI este o formă specifică de IoC. Cu toate acestea, nu toate formele de IoC sunt potrivite din punct de vedere al purității codului. De exemplu, printre antimodele, includem toate tehnicile care lucrează cu starea globală sau așa-numitul Service Locator.
Ce este un Service Locator?
Un localizator de servicii este o alternativă la injecția de dependență. Funcționează prin crearea unui depozit central în care sunt înregistrate toate serviciile sau dependențele disponibile. Atunci când un obiect are nevoie de o dependență, o solicită de la Localizatorul de servicii.
Cu toate acestea, în comparație cu injecția de dependență, pierde din transparență: dependențele nu sunt transmise direct obiectelor și, prin urmare, nu sunt ușor de identificat, ceea ce necesită examinarea codului pentru a descoperi și înțelege toate conexiunile. Testarea este, de asemenea, mai complicată, deoarece nu putem trece pur și simplu obiecte simulate către obiectele testate, ci trebuie să trecem prin intermediul Localizatorului de servicii. În plus, Service Locator perturbă proiectarea codului, deoarece obiectele individuale trebuie să fie conștiente de existența sa, ceea ce diferă de Dependency Injection, unde obiectele nu au cunoștință de containerul DI.
Când este mai bine să nu folosiți DI?
Nu există dificultăți cunoscute asociate cu utilizarea modelului de proiectare Dependency Injection. Dimpotrivă, obținerea dependențelor din locații accesibile la nivel global duce la o serie de complicații, la fel ca și utilizarea unui Service Locator. Prin urmare, este recomandabil să se utilizeze întotdeauna DI. Aceasta nu este o abordare dogmatică, ci pur și simplu nu s-a găsit o alternativă mai bună.
Cu toate acestea, există anumite situații în care nu ne transmitem obiecte între noi și le obținem din spațiul global. De exemplu, atunci când se depanează codul și este nevoie să se descarce valoarea unei variabile într-un anumit punct al programului, să se măsoare durata unei anumite părți a programului sau să se înregistreze un mesaj. În astfel de cazuri, în care este vorba despre acțiuni temporare care vor fi ulterior eliminate din cod, este legitim să se utilizeze un dumper, un cronometru sau un logger accesibil la nivel global. Aceste instrumente, la urma urmei, nu fac parte din proiectarea codului.
Utilizarea DI are dezavantajele sale?
Utilizarea Injecției de dependență implică dezavantaje, cum ar fi creșterea complexității scrierii codului sau o performanță mai slabă? Ce pierdem atunci când începem să scriem cod în conformitate cu DI?
DI nu are niciun impact asupra performanței aplicației sau a cerințelor de memorie. Performanța containerului DI poate juca un rol, dar în cazul Nette DI, containerul este compilat în PHP pur, astfel că sarcina sa în timpul rulării aplicației este practic zero.
La scrierea codului, este necesar să se creeze constructori care acceptă dependențe. În trecut, acest lucru putea consuma mult timp, dar datorită IDE-urilor moderne și promovării proprietăților constructorilor, acum este o chestiune de câteva secunde. Constructorii pot fi generați cu ușurință folosind Nette DI și un plugin PhpStorm cu doar câteva clicuri. Pe de altă parte, nu este nevoie să scrieți singletons și puncte de acces statice.
Se poate concluziona că o aplicație proiectată corespunzător care utilizează DI nu este nici mai scurtă, nici mai lungă în comparație cu o aplicație care utilizează singletons. Părțile de cod care lucrează cu dependențele sunt pur și simplu extrase din clasele individuale și mutate în locații noi, adică în containerul DI și în fabrici.
Cum să rescrieți o aplicație moștenită în DI?
Migrarea de la o aplicație moștenită la Injecția de dependență poate fi un proces dificil, în special pentru aplicațiile mari și complexe. Este important să abordați acest proces în mod sistematic.
- Atunci când se trece la Injectarea dependenței, este important ca toți membrii echipei să înțeleagă principiile și practicile utilizate.
- În primul rând, efectuați o analiză a aplicației existente pentru a identifica componentele cheie și dependențele acestora. Creați un plan pentru care părți vor fi refactorizate și în ce ordine.
- Implementați un container DI sau, și mai bine, utilizați o bibliotecă existentă, cum ar fi Nette DI.
- Refaceți treptat fiecare parte a aplicației pentru a utiliza Injecția de dependență. Acest lucru poate implica modificarea constructorilor sau a metodelor pentru a accepta dependențele ca parametri.
- Modificați locurile din cod în care sunt create obiecte de dependență, astfel încât dependențele să fie injectate de container. Acest lucru poate include utilizarea fabricilor.
Nu uitați că trecerea la Injectarea dependențelor este o investiție în calitatea codului și în durabilitatea pe termen lung a aplicației. Deși poate fi o provocare să faceți aceste schimbări, rezultatul ar trebui să fie un cod mai curat, mai modular și ușor de testat, pregătit pentru extinderi și întreținere viitoare.
De ce este preferată compoziția în locul moștenirii?
Este de preferat să se utilizeze compoziția în locul moștenirii, deoarece aceasta permite reutilizarea codului fără a fi nevoie să ne facem griji cu privire la consecințele modificărilor. Astfel, oferă un cuplaj mai slab, în care nu trebuie să ne facem griji că modificarea unui cod va determina necesitatea de a modifica alt cod dependent. Un exemplu tipic este o situație denumită " iadul constructorilor".
Poate fi utilizat Nette DI Container în afara Nette?
Absolut. Nette DI Container face parte din Nette, dar este conceput ca o bibliotecă autonomă care poate fi utilizată independent de alte părți ale cadrului. Trebuie doar să o instalați folosind Composer, să creați un fișier de configurare care să definească serviciile dvs. și apoi să folosiți câteva linii de cod PHP pentru a crea containerul DI. Și puteți începe imediat să profitați de Injecția de dependență în proiectele dumneavoastră.
Capitolul Nette DI Container descrie cum arată un caz de utilizare specific, inclusiv codul.
De ce este configurația în fișiere NEON?
NEON este un limbaj de configurare simplu și ușor de citit, dezvoltat în cadrul Nette pentru configurarea aplicațiilor, a serviciilor și a dependențelor acestora. În comparație cu JSON sau YAML, acesta oferă opțiuni mult mai intuitive și mai flexibile în acest scop. În NEON, puteți descrie în mod natural legături care nu ar fi posibil de scris în Symfony & YAML, fie deloc, fie doar printr-o descriere complexă.
Analiza fișierelor NEON încetinește aplicația?
Deși fișierele NEON sunt analizate foarte rapid, acest aspect nu contează cu adevărat. Motivul este că analiza fișierelor are loc o singură dată în timpul primei lansări a aplicației. După aceea, codul containerului DI este generat, stocat pe disc și executat pentru fiecare solicitare ulterioară, fără a mai fi nevoie de o analiză suplimentară.
Acesta este modul în care funcționează într-un mediu de producție. În timpul dezvoltării, fișierele NEON sunt analizate de fiecare dată când conținutul lor se modifică, asigurându-se că dezvoltatorul are întotdeauna un container DI actualizat. După cum am menționat mai devreme, parsarea efectivă este o chestiune de o clipă.
Cum pot accesa parametrii din fișierul de configurare în clasa mea?
Rețineți regula nr. 1: Lăsați să vă fie transmisă. Dacă o clasă necesită informații dintr-un fișier de configurare, nu trebuie să ne dăm seama cum să accesăm aceste informații; în schimb, pur și simplu le cerem – de exemplu, prin intermediul constructorului clasei. Și efectuăm transmiterea în fișierul de configurare.
În acest exemplu, %myParameter%
este un spațiu rezervat pentru valoarea parametrului myParameter
,
care va fi transmis constructorului MyClass
:
# config.neon
parameters:
myParameter: Some value
services:
- MyClass(%myParameter%)
Dacă doriți să transmiteți mai mulți parametri sau să utilizați autowiring, este util să includeți parametrii într-un obiect.
Nette acceptă interfața PSR-11 Container?
Nette DI Container nu acceptă direct PSR-11. Cu toate acestea, dacă aveți nevoie de interoperabilitate între containerul Nette DI și bibliotecile sau cadrele care așteaptă interfața PSR-11 Container, puteți crea un adaptor simplu care să servească drept punte între containerul Nette DI și PSR-11.