Reaktywne programowanie - motywacja

0

Chciałem zapytać jakie przykładowe wymagania musiałby spełniać projekt, aby w rzeczywistości był sens wchodzić w reaktywne programowanie.

Nigdy nie programowałem w oparciu o ten paradygmat. Póki co widzę, że abstrakcja strumienia zachęca, do programowania funkcyjnego pozbawionego efektów ubocznych więc z użyciem strumieni raczej trudniej jest pisać kod, który coś przetwarza i na podstawie danych w strumieniu dociąga jeszcze dodatkowe dane z sieci.

Strumienie skoro buferują to mają stan (mogą buforować treść) i przy użyciu operatorów zarządzać nią i momentem emisji. Najpotężniejsza cecha sturmieni jaką widzę, to fakt, że można je łączyć z innymi strumieniami, co w przypadku zdarzeń z wielu źródeł daje podstawę do synchronizacji danych na różne sposoby.

Przykłady jakie jestem w stanie sobie wyobrazić to:

  1. czekanie na dane z kilku źródeł aż wszystkie dostaniemy wszystkie dane o zadanym kryterium, co umożliwia synchronizację zbliżoną do tego jak mamy napisy w filmach
  2. konkurencja z czasem czyli czekamy na dane, ale obok mamy drugi strumień przez który wyjedzie ze zdarzeniem jak nastąpi timeout albo mamy strumień z guzika, gdzie user ma produkuje zdarzenie kliknięcia, które np. w tym przypaku byłoby na równi z timeoutem

Gdy o tym myślę to trochę nie rozumiem czemu fenomenu reaktywnego programowania. Ta rzecz oczywiście upraszcza synchronizację, jest pomocne gdy dane pochodzą z wielu źródeł, ale ja w 90% sytuacji wybrałbym event listenera lub csp na mniejszą skalę niż pakować się we framework od reaktywnego programowania.

Zastanawiam się czego jeszcze nie widzę.

Czy takie strumienie ułatwiają projetkowanie aplikacji gdzie dochodzi do współpracy paru osób na tym samym widoku jednocześnie? Co o tym najbardziej decyduje?

0

Programowanie reaktywne jest bardziej "naturalne" niż programowanie zdarzeniowe. Jego główną zaletą jest to, że widzisz cały szablon w jego wszystkich możliwych stanach. Gdy programujesz zdarzeniowo, szablon odzwierciedla tylko stan początkowy lub ewentualnie zawiera elementy, które są ukryte i przy określonych zdarzeniach zostaną pokazane.

W programowaniu reaktywnym, widok dba sam o siebie. W programowaniu zdarzeniowym, to Ty musisz powiedzieć widokowi: "ej, zmień ten element". Przy tym ostatnim, nie widzisz jakie zmiany pociągnie za sobą to zdarzenie w kontekście całego szablonu. Łatwo jest zmienić jakiś inny element i tym samym zepsuć działanie zdarzenia.

Programowanie reaktywne jest po prostu bardziej transparentne w kwestii widoku.

0
bearek napisał(a):

Programowanie reaktywne jest bardziej "naturalne" niż programowanie zdarzeniowe.

Nie znam się na reaktywnym, dlatego pytanie moje będzie z serii głupich. Jaka jest różnica między reaktywnym, a zdarzeniowym?

Do tej pory wydawało mi się, że reaktywne, to reagowanie na zdarzenia -> coś emituje zdarzenie, jakiś listener na nie reaguje i coś tam robi dalej.

0

To jest właśnie zdarzeniowe :P Reaktywne to takie, które na automatyczny mechanizm "reagowania" na zmianę czegoś. Za kulisami po prostu samo dodaje settera dla wartości i odświeża szablon. To odświeżanie też najczęściej jest sprytne, bo odświeża tylko to, co wymaga odświeżenia.

3

@bearek:

W programowaniu zdarzeniowym, to Ty musisz powiedzieć widokowi: "ej, zmień ten element".

Jeśli dobrze rozumiem to się mylisz. Zdarzenia sygnalizują coś co się stało, a więc nie mówią co ma się zmienić. Nie są imperatywne. To kod obsługujący te zdarzenia wprowadza zmiany.

Przy tym ostatnim, nie widzisz jakie zmiany pociągnie za sobą to zdarzenie w kontekście całego szablonu. Łatwo jest zmienić jakiś inny element i tym samym zepsuć działanie zdarzenia.

Jak już napisałem, zdarzenia opisują coś co już się stało. Nie można więc tego zepsuć bo to już miało miejsce.

Czytając to co piszesz nie widzę żadnych konkretów. Bez urazy ale brzmi to tak jakby określenie "reaktywne programowanie" było kolejnym buzzwordem opisującym już istniejące event-driven programming, udając że jest nowym podejściem tyko dla tego że opiera się na złych założeniach odnośnie podstaw programowania zdarzeniowego. Jednocześnie to żaden atak z mojej strony, sam jestem ciekaw zagadnienia ale piszę tylko jak to wygląda w mojej ocenie.

0

@Aventus: napisałem to samo, co Ty :P "ej zmień ten element", czyli że to się nie odbywa automatycznie, tylko my musimy sami ten element zmienić.

0
bearek napisał(a):

Reaktywne to takie, które na automatyczny mechanizm "reagowania" na zmianę czegoś.

A skąd się ten mechanizm bierze? Masz na myśli jakiś konkretny framework/bibliotekę, która potrafi reagować na pre-definiowane zdarzenia? Próbuję uchwycić tę granicę między "programowaniem zdarzeniowym", a "programowaniem reaktywnym". Mogę sobie wyobrazić jakąś gotową bibliotekę, która reaguje na zdarzenia (a_button42.onClick(action) ) i w tym sensie jest "event driven", ale czy "ractive" ?

0

@yarel: programowanie reaktywne to nazwa konceptu. Tak, realizują go różne frameworki JS-owe, np. Vue.js, Angular i React. Akurat React ma metodę setState(), która inteligentnie odświeża widok, ale np. w Vue.js dzieje się to bardziej magicznie, bo nie musisz wywoływać żadnych metod.

Nie ma czegoś takiego jak "granica" między reaktywnym a zdarzeniowym. To są dwa osobne koncepty. Bliżej in do przeciwieństw niż do podobieństw.

0

Akurat react i spółka, to takie odpowiednio uproszczone programowanie reaktywne. Dlatego może się komuś wydawać, że to to samo co event-driven programming.

Z bardziej ortodoksyjnych frameworków masz https://github.com/reflex-frp/reflex

Ale generalnie tak, reaktywnie programuje się po to, żeby było bardziej modularnie i funkcyjnie.

0

@part: akurat modularność i funkcyjność nie mają z tym nic wspólnego.

Co masz na myśli mówiąc "uproszczone reaktywne programowanie"? Jakie jest nieuproszczone?

0
bearek napisał(a):

@part: akurat modularność i funkcyjność nie mają z tym nic wspólnego.

Programowanie reaktywne jest konceptem mocno rozwijanym w językach funkcyjnych, ponieważ to najbardziej obiecująca droga do tworzenia interfejsów użytkownika. Z modularnością chyba też pewien związek jest.

Co masz na myśli mówiąc "uproszczone reaktywne programowanie"? Jakie jest nieuproszczone?

Programowanie reaktywne bazujące na "architekturze elm-a" jest uproszczone. Jeżeli chcesz nieuproszczone, to masz np. linka wyżej.

0

Przecież funkcyjność to tylko sposób zarządzania danymi, to z interfejsem nie ma najmniejszego związku. Programowanie reaktywne ma za zadanie sprawić, że widzimy logikę szablonu i że to warstwa danych zawsze w taki sam sposób działa na zależne od niej elementy, tj. żaden element nie zostaje "zapomniany". Tyle. To jest koncept programowania widoku. To co Ty podajesz to są skutki uboczne.

0

Proszę o wskazanie wymagań, które przechylają szalę w kierunku reaktywnego programowania. Chodzi mi o takie wymaganie, że pójście w inną stronę oznacza pakowanie się w niezłe kłopoty.

0

Przeczytaj początek dokumentacji któregokolwiek z tych frameworków.

3

Rzadko kiedy się to opłaca, można na to patrzeć jak na tradeoff: optymalizacja zużycia zasobów/maszyn (pod warunkiem, że kod jest IO-intensive) vs czas developmentu i utrzymania takiego kodu (ciężkie testowanie, nie mówiąc o CR czy debugu na prod). Prosta abstrakcja zachęca, potem są problemy - pisałem o tym tutaj na forum, poszukaj.

Tutaj fajny art: https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape

No i prezentacja:

0

@bearek

napisałem to samo, co Ty :P "ej zmień ten element", czyli że to się nie odbywa automatycznie, tylko my musimy sami ten element zmienić.

Wybacz ale nadal nie rozumiem. Co w takim razie jest automatycznym zmienieniem elementu, a co "manualnym"? Załóżmy taki scenariusz:

  • Mam event OrderSubmitted
  • Mam jakiś handler tego eventu w innym serwisie który buduje sobie widok zamówień użytkownika
  • Event jest obsługiwany przez handler który aktualizuje widok zamówień

Rozumiem że to jest ta manualna obsługa? Jak to zrobisz automatycznie, reaktywnie?

EDIT: Trochę poczytałem i wychodzi na to że kogo nie spytać ten będzie miał inną definicję. Nie mówiąc już o mieszaniu reactive programming z reactive systems. Spotkałem się nawet z opiniami że event-driven to jeden z najczęściej używanych sposobów na osiągnięcie "reaktywności", czyli w zasadzie odwrotność tego co Ty napisałeś. Nie twierdzę że ta definicja jest poprawna a Twoja nie. Zaznaczam tylko że wszyscy się chyba gubią w zdefiniowaniu tego, co tylko utwierdza mnie w przekonaniu że jest to buzzword.

0

Chciałem zapytać jakie przykładowe wymagania musiałby spełniać projekt, aby w rzeczywistości był sens wchodzić w reaktywne programowanie.

Zmieniający się stan, jedne obiekty zależące od stanu drugich (czyli np. GUI byłoby dobrym kandydatem, bo tam się co chwila zmieniają dane i te wszystkie przyciski i kontrolki muszą reagować na zmianę danych. Swoją drogą ostatnio robię coś, co pozwoli na reaktywność przeglądarkowych wizualizacji 3D, dzięki temu mogę zdefiniować, że np. położenie jednego obiektu w 3D zależy od drugiego albo od jakiejś innej zmiennej. Ogólnie ma mi to pomóc w pisaniu interaktywnych aplikacji/gierek 3D w bardziej zwięzły sposób).

(przy czym nie zakładam, że wszystko będzie tam reaktywne, raczej chodzi ogólnie, żeby dało się łatwo budowac apki, a reaktywność to tylko narzędzie, które może czasem się przydać, ale też nie znaczy, że całą apkę należy na tym budować)

więc z użyciem strumieni raczej trudniej jest pisać kod, który coś przetwarza i na podstawie danych w strumieniu dociąga jeszcze dodatkowe dane z sieci.

Nie, czemu? Po prostu piszesz deklaratywnie. "Dociąganie" z sieci nie musi być imperatywne. Tj. w podejściu imperatywnym każesz komputerowi "dociągnij z sieci" (np. fetch jest przykładem takiego imperatywnego API), w podejściu deklaratywnym "dociąganie z sieci" może być abstrakcyjną czynnością.

Taki pseudokod:

const catPictures = ajax('https://en.wikipedia.org/wiki/Cat')
    .map(html => parseImagesFromHtml(html)
    .map(url => ajax(url));

zakładając, że ajax byłby naszą deklaratywnym obserwable do "dociągania z sieci".
To pseudokod, ale nawet w Rx.js jest coś takiego widzę: https://rxjs-dev.firebaseapp.com/api/ajax/ajax

I z tego co pamiętam, to efekty uboczne w Rx.js nie uruchamiały się dopóki nie zrobiłeś subscribe, więc samo utworzenie obserwabla nie było efektem ubocznym.

1

Ja bym raczej odszedł od gadki o frameworkach, ale skupił się na najważniejszych kwestiach czyli właśnie reaktywności.

W największym skrócie: w programowaniu reaktywnym warunek mając: a = b + c, wartość a zmieni się gdy zmieni się wartość b. Niesie to za sobą cały szereg konsekwencji, główny to mechanizm pilnujący zależności - każda implementacja (np. ta z Reacta) może mieć swoją specyfikę. Plusem jest na pewno to, że taki kod jest bardzo podatny na różnorakie optymalizacje (bo da się stworzyć graf zależności).

Kiedy się na pewno bawić w programowanie reaktywne? Na pewno wtedy, kiedy źródła twoich danych są od siebie niezależne (mogą to być pola na formularzu, jakieś odczyty z czujników itp.). Przy bardziej skomplikowanych algorytmach raczej bym się w to nie bawił bo wtedy szansa na to, że napisze się coś w stylu: b = b + 1 (może być rozbite na kilka linijek) rośnie.

0

W największym skrócie: w programowaniu reaktywnym warunek mając: a = b + c, wartość a zmieni się gdy zmieni się wartość b.

oprócz Rx.js polecam naukę Mobx, bo tam jest właśnie reaktywność, które polega bardziej na tego typu rzeczach. Poza tym choćby i React też zapewnia reaktywność bo zmieniasz stan komponentu i się sam odświeża, reaguje na zmiany.

No i programowanie wizualne, oparte na tworzeniu grafu zależności i ustalaniu, skąd mają płynąć dane dokąd. Ogólnie programowanie reaktywne zaczyna mieć więcej sensu, kiedy człowiek się pobawi różnymi "node editors".

Ja bym raczej odszedł od gadki o frameworkach,

Bo to pewien paradygmat czy sposób myślenia o programowaniu, niepotrzebna do tego jest żadna biblioteka, żeby pisać w ten sposób.

0

No więc właśnie, programowanie reaktywne to paradygmat i coś więcej (a może inaczej - coś innego) niż jakikolwiek frejmołrk.
Ale skoro już React tu padł (a fuj ;-)) to polecam poświęcenie tych 30 minut i obejrzenie tego:

W Svelte reaktywność jest wbudowana w DNA tego rozwiązania.

0

Czytając https://pragprog.com/titles/smreactjs5/reactive-programming-with-rxjs-5/

napotkałem fajne wprowadzenie, bo omawia plusy minusy callbacków, obietnic, event listenerów i programowania reaktywnego

Najfajniejsza informacje:

  • obietnica jest jak placeholder, ale patrzy tylko na jedną wartość, podczas gdy strumień to też placeholder, lecz zorientowany na wiele wartości
  • event listener rejestruje funkcje, ale praktycznie żadna z tych funkcji nic nie zwraca, stąd funkcje event listenera są skupione na efektach ubocznych i kontekście jaki je otacza, jak emitujesz zdarzenie wtedy wywołujesz efekty uboczne, taki kod trudniej jest kontrolować. Natomiast przy strumieniu to idziemy dużo bardziej w kierunku przewidywalnych działań

1 użytkowników online, w tym zalogowanych: 0, gości: 1