Pogledajte određenu poruku
Staro 21. 03. 2013.   #26
_korso_
profesionalac
Qualified
 
Avatar _korso_
 
Datum učlanjenja: 21.06.2007
Poruke: 166
Hvala: 27
42 "Hvala" u 23 poruka
_korso_ is on a distinguished road
Default

@Djuki Naravno.

Primer je timer klasa koja meri vremena u requestu, od toga koliko se izvrsavaju upiti (svaki pojedinacno jer postoje dve baze Postgres i Mongo koje se istovremeno koriste), do toga koliko se izvrsavaju odredjene metode koje imaju zahtevan posao da odrade (opet u Domain delu appa), te i sam request. Idealan primer za upotrebu singleton klase.

PHP kôd:
//sys.timer servis - konfiguracija
1. $serviceContainer
    
->register('sys.timer''OP\Library\Utilities\SysTimer')
    ->
setArguments(['request_time'$kernel->getRequestStartTime()])
    ->
setShared(true);// I

//negde u kodu koji kreira druge servis objekte koji koriste servis konfigurisan u 1.
2. $serviceContainer->getService('sys.timer'/*, II */);

3.
class PgPdoAdapter {
    public function 
__construct(SysTimer $timer) {}
}

class 
MongoAdapter {
    public function 
__construct(SysTimer $timer) {}
}

class 
ShutdownHandler {
    public function 
__construct(SysTimer $timer) {}
}

class 
ContactsRepository {
    public function 
setSysTimer(SysTimer $timer) {}

Dakle, svaki "service" kako nazivamo ove objekte konfigurisane kroz ServiceContainer, je po defaultu ne deljen. Zato u 1. imamo liniju I. Svaki poziv za tim objektom kao u 2. ce vratiti istu instancu SysTimer objekta. Ukoliko zelimo da nam uvek poziv 2. vraca razlicit novo kreirani objekat, onda mozemo da izostavimo u 1. liniju I.

Ono sto sam stavio u 2. kao II je - prvobitno je bilo moguce da u samom pozivu prosledimo da li je instanca deljena (da li je singleton-like ili ne). I ovakva konfiguracija prilikom poziva `getService` metode ima prednost u odnosu na konfiguraciju 1. u liniji I. Medjutim, ispostavilo se je da ovakva fleksibilnost koja je na prvi pogled primamljiva, za kasnije odrzavanje je nocna mora - jer moramo da pratimo `getService` pozive (mada uglavnom ih ima po 1 za odredjeni servis). Posle nekog vremena je ta funkcionalnost izbacena, gde je zakljucak bio - ako nam ovako nesto treba, ili nesto ne radimo kako treba ili jednostavno sam objekat nije singleton-like.

U 3. mozes videti da je servis opcionalan za ContactsRepository klasu pa se injectuje kroz setter.

Bilo kako bilo, ovo je samo vrh ledenog brega oko koriscenja DI prakse za kreiranje grafa objekata.

I za kraj bih rekao svoje iskustvo povodom koriscenja DI prakse u zadnje 2 godine. Iskreno, prvo sam bio skeptik. Java mi se smucila (licno i subjektivno misljenje), a ovo je dosta slicno sto sam tamo radio. Medjutim, pokazalo se u praksi kao odlicno resenje, ali... Nije bas lako za objasniti svima, trazi dosta discipline, izgleda komplikovano. Sto "tezi" objekat, veca konfiguracija. Ovaj primer koji sam dao je najprostiji moguci. Sama konfiguracija je dosta komplikovana za nekog ko prvi put gleda u sam kod. Sa klijent strane se uvek svodi na `getService`. Planirao sam da pogledam kako to rade u nekim drugim jezicima koji imaju totalno drugu viziju. I oni imaju iste probleme.

Interesantan je pristup u javascript svetu AngularJs-a. Oni "skeniraju" i parsuju kod pre izvrsavanja. Kako svi dependency se deklarisu u konstruktoru po nekom kvazi tipu, sam Angular na osnovu toga radi magiju i ne treba ti konfiguracija. On sam zakljucuje sta treba da radi i koji servis treba da kreira prvo. Mada i Angular ima Javu za uzor (tj. sam Misko - http://misko.hevery.com - je glavni autor). Nije ovo tesko izvesti, probao sam sa DI komponentom - gore pomenutom. Ali su pitanje, performanse - gde mora neko kesiranje, kao i to da konstruktori mogu biti sa *mnogo* objekata - sto mi se ne svidja. Slican fora je i sa requireJs-om.

Sve u svemu, ovo radi odlican posao, ali ono sto mu nedostaje je malo manja kompleksnost i eventualno malo manje konfiguracije.
__________________
Twitter
_korso_ je offline   Odgovorite uz citat
2 članova zahvaljuje _korso_ za poruku: