Przestrzenie nazw w JavaScript

W mojej codziennej pracy dosyć często pracuje nad rozwojem kodu JavaScript w dużych projektach, w których owy kod JS pisało kilku developerów. Przestrzenie nazw w JavaScript nie są wbudowane w język przez co rozbudowane aplikacje narażone są na szereg niebezpieczeństw takich jak nadpisywanie zmiennych i funkcji oraz wszechobecny bałagan, który w znaczący sposób utrudnia rozwój aplikacji. W tym artykule chciałem przedstawić podejście do pisania kodu JS tak, aby nasza aplikacja była łatwa w rozbudowie, czytelna i przede wszystkim odporna na konflikty nazw.

W czym właściwie jest problem?

Konflikty nazw – historia prawdziwa

Pracując zespołowo nad projektem (niech to będzie sklep internetowy) developerzy pracują nad różnymi funkcjonalnościami/modułami systemu np. Janek pracuje nad checkoutem, a Franek robi stronę produktu. Devsi pracują cały dzień nad swoimi funkcjonalnościami i na koniec pracy wrzucają zmiany do repozytorium. Obydwoje zadowoleni, ponieważ nie było konfliktu w repo (pracowali w różnych plikach), więc wyłączają komputer i kończą pracę.

Wszystko wygląda pięknie, niestety na drugi dzień okazało się, ze ich kod nie działa. Manager niezadowolony, klient niezadowolony, a devsi smutni i zdenerwowani. Okazało się, że mimo tego, że pracowali nad zupełnie innymi funkcjonalnościami, w zupełnie innych plikach to przez zupełny przypadek nadpisali sobie nazwy zmiennych i funkcji.

Takie sytuacje przytrafiają się niedoświadczonym developerom, a Ci jeszcze mniej doświadczeni potrafią sobie samemu nadpisać zmienne i kilka godzin myśleć co jest nie tak z ich kodem — taka robota!
Poniżej przedstawię podejście, które pozwoli uniknąć wielu nieporozumień związanych z konfliktami nazw.

Przestrzenie nazw w JavaScript symulowane przez iterał funkcyjny

Aby uniknąć konfliktów nazw musimy przenieść nasze zmienne i metody z przestrzeni globalnej w miejsce, które zapewni im ochronę przed nadpisywaniem. Dobrą i znaną praktyką jest użycie iterału funkcyjnego, którym opakujemy nasze zmienne i funkcje.

checkout.js

product.js

index.html

Właśnie stworzyliśmy dwa moduły, które zawierają proste funkcje wyświetlające tekst powitalny. Moduły są w plikach checkout.js i product.js, natomiast w pliku app.js wywołujemy nasze funkcje.

app.js

Właściwości i metody prywatne

Mamy juz działające moduły, ale możemy je jeszcze ulepszyć. Wszystkie właściwości i metody, które mają być prywatne i widoczne tylko dla członków modułu poprzedzimy słowem var. Dzięki temu zabiegowi będziemy mieli większą kontrolę nad naszym kodem. Do dzieła!

checkout.js

product.js

Po tych modyfikacjach zmiana właściwości prywatnej z poza modułu nie będzie możliwa. Nasze zmienne prywatne są bezpieczne!

Przeszukiwanie zakresu

Nasze moduły wyglądają już bardzo sympatycznie, ale jest jeszcze jeden mały problem. W pliku app.js wywołujemy funkcje naszych modułów. Po wywołaniu interpreter szuka ich najpierw w zakresie lokalnym, a dopiero później w zakresie globalnym. Problem polega na tym, ze jakiekolwiek szukanie to rozwiązanie mało wydajne. Najlepiej powiedzieć naszemu kochanemu interpreterowi gdzie szukać, zęby nie musiał się za dużo napracować.

Aby to zrobić musimy przekazać naszemu modułowi-zarządcy referencje do modułów, które chcemy wykorzystywać. W dolnym nawiasie przekazujemy referencje do modułów, a w górnym nazwy pod jakimi te moduły Będą dostępne. Popatrzmy na nasz zaktualizowany plik app.js

app.js

Po tym zabiegu nasz kod powinien działać bardziej wydajnie.

Pliki do pobrania

Działający kod przedstawiający przedstawiający przestrzenie nazw w JavaScript symulowane poprzez iterał funkcyjny można pobrać z mojego githuba.
https://github.com/Frodigo/javascript-namespaces

Podsumowanie

W tym artykule pokazałem jak można pisać moduły w JavaScript, dzięki, którym nasza aplikacja będzie odporna na konflikty nazw i łatwiejsza do zrozumienia i zarządzania. Jeśli chcesz aby Twoja aplikacja działała stabilnie i nie była narażona na konflikty nazw to zachęcam do stosowania przedstawionego powyżej wzorca, który skutecznie symuluje przestrzenie nazw w JavaScript

Jeśli masz jakieś pytania to zapraszam do dodania komentarza.

Share on FacebookTweet about this on TwitterShare on LinkedIn