Warum sind globale Variablen böse? [geschlossen]

121

Ich versuche herauszufinden, warum die Verwendung von globalin Python (und in der Programmierung im Allgemeinen) als schlechte Praxis angesehen wird. Kann jemand erklären? Links mit mehr Infos wären ebenfalls willkommen.

LarsVegas
quelle
Abstimmung zur Wiedereröffnung - Ich habe die Frage bearbeitet, um den Fokus auf Erklärungen und weg von externen Ressourcen zu verlagern. (Ich gehe davon aus dem ist , warum es geschlossen war, aber nur für den Fall , es ist etwas mit dem Sein eine Frage zu schlechter Praxis, zu vergleichen , diese Fragen zu schlechter Praxis zu tun , die noch offen sind: eval, import *, String - Verkettung , variableid , Attribut Schatten )
wjandrea

Antworten:

156

Dies hat nichts mit Python zu tun. Globale Variablen sind in jeder Programmiersprache schlecht.

Globale Konstanten sind jedoch konzeptionell nicht mit globalen Variablen identisch . globale Konstanten sind vollkommen harmlos. In Python erfolgt die Unterscheidung zwischen den beiden rein konventionell: CONSTANTS_ARE_CAPITALIZEDund globals_are_not.

Der Grund, warum globale Variablen schlecht sind, besteht darin, dass Funktionen versteckte (nicht offensichtliche, überraschende, schwer zu erkennende, schwer zu diagnostizierende) Nebenwirkungen haben, die zu einer Zunahme der Komplexität führen und möglicherweise zu Spaghetti-Code führen .

Eine vernünftige Verwendung des globalen Zustands ist jedoch akzeptabel (ebenso wie der lokale Zustand und die Veränderlichkeit), selbst bei der funktionalen Programmierung, entweder zur Algorithmusoptimierung, zur Reduzierung der Komplexität, zum Zwischenspeichern und zur Memoisierung oder zur praktischen Anwendbarkeit von Portierungsstrukturen, die aus einer überwiegend imperativen Codebasis stammen.

Alles in allem kann Ihre Frage auf viele Arten beantwortet werden. Am besten googeln Sie einfach "Warum sind globale Variablen schlecht?". Einige Beispiele:

Wenn Sie tiefer gehen und herausfinden möchten, warum es um Nebenwirkungen und viele andere aufschlussreiche Dinge geht, sollten Sie die funktionale Programmierung lernen:

Erik Kaplun
quelle
35

Ja, theoretisch sind Globale (und "Staat" im Allgemeinen) böse. In der Praxis werden Sie feststellen, dass die meisten Module dort mit einer Reihe globaler Deklarationen beginnen, wenn Sie in das Paketverzeichnis Ihres Pythons schauen. Offensichtlich haben die Leute kein Problem mit ihnen.

Speziell für Python ist die Sichtbarkeit von Globals auf ein Modul beschränkt, daher gibt es keine "echten" Globals, die das gesamte Programm betreffen - das macht sie weniger schädlich. Ein weiterer Punkt: Es gibt keine const. Wenn Sie also eine Konstante benötigen, müssen Sie eine globale verwenden.

Wenn ich in meiner Praxis ein globales Element in einer Funktion ändere, deklariere ich es immer mit global, auch wenn dies technisch nicht erforderlich ist, wie in:

cache = {}

def foo(args):
    global cache

    cache[args] = ...

Dies erleichtert das Aufspüren der Manipulationen von Globals.

georg
quelle
3
In vielerlei Hinsicht ähnelt ein Modul in Python einer Singleton-Klasse, und Modul-Globals ähneln Klasseneigenschaften.
Corley Brigman
9
@ CorleyBrigman: Singleton-Klassen leiden tatsächlich oft unter den gleichen Problemen, die normalerweise Globals zugeschrieben werden :)
Erik Kaplun
4
Die Sichtbarkeit von Python-Modulen ist nicht auf ein Modul beschränkt. Sie sind im gesamten Interpreter verfügbar, und (hier ist das Wichtigste) Änderungen dort wirken sich auf den gesamten Interpreter aus. Es ist nicht wie eine Zeichenfolge, die Sie Instanzen erstellen ... es ist wie das Ändern aller Zeichenfolgeninstanzen. Affenflicken Geruch.
Graffic
2
Die meisten Module beginnen nicht mit der Definition von Globalen außer Konstanten. Globale sind schlecht bedeutet Variablen / globaler Zustand, keine Konstanten.
BlackJack
2
Die Verwendung von Globals ist eine schreckliche Idee. Ein Grund könnte die Unfähigkeit sein, Funktionen, die ein beliebiges Wörterbuch aktualisieren, das "irgendwo" existiert, ordnungsgemäß zu testen. Eine Codebasis mit Globalen kann nicht als funktionsfähig erwiesen werden.
Tomasz Sosiński
10

Eine persönliche Meinung zu diesem Thema ist, dass die Verwendung globaler Variablen in einer Funktionslogik bedeutet, dass ein anderer Code die Logik und die erwartete Ausgabe dieser Funktion ändern kann, was das Debuggen sehr schwierig macht (insbesondere in großen Projekten) und das Testen erschwert auch.

Wenn Sie andere Personen berücksichtigen, die Ihren Code lesen (Open-Source-Community, Kollegen usw.), fällt es ihnen außerdem schwer zu verstehen, wo die globale Variable festgelegt wird, wo sie geändert wurde und was von dieser globalen Variablen im Gegensatz zu erwarten ist zu einer isolierten Funktion, deren Funktionalität durch Lesen der Funktionsdefinition selbst bestimmt werden kann.

(Wahrscheinlich) Verstoß gegen die Definition der reinen Funktion

Ich glaube, dass ein sauberer und (fast) fehlerfreier Code Funktionen haben sollte, die so rein wie möglich sind (siehe reine Funktionen ). Eine reine Funktion hat folgende Bedingungen:

  1. Die Funktion wertet immer den gleichen Ergebniswert bei gleichen Argumentwerten aus . Der Funktionsergebniswert kann weder von versteckten Informationen oder Zuständen abhängen, die sich während der Programmausführung oder zwischen verschiedenen Programmausführungen ändern können, noch von externen Eingaben von E / A-Geräten (normalerweise - siehe unten).
  2. Die Auswertung des Ergebnisses verursacht keine semantisch beobachtbaren Nebenwirkungen oder Ausgaben , wie z. B. die Mutation veränderlicher Objekte oder die Ausgabe an E / A-Geräte.

Wenn globale Variablen vorhanden sind, wird mindestens einer der oben genannten Punkte verletzt, wenn nicht beide als externer Code zu unerwarteten Ergebnissen führen können.

Eine weitere klare Definition von reinen Funktionen: "Die reine Funktion ist eine Funktion, die alle ihre Eingaben als explizite Argumente verwendet und alle ihre Ausgaben als explizite Ergebnisse erzeugt ." [1] . Globale Variablen zu haben, verstößt gegen die Idee reiner Funktionen, da eine Eingabe und möglicherweise eine der Ausgaben (die globale Variable) nicht explizit angegeben oder zurückgegeben wird.

(Wahrscheinlich) Verstoß gegen Unit-Testing FIRST-Prinzip

Weiter , dass, wenn Sie Unit-Test und dem ersten Prinzip überlegen ( F ast Tests I ndependent Tests, R epeatable, S Elf-Validieren und T imely) wird verletzen wahrscheinlich die Unabhängige Prinzip testet (was bedeutet , dass Tests hängt nicht auf einander).

Eine globale Variable zu haben (nicht immer), aber in den meisten Fällen (zumindest was ich bisher gesehen habe) besteht darin, Ergebnisse vorzubereiten und an andere Funktionen weiterzugeben. Dies verstößt ebenfalls gegen dieses Prinzip. Wenn die globale Variable auf diese Weise verwendet wurde (dh die in Funktion X verwendete globale Variable muss zuerst in einer Funktion Y gesetzt werden), bedeutet dies, dass Sie für die Einheitentestfunktion X zuerst die Test- / Ausführungsfunktion Y ausführen müssen.

Globale als Konstanten

Andererseits und wie bereits erwähnt, kann es etwas besser sein, wenn die globale Variable als "konstante" Variable verwendet wird, da die Sprache keine Konstanten unterstützt. Ich arbeite jedoch immer lieber mit Klassen und habe die "Konstanten" als Klassenmitglied und verwende überhaupt keine globale Variable. Wenn Sie einen Code haben, den zwei verschiedene Klassen benötigen, um eine globale Variable gemeinsam zu nutzen, müssen Sie wahrscheinlich Ihre Lösung umgestalten und Ihre Klassen unabhängig machen.

Ich glaube nicht, dass Globals nicht verwendet werden sollten. Wenn sie jedoch verwendet werden, sollten die Autoren einige Prinzipien (die oben genannten vielleicht und andere Prinzipien und bewährte Methoden der Softwareentwicklung) für einen saubereren und nahezu fehlerfreien Code berücksichtigen.

Rafael
quelle
1
Ich mag die "Globale als Konstanten sind ein Problem" ... denn wenn Sie OO-Design machen ... ist es wirklich so. Warum muss jemand außer der IdCreator-Klasse die ID_LEN kennen?
Erik Aronesty
3

Sie sind wichtig, der Bildschirm ist ein gutes Beispiel. In einer Multithread-Umgebung oder mit vielen beteiligten Entwicklern stellt sich in der Praxis jedoch häufig die Frage: Wer hat sie (fälschlicherweise) festgelegt oder gelöscht? Abhängig von der Architektur kann die Analyse kostspielig sein und häufig erforderlich sein. Während das Lesen der globalen Variable in Ordnung sein kann, muss das Schreiben darauf gesteuert werden, beispielsweise durch einen einzelnen Thread oder eine threadsichere Klasse. Daher entstehen bei globalen Vars die Angst vor hohen Entwicklungskosten, die durch die Folgen möglich sind, für die sie selbst als böse gelten. Daher ist es im Allgemeinen empfehlenswert, die Anzahl der globalen Variablen niedrig zu halten.

Horst Schlawutzke
quelle