Gott-Objekt - Reduziere die Kopplung zu einem 'Master'-Objekt

8

Ich habe ein Objekt mit dem Namen Parameter, das von Methode zu Methode über die Paketgrenzen hinweg in den Aufrufbaum geworfen wird. Es hat ungefähr fünfzig Zustandsvariablen. Jede Methode verwendet möglicherweise eine oder zwei Variablen, um ihre Ausgabe zu steuern.

Ich denke, das ist eine schlechte Idee, weil ich nicht leicht sehen kann, was eine Methode braucht, um zu funktionieren, oder was mit einer bestimmten Kombination von Parametern für Modul Y passieren könnte, die nichts mit meinem aktuellen Modul zu tun hat / p>

Was sind einige gute Techniken, um die Kopplung mit diesem Gottobjekt zu verringern oder es idealerweise zu eliminieren?

%Vor%

Der Anrufer würde tun:

%Vor%     
Andrei Tanasescu 16.10.2009, 20:24
quelle

6 Antworten

9

Erstens, auf die Gefahr hin, das Offensichtliche zu sagen: Übergeben Sie die Parameter, die von den Methoden verwendet werden, und nicht das Gott-Objekt.

Dies kann jedoch dazu führen, dass einige Methoden große Mengen an Parametern benötigen, weil sie andere Methoden aufrufen, die wiederum andere Methoden aufrufen usw. Das war wahrscheinlich die Inspiration, alles in ein Gottobjekt zu legen. Ich werde ein vereinfachtes Beispiel für eine solche Methode mit zu vielen Parametern geben; du musst dir das "zu viele" == 3 hier vorstellen :-)

%Vor%

Die Frage ist also, wie können wir die Anzahl der Parameter reduzieren, ohne auf ein Gott-Objekt zurückzugreifen? Die Antwort ist, prozedurale Programmierung loszuwerden und objektorientiertes Design zu nutzen. Objekte können sich gegenseitig verwenden, ohne die Parameter kennen zu müssen, mit denen ihre Mitarbeiter initialisiert wurden:

%Vor%

Jetzt kann die FilteredReportPrinter.Print-Methode mit nur einem Parameter implementiert werden:

%Vor%

Übrigens ist diese Art der Trennung von Bedenken und Abhängigkeitsinjektion mehr als nur die Eliminierung von Parametern. Wenn Sie über Schnittstellen auf Collaborator-Objekte zugreifen, macht dies Ihre Klasse

  • sehr flexibel: Sie können FilteredReportPrinter mit jeder Filter- / Druckerimplementierung einrichten, die Sie sich vorstellen können
  • sehr überprüfbar: Sie können Schein-Mitarbeiter mit vordefinierten Antworten übergeben und sicherstellen, dass sie in einem Komponententest korrekt verwendet wurden
Wim Coenen 17.10.2009, 02:16
quelle
1

Wenn alle Ihre Methoden dieselbe Parameters -Klasse verwenden, dann sollte es vielleicht eine Membervariable einer Klasse mit den entsprechenden Methoden sein, dann können Sie Parameters in den Konstruktor dieser Klasse übernehmen und zuweisen Eine Membervariable und alle Ihre Methoden können sie verwenden, um sie als Parameter übergeben zu müssen.

Ein guter Weg, um mit der Umgestaltung dieser Gottklasse zu beginnen, ist es, sie in kleinere Teile aufzuteilen. Finden Sie Gruppen von Eigenschaften, die miteinander verwandt sind, und teilen Sie sie in ihre eigene Klasse auf.

Sie können dann die Methoden erneut aufrufen, die von Parameters abhängen, und sehen, ob Sie sie durch eine der kleineren Klassen ersetzen können, die Sie erstellt haben.

Es ist schwierig, eine gute Lösung ohne einige Codebeispiele und reale Situationen zu finden.

    
Ryu 16.10.2009 20:34
quelle
0

Es klingt, als ob Sie keine objektorientierten (OO) Prinzipien in Ihrem Design anwenden. Da Sie das Wort "Objekt" erwähnen, nehme ich an, dass Sie innerhalb einer Art OO-Paradigma arbeiten. Ich empfehle Ihnen, Ihren "Aufrufbaum" in Objekte umzuwandeln, die das Problem modellieren, das Sie lösen. Ein "Götterobjekt" ist definitiv etwas, das man vermeiden sollte. Ich denke, dass Sie etwas Grundlegendes vermissen ... Wenn Sie einige Codebeispiele veröffentlichen, kann ich in der Lage sein, detaillierter zu antworten.

    
SingleShot 16.10.2009 20:37
quelle
0

Fragen Sie jeden Client nach seinen erforderlichen Parametern und injizieren Sie diese?

Beispiel: Jedes "Objekt", das "Parameter" benötigt, ist ein "Client". Jeder "Client" stellt eine Schnittstelle zur Verfügung, über die ein "Configuration Agent" den Client nach seinen erforderlichen Parametern fragt. Der Konfigurationsagent "injiziert" dann die Parameter (und nur diejenigen, die von einem Client benötigt werden).

    
jldupont 16.10.2009 20:26
quelle
0

Für die Parameter, die das Verhalten diktieren, kann ein Objekt instanziiert werden, das das konfigurierte Verhalten aufweist. Dann verwenden Clientklassen einfach das instanziierte Objekt - weder der Client noch der Dienst müssen wissen, wie der Wert des Parameters ist. Zum Beispiel für einen Parameter, der angibt, wo Daten gelesen werden sollen, haben FlatFileReader, XMLFileReader und DatabaseReader die gleiche Basisklasse geerbt (oder implementieren dieselbe Schnittstelle). Instanziieren Sie eine von ihnen basierend auf dem Wert des Parameters, dann fragen Clients der Leserklasse einfach nach Daten zum instanziierten Leserobjekt, ohne zu wissen, ob die Daten aus einer Datei oder aus der Datenbank stammen.

Zum Starten können Sie Ihre große Parame- tresExecution-Klasse in mehrere Klassen zerlegen, eine pro Paket, die nur die Parameter für das Paket enthält.

Eine andere Richtung könnte sein, das Parame- tresExecution-Objekt zur Konstruktionszeit zu übergeben. Sie müssen es nicht bei jedem Funktionsaufruf weitergeben.

    
philant 17.10.2009 09:23
quelle
-2

(Ich gehe davon aus, dass dies in einer Java- oder .NET-Umgebung geschieht.) Konvertieren Sie die Klasse in einen Singleton. Fügen Sie eine statische Methode namens "getInstance ()" oder etwas ähnliches zum Aufruf hinzu, um das Name-Wert-Bündel zu erhalten (und stoppen Sie es "herumzutrampeln" - siehe Kapitel 10 des "Code Complete" -Buchs).

Jetzt der schwierige Teil. Vermutlich ist dies innerhalb einer Web-App oder einer anderen Nicht-Batch / Single-Thread-Umgebung. Um Zugriff auf die richtige Instanz zu erhalten, wenn das Objekt nicht wirklich ein echter Singleton ist, müssen Sie die Auswahllogik innerhalb des statischen Accessors verstecken.

In Java können Sie eine lokale "Thread-Referenz" einrichten und sie initialisieren, wenn jede Anfrage oder Unteraufgabe beginnt. Codieren Sie dann den Accessor in Bezug auf diesen thread-local. Ich weiß nicht, ob in .NET etwas Analoges existiert, aber Sie können es immer mit einem Dictionary (Hash, Map) fälschen, das die aktuelle Thread-Instanz als Schlüssel verwendet.

Es ist ein Anfang ... (es gibt immer eine Dekomposition des Blobs selbst, aber ich habe ein Framework erstellt, das einen sehr ähnlichen halb-globalen Wertspeicher enthält)

    
Roboprog 16.10.2009 20:37
quelle

Tags und Links