Why logic is on backend side?

20 february 2025
Jakub Rojek Jakub Rojek
The graphic, generated by Adobe Firefly, depicts a man in a smart jacket with a yellow helmet on his head, who looks into the camera lens with a friendly smile and holds two cardboard boxes in his hands, suggesting that you choose one of them. In the background, racks of large objects can be seen.
Categories: Programming, IT fundamentals

Wielu specjalistom pytanie zawarte w tytule może wydawać się absurdalne. Przecież, gdy mówimy o podziale oprogramowania na frontend i backend, to od początku powtarza się, że frontend jest od interfejsu, a backend od logiki. Skąd zatem pomysł, aby w ogóle mysleć o roszadach w tym aspekcie i dlaczego w ogóle to tłumaczyć?

Źródłem jest, oczywiście, życie i obserwacja różnych projektów spotykanych zarówno w życiu zawodowym, akademickim, jak i prywatnym. Bywa tak, że programiści, znając lepiej frontend (i do tego jeszcze w postaci konkretnego frameworka, jak np. React), wchodzą do projektów wymagających rozwijania kodu także po stronie backend i gdy napotykają trudności, to wybierają rozwiązanie, z którym czują się lepiej. Nie zawsze jednak jest to rozsądny wybór, a więc taki, który uwzględnia zalety i wady różnych podejść, a na końcu wynikiem jest właściwa, przyszłościowa opcja. Zamiast tego niektórzy idą tropem, że skoro lepiej znają frontend, to zrobią jak najwięcej we frontendzie. W końcu liczy się efekt, prawda? A w przypadku logiki i generalnie różnych obliczeń jest to zazwyczaj błąd.

Natomiast pozostaje pytanie wielu początkujących - dlaczego właściwie to jest błąd? I nie chodzi tutaj tylko o zapis wprowadzonych danych do bazy, gdyż tutaj backend jest często oczywisty. Natomiast umiejscowienie takich kwestii, jak np. obliczenie wieku na podstawie daty urodzenia czy wyciągniecie procentu z dwóch wartości - już nie zawsze. Porozmawiajmy sobie o tym.

Zalety frontendu i backendu

Powtórzmy to raz jeszcze:

  • frontend to część oprogramowania, która odpowiada za interfejs, wyświetlanie informacji użytkownikowi i bezpośrednią obsługę wywołanych przez niego zdarzeń. To jest "to, co widać",
  • backend to część oprogramowania, z którą komunikuje się frontend w celu zdobycia danych lub zapisania ich. To jest "to, czego nie widać".

W świecie aplikacji, zwłaszcza webowych (ale nie tylko), frontend zazwyczaj jest uruchamiany bezpośrednio w środowisku użytkownika, natomiast backend jest ukryty na serwerze, do którego nikt (poza administratorem) nie ma bezpośredniego dostępu. To ma swoje daleko idące konsekwencje, gdyż oznacza, że:

  • frontend jest szybszy w operacjach wykorzystujących sprzęt użytkownika, ponieważ ma do niego dostęp. Do tego może przyjąć różną formę w zależności od preferencji odbiorcy, ale jest narażony m.in. na "hakowanie",
  • backend jest bezpieczniejszy (ukryty w miejscu, do którego użytkownik nie ma wejścia), stanowi jedno źrodło prawdy, ale też przez to jest obciążony zapytaniami z frontendów uruchomionych u różnych użytkowników.

Dawniej, gdyż królowały aplikacje monolityczne, a więc oparte o jeden kawałek oprogramowania znajdujący się na serwerze, architektura była prostsza, ale systemy bardziej obciążone i mniej podatne na skalowanie. Ponadto, ograniczały wybór technologii do jednej, a wiadomo, że istnieją biblioteki czy frameworki lepsze w konkretnych zastosowaniach. Wreszcie, podział na dwie części przynosi po prostu korzyści w zarządzaniu projektem, rozwoju oprogramowania i umożliwia przypisanie odpowiedzialności za poszczególne partie.

Wydajność

Wyobraźmy sobie, że pobieramy datę urodzenia użytkownika, natomiast mamy wyświetlić nie tylko ją, ale też wynikający z niej wiek. Oczywiście, oznacza to pobranie aktualnej daty i odjęcie od niej tej urodzenia. Mechanizmy ku temu znajdują się po obu stronach technologicznych, ale jednak w większości wypadków zalecenie będzie takie, aby zrobić to w backendzie. Dlaczego?

W przypadku jednej wartości nie ma to wielkiego znaczenia. Jednak wyobraźmy sobie, że programiści przyzwyczają się do tego, aby tego typu małe obliczenia robić głównie na frontendzie. Spowoduje to, że owszem, backend będzie dość wydajny, gdyż będzie przekazywał tylko surowe dane i nie obliczał dodatkowych informacji. Natomiast przeglądarka po stronie użytkownika, który dysponuje jednak zazwyczaj gorszym sprzętem niż serwer, będzie wykonywała działania, które w dużej liczbie po prostu spowolnią stronę. Można z tym walczyć różnymi technikami związanymi z opóźnionym ładowaniem, asynchronicznością itd., jednak jest to bohaterskie rozwiązywanie problemu, który sami sobie sprowadziliśmy.

Użytkownicy w dzisiejszych czasach są przyzwyczajeni do tego, że aplikacje ładują się błyskawicznie, szczególnie strony WWW. Jest to związane z tym, że dostęp do szybkiego Internetu jest już dużo szerszy niż kiedyś (nie chcę mówić, że powszechny, gdyż nie wszyscy mają szczęście go posiadać), a przez to wymagania internautów wzrosły, szczególnie wobec usług e-commerce'owych czy portali newsowych. Jasne, że im dłużej backend będzie przetwarzał dane, tym większa szansa na to, iż zirytowany użytkownik wyłączy stronę, natomiast do tego samego doprowadzimy przenosząc obciążenie na frontend. A może być nawet gorzej, gdyż ta praca przeniesie się na silnik przeglądarki, co może nie pozostać bez wpływu na środowisko osoby próbującej uruchomić stronę.

Ale nie tylko o "zajęcie" komputera chodzi. Przeglądanie Internetu ma to do siebie, że przeglądarki, wyświetlając użytkownikowi jakąś witrynę, pobierają ją na komputer odbiorcy. Robią to tym szybciej, im mniejsze są pliki składają się na stronę WWW. Dlatego tak ważna jest optymalizacja frontendów, szczególnie w przypadku często wyświetlanych i nastawionych na zysk serwisów. Dodanie dodatkowego kodu logiki powoduje, że strony stają się większe i są wolniej zaciągane oraz wyświetlane przez przeglądarkę.

Dodatkowo, wykorzystanie backendu do obliczeń często mobilizuje do zastosowania różnych technik przyspieszających, jak np. cache'owanie. Jeśli aplikacja często jest zmuszona do wyświetlenia wieku użytkowników i pyta o to wiele osób, to szybko dojdziemy do tego, że można wiek obliczać raz, aktualizować w odpowiednich momentach (np. w nocy, za pomocą crona), zapisać w bazie danych i zwracać już obliczoną wartość. Po stronie frontendu też jest możliwe wykorzystanie pamięci podręcznej, ale u każdego użytkownika osobno i niekoniecznie tak szybko.

Przykład z datą urodzenia jest dość klarowny, natomiast w rzeczywistości "uroczy", gdyż odjęcie dwóch dat nie stanowi odpowiedniego wyzwania dla żadnego nowego komputera. Tym niemniej, ta zasada może być rozszerzona na bardziej wymagające obliczenia, jak liczenie podsumowania tysiąca obiektów, wyszukiwanie frazy w wielu długich tekstach czy inne, skomplikowane elementy logiki. Wówczas rzeczywiście urządzenie użytkownika może się "spocić".

Trzeba też nadmienić o tym, że... nie zawsze wydajność serwera jest argumentem za backendem. Jeśli wiemy, że część serwerowa będzie bardzo obciążona, chwilowo nie możemy pozwolić sobie na jej zduplikowanie, a dodatkowy kod po stronie klienta nie spowoduje żadnej różnicy, to być może warto się na ten krok zdecydować. Tutaj przykładem są sieciowe gry wideo, które muszą działać wyjątkowo szybko i sprawnie, gdyż nawet milisekundy mogą mieć znaczenie w batalii pomiędzy graczami. Tam na serwerze są wykonywane tylko absolutnie niezbędne operacje, natomiast kwestie związane z ich wizualizacją i elementy, przy których można pozwolić na pewne "rozsynchronizowanie" są już wykonywane na komputerze odbiorcy. To dlatego w strzelankach typu Valorant bywa podczas tzw. lagowania, że mimo iż poruszyliśmy się na mapie, to gra cofa nas do poprzedniego miejsca, gdyż backend przesyła informację o ostatniej uzgodnionej pozycji gracza, mimo że frontend (aplikacja na komputerze użytkownika) obliczyła już dalszą drogę.

Czytelność kodu

Gdy jeszcze większość aplikacji powstawała w architekturze monolitycznej (np. w PHP), bardzo duże znaczenie miało to, ile kodu znajdowało się w plikach widoku. Idealnie powinna być tam wyłącznie struktura HTML-owa z niezbędnymi dodatkami z danego języka, które wstawiają już przygotowane dane. Powód był dość prosty - im więcej logiki "upychało się" w widoki, tym mniej czytelny kod się stawał. Pomagały (i nadal pomagają) w tym różne silniki szablonów, natomiast jeśli ktoś bardzo chce, to można tak zamącić w warstwie widoku, że kontrolery i klasy logiki się wręcz nudzą.

Wprowadzenie javascriptowych frameworków po stronie frontendu pozwoliło na trochę więcej, gdyż one naturalnie są podzielone i separują kod logiki widoku od samego widoku. Natomiast, jeśli ktoś nie będzie uważał, to również w takiej architekturze jest w stanie napisać frontend w sposób nieczytelny i trudny w orientacji dla innych programistów. Im więcej dłuższych, logicznych fragmentów się w nim znajduje, tym większa szansa, że o danym kodzie powiemy "brzydki" i zostanie źle oceniony podczas przeglądu kodu.

Ma to też znaczenie ze względu na specjalizację programistów - frontendowcy zazwyczaj mają do czynienia z inną logiką niż backendowcy, gdyż w obecnych czasach aplikacje klienckie są na tyle skomplikowane, że - mówiąc kolokwialnie - jest w nich co robić i sporo kodu jest do upchnięcia w różnych klasach oraz komponentach. Jeśli jeszcze do tego dołożymy elementy z backendu, to może się okazać, że odnalezienie się w aplikacji będzie karkołomnym zadaniem.

Ktoś może teraz zapytać, że skoro kod logiki jest w stanie wprowadzić zamieszanie, to czy nie powoduje on bałaganu również po stronie backendu. Otóż, jak najbardziej może. Ale architektura backendu naturalnie tworzy miejsce na taki kod i jego odpowiedni wewnętrzny podział, więc można tam napisać go ładnie i składnie. Jest to też możliwe we frontendzie, ale z uwagi na jego przeznaczenie, trudniej go tam utrzymać.

Bezpieczeństwo

Moim zdaniem kluczowy powód, dla którego logika powinna znajdować się po stronie backendu lub przynajmniej to tam powinny być weryfikowane informacje wprowadzane przez użytkownika. Sprawdzałem - ChatGPT też tak twierdzi.

Wyobraźcie sobie sytuację, w której dodajecie do koszyka produkty w sklepie internetowym. Koszt nabywanych rzeczy jest sumowany i użytkownik może przejść do formularza składania zamówienia. Większość użytkowników nie pomyśli nawet o tym, że mogłaby zmodyfikować cenę, ale są też osoby, które wiedzą o tym, iż przeglądarki internetowe umożliwiają podejrzenie wielu aspektów wyświetlanej strony, w tym jej kod, zarówno HTML, jak i JavaScript. Mało tego - ten kod można zmienić, modyfikując tym samym nie tylko wygląd, ale też zachowanie witryny. Możecie zatem domyśleć się, co by nastąpiło, gdyby ktoś edytował algorytm wyliczający koszt, a backend by tego nie sprawdził.

Dlatego to właśnie część serwerowa, zabezpieczona przed bezpośrednią modyfikacją użytkowników, powinna być miejscem, gdzie znajdują się kluczowe elementy logiki. Wspomniałem wyżej o przykładzie gry wideo, gdzie tylko taki krytyczny obszar znajduje się na serwerze dyrygującym i sędziującym mecz rozgrywany przez graczy. Właśnie dlatego, że o ile nie ma problemu, aby ktoś sobie zmodyfikował kolory banerów czy zmniejszył okno, o tyle niedozwolona jest modyfikacja np. stanu punktów życia i innych elementów mogących wpłynąć na rezultat.

Oczywiście, są obliczenia mniej istotne dla bezpieczeństwa aplikacji. Przykładowo, w większosci przypadków nic by się nie stało, gdyby ktoś zmodyfikował swój wiek. Jednak, naturalne jest przechowywane logiki w jednym miejscu i backend nadaje się do tego znacznie lepiej niż frontend z uwagi na ukrycie go przed użytkownikiem. A sam wiek przecież też może być ważny, np. w operacjach wymagających 18-tego roku życia.

Jednolite środowisko

Jeśli już ktoś umieszcza logikę po stronie frontendu, to najczęściej wykorzystuje do tego najpopularniejszy język obsługiwany przez przeglądarki internetowe - JavaScript. A konkretna technologia ma to do siebie, że czasem się zmienia lub wręcz jest zastępowana. W przypadku dynamicznego świata Internetu ma to dodatkowe znaczenie.

Oczywiście, prawdopodobieństwo, że logika napisana w JavaScripcie nie będzie obsługiwana u każdego użytkownika tak samo, nie jest bardzo wysokie, ale jednak istnieje i nie jest minimalne. Wystarczy jedna nowsza konstrukcja, aby nieco starszy silnik w nieaktualizowanych przeglądarkach sobie nie poradził i albo zgłosił błąd na stronie (powodujący wściekłość i niedowierzanie odbiorcy), albo - co gorsza - spowodował tzw. cichy błąd, czyli aplikacja zadziała, ale z pomyłką w obliczeniach, co może przynieść koszmarne skutki.

Czy w backendzie też nie może to wystąpić? Oczywiście, że może. Ale jako że jako zespół IT zazwyczaj kontrolujemy serwer, na którym umieszczono tę "logiczną" część aplikacji, to mamy też wpływ na aktualizację silników, oprogramowania i konfiguracji. Co za tym idzie - na serwerze konfiguracja jest jedna i wiadomo, na co można sobie pozwolić pisząc kod oraz jaka technologia czy konstrukcje językowe zostaną prawidłowo zinterpretowane na maszynie, z której korzystają wszystkie frontendy.

Zresztą, możemy pójść dalej i przewidzieć wyłączenie JavaScriptu w przeglądarce przez użytkownika. Jest to możliwe i choć obecnie trudno znaleźć złożoną aplikację, która poprawnie zadziała bez JS, to nadal osoby wyjątkowo mocno dbające o swoje bezpieczeństwo nadal wykorzystują tę funkcję. Jeśli nasza logika była właśnie napisana w JS po stronie frontendu, to cóż...

Testowanie

Ten punkt nie ma już takiego znaczenia jak kiedyś, gdyż obecnie istnieją frameworki testujące skupione na technologiach frontendowych. Tym niemniej, nadal zautomatyzowana weryfikacja oprogramowania jest częściej kojarzona z backendem i czasami jest tam zwyczajnie prostsza. A najczęściej testowany jest właśnie kod logiki.

Podsumowanie

Czy to wszystko oznacza, że absolutnie nie można umieszczać logiki po stronie frontendu? Nie do końca - mogą istnieć sytuacje, w których zrobienie tego nie spowoduje znaczących szkód w projekcie. Tym niemniej, na pewno nie powinno być to zasadą, gdyż miejsce obliczeń (szczególnie tych "ciężkich") jest po stronie backendu, a jako główne dwa argumenty należy wymienić bezpieczeństwo (odmieniane w ostatnich latach przez wszystkie przypadki) oraz wydajność (na które zwraca uwagę choćby marketing). Dlatego, jeśli pracujecie jako programiści tzw. full stack, ale historycznie bliżej Wam do frontendu w JS, to zastanówcie się dwa razy, zanim umieścicie tam kod logiki - być może jednak warto przekonać się w tym obszarze do części serwerowej.

Pozdrawiam i dziękuję - Jakub Rojek.

We like to write, even a lot, but on a daily basis we develop web and mobile applications. Check some of the programs we have made.

About author

Jakub Rojek

Lead programmer and co-owner of Wilda Software, with many years of experience in software creation and development, but also in writing texts for various blogs. A trained analyst and IT systems architect. At the same time he is a graduate of Poznan University of Technology and occasionally teaches at this university. In his free time, he enjoys playing video games (mainly card games), reading books, watching american football and e-sport, discovering heavier music, and pointing out other people's language mistakes.

Jakub Rojek