Wie zu gehorchen Gesetz von Demeter?
Jedes mal, wenn ich Artikel über das Gesetz von Demeter, der Autor scheint nie zu geben, ein solides Beispiel dafür, wie, dieses Gesetz zu befolgen. Sie alle erklären, was es ist, und zeigen ein Beispiel für das Gesetz brechen, aber das ist einfach.
Gibt es wahrscheinlich viele Möglichkeiten, dieses Gesetz zu befolgen (gute design und Planung als einer), aber in sehr einfachen Worten würde dies ein Weg sein, ihm zu gehorchen?
Sagen wir, ich habe eine Klasse mit folgenden Eigenschaften:
public class Band {
private Singer singer;
private Drummer drummer;
private Guitarist guitarist;
}
Bin ich irgendwo im Programm, und ich habe eine Instanz dieser Band
Klasse und ich wollen die Gitarristen namens, was ich in der Regel sehen, ist so etwas wie:
guitaristName = band.getGuitarist().getName();
Dass man gar nicht so schlecht scheint, wie es ist, nicht zu tief in die Kette, aber ist das Gesetz von Demeter zu sagen, dass vielleicht sollte es auf diese Weise getan:
guitaristName = band.getGuitaristName();
und meine Band
Klasse hat eine Methode:
public String getGuitaristName() {
return guitarist.getName();
}
Ist dies, wie Sie sollen, dem Gesetz zu gehorchen?
Dank.
- Einige würden sagen, dass das hinzufügen einer
getGuitaristName
MethodeBand
wäre gegen das Gesetz von Demeter: haben Sie gezwungenBand
Kenntnis von der Struktur derGuitarist
. Das schafft ein design Abhängigkeit, wo keine existiert haben mögen, bevor. Es ist alles eine Frage der Perspektive, denke ich. - Diese Menschen würden falsch sein. Die LoD nicht verhindern, dass
Band
aus senden von Anfragen anGuitarists
da er bereits darüber weiß. Es einfach verhindert, dass Benutzer vonBand
Zugriff aufGuitarists
direkt, da die Nutzer vonBand
sollte nicht wissen über seine Interna - Also würden Sie sagen, was ich gemacht habe oben mit der
getGuitaristName()
Methode ist eine gültige Art und Weise, dieses Gesetz zu befolgen? Zumindest dann, wenn die Objekt-Graphen sind nicht zu groß wie oben. - Ist das wahr; in der Tat, die Verbreitung solcher Verfahren in den Klassen wie
Band
ist zitiert als einer der Nachteile des LoD. Meine Ansicht, jedoch, ist, dass, während eine solche Umgestaltung passt zu dem Buchstaben des Gesetzes, es ist in direkter Verstoß gegen den Geist des Gesetzes. (Warum sollteBand
Objekt wissen müssen, dass einGuitarist
hat eineString
-Wert name-Attribut?) Aus der Perspektive des Designs, der Struktur einerGuitarist
ist nicht wirklich Teil des "tiefen-Struktur" einerBand
. - Das zitieren von Wikipedia: "ein bestimmtes Objekt übernehmen sollten so wenig wie möglich über die Struktur oder Eigenschaften von etwas anderem (einschließlich deren Teilkomponenten)"---Hervorhebung von mir.
- Ich bin geneigt zu, einverstanden mit, die Sie auf diese Methode (und andere wie es), wo Sie haben im wesentlichen 'codiert' der internen Objekt-Typ in den Namen der Methode. Es ist ein cheat um die strenge definition von LoD
- Also das bedeutet, dass ein
getGuitaristName
Methode ist nicht die beste Wahl, aber das bedeutet dann, ich habe zu tungetGuitarist.getName()
. Ich weiß, dass die Kette nicht zu tief ist, aber was ist, wenn ich wollte, dass seine Gitarre machen also wäreband.getGuitarist().getGuitar().getMake()
. Ich weiß wirklich nicht, wie das Aussehen von diesem, es scheint zu lange. - David, besser Lesen meine Antwort. Das war eine Randnotiz, unter der Annahme der Prämisse, dass das gesamte Gespräch ist sinnvoll, ich denke, das ist es nicht.
- Im Fall von
band.getGuitarist().getGuitar().getMake()
, die Frage ist, ob die Gitarre (und der Gitarre selbst) ist ausschließlich eine Eigenschaft der Gitarrist ist, oder ob es eine Eigenschaft von "der Gitarrist in dieser band". Meiner Ansicht nach ist es vernünftiger zu erweitern, dieBand
Schnittstelle im letzteren Fall als in der ehemaligen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie nicht anwenden LoD auf der entsprechenden Ebene: beide
Band
undGuitarist
sollte als ein Teil des gleichen Moduls und das dilemma, das Sie haben, wird entschieden, auf dem Gelände der maximalen Bequemlichkeit.Ihre Frage ist ein Beispiel für ein viel größeres problem, dem ich Häufig begegnet, in Büchern über design patterns und ähnlich: Sie versuchen zu erklären, weitreichende Grundsätze, die sich auf den Entwurf eines komplexen Systems, auf lächerlich unterdimensioniert Probleme. Das Ergebnis ist einfach nur Leser Verwirrung.
Wo würden Sie tatsächlich sehen, dieses Prinzip in der Tat ist so etwas wie dieses: Sie sind mit
AsyncHttpClient
, das ist eine Abstraktion, die aufNetty
, das ist eine Abstraktion, die auf Java NIO. Nun, wennAsyncHttpClient
's API Zwang Sie, an einem Ort zu verwalten direkt ein Java-NIO-Objekt, dessen API ist viel mehr roh, und befasst sich mit Konzepten komplett FremdAsyncHttpClient
, das wäre ein Beispiel für das brechen LoD.Ich finde die Idee des Gesetzes ist, wie Dancrumb sagt oben, um sicherzustellen, dass die Menschen den Zugriff auf Objekte auf der entsprechenden Ebene.
Vorstellen, dass unsere
Band
Klasse Modelle die Rezeption der band und die Büros. Es hat die Aufgabe als PA für die band-Mitglieder & befassen sich mit jedermann, das will, um die Interaktion mit der band.Nun sagen wir, wir hatten eine tour promoter von einer PR-Firma, die will, um zusammen einige PR-material für Ihre nächste tour. Wir könnten ihm Modell mit einer Klasse:
Im wirklichen Leben, ist dies gleichbedeutend mit dem tour-Veranstalter Klingeln bis der Büro & zu sagen:
Es genügt zu sagen, dass die PA würde gefeuert ziemlich schnell. Die meisten vernünftigen Leute würden Fragen: "Konnten Sie nicht gelöst haben, dieser Anruf für uns?"
Konnten wir eine
getGuitaristsName()
Methode, die technisch Ehren das Gesetz von Demeter, aber wir sind immer noch Fragen unsereTourPromoter
Klasse zu erinnern, Einzelheiten über die band — also, dass Sie einen Gitarristen — in der Erwägung, dass diese information sollte wirklich gehören zu der band selbst.Um sicherzugehen, dass wir die Einführung von Methoden in einer sinnvollen Art und Weise, wir müssen schauen, was die tour-Veranstalter eigentlich freuen — also die Namen aller band-Mitglieder. Wenn wir das Modell, die Methode im code, es gibt uns mehr Flexibilität, um änderungen an der
Band
später auf, ohne auch nur zu berührenTourPromoter
:Wenn wir jetzt hinzufügen, ein Bassist oder wundervollen Keyboardspieler, nur die Band Klasse, Bedürfnisse, den Unterschied zu kennen & der Tour-Veranstalter nicht ändern müssen. Dies bedeutet, dass wir nun auch die Ehrung der Prinzip der Einzigen Verantwortung zu — d.h. unsere
makePosterText()
Methode nur ändern muss, wenn wir ändern unsere poster-format, nicht wenn sich das band ändert.Ich glaube nicht, dass das Gesetz von Demeter wird Ihnen sagen, welche Methode, die Sie brauchen, um zu ziehen aus, um das Prinzip in der besten Weise (z.B.
getMembers()
eher alsgetGuitaristsName()
oben) & so, ich glaube, Sie haben Recht — es zeigt Ihnen, wenn etwas kaputt sind, aber nicht unbedingt, wie Sie zu beheben. Mit dem LoD im Hinterkopf, obwohl, bedeutet, dass Sie ein Auge heraus für Verstöße, die können dann behoben werden, durch eine Kombination von anderen design-Prinzipien, wie SRP.getBandMemberInfo
das gibt einenCollection<BandMemberInfo>
woBandMemberInfo
ist eine Schnittstelle implementiert, Sänger, Schlagzeuger und Gitarristen, die hat Getter (aber keine setter) für name, instrument, Bild, Biografie und alles was sonst noch benötigt wird, um info-material über die band. Aber ich denke, dass dein Beispiel schon erklärt es ziemlich gut.Das Gesetz von Demeter selbst nicht anwesend Methodik für die gute Nachfrage. Am besten, es ist eine hilfreiche Heuristik für die Identifikation von potenziell problematischen Bereiche des Codes. Abweichungen vom Gesetz können alscode smell'
Es kann die Tendenz haben, erweitern die Schnittstellen der Klassen, da es Ergebnisse im proxy oder wrapper-Methoden, um Ihnen den Zugang zu Eigenschaften, die im Besitz von den internen Objekten. Als Ergebnis, Ihrer Vorteile sollte ausgewogen sein, gegen die Nachteile (potentiell erstellen unhandlich Klassen und module).
Ist es am besten angewandt, als Instrument zur Identifizierung von code auf die Umgestaltung. Allerdings, ein einfacher swap von Methoden aus
zu
ist nach den Buchstaben des Gesetzes, ohne den Geist (Dank an @TedHopp für diesen Punkt). Stattdessen sollten Sie sich in das, was die Nutzer versuchen, zu tun, wenn Sie pierce
a
's Abstraktion umx
'sfoo
und definieren Sie die Methode entsprechend. Es kann nicht eine triviale Aufgabe, aber das ist, warum wir bezahlt, das große Geld 🙂Ich würde eine Band, die eine Antwort auf die Frage, wer dieses instrument zu spielen?
Dann, wenn Sie brauchen einen Gitarristen-Namen, die Sie würde sagen:
Nichts hält Sie Ping für andere Instrumente auch.