Zarządzanie kodem javascript w projekcie

Zarządzanie kodem javascript w projekcie

W ostatnim czasie zaliczyłem mały “powrót do przeszłości” ponownie wkraczając na ścieżkę freelancer-a, co więc za tym idzie znacząco zwiększyła mi się różnorodność projektów nad którymi pracuje lub w których “maczam palce”.  Z tego wszystkiego udało mi się wysnuć pewną zadziwiającą i niestety bolesną konkluzję, mianowicie, ludzie nadal nie potrafią/nie chcą się nauczyć, jak zarządzać kodem JS-a. Szkoda, bo sztuka ta nie należy do najtrudniejszych, wystarczy trzymać się paru prostych zasad…

Nie mieszaj widoku z kodem javascript

Miejscem javascript-u jest nie szablon (html, phtml, tpl czy inne cudo), a zewnętrzny plik zakończony końcówką “js”. Można go umieścić z innymi zasobami niezbędnymi do prawidłowego funkcjonowania naszej strony/portalu, np obok zewnętrznych bibliotek. By łatwiej go później zlokalizować można nadać mu nazwę która w naturalny sposób będzie sugerowała, że to tutaj będzie można znaleźć całą naszą magię. Za popularne nazwy można przyjąć np.  ”scripts”, “app”, “main”.

Używaj komentarzy/przypisów

Umieszczenie javascriptu w osobnym pliku znacząco podnosi jego czytelność, jednakże może powodować problemy z odnalezieniem docelowej części szablonu do której się odnosi. Naturalnym rozwiązaniem są w tym przypadku komentarze, choćby w formie <sciezka_do_pliku>:<linijka_w_kodzie>. Ich dopisanie nie zajmuje wiele czasu, a znacznie uprzyjemni modyfikację kodu gdy wrócimy do projektu po pewnym czasie. Wdzięczne powinny być również osoby, które do prac dołączą później, takie rozwiązanie uratuje ich przed rozczytywaniem się w setkach lini HTML-a przy poszukiwaniach zaginionego elementu.  Poniżej przykład jak to może wyglądać.

$(document).ready(function (){
    //\application\views\scripts\index\index.phtml:59
    var $search = $('input.search'),
        $searchBtn = $('button.search'),
    //\application\views\scripts\index\index.phtml:65
        $searchList = $('div.search-list');
    $searchBtn.on('click', function (e) {
        e.preventDefault();
        $.get(
            "/search/search/",
            {
                'query': $search.val()
            }
        ).success(
            function (resp) {
                $searchList.empty();
                $searchList.append(resp);
            }
        );
        return false;
    });
});

Cache’uj selektory

Każdorazowe wyszukiwanie elementu w DOM kosztuje! Jeżeli zamierzamy skorzystać z jakiegoś selektora więcej niż raz, najlepiej zrobić to już na samym początku, a znaleziony element przypisać do zmiennej i to z niej korzystać przy następnych wywołaniach. Przykład możemy znaleźć w kodzie zamieszczonym powyżej, linijki 3,4 oraz 6.

Wydziel podobną funkcjonalność i umieść ją w osobnych modułach

Wydzielenie kodu js do oddzielnego pliku to dopiero początek, przy mniejszych projektach może nawet wystarczający. Jednak w momencie kiedy jego ilość zaczyna gwałtownie wzrastać, warto zastanowić się nad podzieleniem kodu według funkcjonalności. W momencie kiedy uda nam się to wszystko poukładać zabierzemy się za stworzenie modułu, co samo w sobie nie jest niczym trudnym. Zaczynamy od utworzenia katalogu (“<katalog_główny_projektu>/js/helpers/“) oraz pliku (powiedzmy, że w naszym przypadku “search.js“), przygotowujemy szkielet, a następnie wypełniamy  go naszym kodem. Ostatecznie załączamy jeszcze nowo utworzony skrypt tak jak robiliśmy to z innymi plikami “js” i inicjalizujemy moduł w miejscu gdzie wcześniej znajdował się nasz kod.  Jak to powinno wyglądać postaram się przedstawić poniżej.

Przyjmijmy, że w pliku “main.js” znajduje się kod zaprezentowany we wcześniejszych przykładach. Postanowiliśmy go wydzielić i stworzyć z niego moduł, który przechowywany będzie w “search.js”. Zaczynamy od paru linijek kodu, które traktować powinniśmy jako szablon:

// tworzymy nową przestrzeń tak aby uniknąć nadpisywania zmiennych globalnych
// przekazujemy referencje do obiektu okna (window)
// a jako drugi parametr podajemy własność undefined dzięki czemu
// nawet jeżeli znajdzie się szaleniec gotów nadpisać te zmienne
// nie wpłynie to na działanie naszego kodu
(function (window, undefined) {
    // odpalamy tryb "strict", dodatek wprowadzony do specyfikacji ECMA5 wymuszaja
    // na nas przestrzeganie pewnych zasad oraz wyłącza
    // mniej lub bardziej niestabilne i/lub przestarzałe funkcje
    "use strict"
    // w tym miejscu możemy zadeklarować prywatne zmienne lub
    // dołożyć funkcje widoczne tylko w tej przestrzeni
    // nastęnie deklarujemy nasz moduł
    var searchHelper = {
        //ta funkcja będzie inicjalizować całość
        init: function () {
        },
        //tutaj (gdy będzie to przydatne) będziemy dodawać stałe
        _const: {
        }
    };
    // na końcu wyeksportujemy jeszcze moduł do przeglądarki
    window.search = searchHelper;
}(window));

by później dodać już właściwy kod:

(function (window, undefined) {
    "use strict"
    /**
     * zaczynamy od deklaracji samych zmiennych
     */
    var $search,
        $searchBtn,
        $searchList;

    /**
     * tworzymy funkcje w której przypiszemy referencje elementów do zmiennych
     */
    function bindElements() {
        //\application\views\scripts\index\index.phtml:59
        $search = $('input.search');
        $searchBtn = $('button.search');
        //\application\views\scripts\index\index.phtml:65
        $searchList = $('div.search-list');
    }

    /**
     * oraz funkcje w której podepniemy event'y
     */
    function bindEvents() {
        $searchBtn.on('click', onSearchBtnClick);
    }

    /**
     * funkcja wywoływana w momencie kliknięcia na przycisk "search"
     * @param e
     * @returns {boolean}
     */
    function onSearchBtnClick(e) {
        e.preventDefault();
        $.get(
            "/search/search/",
            {
                'query': $search.val()
            }
        ).success(
            function (resp) {
                $searchList.empty();
                $searchList.append(resp);
            }
        );
        return false;
    }
    var searchHelper = {
        init: function () {
            bindElements();
            bindEvents();
        },
        _const: {
        }

    };
    window.search = searchHelper;
}(window));

Ostatecznie tak jak pisaliśmy na wstępie, inicjalizujemy jeszcze moduł w naszym głównym skrypcie (“main.js”):

$(document).ready(function () {
    //odpalamy nasz moduł
    search.init();
});

I to wszystko, nasz kod przybrał teraz całkowicie inną, znacznie czytelniejszą i bardziej ustrukturyzowaną formę.

Komentarze:

Zostaw odpowiedź

Proszę wypełnij wymagane pola aby dodać komentarz.


Drag circle to the rectangle on the right!

Wyślij