Metody parametryzacji a zmienne globalne

10

Mam bardzo proste pytanie, które prześladuje mnie od jakiegoś czasu, gdy mój kod zaczyna się powiększać.

Czy parametry powinny być zastępowane zmiennymi globalnymi, gdy przechodzą przez długie trasy zagnieżdżonych wywołań funkcji?

Rozumiem, że środowisko globalne może sprawić, że stan programu jest nieprzewidywalny, ponieważ wiele funkcji może modyfikować wspólne zmienne, ale globalna przestrzeń sprawia, że ​​wszystko jest takie proste.

Pozwól mi wyjaśnić:

functionA(){
   x = something
   functionB(x)
}
functionB(x){
   functionC(x)
}
functionC(x){
   finallyDoSomethingWithX(x)
}
finallyDoSomethingWithX(x){
  x += 1 //Very dummy example ignoring pass by value, not reference.
}

Zastąpione przez:

globalX;
functionA(){
   globalX = something
   functionB()
}
...
...
...
finallyDoSomethingWithX(){
   globalX += 1
}

Wydaje mi się, że drugi sposób daje tyle swobody w programowaniu, ponieważ parametry mogą się łatwo kumulować, a czasami mogą być bardzo ograniczające, gdy kod musi być ponownie użyty, ale jednocześnie mam wrażenie, że funkcja straci swoją modułowość, gdy jest powiązana ze zmienną w środowisku globalnym, tracąc także możliwość ponownego użycia, gdy na przykład chcę operować finallyDoSomethingWithXinną zmienną niż ta globalX.

Wydaje mi się, że tak się dzieje, ponieważ tak naprawdę nie używam wzorców projektowych, ponieważ programuję w języku JavaScript, co dla mnie wydaje się być językiem jednego skryptu dla wszystkich średnich projektów.

Jakieś porady? wzory? W razie potrzeby mogę być bardziej szczegółowy.

AFP_555
źródło
5
Zazwyczaj, jeśli przekazujesz zmienne bardzo głęboko, problem nie został rozwiązany poprawnie. Jeśli chodzi o zmienne globalne prowadzące stan gdzie indziej w systemie, unikaj go jak zarazy. W pewnym momencie nie można sobie poradzić, a znajdziesz rzeczy, które psują się losowo, ponieważ pewien stan jest mutowany przez funkcję, której nie spodziewałeś się losowo.
mgw854
Unikaj tego jak zarazy. Zrozumiany. Czy mógłbyś bardziej szczegółowo rozwinąć kwestię „nie rozwiązałeś poprawnie problemu”. Rozumiem ogólną ideę, ale nie mogę wymyślić żadnego przykładu ani czegoś, co mogłoby to naprawdę zrozumieć.
AFP_555
2
Powszechnym lekarstwem na argumenty o głębokości wielu warstw jest utworzenie obiektu metody : obiektu nowej klasy, którego metody odpowiadają funkcjom przekazującym parametry. Parametry mogą następnie stać się zmiennymi lokalnymi dla obiektu, a jego metody nie muszą już przekazywać wartości.
Kilian Foth
@KilianFoth Thanks. Czy mógłbyś opracować kod, abym mógł sprawdzić odpowiedź?
AFP_555
1
Zastanów się nad traktowaniem struktury kodu JavaScript tak, jak w innych językach (takich jak te, które używają „prawdziwych” klas). Kilka przydatnych linków do tego pokrewnego pytania na SO: stackoverflow.com/questions/927651/…
Ben Cottrell 15'17

Odpowiedzi:

7

Nie używaj zmiennych globalnych.

Nie przekazuj również parametrów w dół łańcuchów funkcji!

Jest to trudne, ponieważ nie podajesz rzeczywistego przykładu. Ale zwykle będzie lepsze podejście.

Powiedzmy, że mamy zmienną hasła, której musimy użyć, aby wywołać api, które są używane przez różne funkcje niskiego poziomu.

Podejście globalne (kod psudo)

var pass;

function multiply(a,b) {
   return apiMultiply(pass,a,b);
}

Podejście do przekazywania parametrów

function multiply(a,b,pass) {
    return apiMultiply(pass,a,b);
}

Podejście obiektowe

class math {
    var api;
    constructor(pass) {
        api = new api(pass);
    }

    function Multiply(a,b) {
        api.Multiply(a,b); //uses pass from constructor
    }
}
Ewan
źródło
Doskonały W ten sposób przekazanie nie odbywa się w środowisku globalnym, a także nie jest parametrem funkcji múltiple, ponieważ można go pobrać z atrybutów obiektu. Dzięki.
AFP_555
3

Unikaj globali jak zarazy.

Każdy kod może modyfikować globalny. Więc jeśli miałeś łańcuch A (x) -> B (x) -> C (x) -> ... -> Z (x), i zapisujesz x w globalnym X, a teraz masz łańcuch A- > B-> C -> ...-> Z, a następnie na każdym kroku tego długiego łańcucha lub w całkowicie niezależnym kodzie ktoś może zmienić X. A wartość, której używa Z, może być zupełnie inna niż wartość A zaczął od.

To koszmar, jeśli kiedykolwiek chcesz mieć pewność, że Twój kod robi to, co powinien, lub że robi to, co myślisz.

gnasher729
źródło
1
Kompletnie się zgadzam. Jeśli używasz globałów do rozwiązania problemu, teraz masz dwa problemy.
Caleb Mauer