PHPCenter.pl - Twoje Centrum Informacji - PHP, Wydarzenia, Artykuły, Oferty pracy
Twoje Centrum Informacji
PHP, Artykuły, Meetupy, Oferty pracy

Event Listener to tylko warstwa pośrednicząca

Ile razy zdarzyło Ci się otworzyć jakiś Event Listener (czy Subscriber) a tam 250 linijek kodu w 6 metodach? A teraz odpowiedz sobie na pytanie – ile razy sam zrobiłeś taki listener? Często mylimy listenery z innymi warstwami naszej aplikacji, i wrzucamy do nich logikę, która nie powinna się tam znajdować. Powoduje to ich przerośnięcie, problemy z testowaniem a w ostateczności problemy w utrzymaniu kodu.

Jak pisać listenery by były przyjazne i nie nastręczały nam problemów? Najpierw trzeba zrozumieć czym one tak na prawdę są i jaką mają odpowiedzialność.

Info: W tym artykule używam słowa „listener”, ale mam również na myśli „subscribery”.

Czym jest Event Listener?

Jest to klasa, która odpowiada za wywołanie jakiejś akcji, gdy system rzuci zdarzeniem pod które jest ona podpięta.

Na przykład: system zarejestrował użytkownika i wysłał UserRegisteredEvent. Listener łapie ten event, i wysyła powiadomienie za pomocą SwiftMailera. Użytkownik zostaje przywitany na stronie.

Proste, prawda? No nie do końca…

Odpowiedzialność

Odpowiedzialnością listenera jest tylko i wyłącznie załapanie danego Eventu i wykonanie jakiejś konkretnej akcji. I tutaj następuje pewien problem, ponieważ co to znaczy, że „listener ma wykonać jakąś akcję”?

W większości przypadków wygląda to tak, że zwyczajnie bierzemy SwiftMailera, budujemy sobie treść maila i wysyłamy go bezpośrednio w listenerze. Teoretycznie jest to wykonanie akcji, jednak nie o to tutaj chodzi.

Prawdziwa natura Listenerów

Listener jest tylko i wyłącznie bramą, pomiędzy rzucanymi Eventami, a serwisami, które wykonują akcje. W lwiej części przypadków nie powinien on robić nic, oprócz wywołania jakiegoś serwisu lub Commanda (CQRS). Czasami może mieć jakieś warunki które spełnione pozwolą na wykonanie akcji (jednak te warunki i tak siedzą poza listenerem, on tylko pyta zewnętrzny serwis, czy może wykonać dana akcję).

I tutaj jest właśnie ta „akcja” o której wspominałem wcześniej. Listener wykonuje akcję, ale nie jest to akcja sam w sobie. Pamiętasz zapewne nagonkę na to, aby Kontroler był jak najbardziej odchudzony? Chodziło o to, by całą logikę z kontrolera wyciągnąć do osobnych klas. W przypadku listenerów jest dokładnie tak samo. Im będzie on mniejszy tym lepiej.

Przykładowy listener wysyłający powiadomienie o rejestracji użytkownika mógłby wyglądać tak.

class UserCreatedListener
{
    private $greeter;

    public function __construct(GreetingsService $greeter)
    {
        $this->greeter = $greeter;
    }

    public function __invoke(UserRegisteredEvent $event)
    {
        $this->greeter->greetNewUser($event->getUserId());
    }
}

Mały Listener = Wielkie Możliwości

Gdy listener zawiera raptem jedną metodę z jedną linijką kodu, która odpowiada za wywołanie metody z jakiegoś serwisu, możesz nawet pominąć testy tego listenera. Nie ma tutaj logiki! Jest tylko delegowanie wykonywania akcji do innego serwisu – to tam powinny być testy.

Co jeśli wiadomość powitalną będziesz chciał wysłać również samodzielnie przez CLI, w razie gdyby do kogoś nie doszła? W tedy oprócz dodania Commanda musisz przenieść logikę listenera do osobnego serwisu. A razem z nią zrefaktoryzować testy. Ale czy nie lepiej było od razu odchudzić listener i logikę wysyłania powiadomień przenieść do serwisu?

Podumowanie

Jesteśmy nygusami, My – programiści, nie lubimy tworzyć niepotrzebnie zbędnych plików/klas. Jeśli mamy wysłać maila na dany event, to łatwiej nam jest stworzyć jeden listener i tam zrobić wszystko co potrzebujemy, niż rozmieniać się na drobne i tworzyć kilka powiązanych ze sobą, wyspecjalizowanych klas. Jednak prowadzi nas to czasami do złych decyzji wdrożeniowych które odbijają się czkawką. Niektóre warstwy aplikacji wymagają szczególnego traktowania by miały sens. Tak własnie jest w przypadku Event Listenerów.

Zapamiętaj: EventListener === KISS
Im mniej kodu tym lepiej.

114560cookie-checkEvent Listener to tylko warstwa pośrednicząca
A co tam, udostępnij:
avatar
  Subscribe  
Powiadom o
Podoba Ci się to co czytasz, chcesz więcej treści od phpcenter.pl?
×
Wyszukaj