Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> EventListener, Czekam na opinie ;)
serafin
post 11.07.2005, 18:26:16
Post #1





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 23.11.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Jak w temacie, czy myslicie ze tworzenie specjalnej grupy obiektow do obslugi roznorodnych zdarzen: informacji debug, wyjatkow, bledow jest dobrym pomyslem?

W praktyce wygladaloby to tak:

$events = new EventListener();
$events->registerHandler('Exception', new ExceptionHandler());

// Zlapany w bloku catch() wyjatek:
$events[] = $e;

Powiadamiamy w ten sposob EventListenera o zajsciu nowego zdarzenia. Nastepnie zostaje wykonany lancuszek klas odpowiedzialnych za obsluge danego typu zdarzenia.

Co sadzicie o tym?

Pozdrawiam,


--------------------
Making IT works
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 24)
Vengeance
post 11.07.2005, 23:23:43
Post #2





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Czy nie chodzi ci o to samo, czym było by wykorzystanie funkcji set_exception_handler() ?


--------------------
Go to the top of the page
+Quote Post
serafin
post 12.07.2005, 00:53:51
Post #3





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 23.11.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Nie, bo imho zdarzenia nie musza miec nic wspolnego z wyjatkami...


--------------------
Making IT works
Go to the top of the page
+Quote Post
Vengeance
post 12.07.2005, 00:59:40
Post #4





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


A może wzorzec Observer ? Sama nazwa, jak i zastosowanie spełnią chyba twoje wymagania.


--------------------
Go to the top of the page
+Quote Post
NuLL
post 13.07.2005, 11:33:41
Post #5





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


Serafin - podoba mi się to rozwiązanie smile.gif


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
hawk
post 13.07.2005, 19:37:19
Post #6





Grupa: Zarejestrowani
Postów: 521
Pomógł: 0
Dołączył: 3.11.2003
Skąd: 3city

Ostrzeżenie: (0%)
-----


Kilka luźnych uwag:

1) To jest chyba wykorzystanie interfejsu ArrayAccess?

2) Jak Observer, to warto (jeżeli się da) wykorzystać kod z SPL. Nic odkrywczego nie wymyślili, ale może uda się wypracować jakiś standard/

3) Bardzo by się przydał lazy loading, bo przecież ExceptionHandler przeważnie nie będzie wywoływany. Albo handle/proxy (jak w WACT lub phiend.handle), albo delegate/invoker (jak w WACT lub niepublikowanej jeszcze części phiend.handle).

4) Zmieniłbym nazewnictwo, bo EventListener sugeruje, że jest to Observer, a tymczasem jest to drugi element tego wzorca - Observable. Robiony przeze mnie pakiet phiend.logger ma klasę Logger, którza przyjmuje wiadomości/zdarzenia i kieruje do listenerów. Efekt jest chyba podobny...
Go to the top of the page
+Quote Post
NuLL
post 13.07.2005, 23:51:51
Post #7





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


@Hawk Wątpię aby to byl ArrayAccess. Ja osobiscie tez wykorzystuje statyczny rejestr w ktorym zapisuje komunikaty -np. nie mozna sie polaczyc z baza i jechac tylko na cache o ile sie da.

Co handlerow - tez mam swoje - inicjowane wraz z jadrem systemu - choc zastanawiam sie czy jest jakas metoda ktora pozwoli na to aby ominac wywolanie handler jesli w aplikacji nie zajdzie zaden wyjatek cool.gif Logger tez jest a majac do dyspozycji Reflection Class mozna robic naprawde fajne rzeczy smile.gif


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
jaco
post 13.07.2005, 23:57:57
Post #8





Grupa: Zarejestrowani
Postów: 115
Pomógł: 1
Dołączył: 15.01.2003

Ostrzeżenie: (0%)
-----


@NuLL: Twoje watpliwosci sa nieuzasadnione - chyba nie uwazasz na lekcji tongue.gif

  1. <?php
  2.  
  3. $events = new EventListener();
  4. $events->registerHandler('Exception', new ExceptionHandler());
  5. $events[] = $e;
  6.  
  7. ?>


Ciekawe jak inaczej? winksmiley.jpg
Go to the top of the page
+Quote Post
NuLL
post 14.07.2005, 00:06:59
Post #9





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


Ale ja nie chce rejestrowac tego handlera dopoki nie jest mi potrzebny - ba, najlepiej zadnego handlera nie inicjowac. Tu robisz wywolanie jawnie inicjujac aplikacje - ja chce tego uniknac. Pomysl juz mam smile.gif
Pozatym pomysl z tablica jest poroniony. Lepiej wg mnie.
  1. <?php
  2.  
  3. Logger::Register(&#092;"/e NoSuchComponent\");
  4.  
  5. ?>

Przelaczniki ala DOS i to mi sie podoba smile.gif


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
serafin
post 14.07.2005, 08:18:15
Post #10





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 23.11.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Zmienilem nieco idee. Pokazuje wiec kod:

  1. <?php
  2.  
  3. // Prosty obserwator;)
  4. final class DebugPrint implements Observer {
  5.  
  6. private $subject;
  7.  
  8. public function register(Subject $s) {
  9. $this->subject = $s;
  10. $s->attach($this);
  11. }
  12.  
  13. public function unregister(Subject $s) {
  14. if($this->subject) {
  15. $this->subject->detach($this);
  16. }
  17. }
  18.  
  19. public function update(Subject $s) {
  20. $this->subject = $s;
  21.  $call = debug_backtrace();
  22.  $call = $call[2];
  23.  echo '<p style=\"font-family: Verdana; font-size: 10px; padding: 0px; margin: 0px;\"><b style=\"color: red\">Debug</b>: ' . $this->subject->getMsg() . ' <!--<a href=\"source.php?file='.$call['file'].'&line='.$call['line'].'\" target=\"_blank\">'.basename($call['file']) . ' @ line '.$call['line']. '</a>--></p>';
  24. }
  25. }
  26. // Obserwowane zdarzenie
  27. class Debug implements Subject, ISingleton {
  28. protected $msg;
  29. private $observers;
  30.  
  31. public function attach(Observer $o) {
  32. $this->observers[] = $o;
  33. }
  34.  
  35. public function detach(Observer $o) {
  36. foreach($this->observers as &$observer) {
  37. if($observer === $o) {
  38. unset($observer);
  39. }
  40. }
  41. }
  42.  
  43. public function notify() {
  44. if(count($this->observers)) {
  45. foreach($this->observers as $observer) {
  46. $observer->update($this);
  47. }
  48. }
  49. }
  50.  
  51. public static function &singleton() {
  52. static $instance;
  53.  
  54. if(!($instance instanceof Debug)) {
  55. $instance = new Debug();
  56. }
  57. return $instance;
  58. }
  59.  
  60. public function getMsg() {
  61. return $this->msg;
  62. }
  63.  
  64. public function info($msg) {
  65. $this->msg = $msg;
  66. $this->notify();
  67. }
  68. }
  69.  
  70. // ErrorHandler;)
  71. final class ErrorHandler extends Debug {
  72.  
  73. public function __construct() {
  74. }
  75.  
  76. public static function &singleton() {
  77. static $instance;
  78.  
  79. if(!($instance instanceof ErrorHandler)) {
  80. $instance = new ErrorHandler();
  81. }
  82.  
  83. return $instance;
  84. }
  85.  
  86. public function info($errno, $errstr, $errfile, $errline) {
  87. $this->msg = 'PhpError: ' . $errstr . ' [<u>' . basename($errfile) . '</u> at line <u>' . $errline . '</u>]';
  88. $this->notify();
  89. }
  90. }
  91. // Inicjacja wszystkiego
  92.  
  93. $debug = Debug::singleton();
  94. $ehandle = ErrorHandler::singleton();
  95.  
  96. set_error_handler(array($ehandle, 'info'));
  97.  
  98. /* Debug print to output */  
  99. $d = new DebugPrint();
  100. $d->register($debug);
  101. $d->register($ehandle);
  102.  
  103. /* Debug logging into file observer */
  104. $f = new FileLog();
  105. $f->register($debug);
  106.  
  107. $debug->info(&#092;"Application start\");
  108.  
  109. ?>


Jak widac skorzystalem z wzorca Obserwator. To rozwiazanie jest teraz w miarę szybkie i dosyc skuteczne. Postaram sie zaimplementowac cos jeszcze.

Pozdrawiam,

// Edit

Hawk: Co do lazy loading, masz racje obserwatorzy czy tez exceptionhandler nie zawsze beda potrzebni, w takim razie mozna nieco zmodyfikowac cala idee by zamiast obiektow przekazywac tylko nazwy odpowiednich obserwatorow.

Ten post edytował serafin 14.07.2005, 08:32:03


--------------------
Making IT works
Go to the top of the page
+Quote Post
dasko
post 14.07.2005, 09:06:20
Post #11





Grupa: Zarejestrowani
Postów: 179
Pomógł: 0
Dołączył: 9.11.2004

Ostrzeżenie: (0%)
-----


@NuLL: Reflection API sprawdziłoby się raczej tylko w przypadku statycznych handlerów klas - tzn jesli masz handler np. XYZ::onDoSomething(). W tym wypadku moznaby albo za kazdym razem leciec reflectionem po klasachw wposzukiwaniu obsługi zdarzeń, albo (tylko raz) stworzyć mapę klas z danymi handlerami.

Ale co jeśli obiektów danego typu jest dużo? Na dodatek lokalnych w jakiejś funkcji? W tym wypadku chyba właśnie lepiej zastosować obserwatorów(chyba nawet trzeba) i po kolei ich rejestrować, tak jak zrobił serafin. Chyba nie ma innego wyjścia smile.gif

Może się mylę, poprawcie jakby co tongue.gif
Go to the top of the page
+Quote Post
Nievinny
post 14.07.2005, 09:15:39
Post #12





Grupa: Zarejestrowani
Postów: 134
Pomógł: 0
Dołączył: 27.01.2005
Skąd: Białystok

Ostrzeżenie: (0%)
-----


hymm..., ja myślę, żę obserwator nie jest tu niezbędny, ale bardzo ułatwia pracę. Choć sam debug zrobił bym inaczej (wyświetlanie komunikatów na końcu) i oddzielny obserwator dla wyjątków i błędów. Ogólnie myślę, że jest wiele sposobów prowadzenia debugera i jeżeli chodzi o uniwersalność "statyczne klasy", które mają metody i właściwości statyczne są lepsze i nie trzeba znać wzorca obserwatora. Aczkolwiek eventy mi się podobają, proste i w miarę skuteczne.


--------------------
Go to the top of the page
+Quote Post
Vengeance
post 14.07.2005, 12:22:56
Post #13





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


serafin: zastanawiam się po co te register() i unregister() w Obserwatorze. Chyba przejrzyściej by wyglądało, gdybyś to w obiekcie obserowanym registrował obserwator, a nie odwrotnie.


--------------------
Go to the top of the page
+Quote Post
serafin
post 14.07.2005, 13:24:09
Post #14





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 23.11.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Vengeance: rejestrujesz w Obserwatorze Podmiot ktory ma obserwowac. Wiec logiczny jest taki kierunek rejestracji winksmiley.jpg


--------------------
Making IT works
Go to the top of the page
+Quote Post
Vengeance
post 14.07.2005, 13:38:11
Post #15





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


A co logicznego jest w tym, że w Obserwatorze rejestruje Podmiot do obserwacji... z czego ten Obserwator tak na prawde potem rejestruje się w Podmiocie :]

Nie wydaje ci sie to drogą "na około" ?


--------------------
Go to the top of the page
+Quote Post
Nievinny
post 14.07.2005, 16:51:38
Post #16





Grupa: Zarejestrowani
Postów: 134
Pomógł: 0
Dołączył: 27.01.2005
Skąd: Białystok

Ostrzeżenie: (0%)
-----


Możesz wyciąć w tych metodach dodawanie do stosu podmiotów, choć ich rejestrowanie jest pomocne. A jak rejestruje się wiele podmiotów pod jednym obserwatorem to jest po prostu zbawienie.


--------------------
Go to the top of the page
+Quote Post
hawk
post 14.07.2005, 17:32:09
Post #17





Grupa: Zarejestrowani
Postów: 521
Pomógł: 0
Dołączył: 3.11.2003
Skąd: 3city

Ostrzeżenie: (0%)
-----


Reflection API jest fantastyczne w przypadku wywalania na ekran informacji o błędzie. Ja np. wyciągam definicję każdej metody z backtrace, włącznie z wszystkimi przełącznikami (final, static, itd), z nazwami i typami argumentów itd. W wolnym czasie chciałem zrobić parsowanie phpdoc w celu wyciągnięcia dodatkowych informacji o argumentach i zwracanym typie (i oczywiście opisu). Jak zrobię, będę mógł zaprezentować phiend.logger biggrin.gif. Chyba że ktoś chce się tym za mnie pobawić...
Go to the top of the page
+Quote Post
serafin
post 14.07.2005, 22:49:37
Post #18





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 23.11.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


hawk: przejrzalem twojego phienda2. I'm quite impressed.

Bardzo spodobal mi sie plugin loader i sposob w jaki go zaimplementowales (zwlaszcza Handles i Lazy Loading)

P.S. Nie obrazisz sie jak skorzystam z kilku twoich pomyslow ;> ?


--------------------
Making IT works
Go to the top of the page
+Quote Post
Vengeance
post 14.07.2005, 22:54:09
Post #19





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Czy czasem Lazy Loader nie odnosił się bardziej to logiki biznesowej niż zarządzaniem obiektami ?!


--------------------
Go to the top of the page
+Quote Post
serafin
post 14.07.2005, 23:15:47
Post #20





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 23.11.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Lazy loading odnosi sie do zarzadzania obiektami. Obiekt tworzony jest wylacznie wtedy kiedy jest potrzebny, nie wczesniej. Podobnie dziala chyba mechanizm dynamicznego wiazania w javie, obiekt tworzony jest w momencie kiedy jego instancja jest potrzebna.

pozdrawiam,


--------------------
Making IT works
Go to the top of the page
+Quote Post
chmolu
post 27.08.2005, 17:36:11
Post #21





Grupa: Zarejestrowani
Postów: 179
Pomógł: 0
Dołączył: 8.10.2004

Ostrzeżenie: (0%)
-----


Sorry, że odgrzewam stary temat smile.gif

Przejrzałem kod WACTa i Phienda2 i tak się zastanawiam po co są te Handles. No dobrze, obiekty są tworzone tylko kiedy są naprawdę potrzebne, ale przecież dodatkowo mamy klasę Handle, która musi być załadowana zawsze. Wg mnie to dodatkowe obciążenie, a nie żadna korzyść. Chyba, że źle rozumuję?
Go to the top of the page
+Quote Post
hawk
post 28.08.2005, 15:40:26
Post #22





Grupa: Zarejestrowani
Postów: 521
Pomógł: 0
Dołączył: 3.11.2003
Skąd: 3city

Ostrzeżenie: (0%)
-----


No ale skoro "tylko wtedy kiedy są naprawdę potrzebne", to znaczy że nie zawsze, prawda? I tutaj właśnie mamy korzyść, bo obiekt Handle/Proxy/whatever jest malutki, a obiekt docelowy zapewne większy.
Go to the top of the page
+Quote Post
emilio
post 28.08.2005, 17:27:24
Post #23





Grupa: Zarejestrowani
Postów: 16
Pomógł: 0
Dołączył: 21.02.2005
Skąd: internet

Ostrzeżenie: (0%)
-----


Cytat(hawk @ 2005-08-28 14:40:26)
No ale skoro "tylko wtedy kiedy są naprawdę potrzebne", to znaczy że nie zawsze, prawda? I tutaj właśnie mamy korzyść, bo obiekt Handle/Proxy/whatever jest malutki, a obiekt docelowy zapewne większy.

Ja uważam że w warstwie prezentacji nie powinno się ich stosować. Utrudnia to zrozumienie kodu i co najważniejsze nie daje wymiernych korzyści. Nie ma tam takiego stopnia skomplikowania, jaki panuje w warstwie dziedziny. Czyli mamy całkowitą kontrolę nad tym co robimy, czego nie można powiedzieć o modelu dziedziny.

Konkrety, Tworzysz plik index.php a w nim inicjujesz pluginy i filtry (wszystko skoncetrowane w jednym miejscu). Wyklucza nam to problem wielokrotnego ładowania jednego, tego samego elementu (jedna z głównych przyczyn dla których stosuje się Lazy Initialization). Dwa, Stosujesz 'pustą' inicjalizację, czyli nie wykonujesz żadnych konkretnych operacji podczas tworzenia obiektu. Dopiero na samym końcu następuje właściwa faza działania programu, tzn. operacje na modelu i tym podobne rzeczy. Czyli poza znikomym spadkiem użycia pamięci (powtarzam, jest to warstwa prezentacji, tj. filtry, akcje, itp. małe klasy, które nigdy nie będą potężnymi bibliotekami) nie osiągasz nic więcej bo nie generujesz większych obciążeń podczas tworzenia obiektów (czego nie można powiedzieć o elementach warstwy dziedziny).

Posumowując, jeżeli podczas inicjalizacji nie wykonuje się 'większych' operacji (takich jak np. nawiązanie połączenia z bazą danych) to jak dla mnie, nie opłaca się stosować takich rozwiązań (pokreślam, cały czas mam na myśli warstwę prezentacji, która ma nieporównywalnie mniejszy współczynnik stopnia skomplikowania niż dziedzina czy warstwa usług).

Pozdrawiam, emilio.


--------------------
Biorąc pod uwagę wszystkie akty tworzenia, odkrywa się jedną elementarną prawdę: gdy się czemuś prawdziwie poświęcamy, wspiera nas opatrzność. [JOHANN WOLFGANG GOETHE]

Tylko krowy chodzą stadem, lwy zawsze samotnie...
Go to the top of the page
+Quote Post
chmolu
post 28.08.2005, 17:33:08
Post #24





Grupa: Zarejestrowani
Postów: 179
Pomógł: 0
Dołączył: 8.10.2004

Ostrzeżenie: (0%)
-----


Cytat
No ale skoro "tylko wtedy kiedy są naprawdę potrzebne", to znaczy że nie zawsze, prawda? I tutaj właśnie mamy korzyść, bo obiekt Handle/Proxy/whatever jest malutki, a obiekt docelowy zapewne większy.

Hmm... ale przyznaj szczerze, ile z tych obiektów rzeczywiście nie zostanie użytych? W WACT'cie może i się to przydaje, bo tam ładujesz uchwyty do wszystkich akcji w jednym wywołaniu skryptu (przynajmniej z tego, co widziałem na przykładach). W tym wypadku wiadomo, że nie będzie potrzeby ładowania każdej klasy, bo zazwyczaj wystarczy jedna akcja.

Chociaż to też dla mnie jest mniej efektywne rozwiązanie, bo po co w każdym requescie ładować handles do wszystkich akcji?

Rozwiązanie jest ładne i ciekawe, ale ładniejsze i ciekawsze byłoby w javie tongue.gif

Ten post edytował chmolu 28.08.2005, 17:34:28
Go to the top of the page
+Quote Post
emilio
post 28.08.2005, 18:41:32
Post #25





Grupa: Zarejestrowani
Postów: 16
Pomógł: 0
Dołączył: 21.02.2005
Skąd: internet

Ostrzeżenie: (0%)
-----


Cytat(chmolu @ 2005-08-28 16:33:08)
Rozwiązanie jest ładne i ciekawe, ale ładniejsze i ciekawsze byłoby w javie tongue.gif

W C++ mogę zrobić coś takiego:
Kod
int i = 23521;
long l;
l = static_cast<long>(i);
...

Ten post edytował emilio 28.08.2005, 18:46:24


--------------------
Biorąc pod uwagę wszystkie akty tworzenia, odkrywa się jedną elementarną prawdę: gdy się czemuś prawdziwie poświęcamy, wspiera nas opatrzność. [JOHANN WOLFGANG GOETHE]

Tylko krowy chodzą stadem, lwy zawsze samotnie...
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 14.08.2025 - 13:53