Programowanie reaktywne – wprowadzenie

Programowanie reaktywne – wprowadzenie

Cześć!

     W dzisiejszych czasach programowanie reaktywne wydaje się coraz bardziej popularnym rozwiązaniem. Statyczne strony, gdzie trzeba odświeżyć przeglądarkę by uzyskać najbardziej aktualny stan są coraz rzadziej spotykane. W związku z tym chciałbym rozpocząć krótką serię postów, gdzie najpierw przybliżę ogólnie programowanie reaktywne, a później na przykładzie języka Java wyjaśnię, jak to działa w praktyce. Do dzieła!

Definicja oraz działanie

Programowanie reaktywne (reactive programming) to paradygmat programowania, który polega na asynchronicznym przetwarzaniu strumieni danych i propagacji zmian. Każde przetwarzanie danych możemy nazwać zdarzeniem (event), które przekazywane jest pomiędzy:
a. publisherem - odpowiada za publikowanie
b. subscriberem - odpowiada za nasłuchiwanie i odczytywanie danych

     Wszystko to zachodzi za pomocą subskrypcji. Kiedy raczkowałem w tej dziedzinie, próbowałem sobie to wszystko wytłumaczyć na zasadzie subskrypcji w serwisie YouTube. Kiedy klikam w przycisk subskrypcji kanału, który mnie interesuje, ja jako subscriber nasłuchuje na jakieś nowe wydarzenia, czyli filmy na Youtube – a twórca kanału zostaje publisherem, który odpowiedzialny jest za publikowanie filmów.

Podsumowując założenie: tworzy się subskrypcja, gdzie Subscriber nasłuchuje zdarzeń od Publishera. Kiedy zostają wyemitowane dane, Subscriber od razu pozyskuje te dane.

Komunikacja również może zachodzić w przeciwnym kierunku. Takie zjawisko nazywamy BackPressure – czyli to zjawisko, gdzie Subscriber przekazuje informacje do Publishera. Można zadać sobie pytanie: po co to z założenia coś, co jedynie oczekuje na dane ma również publikować jakieś dane? Dzieję się tak dlatego, że Subscriber może poinformować Publishera, że np. nie nadąża przetwarzać otrzymywanych danych lub jeśli wystąpił bląd związany z przetwarzaniem danych i kolejna porcja danych nie jest już potrzebna.

Komunikacja pomiędzy Publisherem a Subscriberem trwa tak długo, aż ktoś Subscriber nie odsubskrybuje danych. Tak to wygląda na wykresie:

backpressure-publisher-subscriber
Komunikacja zachodząca pomiędzy Publisher a Subscriber. Źródło: bykowski.pl

Wątki blokujące oraz nieblokujące

     W wstępie wspomniałem, że strony statyczne, gdzie trzeba odświeżyć przeglądarkę by uzyskać dane jest prawie idealnym przykładem modelu reaktywnego. Użytkownik strony (Subscriber) klika w przycisk odświeżający stronę, by uzyskać porcję danych od Subscribera. Niemniej jednak, żeby powyższy przykład stanowił założenia programowania reaktywnego, muszą zostać spełnione dodatkowe założenia:

a. Non Blocking:

  • czyli przyjęcie żądania przez wątek
  • oddelegowanie żądania dalej
  • nasłuchiwanie kolejnych żądań

b. Asynchroniczność:

  • zdarzenia przetrwarzane są asynchronicznie
  • inne funkcjonalności są odpowiedzialne kolejno za wywołanie zdarzenia oraz inna kiedy emitowany jest błąd

W przypadku klasycznym, gdzie użytkownik musi odświeżyć stronę by uzyskać dane wątki mogą się zablokować. Wątek, który obsługuje dane żądanie musi czekać, aż dostanie odpowiedź z bazy danych. Dopiero po uzyskaniu odpowiedzi od bazy danych może wyświetlić to na stronie. Uważam, że słowo klucz jest tutaj „musi czekać”. Niektóre bazy danych bardzo szybko przetworzą zapytanie ale są też takie przypadki, gdzie w celu uzyskania odpowiedzi trzeba poczekać nawet kilka sekund. W czasie czekania wątek jest bezużyteczny, zamrożony.

 

komunikacja-blokujaca
Komunikacja blokująca (czyli wątki mogą się blokować). Źródło: bykowski.pl

Kiedy mamy do czynienia z programowaniem reaktywnym mamy również do czynienia z podejściem nieblokującym. Czyli w praktyce, w odróżnieniu od klasycznego przykładu, kiedy jeden wątek  odpowiada za obsługę danego żądania – on jedynie przyjmuje te żądanie i deleguje dalszą obsługę żądania do innego wątku. Dzięki temu nie tworzy się tak zwany „zator”, a każdy wątek nie czeka i są gotowe ciągle działać. Dzięki odpowiedziom na zdarzenie, wątek który deleguje żądanie do innego wątku, dowiaduje się o jego ukończeniu i może przekazać odpowiedź do Subscribera. 

 

komunikacja-noblocking
Komunikacja nieblokująca. Źródło: bykowski.pl

Reasumując – w porównaniu do klasycznych przykładów, w programowaniu reaktywnym nie ma miejsca na czekanie i blokowanie żądań. Wyczerpanie puli wątków wydaje się zatem bardzo mało prawdopodobne.

Jak nie strzelać z armaty do wróbla – czyli w jakich przypadkach wykorzystywać programowanie reaktywne?

  Programowanie reaktywne mają większą złożoność od rozwiązań klasycznych. Są bardziej skomplikowane do zaimplementowania. Zwykle programowanie reaktywne wykorzystuje się w przypadku bardziej złożonych rozwiązań oraz projektów. Niemniej jednak osobiście uważam, że nawet w małym, prywatnym projekcie można bezproblemowo takie rozwiązania wykorzystywać, nawet jeśli z założenia aplikacja nie musi spełniać założeń aplikacji reaktywnej. W przyszłości zawsze może zmienić się wizja, a posiadanie bardzo dobrej architektury od samego początku nie zmusi nas do refaktoryzacji całego projektu.

Podsumowanie

     Reasumując, uważam, że w dzisiejszych czasach zagadnienie programowania reaktywnego z dnia na dzień zyskuje na popularności. Chciałbym, żebyście Wy – czytelnicy wyciągnęli z tego jeden, najważniejszy wniosek: najważniejszą zaletą programowania reaktywnego jest optymalne zarządzanie wątkami. Kolejne wpisy o tematyce programowania chciałbym poświęcić na bardziej szczegółowe omówienie programowania reaktywnego na konkretnych przykładach. Mieliście przyjemność wykorzystywać już programowanie reaktywne? Jaka jest Wasza opinia na ten temat?

Pozdrawiam serdecznie,
biegajacyprogramista.pl

Źródła:
https://en.wikipedia.org/wiki/Reactive_programming
https://spring.io/reactive
https://bykowski.pl/programowanie-reaktywne-czym-jest-i-kiedy-stosowac/

Dodaj komentarz

18 − 12 =

Close Menu