W naszej aplikacji Delphi 2007 używamy wielu następujących konstrukcji
FdmBasic:=TdmBasicData(FindOwnerClass(AOwner,TdmBasicData));
FindOwnerClass podróżuje w górę hierarchii właściciela bieżącego komponentu w celu znalezienia określonej klasy (w przykładzie TdmBasicData). Powstały obiekt jest przechowywany w zmiennej Field FdmBasic. Używamy tego przede wszystkim do przekazywania modułów danych.
Przykład: podczas generowania raportu dane wynikowe są kompresowane i przechowywane w polu Blob tabeli dostępnej przez moduł danych TdmReportBaseData. W oddzielnym module naszej aplikacji jest funkcjonalność umożliwiająca wyświetlanie danych z raportu w formie stronicowanej przy użyciu ReportBuilder. Główny kod tego modułu (TdmRBReport) wykorzystuje klasę TRBTempdatabase do konwersji skompresowanych danych obiektów blob na różne tabele, które można wykorzystać w narzędziu Reportdesigner środowiska wykonawczego Reportbuilder. TdmRBReport ma dostęp do TdmReportBaseData dla wszystkich rodzajów danych związanych z raportem (rodzaj raportu, ustawienia obliczeń raportów itp.). TRBTempDatabase jest zbudowany w TdmRBReport, ale musi mieć dostęp do TdmReportBasedata. Jest to teraz wykonywane przy użyciu powyższej konstrukcji:
constructor TRBTempDatabase.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
FdmReportBaseData := TdmRBReport(FindOwnerClass(Owner, TdmRBReport)).dmReportBaseData;
end;{- .Create }
Mam wrażenie, że oznacza to, że TRBTempDatabase zna wielu swoich właścicieli i zastanawiałem się, czy to jest jakiś zapach kodu lub anty-wzór.
Co o tym sądzisz? Czy to zapach kodu? Jeśli tak, jaki jest lepszy sposób?
źródło
Odpowiedzi:
Ten rodzaj wygląda jak wzorzec lokalizatora usług, który został po raz pierwszy opisany przez Martina Fowlera (który został zidentyfikowany jako wspólny anty-wzorzec).
Wstrzykiwanie zależności w oparciu o konstrukcję jest preferowane w stosunku do lokalizatora usług, ponieważ promuje widoczność wymaganych parametrów i promuje prostsze testowanie jednostek.
Co najważniejsze, łamie także prawo Demeter
The Better Way
Skutecznie lepszym sposobem jest usunięcie wywołania lokalizatora usług w klasie i przekazanie poprawnego właściciela jako parametru wewnątrz jego konstruktora. Nawet jeśli oznacza to, że masz klasę usług, która wykonuje wyszukiwanie właściciela, a następnie przekazuje to do konstruktora klasy
źródło
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.
Jedną z trudności w tym, że obiekty potomne wiedzą za dużo o rodzicu, jest to, że w końcu wdrażasz wzorce, które mogą (i najczęściej tak robią) być zbyt ściśle powiązane, co powoduje poważne uzależnienia i często później bardzo trudno jest je bezpiecznie modyfikować i utrzymywać później.
W zależności od tego, jak głęboko są połączone dwie klasy, brzmi to trochę tak, jakby były widoczne opisy Fowlera dotyczące cech zazdrości lub nieprzyjemnych zapachów kodu intymności.
Wydaje się, że trzeba załadować lub odczytać klasę z danymi, w którym to przypadku można użyć szeregu alternatywnych wzorców, aby przełamać zależność między dzieckiem a jego łańcuchem rodziców, i wygląda na to, że trzeba przekazać zadanie dostępu twoją klasę danych, zamiast uczynić klasę akcesorów odpowiedzialną za robienie wszystkiego sama.
źródło