Ten niedobry JavaScript - odc. 2543

Ten niedobry JavaScript - odc. 2543

Opinii na temat wad JavaScriptu i rzekomej trudności utrzymania kodu opartego o ten język naczytałem się już tyle, że każdy kolejny post komentujący ten temat przychodzi mi z jeszcze większą trudnością. Ostatnio natknąłem się jednak na fragment kodu wobec którego nie mogłem przejść obojętnie i w efekcie powstał post który właśnie czytasz. Czy sześć linijek kodu może być znakomitym argumentem w dyskusji? Przekonajcie się sami!

Chciałbym wam na początku zaprezentować stosunkowo prosty fragment kodu, który znakomicie obrazuje źródło problemu związanego z językiem JavaScript. Przyjrzyjmy się mu mając z tyłu głowy to, co w wielu środowiskach mówi się o tej właśnie technologii:

Mogłoby się wydawać – głupie sześć linijek kodu. Funkcja extractData przyjmuje parametr request a następnie – sądząc po nazwie – wydobywa pewną część danych i zwraca ją.

Patrząc na implementację tej funkcji moją uwagę zwrócił jeden bardzo istotny fakt, który często jest głównym źródłem problemów związanych z utrzymaniem i rozwijaniem aplikacji opartych o JS. O co chodzi?

Dygresja o funkcjach

Zanim odpowiemy sobie na pytanie postawione we wcześniejszym akapicie to zastanówmy się, z jakiego typu funkcjami chcielibyśmy mieć do czynienia w naszym programistycznym życiu. Odpowiedzi może być wiele, ale bazując na moim doświadczeniu powiem, że funkcja musi być przede wszystkim przewidywalna. Przewidywalność funkcji możemy ocenić patrząc na to, co dzieje się z jej parametrami (czy są modyfikowane bez naszej wiedzy?), zwracanym rezultatem (czy można przewidzieć co zostanie zwrócone?) oraz na to, jak funkcja wpływa na otoczenie (czy działanie funkcji powoduje efekty uboczne?).

Jeśli miałbym przed sobą funkcję getTotalPrice, która w trakcie działania uruchamia drukarkę, wysyła wiadomość e-mail i do tego zapisuje coś do bazy danych to mógłbym powiedzieć, że jej działanie jest trudne do przewidzenia. Jej nazwa mówi jedno (get total price), a działanie drugie. Budowanie modułów bazujących na takich funkcjach powoduje, że po czasie stają się one niemożliwe do rozwijania i utrzymywania. Jedyną odpowiedzią jest często przepisanie danego fragmentu aplikacji na nowo.

Czy funkcja przedstawiona na początku posta jest w takim razie przewidywalna?

Ah te typy…

Niestety – funkcja którą przedstawiłem na początku nie jest przewidywalna. Zobaczmy jeszcze raz na jej implementację aby zrozumieć w czym tkwi problem:

W zależności od zawartości parametru request nasza funkcja zwróci tablicę, lub… null. Oznacza to tyle, że w każdym miejscu w którym ktoś będzie chciał skorzystać z wartości zwróconej z tej funkcji, będzie musiał przygotować się na operowanie z tablicą, lub wartością null. Sześć linijek kodu będzie mieć wpływ na to, jak po kilku tygodniach będzie prezentował się cały system w którym znajduje się właśnie tak napisana funkcja:

  • Jeśli chcesz sprawdzić jaki rozmiar ma zwrócona z tej funkcji tablica, to najpierw upewnij się, że nie dostałeś nulla
  • Jeśli chcesz iterować po kolejnych wartościach w tablicy zwróconej przez tę funkcję, to najpierw upewnij się, że nie dostałeś nulla
  • Jeśli przekażesz wynik działania tej funkcji do innej funkcji, to w kolejnej funkcji najpierw upewnij się, że nie dostałeś nulla
  • Jeśli opisujesz tę funkcję komentarzem JSDoc, to nie zapomnij, że czasami zwracany jest null
  • Jeśli pracujesz z modułem który w jakikolwiek sposób powiązany jest z tą funkcją, albo funkcją która korzysta z tej funkcji, albo funkcją, która… no sami wiecie – po prostu upewnij się, że nie dostałeś nulla

Każde działanie mające jakikolwiek związek z tą funkcją musi więc brać pod uwagę to, że zwracany typ może się różnić w zależności od parametru z którym funkcja została wywołana. Podkreślam – różnić może się typ, a nie tylko wartość.

W takich momentach JavaScript nie może zaprotestować – język ten został zaprojektowany w taki sposób, że w momencie deklarowania funkcji nie musimy zamykać się na jeden typ danych który będzie z niej zwracany. Skoro programista decyduje się na taki krok, to bierze za niego pełną  odpowiedzialność.

Warto więc zadać sobie pytanie – czy tworzenie tego typu funkcji które powodują wzrost złożoności całego systemu to tylko i wyłącznie wina tego niedobrego JavaScriptu?

Poważny język zabroniłby mi pisania kodu w taki sposób…

…powiedzą ci, którzy i tak nie przykładają uwagi do kodu który tworzą w jakiejkolwiek technologii. No niestety – tak to bardzo często wygląda.

Mało kto zgodzi się z twierdzeniem, że powodem potrąceń pieszych są samochody same w sobie. Każdy z nas rozumie, że wypadki to konsekwencja nieumiejętnego prowadzenia samochodu, zaniedbań związanych z jego stanem, albo stanu samych kierowców. Ogólnie rzecz biorąc – czynnik ludzki jest nieunikniony.

Wygląda na to, że w przypadku programowania jest inaczej – tutaj wina nie leży po stronie programisty, a po stronie “tego głupiego języka w którym nie można tworzyć poważnych aplikacji”. Dla mnie to nic innego jak zrzucanie z siebie odpowiedzialności za efekty własnej pracy. Jako człowiek który na codzień pracuje z JavaScriptem irytuje mnie to szczególnie – różnego typu komentarze i opinie krytykujące ten język opierają się o takie właśnie zaniedbania i praktyki przez które komplikujemy sobie życie (świadomie i na własne życzenie).

Czy w językach typowanych dynamicznie można tworzyć tzw. “poważne aplikacje”? Oczywiście, że tak! Ogromną rolę odgrywa tutaj kultura tworzenia kodu, oraz praktyki wobec których nie przejdziemy obojętnie.

Konsekwentne stosowanie typów to coś, na co zwracam szczególną uwagę jeśli chodzi o projekty oparte o JS – szczególnie jeśli chodzi o rozbudowę tzw. kodu zastanego. Zapewniam was, że jeśli kontrakty pomiędzy back-endem oraz front-endem dotyczą nie tylko nazewnictwa, ale też formatu danych, a następnie jeśli ten format danych nie zmienia się na przestrzeni czasu (tutaj główną rolę odgrywamy my – autorzy kodu), to utrzymanie np. aplikacji front-endowej nie różni się niczym od utrzymania kodu np. w Javie czy C#. Liczba bugów również zaskakuje, o czym przeczytacie np. w tym artykule Erica Elliotta.

Czy przekonałem cię, że JavaScript to nie jedyne źródło problemów w twoim projekcie? Czekam na twój komentarz na ten temat!

Powiązane

Jak było na tegorocznym Ng-Poland? Konferencje i meetupy programistyczne to jedna z najprzyjemniejszych części życia programisty. W ich trakcie możesz nie tylko poznać najnowsze technol...
books#9 – “JavaScript – Wzorce&#... W trakcie naszej przygody z programowaniem zetknęliśmy się z książkami poruszającymi najróżniejsze tematy. Programowanie, branża IT, biznes, nowe te...
Getting started on ASP.NET Core & React – epi... Contents Episode 1 - Introduction Episode 2 - Backend / Infrastructure Episode 3 - Frontend Setup (you are here) Episode 4 - Data flow...
jQuery rządzi. Nie, Angular rządzi. Nie, React rzą... Jak spośród otaczających nas gigabajtów informacji wybierać najbardziej wartościowe porady i dobre praktyki? Opierać się na trendach? Chwilowej modzie...