In unserer Delphi 2007-Anwendung verwenden wir viele der folgenden Konstrukte
FdmBasic:=TdmBasicData(FindOwnerClass(AOwner,TdmBasicData));
Die FindOwnerClass wandert die Eigentümerhierarchie der aktuellen Komponente nach oben, um eine bestimmte Klasse zu finden (im Beispiel TdmBasicData). Das resultierende Objekt wird in der Feldvariablen FdmBasic gespeichert. Wir verwenden dies hauptsächlich, um Datenmodule weiterzugeben.
Beispiel: Beim Generieren eines Berichts werden die resultierenden Daten komprimiert und in einem Blob-Feld einer Tabelle gespeichert, auf die über ein Datenmodul TdmReportBaseData zugegriffen wird. In einem separaten Modul unserer Anwendung gibt es Funktionen zum Anzeigen der Daten aus dem Bericht in einer Seitenform mit ReportBuilder. Der Hauptcode dieses Moduls (TdmRBReport) verwendet eine Klasse TRBTempdatabase, um die komprimierten Blob-Daten in verschiedene Tabellen zu konvertieren, die im Reportbuilder-Laufzeit-Reportdesigner verwendet werden können. TdmRBReport hat Zugriff auf TdmReportBaseData für alle Arten von berichtbezogenen Daten (Berichtstyp, Berichtsberechnungseinstellungen usw.). TRBTempDatabase wird in TdmRBReport erstellt, muss jedoch Zugriff auf TdmReportBasedata haben. Dies geschieht nun mit der obigen Konstruktion:
constructor TRBTempDatabase.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
FdmReportBaseData := TdmRBReport(FindOwnerClass(Owner, TdmRBReport)).dmReportBaseData;
end;{- .Create }
Mein Gefühl ist, dass dies bedeutet, dass TRBTempDatabase viel von seinem Besitzer kennt, und ich habe mich gefragt, ob dies eine Art Codegeruch oder Anti-Pattern ist.
Was denkst du darüber? Ist das ein Code-Geruch? Wenn ja, was ist ein besserer Weg?
quelle
Antworten:
Diese Art von sieht aus wie ein Service Locator Pattern, das zuerst von Martin Fowler beschrieben wurde (das als allgemeines Anti-Pattern identifiziert wurde).
Die konstruktionsbasierte Abhängigkeitsinjektion wird einem Service Locator vorgezogen, da sie die Sichtbarkeit der erforderlichen Parameter fördert und das Testen von Einheiten vereinfacht.
Vor allem verstößt es auch gegen das Gesetz von Demeter
Der bessere Weg
Tatsächlich ist es besser, den Service Locator-Aufruf innerhalb der Klasse zu entfernen und den richtigen Eigentümer als Parameter innerhalb des Konstruktors zu übergeben. Selbst wenn dies bedeutet, dass Sie eine Serviceklasse haben, die eine Besitzersuche durchführt und diese dann an den Klassenkonstruktor übergibt
quelle
As a simple example, when one wants to walk a dog, it would be folly to command the dog's legs to walk directly; instead one commands the dog and lets it take care of its own legs.
Eine der Schwierigkeiten, wenn untergeordnete Objekte zu viel über die Eltern wissen, besteht darin, dass Sie am Ende Muster implementieren, die (und meistens) zu eng gekoppelt werden können, was zu großen Abhängigkeitskopfschmerzen führt und später oft sehr schwierig zu ändern und sicher zu warten ist später.
Abhängig davon, wie eng Ihre beiden Klassen miteinander verbunden sind, klingt es ein bisschen so, als ob Fowlers Beschreibung des Feature Envy oder unangemessene Intimacy-Code-Gerüche offensichtlich sind.
Es scheint notwendig zu sein, eine Klasse mit Daten zu laden oder zu lesen. In diesem Fall können Sie eine Reihe alternativer Muster verwenden, um die Abhängigkeit zwischen dem Kind und seiner Elternkette zu lösen, und es scheint, als müssten Sie die Zugriffsaufgabe delegieren Ihre Datenklasse, anstatt die Datenzugriffsklasse dafür verantwortlich zu machen, dass alles selbst erledigt wird.
quelle