Gesetz des Demeter - Datenobjekte

8

Ich versuche dem Gesetz von Demeter zu folgen (siehe Ссылка , Ссылка ) wie ich die Vorteile sehen kann, jedoch bin ich ein wenig festgefahren, wenn es um Domain-Objekte geht.

Domänenobjekte haben natürlich eine Kette und manchmal müssen die Informationen über die gesamte Kette angezeigt werden.

Zum Beispiel ein Einkaufskorb:

Jede Bestellung enthält einen Benutzer, Lieferinformationen und eine Liste von Artikeln Jede Bestellposition enthält ein Produkt und eine Menge Jedes Produkt hat einen Namen und einen Preis. Jeder Benutzer enthält einen Namen und eine Adresse

Der Code, der die Bestellinformationen anzeigt, muss alle Informationen über die Bestellung, Benutzer und Produkte verwenden.

Sicherlich ist es besser und wiederverwendbarer, diese Information durch das Auftragsobjekt zu erhalten, z. "order.user.address.city" als für einen Code, der höher ist, um Abfragen für alle oben aufgelisteten Objekte durchzuführen, diese dann separat in den Code zu übertragen?

Alle Kommentare / Vorschläge / Tipps sind willkommen!

    
Tom B 05.09.2012, 14:44
quelle

5 Antworten

8

Ein Problem bei der Verwendung von verketteten Verweisen wie order.user.address.city besteht darin, dass Abhängigkeiten höherer Ordnung in die Struktur von Code außerhalb der Klasse "hineingebacken" werden.

Im Idealfall sollten Ihre "erzwungenen Änderungen" in den Fällen, in denen Sie Ihre Klasse umgestalten, auf die Methoden der zu refaktorierenden Klasse beschränkt sein. Wenn Sie im Client-Code mehrere verkettete Verweise haben, führt das Refactoring dazu, dass Sie Änderungen an anderen Stellen Ihres Codes vornehmen.

Betrachten Sie ein Beispiel: Angenommen, Sie möchten User durch eine OrderPlacingParty ersetzen, eine Abstraktion, die Benutzer, Firmen und elektronische Agenten einkapselt, die eine Bestellung aufgeben können. Dieses Refactoring führt sofort zu mehreren Problemen:

  • Die Eigenschaft User wird anders benannt und hat einen anderen Typ
  • Die neue Eigenschaft darf kein address haben, das city hat, wenn der Auftrag von einem elektronischen Agenten erteilt wird
  • Der mit der Bestellung verknüpfte Mensch User (angenommen, Ihr System benötigt einen aus rechtlichen Gründen) kann indirekt mit der Bestellung in Verbindung stehen, z. B. indem er in der Definition von% co_de als Zielperson fungiert %.

Eine Lösung für diese Probleme wäre, der Bestellungslogik alles, was sie benötigt, zu übergeben, anstatt die Struktur der übergebenen Objekte "verstehen" zu müssen. Auf diese Weise könnten Sie die Änderungen am Code lokalisieren refaktorisiert werden, ohne die Änderungen auf anderen potenziell stabilen Code zu verteilen.

%Vor%     
dasblinkenlight 03.12.2012, 18:03
quelle
2

Ich denke, wenn die Verkettung verwendet wird, um auf eine Eigenschaft zuzugreifen, geschieht dies in zwei (oder mindestens zwei) verschiedenen Situationen. Zum Beispiel haben Sie in Ihrem Präsentationsmodul erwähnt, dass Sie ein Auftrag -Objekt haben und nur die Adresse des Eigentümers / Benutzers oder Details wie Stadt anzeigen möchten. In diesem Fall denke ich, dass es kein großes Problem ist, wenn Sie das tun. Warum? Weil Sie keine Geschäftslogik für die aufgerufene Eigenschaft ausführen, was (möglicherweise) eine enge Kopplung verursachen kann.

Aber die Dinge sind anders, wenn Sie eine solche Verkettung verwenden, um eine Logik in der Eigenschaft, auf die zugegriffen wird, auszuführen. Zum Beispiel, wenn Sie haben,

%Vor%

Das ist problematisch. Weil diese Logik in einem Modul, das näher an dem Zielattribut city liegt, geeigneter ist / sollte. Zum Beispiel an einer Stelle, an der das Address-Objekt zuerst aufgebaut wird, oder wenn nicht, zumindest dann, wenn das User-Objekt konstruiert wird (wenn User beispielsweise die Entity ist und den Value-Typ adressiert). Aber wenn es weiter geht, je weiter es geht, desto unlogischer und problematischer wird es. Weil es zu viele Zwischenhändler zwischen der Quelle und dem Ziel gibt.

Wenn Sie also nach dem Demeter-Gesetz eine Logik für das Attribut "city" in einer Klasse ausführen, sagen Sie OrderAssmebler , das auf das city-Attribut in einer kettenähnlichen Reihenfolge zugreift. user.address.city, dann sollten Sie daran denken, diese Logik an einen Ort / ein Modul zu verschieben, der näher am Ziel liegt.

    
Nazar Merza 01.12.2012 17:04
quelle
1

Sie haben Recht, und Sie werden wahrscheinlich Ihre Wertobjekte so modellieren

%Vor%

Wenn Sie anfangen zu überlegen, wie Sie diese Daten in einer Datenbank speichern (zB ORM ), fangen Sie an zu denken über die Leistung. Denken Sie daran, dass Sie gegen das Verlieren von Eager vs Lazy tauschen.

    
Brad 05.09.2012 15:09
quelle
1

Generell halte ich mich an das Demeter-Gesetz, da es hilft, Änderungen in einem reduzierten Umfang zu halten, so dass sich eine neue Anforderung oder ein Bugfix nicht überall auf Ihrem System ausbreitet. Es gibt andere Entwurfsrichtlinien, die in dieser Richtung helfen, z. die in diesem Artikel aufgeführten. Nachdem ich das gesagt habe, betrachte ich das Gesetz von Demeter (sowie Design Patterns und andere ähnliche Sachen) als hilfreiche Designrichtlinien, die ihre Kompromisse haben und dass Sie sie brechen können, wenn Sie das für richtig halten. Zum Beispiel teste ich im Allgemeinen nicht private Methoden , hauptsächlich weil es erstellt fragile Tests . In einigen sehr speziellen Fällen habe ich jedoch eine private Objektmethode getestet, weil ich sie in meiner App als sehr wichtig erachte, da ich weiß, dass dieser bestimmte Test Änderungen unterliegt, wenn sich die Implementierung des Objekts ändert. Natürlich müssen Sie in solchen Fällen besonders vorsichtig sein und mehr Dokumentation für andere Entwickler hinterlassen, die erklären, warum Sie das tun. Aber am Ende müssen Sie Ihr gutes Urteilsvermögen verwenden:).

Nun zurück zur ursprünglichen Frage. Soweit ich verstehe, ist Ihr Problem hier das Schreiben der (Web?) GUI für ein Objekt, das die Wurzel eines Graphen von Objekten ist, auf die über Nachrichtenketten zugegriffen werden kann. Für diesen Fall würde ich die GUI auf ähnliche Weise modularisieren, wie Sie Ihr Modell erstellt haben, indem Sie für jedes Objekt Ihres Modells eine Ansichtskomponente zuweisen. Als Ergebnis haben Sie Klassen wie OrderView , AddressView usw., die wissen, wie Sie HTML für ihre jeweiligen Modelle erstellen. Sie können dann diese Ansichten erstellen, um Ihr endgültiges Layout zu erstellen, entweder indem Sie die Verantwortung an sie delegieren (z. B. die OrderView erstellt die AddressView ) oder indem Sie eine Mediator , der sich darum kümmert, sie zu komponieren und mit Ihrem Modell zu verknüpfen. Als Beispiel für den ersten Ansatz könnte man so etwas haben (ich verwende PHP für das Beispiel, ich weiß nicht, welche Sprache Sie verwenden):

%Vor%

und dann die Ansichten:

%Vor%

und in deiner view.php würdest du so etwas machen wie:

%Vor%

Dieser Ansatz basiert auf einem Komponentenmodell, bei dem die Ansichten als zusammensetzbare Komponenten behandelt werden. In diesem Schema respektieren Sie die Grenzen des Objekts und jede Ansicht hat eine einzige Verantwortung.

Bearbeiten (Hinzugefügt basierend auf dem OP-Kommentar)

Ich nehme an, dass es keine Möglichkeit gibt, die Ansichten in Unteransichten zu organisieren, und dass Sie die Warenkorb-ID, das Bestelldatum und den Benutzernamen in einer einzigen Zeile darstellen müssen. Wie ich in dem Kommentar gesagt habe, würde ich für diesen Fall sicherstellen, dass der "schlechte" Zugriff an einem einzigen, gut dokumentierten Ort ausgeführt wird, der die Ansicht nicht beachtet.

%Vor%

Wenn Sie später Ihr Domänenmodell neu anordnen und Ihre ShoppingBasket -Klasse die getUser() -Nachricht nicht mehr implementieren kann, müssen Sie einen einzelnen Punkt in Ihrer Anwendung ändern. Vermeiden Sie, dass diese Änderung auf Ihr gesamtes System verteilt wird.

HTH

    
Andrés Fortier 28.11.2012 20:25
quelle
0

Das Demeter-Gesetz behandelt Methoden aufzurufen, nicht auf Eigenschaften / Felder zuzugreifen. Ich weiß, dass technisch Eigenschaften Methoden sind, aber logisch sind sie Daten. Also, Ihr Beispiel von order.user.address.city scheint mir gut zu sein.

Dieser Artikel ist interessant in der weiteren Lektüre: Ссылка

    
TarkaDaal 03.12.2012 15:25
quelle

Tags und Links