Methoden gegen globale Variablen parametrisieren

10

Ich habe eine sehr einfache Frage, die mich schon eine Weile verfolgt, als mein Code zu wachsen beginnt.

Sollten Parameter durch globale Variablen ersetzt werden, wenn sie lange Wege verschachtelter Funktionsaufrufe durchlaufen?

Ich verstehe, dass die globale Umgebung den Status eines Programms unvorhersehbar machen kann, da viele Funktionen gemeinsam genutzte Variablen ändern können, aber der globale Raum die Dinge so einfach macht.

Lassen Sie mich erklären:

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.
}

Ersetzt durch:

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

Ich bin der Meinung, dass der zweite Weg so viel Freiheit beim Programmieren bietet, weil sich Parameter leicht ansammeln können und manchmal auch sehr einschränkend sein können, wenn Code wiederverwendet werden muss, aber gleichzeitig habe ich das Gefühl, dass die Funktion ihre Modularität verliert, wenn sie sich auf eine Variable bezieht in der globalen Umgebung auch die Wiederverwendbarkeit verlieren, wenn ich zum Beispiel finallyDoSomethingWithXmit einer anderen Variablen arbeiten möchte, die anders ist als diese globalX.

Ich denke, das passiert mir, weil ich eigentlich keine Entwurfsmuster verwende, weil ich in Javascript programmiere, was sich für mich wie eine Ein-Skript-Umgang-mit-All-Sprache für mittlere Projekte anfühlt.

Irgendwelche Ratschläge? Muster? Ich kann bei Bedarf genauer sein.

AFP_555
quelle
5
Wenn Sie Variablen sehr tief übergeben, haben Sie das Problem normalerweise nicht richtig gelöst. Vermeiden Sie globale Variablen, die den Zustand an anderer Stelle im System bestimmen, wie die Pest. Es ist unmöglich, an einem bestimmten Punkt zu verwalten, und Sie werden feststellen, dass Dinge zufällig brechen, weil ein Zustand durch eine Funktion mutiert ist, die Sie nicht zufällig erwartet haben.
mgw854
Vermeiden Sie es wie die Pest. Verstanden. Könnten Sie etwas näher auf "Sie haben das Problem nicht richtig aufgelöst" näher eingehen. Ich verstehe die allgemeine Idee, aber ich kann mir kein Beispiel oder etwas einfallen lassen, um sie wirklich zu verstehen.
AFP_555
2
Wenn Sie Argumente übergeben, die viele Ebenen tief sind, können Sie häufig ein Methodenobjekt erstellen : ein Objekt einer neuen Klasse, dessen Methoden den Funktionen entsprechen, die die Parameter weitergeben. Die Parameter können dann zu objektlokalen Variablen werden, und ihre Methoden müssen die Werte nicht mehr weitergeben.
Kilian Foth
@ KilianFoth Danke. Könnten Sie bitte einen Code ausarbeiten, damit ich die Antwort überprüfen kann?
AFP_555
1
Behandeln Sie die Struktur Ihres JavaScript-Codes wie in anderen Sprachen (z. B. solchen, die "echte" Klassen verwenden). Einige nützliche Links zu dieser verwandten Frage auf SO: stackoverflow.com/questions/927651/…
Ben Cottrell

Antworten:

7

Verwenden Sie keine globalen Variablen.

Übergeben Sie Parameter auch nicht an Funktionsketten!

Es ist schwierig, weil Sie kein aktuelles Beispiel verwenden. Aber normalerweise wird es einen besseren Ansatz geben.

Nehmen wir an, wir haben eine Passwortvariable, mit der wir apis aufrufen müssen, die von verschiedenen Funktionen auf niedriger Ebene verwendet werden.

Globaler Ansatz (Psudo-Code)

var pass;

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

Parameterübergabeansatz

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

Objektansatz

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

    function Multiply(a,b) {
        api.Multiply(a,b); //uses pass from constructor
    }
}
Ewan
quelle
Hervorragend. Auf diese Weise befindet sich pass nicht in der globalen Umgebung und ist auch kein Parameter für mehrere Funktionen, da er aus den Attributen des Objekts entnommen werden kann. Vielen Dank.
AFP_555
3

Vermeiden Sie Globale wie die Pest.

Jeder Code kann einen globalen Code ändern. Wenn Sie also eine Kette A (x) -> B (x) -> C (x) -> ... -> Z (x) hatten und x in einem globalen X speichern und jetzt eine Kette A- haben > B-> C -> ...-> Z, dann könnte bei jedem einzelnen Schritt dieser langen Kette oder in völlig unabhängigem Code jemand X ändern. Und der Wert, den Z verwendet, könnte sich völlig von dem Wert unterscheiden, den A. begann mit.

Es ist ein Albtraum, wenn Sie jemals sicher sein möchten, dass Ihr Code das tut, was er tun soll, oder dass er das tut, was Sie denken.

gnasher729
quelle
1
Stimme voll und ganz zu. Wenn Sie Globale verwenden, um Ihr Problem zu lösen, haben Sie jetzt zwei Probleme.
Caleb Mauer