O programowaniu reaktywnym w 3 minuty
Programowanie reaktywne to temat, który w ostatnich latach zyskuje na popularności. Żeby lepiej zrozumieć, czym jest programowanie reaktywne, musimy najpierw poznać różnice między programowaniem imperatywnym a deklaratywnym.
Trendy dla frazy “Reactive programming”
Programowanie imperatywne
W skrócie jest to programowanie instruujące komputer krok po kroku, jaką czynność należy teraz wykonać. Obecnie to bardzo popularny sposób programowania. Większość narzędzi czy frameworków napisanych w językach takich jak JavaScript, C# czy Java, zakłada, że właśnie w ten sposób tworzone jest oprogramowanie. Jeśli nie wiesz, jaki paradygmat wykorzystują napisane przez Ciebie programy, to mogę stwierdzić, że z dużym prawdopodobieństwem jest to właśnie programowanie imperatywne. Pisanie w ten sposób nie jest jednak jedyną możliwością. Istnieją inne paradygmaty programowania.
Programowanie deklaratywne
Jednym z nich jest programowanie deklaratywne. W przeciwieństwie do poprzednika, w tym przypadku opisujemy efekt, jaki chcemy uzyskać. Nie prowadzimy komputera za rękę z punktu A do punktu B, a zamiast tego mówimy: „Chcę być w punkcie B!”.
Przykładem języka wykorzystującego paradygmat deklaratywny jest język SQL. Tworząc zapytanie SQL informujemy, że chcemy uzyskać określony zbiór danych spełniający konkretne kryteria i dodatkowo posortowany w odpowiedniej kolejności. Interesuje nas efekt, a nie sposób, w jaki zostanie on osiągnięty.
Jednym z rodzajów programowania deklaratywnego jest właśnie programowanie reaktywne. Istnieje wiele definicji na temat tego, czym jest, a czym nie jest takie programowanie. Dla mnie najlepsza jest ta:
Programowanie reaktywne to programowanie wykorzystujące asynchroniczne strumienie danych.
Co może być takim strumieniem? W tym podejściu wszystko. Kliknięcia użytkownika w przycisk, wpisywanie tekstu w pole tekstowe, obliczanie nowej wartości zmiennej. Wszystkie te elementy mogą być interpretowane jako asynchroniczne strumienie danych. Jeśli dodamy do tego możliwości operowania na strumieniach, jakie niesie ze sobą programowanie funkcyjne (kolejny rodzaj programowania deklaratywnego), otrzymamy coś, co zwykło się nazywać funkcyjnym programowaniem reaktywnym.
Programowanie reaktywne
Ideę programowania reaktywnego najlepiej pokazać na przykładzie. Załóżmy, że tworzymy system wspomagający pracę menadżerów wysokiego poziomu. Użytkownik w pole tekstowe wpisuje nazwy zespołów, dla których chce wygenerować raport, oddzielając je przecinkiem. Chcemy, żeby system na bieżąco reagował i wyświetlał odpowiednie dane bez oczekiwania na kliknięcie przycisku w stylu “Generuj raport”.
Zarówno w przypadku programowania deklaratywnego, jak i imperatywnego musimy określić moment rozpoczęcia generowania raportu (zgodnie z wymaganiem klienta nie mamy przycisku, w który moglibyśmy kliknąć). Ustalmy, że będzie to 500 ms po wpisaniu ostatniego znaku. Jeśli użytkownik w tym czasie nie wprowadzi nowego znaku, zaczynamy generować raport. Gdybym miał zrealizować powyższe używając podejścia imperatywnego, pewnie zapisałbym do zmiennej pomocniczej moment wprowadzenia ostatniego znaku, a następnie w osobnym wątku (żeby nie blokować UI) sprawdzał, czy minęło już pół sekundy i zaczynał generować raport. Gdybym jednak mógł pisać reaktywnie, napisałbym kod z listingu 1, który realizuje powyższą funkcjonalność.
const selectedTeams$ = rxjs.fromEvent(teamsInput, 'keyup').pipe(
rxjs.operators.map(event => event.target.value),
rxjs.operators.debounceTime(500),
rxjs.operators.map(teams=> teams.split(',')),
rxjs.operators.startWith(null)
);
W tym momencie zmienna selectedTeams$
przechowuje zawsze aktualną listę wybranych zespołów. Tak jest! Za każdym razem, gdy użytkownik wprowadzi nowe dane, strumień automatycznie wyemituje nowe wartości. Jedyne, co nam pozostało, to nasłuchiwać, co wyemituje strumień i generować raport. Można to zrobić na przykład tak, jak pokazano na listingu 2.
selectedTeams$.subscribe(teams => {
//kod generujący raport
})
Warto zauważyć jeszcze jedną rzecz. Tworzymy kod, który po prostu przedstawia to, co chcemy osiągnąć. Przez to jest on łatwiejszy w zrozumieniu. Pamiętajmy, że jednym z najważniejszych zadań współczesnego programisty jest właściwe wyrażanie intencji. Programowanie reaktywne zdecydowanie w tym pomaga.
Uwaga: powyższe przykłady zostały napisane z użyciem biblioteki RxJS, która wspomaga pisanie reaktywne.
Jeśli chcesz dowiedzieć więcej o programowaniu reaktywnym i nie tylko, zapisz się na pozitive technologies 2019!
O autorze
Michał Jawulski to Senior Software Developer w Capgemini* Software Solutions Center we Wrocławiu. Od ponad siedmiu lat projektuje systemy dla firm finansowych z całego świata – to prawdziwy pasjonat nowych technologii i inżynierii oprogramowania. W wolnym czasie lubi poznawać nowe frameworki i narzędzia. Występuje na konferencjach i meetupach, gdzie robi to, co lubi najbardziej, czyli dzieli się wiedzą. Poza tym – wierny kibic Premier League.
*Capgemini Polska Software Solutions Center to centrum rozwoju oprogramowania i usług informatycznych firmy Capgemini. Ekspertów, którzy zajmują się projektowaniem rozwiązań dla znanych na całym świecie firm, można spotkać w Poznaniu oraz Wrocławiu. To właśnie w tych miastach poszukiwani są specjaliści, dla których ważna jest różnorodność zadań i ciągły rozwój i „legendarna” już atmosfera :)