![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 95 Pomógł: 7 Dołączył: 16.07.2007 Skąd: Gorzów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
Ostatnio zainteresowałem się tym artykułem: http://phpgeek.pl/112/dependency-injection-container/ Ciekawi mnie jedna kwestia, czy instancję Containera przekazywać gdzieś dalej do obiektów i do obiektów w obiektach przez parametr, czy skorzystać z tego, że tablica jest zmienną statyczną i w kolejnych "zagnieżdżeniach" obiektów tworzyć nowy obiekt Containera? Bo jeśli przez parametr to można wywalić zmienną statyczną (większa śladowa wydajność, większy bałagan w parametrach) a jeśli tworzyć nowy obiekt to niby nam ta wydajność spada, bo i zmienna statyczna i do tego kolejne obiekty... np 3 obiekty przy jednym żądaniu. Chociaż nie wiem jak się ma to do zmiennych statycznych, to podobno stosowanie metod statycznych (w większej dawce) odbywa się kosztem spadku wydajności. Co Wy o tym wszystkim myślicie?
-------------------- "It's always darkest before the dawn." |
|
|
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Wydajność nie ma tu większego znaczenia - chodzi bardziej o wygodę działania.
Tutaj masz przykładową implementację http://components.symfony-project.org/dependency-injection/ |
|
|
![]()
Post
#3
|
|
![]() Grupa: Zarejestrowani Postów: 95 Pomógł: 7 Dołączył: 16.07.2007 Skąd: Gorzów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
W tym poście chodzi mi o to, aby głównie się skupić na tej prostej implementacji zaprezentowanej przez autora
![]() -------------------- "It's always darkest before the dawn." |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 130 Pomógł: 11 Dołączył: 7.04.2003 Ostrzeżenie: (10%) ![]() ![]() |
A My o tym wszystkim myślimy, że z całą pewnością NIE powinineś przekazywać kontenera jako parametru w metodach (czy konstruktorach) obiektów, które ten że kontener inicjalizuje i w którym one "pływają".
To było było by doprawdy kuriozum. Ideą IoC jest eliminacja sprzężeń w kodzie, czyli ZBĘDNYCH zależności pomiędzy poszczególnymi fragmentami systemu. Tymczasem w ten sposób wprowadził byś dodatkowe zupełnie zbędne sprzężenia. Po prostu korzystaj z kontenera w taki sposób w jaki opisuje to jego dokumentacja. Przykładowo jeżeli jest:
To wywołujesz kontener właśnie w taki sposób wszędzie tam gdzie jest potrzebny. Będzie on inicjalizowany tylko za pierwszym razem reszta to odwołania do tego samego obiektu. Poczytaj o singletonach. Ten post edytował smentek 8.09.2010, 20:55:20 -------------------- .:SMENTEK:.
|
|
|
![]()
Post
#5
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
@smentek: To Tobie radziłbym poczytać o tym wzorcu, bo to co proponujesz:
To właśnie powód dla którego ten normalny wzorzec ma opinię anty-wzorca... nie takie jest jego zastosowanie! Co więcej takie partactwo przynosi jedynie więcej problemów niż pożytku. Jedyne co zrobiłeś to zamieniłeś global na :: i narzuciłeś sobie dodatkowych sztucznych ograniczeń i, o ironio, zbędnych zależności. A żeby nie było: celem tego wzorca jest zapewnienie dokładnie jednej instancji danej klasy, a nie globalny dostęp do obiektu - od tego jest global. |
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarejestrowani Postów: 130 Pomógł: 11 Dołączył: 7.04.2003 Ostrzeżenie: (10%) ![]() ![]() |
@smentek: To Tobie radziłbym poczytać o tym wzorcu, bo to co proponujesz: To właśnie powód dla którego ten normalny wzorzec ma opinię anty-wzorca... nie takie jest jego zastosowanie! Co więcej takie partactwo przynosi jedynie więcej problemów niż pożytku. Jedyne co zrobiłeś to zamieniłeś global na :: i narzuciłeś sobie dodatkowych sztucznych ograniczeń i, o ironio, zbędnych zależności. A żeby nie było: celem tego wzorca jest zapewnienie dokładnie jednej instancji danej klasy, a nie globalny dostęp do obiektu - od tego jest global. Rozumiem, i masz rację, że bez singletonu można się tu obejść. Nie zaproponowałem jednak niczego poza tym żeby nie przekazywać Kontenera po kodzie tworzonej aplikacji z obiektu do obiektu w wywołaniach metod i aby robić to zgodnie z dokumenacją danego kontenera. I jeżeli ten kontener opierał by się na singletonie (przyjmujemy że dobry kontener nie powinien sie na nim opierac) to niestety ale właśnie tak należało by to robić jak to przedstawiłem. A jeżeli na nowo tworzonym obiekcie z urzyciem new to analogicznie należało by tworzyć nowy obiekt tam gdzie byl by potrzebny kontener. I to proszę traktować jako myśl przewodnią mojego postu ![]() A już na na pewno nie proponowałem aby kontener uczynić zmienną obiektu, rozumiem że jest to Twoja propozycja? ![]() Ten post edytował smentek 8.09.2010, 21:53:51 -------------------- .:SMENTEK:.
|
|
|
![]()
Post
#7
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Cytat Nie zaproponowałem jednak niczego poza tym żeby nie przekazywać Kontenera po kodzie tworzonej aplikacji z obiektu do obiektu Jeżeli nie przekazywać to... zrobić z niego globala. Jeżeli zrobić z niego "singletonowego globala" to tak jakby użyć zwykłego globala (tylko bardziej "pro"). Idąc dalej nasz kod zyskuje wszystkie "zalety" globala, tj.: zależności od jakiś zewnętrznych, niekontrolowanych źródeł. W dodatku zamiast opierać się na interfejsach (co w teorii powinno być dla OOP w PHP naturalne - no niestety nie wyszło) musimy opierać się na klasach, czyli innymi słowy wymuszamy implementację zależności. A wszystko to by pozbyć się przekazania tej jednej zależności w konstruktorze obiektu. IMO do d..y takie "udogodnienie".
|
|
|
![]()
Post
#8
|
|
![]() Grupa: Zarejestrowani Postów: 130 Pomógł: 11 Dołączył: 7.04.2003 Ostrzeżenie: (10%) ![]() ![]() |
Ale dlaczego uważasz że kontener miał by mieć zasięg globalny?
-------------------- .:SMENTEK:.
|
|
|
![]()
Post
#9
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Bo skoro nie lokalny (i bezpośrednio przekazywany dalej) to musi być globalny? Pokaż może fragment kodu ilustrujący co Ty masz na myśli.
|
|
|
![]()
Post
#10
|
|
![]() Grupa: Zarejestrowani Postów: 130 Pomógł: 11 Dołączył: 7.04.2003 Ostrzeżenie: (10%) ![]() ![]() |
Ok przyznaję, że daleko mi do eksperta jeżeli chodzi o IoC ale zaryzykuję stwierdzenie że nie musi mieć on zasięgu globalnego (choć może istnieją kontenery które muszą, nie wykluczam tego ). A wiem to z doświadczenia. Przykład: pico
Pierwsze wywołanie linia 31kolejne linia 65. W innych klasach w kodzie, chyba też go użyłem, jak widzisz nie ma on zasięgu globalnego a kod śmiga jak powinien... Ten post edytował smentek 9.09.2010, 07:11:34 -------------------- .:SMENTEK:.
|
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 30 Pomógł: 0 Dołączył: 9.09.2010 Ostrzeżenie: (0%) ![]() ![]() |
Wzorzec jak wzorzec. Jak dla mnie to po prostu ciekawe zastosowanie kolekcji. Sam użyłem coś podobnego w moim systemie.
Główny obiekt przechowuje obiekty odpowiedzialne za użytkownika, sesje, dostęp, przepływ danych itp itd etc. Do tego można w nim zarejestrować rozszerzenia wszelakiej maści lub "wyrejestrować" usługę sesji zastępując ją własnym mechanizmem. Fakt że są pewne różnice. Główny obiekt ma zasięg globalny z prostego względu. Daje możliwość modułom (w tym systemie posunąłem się do granic absurdu gdzie nie pytamy już co JEST modułem a co NIE JEST modułem ze względu na to że gdybym tego nie zrobił - szereg modyfikacji które nie raz życzą sobie klienci nastręczały by trudności - a tak jeżeli klient życzy sobie coś specjalnego to nie grzebiąc w kodzie dodaje nowy moduł i ustawiam go w systemie - wyniki po profilowaniu mam zaskakująco dobre więc nie ma co narzekać) dobrać się do interesujących go danych (dane użytkownika, przywileje, dostępne usługi, parametry itp) z każdego miejsca. Działanie rozwiązania które podałeś jest bardzo zbliżone. Różnica polega na tym że część obiektów jest zaszyta na stałe i mamy tylko i wyłącznie możliwość ich wymiany (tzw rdzeń) na inne a reszta jest rejestrowana i może być wywoływana. |
|
|
![]()
Post
#12
|
|
![]() Grupa: Zarejestrowani Postów: 130 Pomógł: 11 Dołączył: 7.04.2003 Ostrzeżenie: (10%) ![]() ![]() |
Cytat Jak dla mnie to po prostu ciekawe zastosowanie kolekcji Można na to patrzyć zróżnych stron ale należy pamiętać, że w kolekcjach chodzi o PRZECHOWYWANIE obiektów w jakiś tam inteligentny sposób. Np. kolekcja która nie pozwoli na 2 identyczne elementy, albo kolekcja która nie wpuści elementu o typach innych niż te dozwolone. Kontenery IoC nie mają z takim zachowaniem nic wspólnego. W kontenerach chodzi o to aby wprowadzić do systemu kolejną wyraźnie odseparowaną warstwę abstrakcji do której przenosimy inicjalizację obiektów. @Crozin Wracając do tego co napisałeś wcześniej: Cytat A żeby nie było: celem tego wzorca jest zapewnienie dokładnie jednej instancji danej klasy, a nie globalny dostęp do obiektu - od tego jest global. Zgadzam się z pierwszą częścią i może Cię źle rozumiem jeżeli tak to mnie popraw, ale mam wrażenie, że uważasz, że wprowadzanie globalności przy pomocy singletonu jest złe a korzystanie z niej przy pomocy global jest ok. A przecież nie chodzi o to że wprowadzanie globalności przez singleton jest złe, chodzi o to że sama globalność jest zła niezależnie od tego czy wprowadzana poprzez singleton czy przez global. Wracając do globalności kontenera. Wyobraźmy sobie że mamy globalny kontener mający w sobie referencje do wszystkich już zainicjalizowanych w systemie obiektow. Teraz chcemy zainicjalizować z niego nowy obiekt, który miał by być utworzony z referencjami do obieków które kontener już posiada. Ale nie jakichś tam obiektów tylko konkrtnych obiektów tak jak to zwykle bywa w programach ![]() A w jaki sposób możemy mu to powiedzieć? Dostarczając referencję do tych obiektów. Mam rację? ![]() A skoro musimy dostarczać tych referencji w momencie inicjalizacji nowego obiektu, to równie dobrze możemy tworzyć sobie nową instancje kontenera zamiast korzystać z jednej globalnej. Globalność kontenra może się przydać w pewnych sytuacjach ale w innych jak wyżej opisywana nie jest przydatna. -------------------- .:SMENTEK:.
|
|
|
![]()
Post
#13
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Tak, źle zrozumiałeś. Napisałem, że robienie z Singletona globala, jest złe, że od tego jest global - ale nie napisałem, że global jest dobry. Bo jest zły (w aplikacjach webowych średnio widzę dla niego zastosowanie).
Kontener może przecież przekazać samego siebie usłudze (tak by był dostępny w jej wnętrzu), a ona już sobie sama wybierze potrzebne jej usługi. Cytat to równie dobrze możemy tworzyć sobie nową instancje kontenera zamiast korzystać z jednej globalnej Przecież jeżeli utworzysz nową instancję to skąd wytrzaśniesz w niej referencje do różnego rodzaju usług?
|
|
|
![]()
Post
#14
|
|
![]() Grupa: Zarejestrowani Postów: 95 Pomógł: 7 Dołączył: 16.07.2007 Skąd: Gorzów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
Ja swój problem rozwiązałem tak: Container przechowuje po jednej instancji wybranych klas, nie przechowuje instancji WSZYSTKIEGO (modeli, kontrolerów, widoku) ale np. coś, co tworzone powinno być jedynie raz na jedno żądanie - np. sesje. Instancję containera przekazuję przez paramter do konstruktora - tak, bo jest mi tak wygodnie - do czasu. Kiedy zagnieżdżenia robią się naprawdę zagnieżdżone, gdzieś tam naprawdę nisko, gdzie dostępu do niego nie ma, a przekazywane jest już trochę więcej parametrów - tworzę po prostu nowy obiekt containera. W statycznej zmiennej trzymam tablicę z instancjami klas. Myślę, że to najbardziej kompromisowe rozwiązanie, bo global odpada i nie ma co o to pytać nawet, przekazywania miliona parametrów też odpada.
-------------------- "It's always darkest before the dawn." |
|
|
![]()
Post
#15
|
|
![]() Grupa: Moderatorzy Postów: 8 989 Pomógł: 1550 Dołączył: 8.08.2008 Skąd: Słupsk/Gdańsk ![]() |
Przecież jeżeli utworzysz nową instancję to skąd wytrzaśniesz w niej referencje do różnego rodzaju usług? Może zagłębmy się w definicję słów Inversion of Controler = Odwrócenie sterowania. Nie polega to jedyna na ukryciu zależności ale też m.in odciążenie innych klas od tworzenia i dorzucania do kontenera pojedynczych obiektów. Dodatkowo, żeby aplikacja była "hermetyczna" obiekt kontenera NIE MOŻE być globalny, statyczny ale LOKALNY. Czyli, przekazywać go tam gdzie potrzeba. Co nam to daje? Nie tworzymy, np połączenia z bazą danych kiedy jest ono kompletnie niepotrzebne, masy obiektów których nie użyjemy. Samo wykorzystanie DIC jest bardzo elastyczne i wygodne aczkolwiek wydajność... to już inna kwestia. Parsowanie xml-a, badania zależności, badanie koniecznych parametrów do przekazania trochę czasu zajmuje. U siebie zrezygnowałem z xml-a i zależności wstrzykuje "ręcznie" w kontenerze. W statycznej zmiennej trzymam tablicę z instancjami klas. Myślę, że to najbardziej kompromisowe rozwiązanie, bo global odpada i nie ma co o to pytać nawet, przekazywania miliona parametrów też odpada. Czyli po prostu inaczej ubrałeś słówko "global". Każdy obiekt statyczny, singleton jest po prostu bezpieczniejsza forma globala także nie tędy droga. Oczywiście wszystko zależy od gustu i upodobań. Ten post edytował wookieb 12.09.2010, 10:49:48 -------------------- |
|
|
![]()
Post
#16
|
|
![]() Grupa: Zarejestrowani Postów: 95 Pomógł: 7 Dołączył: 16.07.2007 Skąd: Gorzów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
Okej, to mogę wywalić zmienną statyczną i wszędzie instancję kontenera przekazywać przez parametr, nawet tam gdzie to więcej komplikuje niż pomaga - tędy droga? Zresztą jaki był cel wprowadzania możliwości deklarowania zmiennych statycznych? Myślałem, że po to, aby korzystać z nich w takich przypadkach, niewielkiej ilości na skalę projektu (ja np użyłem dwóch zmiennych statycznych w całym swoim projekcie). Bo jeśli tego się nie stosuje, bo jest be i kojarzy się z globalem to po co pisać o tym w manualu w ogóle..
Ten post edytował Luneth 12.09.2010, 11:52:50 -------------------- "It's always darkest before the dawn." |
|
|
![]()
Post
#17
|
|
![]() Grupa: Moderatorzy Postów: 8 989 Pomógł: 1550 Dołączył: 8.08.2008 Skąd: Słupsk/Gdańsk ![]() |
Właściwości statyczne przydają się w miejscach gdzie klasa nie musi tworzyć instancji i jej wewnętrzne właściwości nie wpływają na resztę aplikacji. Przykładem jest mój kalkulator ze stopki.
Cytat Okej, to mogę wywalić zmienną statyczną i wszędzie instancję kontenera przekazywać przez parametr, nawet tam gdzie to więcej komplikuje niż pomaga - tędy droga? Napisałem, że to zależy od upodobań oraz gustu. Jeżeli przekazujesz instancję kontrolera tam gdzie jest to wskazane powodujesz tym samym, że twoja aplikacja jest hermetyczna. Bardzo łatwo ją testować a także uruchamiać równolegle z innym egzemplarzami twojej aplikacji (2 lub więcej aplikacji odpalonych w jednym skrypcie). Cytat Bo jeśli tego się nie stosuje, bo jest be i kojarzy się z globalem to po co pisać o tym w manualu w ogóle.. Jest dobre przekonanie, że globala nie powinno się stosować i jestem jak najbardziej za. Ale jeżeli ktoś się zapyta "co poza global?" a ty odpowiesz mu, że klasa statyczna to wcale nie pomożesz a jedynie usadowisz użytkownika w tym samym punkcie. Dlatego o tym wspomniałem. PHP powstał i jest dla początkujących użytkowników, dlatego GLOBAL pozostał jako taki. Dla bardziej zaawansowanych programistów jest on bezużyteczny. Ten post edytował wookieb 12.09.2010, 12:06:42 -------------------- |
|
|
![]()
Post
#18
|
|
![]() Grupa: Zarejestrowani Postów: 95 Pomógł: 7 Dołączył: 16.07.2007 Skąd: Gorzów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
Nie zrobiłem klasy statycznej, jedynie atrybut przechowujący instancje jest statyczny, a każdą instancję pobiera się odp. getterem(który statyczny już nie jest), który umożliwia też umieszczenie różnych parametrów, ale być może okaże się, że jest to jakieś pomieszanie, a właściwym byłoby przekazywanie wszędzie przez parametr, w wyniku czego container będę przekazywany wszędzie - do modelu, do widoku, do kontrolera. Jeśli takie rozwiązanie byłoby uznane przez profesjonalnych programistów to ja jestem gotów zrezygnować ze zmiennej statycznej w swojej sytuacji na rzecz przekazywania parametrem wszędzie i zawsze.
-------------------- "It's always darkest before the dawn." |
|
|
![]()
Post
#19
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Cytat Nie zrobiłem klasy statycznej Tak, wiemy - bo PHP czegoś takiego nie obsługuje.Cytat jedynie atrybut przechowujący instancje jest statyczny Innymi słowy masz coś takiego?Jeżeli tak to masz z du.y rozwiązanie, bo ograniczasz się do jednego kontenera, którego interfejs jest strasznie nielogiczny. Składowe statyczne służą do przechowywania danych związanych z klasą, nie obiektem - a Ty operujesz każdorazowo na nowym obiekcie. |
|
|
![]()
Post
#20
|
|
![]() Grupa: Zarejestrowani Postów: 95 Pomógł: 7 Dołączył: 16.07.2007 Skąd: Gorzów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
Owszem, mam coś na tej zasadzie. Nie tworzę za każdym razem nowego obiektu, zaznaczam
![]() Ten post edytował Luneth 12.09.2010, 14:06:58 -------------------- "It's always darkest before the dawn." |
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 19.07.2025 - 11:30 |