2010-05-05 2 views
6

Die meisten Programme, die ich schreibe, sind relativ flussdiagrammfähige Prozesse mit einem definierten Start und einem erhofften Ende. Die Probleme selbst können komplex sein, neigen jedoch nicht zu einer zentralen Verwendung von Objekten und einer ereignisgesteuerten Programmierung. Oft stoße ich einfach durch große, verschiedenartige Chargen von Textdaten, um verschiedene Textdaten zu erzeugen. Nur gelegentlich muss ich eine Klasse erstellen: Um beispielsweise Warnungen, Fehler und Debugmeldungen zu verfolgen, habe ich eine Klasse (Probleme) mit einer Instanziierung (myErr) erstellt, von der ich glaube, dass sie ein Beispiel für das Singleton-Entwurfsmuster ist . Als weiteren Faktor sind meine Kollegen eher altschulisch (prozedural) als ich und sind mit der objektorientierten Programmierung nicht vertraut, so dass ich es verabscheue Dinge zu schaffen, die sie nicht durchspielen konnten.Beschreiben Sie Ihre Probleme mit der Minimierung der Verwendung globaler Variablen

Und doch höre ich immer wieder, wie sogar das Singleton Design Pattern wirklich ein Anti-Pattern ist und vermieden werden sollte, weil Globale Variablen schlecht sind.

Geringfügige Funktionen brauchen nur wenige Argumente, die an sie weitergegeben werden und müssen nicht von Konfiguration (unveränderlich) oder Programmstatus (Änderung) wissen - ich stimme zu. Die Funktionen in der Mitte der Kette, die hauptsächlich den Programmablauf steuern, benötigen jedoch eine große Anzahl von Konfigurationsvariablen und einige Programmstatusvariablen. Ich glaube, ein Dutzend oder mehr Argumente an eine Funktion weiterzugeben ist eine "Lösung", aber kaum eine attraktive. Ich könnte natürlich Variablen in ein einzelnes Hash/dict/assoziatives Array stopfen, aber das scheint zu betrügen.

Zum Beispiel die Verbindung mit dem Active Directory, um ein neues Konto zu erstellen, brauche ich solche Konfigurationsvariablen wie ein administrativer Benutzername, ein Kennwort, eine Ziel-OU, einige Standardgruppen, eine Domäne usw. Ich würde diese Argumente übergeben müssen Durch eine Vielzahl von Funktionen, die sie nicht einmal verwenden würden, mische man sie einfach durch eine Kette herunter, die schließlich zu der Funktion führen würde, die sie tatsächlich benötigt.

Ich würde zumindest die Konfigurationsvariablen als konstant erklären, um sie zu schützen, aber meine Sprache der Wahl dieser Tage (Python) bietet keine einfache Möglichkeit, dies zu tun, obwohl Rezepte als Workarounds existieren.

Zahlreiche Fragen zum Stack-Overflow sind auf das Warum gekommen? von der Schlechtigkeit und der notwendigen Meidung, aber nicht oft erwähnen Tipps zum Leben mit dieser quasi-religiösen Einschränkung. Wie haben Sie das Problem der globalen Variablen und des Programmstatus gelöst oder zumindest geschlossen? Wo haben Sie Kompromisse gemacht? Was sind deine Tricks gewesen, abgesehen davon, dass du die Herden von Argumenten zu Funktionen schubst?

+0

Gute Frage - kategorisieren Sie Variablen auf Klassenebene (Mitglied) als globale Variablen? –

Antwort

5

Ich denke, dass es eine Zeit und einen Ort für das Singleton-Muster oder ähnliche Situationen gibt. Der wichtigste Punkt, an den man sich erinnern sollte, ist, dass viele Menschen immer wieder besonderen Horror erlebt haben, wenn es um die "falsche" Entscheidung geht, globale/geteilte/statische Variablen sowie das Singleton-Muster zu verwenden.

In Ihrem Fall sprechen Sie über Konfiguration speziell. Ich sehe kein Problem darin, ein Singleton-Stilmuster für den Zugriff auf diese Konfigurationselemente zu verwenden. Jede Anwendung hat eine Konfiguration, sie SOLLTE sich an einem Ort befinden, den Sie anrufen können, es gibt keine Notwendigkeit, sie einfach weiterzugeben, das macht mehr kompliziert als es hilft.

Der Schlüssel hier ist, um sicherzustellen, dass Sie wirklich brauchen, dass die Informationen nur einmal existieren, Konfiguration ist bei weitem einer der besten Gründe, die ich gefunden habe, diese Art von Muster zu verwenden.

3

Globale Daten, die sich nicht ändern oder wohldefinierte, prozessweite Objekte (z. B. Protokollierung) sind im Allgemeinen OK, um als globale Daten zu verwenden. Konfigurationsdaten, insbesondere wenn sie in einer lokalen Datei gespeichert sind, fallen unter die gleiche Kategorie (es gibt nur eine Datei für den gesamten Prozess/die Anwendung, ähnlich der Protokollierung).

Wenn Sie im Allgemeinen finden, dass Sie zusätzliche Argumente übergeben müssen, um sie an eine andere Funktion zu übergeben, sollten Sie diese Funktion "nach oben" ziehen und eine andere haben, die vermittelt. Ein anderer, praktischerer Ansatz, der dies veranschaulicht, ist die testgetriebene Entwicklung, da Sie gezwungen sind, Abhängigkeiten zu übergeben. Eine andere Art darüber nachzudenken ist: Wenn diese Funktion nicht alle Details leicht kennt, um eine Unterfunktion aufzurufen, ziehen Sie die Unterfunktion nach oben und zwingen Sie eine höhere, besser erkennbare Schicht, um die benötigte zu erhalten Information. Ich habe herausgefunden, dass diese Technik sehr gut für die Codequalität geeignet ist, da sie kompartimentierte Teile anstelle von monolithischen Biestern erzeugt.

In Ihrem Beispiel über Active Directory, anstatt auf die ad_connect um die Argumente vorbei, um ein Objekt übergeben, die die notwendige Logik übernimmt, müssen dann eine Funktion, die die Interaktion zwischen dem Objekt und der Funktion ihm

mit vermittelt
def create_user(name, ad_user, ad_pass, ad_ou, ...): 
    conn = ad_connect(ad_user, ad_pass, ...) 
    conn.CreateRecord(ad_user) 

def create_user_mediator(name, ad_controller): 
    ad_controller.CreateRecord("cn=%s" % name) 

Das ist nur eine Möglichkeit, und es hat natürlich seine Vor- und Nachteile. Es ist nur ein Beispiel dafür, wie create_user vermeiden kann, globale Variablen zu verwenden.