Witam,
Chciałbym się dowiedzieć jakimi czynnikami powinienem się kierować przy wyborze architektury opartej o komunikację restową?
Konkretnie mam tutaj na myśli wyświetlanie statystyk danych, zaciąganych z bazy NoSQL (MongoDB) przez Javę. Backend w Javie służyłby do obliczania m.in statystyk i wystawianiu ich na warstwę widoku, gdzie miałbym Angulara.
A jesteś wstanie oszacować docelowy ruch?
Prawdopodobnie nie potrzebujesz w ogóle reaktywności.
Rozumiem, a jaki byłby use-case kiedy musiałbym rozważyć reaktywność? Bardzo dużo zapytań do Api?
Mówi się, że tyle co Netfix.
Pamiętaj, że reaktywność to też narzut na "koszt" tworzenia kodu (jest "brzydszy")
danek napisał(a):
Mówi się, że tyle co Netfix.
Pamiętaj, że reaktywność to też narzut na "koszt" tworzenia kodu (jest "brzydszy")
A ja bym powiedział, że wręcz przeciwnie. Piszesz wszystko czysto funkcyjnie i kod jest DUŻO prostszy i "ładniejszy":
userService.getFavorites(userId, new Callback<List<String>>() {
public void onSuccess(List<String> list) {
if (list.isEmpty()) {
suggestionService.getSuggestions(new Callback<List<Favorite>>() {
public void onSuccess(List<Favorite> list) {
UiUtils.submitOnUiThread(() -> {
list.stream()
.limit(5)
.forEach(uiList::show);
});
}
public void onError(Throwable error) {
UiUtils.errorPopup(error);
}
});
} else {
list.stream()
.limit(5)
.forEach(favId -> favoriteService.getDetails(favId,
new Callback<Favorite>() {
public void onSuccess(Favorite details) {
UiUtils.submitOnUiThread(() -> uiList.show(details));
}
public void onError(Throwable error) {
UiUtils.errorPopup(error);
}
}
));
}
}
public void onError(Throwable error) {
UiUtils.errorPopup(error);
}
});
To samo funkcyjnie:
userService.getFavorites(userId)
.flatMap(favoriteService::getDetails)
.switchIfEmpty(suggestionService.getSuggestions())
.take(5)
.publishOn(UiUtils.uiThreadScheduler())
.subscribe(uiList::show, UiUtils::errorPopup);
danek napisał(a):
Mówi się, że tyle co Netfix.
Pamiętaj, że reaktywność to też narzut na "koszt" tworzenia kodu (jest "brzydszy")
Pomijając że to 100% subiektywne stwierdzenie, to jest na tyle brzydszy na ile osoba go pisząca pozwoli. Co to w ogóle za pomysł że kod reaktywny jest brzydszy? To samo można powiedzieć o jakimkolwiek innym rodzaju kodu/paradygmacie.
Z resztą z tym Netflixem też ciekawe stwierdzenie. Mówi się gdzie? Tam gdzie widziałeś brzydki kod? :D
@mieszko30 może te artykuły trochę pomogą:
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/asynchronous-message-based-communication
https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber
TL;DR jeśli nie zyskasz na „wydajności”, nie rób tego
Co do prezentacji powyżej - jest jeszcze kwestia jezyka.
Przykład z prezentacji wygląda dużo lepiej po przerobieniu na scalę : https://gist.github.com/jarekratajski/2adb5680b28388339636578ccf6ab6f8
Ja to widzę tak: początkujący, szczególnie w javie, nie powinni ruszać tego reactive prawie w ogóle.
Jak ktoś potrzebuje wydajności to powinien poznać (ale nie musi używac).
Jak ktoś pisze funkcyjnie i rozwija się w tym kierunku to też na reactive sam trafi. Szczególnie w Scali, czy Haskellu działa to naturalnie. W kotlinie... jak mamy pewne reguły kodowania.
Z ciekawostek - w JS reactive też jest naturalnym rozwiązaniem.
Co do debugu itp., jest gorzej niż debugowanie kalkulatora 1+1, ale takiego wielkiego dramatu nie ma. Na pewno mniej męczące niż debugowanie czegokolwiek na serwerach JavaEE, czy szukanie co się stało z kontekstem security w springu :-) (Hooks.onOperatorDebug()
faktycznie pomaga )
Najgorszy problem - błędy w projectreactor. To dziwne, że projekt, który jest tak popularny i ma już ładnych parę lat i wersji... ma tak absurdalne błedy czasem (see isssues na githubie zwłaszcza pozamykane w ostatnim roku). Jak się na takiego buga trafi to można się zdenerwować.
Drugi problem - pole minowe. Znowu dotyczy Javy, mniej troche kotlina, jeszcze mniej Scali - trzeba uważać. Nie cierpię tworów, które wprowadzają sztuczną dodatkową dyscyplinę. W reactive
prosta dyscyplina jest taka, że subscribe to robimy JEDEN raz na dany "process". W ostatnim kroku, albo najlepiej wcale, jeśli inna biblioteka ciągnie dane z naszego strumienia. Niestety w jezyku (programowanui) imperatywnym można to zrobić więcej niż raz, i to przypadkiem, i często będzie to działać. W końcu gdzieś kiedyś po małym refaktoringu się wywali i bedzie bolało. Jeszcze śmieszniejsze jest nie zrobienie żadnego subscribe i pozostawienie zainicjowanego strumienia.
To chyba najczęstszy problem z reactive jaki się pojawia w pytaniach, problemach na forach - czasem wcale nie jest łatwo znaleźć gdzie jest ta zwałka (nadmiarowy subsribe, całkowity brak subscribe).