Nasza strona używa cookies. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Prawie wylali mnie za użycie Reacta w aplikacji biznesowej. Dlaczego?

Razvan Dragomir Software Architect / TSS-Yonder
Poznaj historię tworzenia pewnej aplikacji biznesowej i dowiedz się, dlaczego React nie był tam zbyt dobrym wyborem.
Prawie wylali mnie za użycie Reacta w aplikacji biznesowej. Dlaczego?

Lato 2018. Mój szef, Adrian, zaprasza mnie na calla z CTO dużej kanadyjskiej firmy. W miarę, jak się poznawaliśmy, zdążyłem zauważyć, że CTO to bystry facet o dużych ambicjach. Jego wizją była migracja masywnej aplikacji desktopowej WPF na aplikację webową w chmurze. 

Podoba mi się jego przyjazne nastawienie i mogę śmiało powiedzieć, że bardzo chce z nami pracować. Ma już partnera do developmentu w Indiach, ale brakuje im doświadczenia w tworzeniu aplikacji webowych. 

Wraz z Adrianem trzymamy się standardowego podejścia w takich sytuacjach. Mamy kilka calli, a potem zaczynamy fazę odkrywczą, w której próbujemy uzyskać pełny obraz sytuacji i znaleźć wymagania niefunkcjonalne. Oto główne rzeczy, na których będziemy się skupiać: 

  1. Duża aplikacja - ponad 220 stron, z których większość to maintenance screens. Około 20% to strony niestandardowe.
  2. Wyświetlanie dużych ilości danych, zwłaszcza w siatce, razem z tymi wszystkimi funkcjami: grupowanie, zamrażanie kolumn, rozszerzanie wierszy, niestandardowe kolumny itd. 
  3. Modularna architektura, która pozwala wielu zespołom na pracę nad jednym projektem w tym samym czasie. 
  4. Projekt, który będzie rozwijany jeszcze wiele lat. Nowe funkcje będą dodawane z czasem. 
  5. Obsługa offline nie jest wymagana
  6. Szybki onboarding dla nowych członków zespołów, zwłaszcza dla .NET developerów, którzy pracują przy starej aplikacji desktopowej.


Jako architekt tworzę techniczne projekty, które zawierają szczegóły dotyczące architektury, podejście, roadmapę, wytyczne, i co najważniejsze, stos technologiczny, z którego będziemy korzystać. 

CTO kilka razy mówił o tym, że chce użyć technologii odpornej na upływ czasu i że nie lubi Angulara, ponieważ ma on złą reputację po zaprzestaniu prac nad AngularJS. 

Udało mi się dobrze zaimplementować kilka małych i średnich projektów przy użyciu zarówno Angulara i Reacta, więc wszystko mi jedno, którego wybiorę. Mam wrażenie, że każdy z nich by sobie dobrze poradził. 

A dla tego konkretnego projektu chcę wybrać Reacta z Redux… i niestety pożałuję tego dwa lata później. 

Stworzyliśmy team złożony z 3 developerów, którzy pracowali nad proof of concept i po dwóch miesiącach mamy sukces. Bardzo responsywne UI, super szybki czas budowania połączony ze sprawnym developmetem. Wszyscy są zadowoleni. Ale nie wszystko wyglądało tak kolorowo.

Oto lista przeszkód, które napotkaliśmy po drodze. 


1. Do zespołu dołącza .NET developer

Po wykonaniu proof of concept czas na deweloperów z teamu klienta. Nie zaczęliśmy jeszcze z sesjami, na których dzielimy się wiedzą, a CTO wysłał mi takiego maila: “Hej, Răzvan. Spotkajmy się jutro z moim teamem outsorucingowym. To ważne.”

  • “Gdzie znajduje się wstrzykiwanie zależności. Co masz na myśli, mówiąc, że nie ma takiej potrzeby. Oto jedno z nich: InversifyJS!”
  • “Komponenty funkcyjne? Nie, nie i jeszcze raz nie. Nie lubimy tego. Wykorzystajmy komponenty klasowe.” 
  • “Dlaczego te funkcje wiszą sobie po prostu i nie zawierają się w żadnej klasie, która sprawi, że będą statyczne?”
  • “Gdzie jest Retry Policy dla naszego API? Zaimplementujmy ją przy użyciu PollyJS.” 
  • “Dlaczego nazwy plików są pisane z myślnikami, a nazwy klas są PascalCase? Nazwy plików powinny odzwierciedlać nazwę klas, więc teraz będziemy je nazywać SomePageComponent.tsx.”
  • O, i to mnie najbardziej irytuje: “Jak mogę to uruchomić z Visual Studio. Muszę to uruchamiać w Visual Studio Code?”


Wszystko jasne. Chcą korzystać z wytycznych dotnetowych i wzorców projektowych Reacta. Widziałem to wiele razy - programistom ciężko jest się przystosować do nowej technologii. Nie chcę wchodzić w dyskusję na temat tych niestandardowych wzorców Reacta. 

W tym przypadku CTO stoi murem za swoim zespołem, co jest w sumie normalne. Znał mnie wtedy tylko dwa miesiące. Muszę pójść na kompromis i zgodzić się na ich propozycję. 

Zdałem sobie właśnie sprawę z tego, że React nie jest zbyt przyjazny dla developerów dotnetu i Javy. Angular byłby tutaj lepszy, bo ma podobne wzorce projektowe. 


2. Zawsze jest coś więcej, niż React

React to dość elastyczna biblioteka. Oznacza to, że nie sugeruje ona określonych rozwiązań dla wielu problemów. 

Ty i Twój zespół musicie określić sposób, w jaki macie to robić, a zwłaszcza, jakich bibliotek użyć. Najlepiej jest jednak używać bibliotek zewnętrznych, aby uniknąć pracy od nowa. A w React jest tyle opcji do wszystkiego, że głowa mała. 

Mamy już sposób na obsługę większości podstawowych przypadków. Trzeba to jeszcze omówić z resztą zespołu. Oto lista rzeczy do przedyskutowania:

  • Jakiego routera użyjemy?
  • Czego poza Redux należy użyć do akcji asynchronicznych? Trunk? Saga? 
  • Czy powinniśmy unikać Axios albo API przeglądarki fetch?
  • Redux-Forms, Formiq, czy Final-Form?
  • Styled-Components, makeStyle, SASS, czy czysty CSS?


Następne 3 tygodnie zlatują nam na tych dyskusjach. Już słyszę, jak mówisz: “no kurde, jak to 3 tygodnie? Nie ma możliwości, żeby wybór tych bibliotek zajął tyle czasu”.

Witamy w projektach biznesowych. Trzeba tu podjąć wiele decyzji. Dla każdej trzeba stworzyć odpowiednie kryterium, zrobić research, sprawdzić wyniki tworząc proof of concept, zaprezentować te wyniki, udokumentować wszystko w logu decyzyjnym i zaktualizować biblioteki. Trzeba na to wszystko poświęcić bardzo dużo czasu. Zdecydowanie nie bawiłem się przy tym dobrze. 

Nie biorę tutaj pod uwagę czasu, w którym każdy programista uczy się tych wszystkich bibliotek zewnętrznych. Nigdy nie spotkałem dwóch projektów Reacta z tymi samymi zależnościami, strukturą projektu i wytycznymi. Oznacza to, że wiedzy nie należy przenosić z projektu do projektu, co można z kolei robić w przypadku Angulara, czy Vue. 

Po 3 tygodniach bez żadnych postępów w implementacji user stories CTO zaczął się niepokoić. 


3. React Hooks staje się coraz bardziej popularny

Po 9 miesiącach stworzyliśmy już ponad 50 ekranów. Developerzy zauważali, że komponenty funkcyjne są tak samo dobre, jak komponenty klasowe i zaczęli z nich korzystać. Od teraz projekt nie trzyma się już oryginalnych wytycznych pisania kodu. Developerzy sami sobie wybierają, co chcą robić. Coś takiego jest dla mnie OK.  

React Hooks staje się po wydaniu coraz bardziej popularny. Team ma jednak mieszane uczucia. Niektórych programistów uraziła sugestia, że klasy są mylące dla ludzi i maszyn, ale inni cieszyli się na myśl pisania kodu z nowym wzorcem. 

Wszystkie zewnętrzne biblioteki, z których korzystaliśmy, dodały wsparcie dla Hooks - cały świat Reacta chyba zmierza właśnie w tym kierunku. Co powinniśmy więc zrobić? Czy powinniśmy odejść od tego, co sobie oryginalnie założyliśmy i dodać kolejny sposób na implementację komponentów? Nie ma co się cofać i migrować istniejące strony i komponenty do React Hooks! 

Cały team chciałby korzystać z Redux Hooks, ponieważ nie ma potrzeby korzystać z Redux connect() i oddzielać zrzucone komponenty od kontenerów. Ma to sens, więc zgadzamy się co do tego, że nowe strony i komponenty będą od teraz korzystać z Hooks. Starsze komponenty zostaną w takim stanie, w jakim są. 

I tak właśnie zostajemy z trzema sposobami na robienie rzeczy. Pożegnaliśmy się ze spójnością. A żeby było jeszcze gorzej, to niektórzy developerzy zaczęli forsować nieużywanie Redux - zamiast tego chcieli korzystać z useState. Pokrzyżuje to plany posiadania jednego stanu globalnego. 

Suspense to nadal funkcja eksperymentalna. Martwię się tym, co się stanie, kiedy będzie ona stabilna. 


4. Development zwalnia 

Kiedy skonfigurowaliśmy Continuous Integration, to build zajął około trzech minut i to razem z npm install. A teraz, po roku, zajmuje około 15 minut. 

Musieliśmy również skonfigurować Node.js, aby zwiększyć RAM do 4GB, ponieważ 2GB już nie starczały. Nie jest to jakiś duży problem. Co natomiast martwi, to fakt, że deveoperzy zaczęli narzekać, że buildy zajmują za dużo czasu, a hot reloading zatrzymuje się po 45-60 minutach developmentu. Restart maszyny zabiera natomiast ponad 5 minut - zwłaszcza dla tych z Windowsem (systemy Linuksowe są najwyraźniej o wiele szybsze dla Node.js).

Niekiedy muszą oni całkowicie usuwać node_modules i ponownie pobierać zależności, ponieważ inaczej to nie zadziała. A czego możesz się spodziewać, kiedy masz ponad 1 200 zależności w node_modules i 600MB całkowitego rozmiaru? 

Jeśli chodzi o aplikacje biznesowe, to wszystko rozbija się o koszty. Powiedzmy, że dany programista musi wykonać restart 6 razy ze stawką godzinową na poziomie 40 dolarów. 6 razy dziennie x 5 minut x 240 dni na rok x 40$ na godzinę x 8 developerów = $38,400 na rok. Nie jest to duża ilość, jeśli chodzi o aplikacje biznesowe, ale sprawia, że sponsorzy złapią roczny bonus. Co jak co, ale tyle kosztuje Tesla Model 3. 


5. Redux-Saga powoli umiera

Większość developerów się ze mną nie zgodzi, ale czuję, że duża część logiki biznesowej znajduje się wewnątrz Redux async actions. Jest to miejsce, w którym wykonujesz walidację, wywołania API, obsługę błędów, wyzwalasz mutacje redux i toaster notyfikacji. Jeśli to nie jest logika biznesowa aplikacji frontendowych, to nie wiem, co nią może być.  

My korzystamy z Redux-Saga, co było jednak złą decyzją - dodaje to niepotrzebną złożoność. Thunk byłoby tutaj lepsze. 

Jeśli chodzi o aplikacje biznesowe, to musisz czasem zaktualizować i ocenić na nowo zależności. To dobra praktyka, ponieważ zależy nam na aktualizacjach dotyczących bezpieczeństwa, usprawnieniach wydajności i małych przyrostowych zmian w API oraz braku zmian psujących kod. A wygląda niestety na to, że Redux-Saga jest w tyle. Ostatnia aktualizacja miała miejsce ponad rok temu, a liczba GitHub issues rośnie i nikt się nimi nie zajmuje. 

Developerzy uwielbiają Reacta z 3 powodów: prostota, elastyczność i ekosystem. Team Reacta lubi eksperymentować z nowymi pomysłami, ale niestety zabija to ekosystem! Powinni wziąć to wszystko na siebie. 

React jest w większości przypadków kompatybilny wstecznie. Ekosystem, który jest wokół niego już jednak nie. Developerzy oraz biblioteki zewnętrzne zawsze będą korzystać z najnowszych funkcji, wzorców architektonicznych, a stare eksperymenty sobie na spokojnie umrą. Nie ma z tym problemu w małych i średnich projektach, ponieważ łatwiej się tam dostosować. Ale dla projektów które trwają kilka lat? Takie eksperymenty to cecha niepożądana. 

Mamy wrzesień 2020 i decyduję się na uwzględnienie React-Saga w wynikach oceny ryzyka przygotowanym dla komitetu technicznego.

Ponieważ 30% logiki biznesowej było opakowane sagami, to oznaczyłem to jako wysokie ryzyko. I to był ten moment, w którym CTO stracił cierpliwość i obarczył mnie winą za złe decyzje, które podjąłem na początku projektu. 

To było coś, czego potrzebował PM do zadania mi następujących pytań:

  • “Dlaczego spędzamy tyle czasu na aktualizacji bibliotek?”
  • “Dlaczego development zwalnia?”
  • “Dlaczego aplikacja stała się zbugowana i niestabilna?”


Rzeczy docierają do managementu. Spędzam wiele godzin na szukaniu dowodu na to, że podjęliśmy najlepszą decyzję, jaką można było wtedy podjąć (wolałbym tak nie spędzać weekendów). Kilka spotkań później znowu jestem na spokojnych wodach. Projekt jest prawie skończony. Niedługo będziemy wchodzić w tryb utrzymania. 


Podsumowanie

Uwielbiam Reacta. Używam go w moich osobistych projektach i chciałbym go polecić do pracy. Niemniej jednak nie polecam korzystania z niego w aplikacjach biznesowych - a już na pewno nie po moich doświadczeniach. 

Tak na marginesie, nie tylko ja mam takie odczucia.  


Oryginał tekstu w języku angielskim możesz przeczytać tutaj

1 komentarz

Lubisz dzielić się wiedzą i chcesz zostać autorem?

Podziel się wiedzą z 160 tysiącami naszych czytelników

Dowiedz się więcej