Nehmen wir an, es gibt eine Methode, die Buchautoren nach Buch-ID sucht. Was sollte dieser Methode als Parameter übergeben werden - nur book.id (int) oder ganzes Buchobjekt?
Oder ein anderes Beispiel. In Java muss ich mit der aktuellen URL der Seite arbeiten. Was sollte an solche Methode übergeben werden - nur request.getRequestURL () oder ganze Anfrage?
Ich sehe Vorteile von jeder Methode, kann aber keine gute Regel finden, wann was zu verwenden ist.
Danke.
Ich bin mir nicht sicher, ob es eine "Regel" für das Beste gibt, aber ich gebe meistens nur die Parameter, die ich brauche, an die Methode weiter. In Ihrem ersten Beispiel würde ich nur die book.id übergeben und in Ihrem zweiten Beispiel würde ich nur die request.getRequestURL () übergeben.
Ich versuche zu vermeiden, dass ich mehr hereinbringe, als ich brauche.
Ich werde ein Abweichler sein und dafür eintreten, dass ich das gesamte Buchobjekt weitergeben werde.
Grund 1: Typprüfung. Wenn Sie nur eine Integer-ID übergeben, gibt es keine Möglichkeit, Code zu sehen, wenn Sie die richtige "Art" der Integer-ID haben. Vielleicht haben Sie eine Ganzzahlvariable übergeben, von der Sie denken, dass sie die Buch-ID ist, aber es ist tatsächlich die Autoren-ID. Der Compiler wird Ihnen nicht helfen, diesen Fehler zu finden, und die Ergebnisse werden auf unerwartete Weise fehlerhaft sein.
Grund 2: Zukunftssicherheit. Einige haben das Argument gemacht, dass wenn Sie nur die ID übergeben, Sie die Option geben, die Struktur des Book-Objekts später zu ändern, ohne die doSomethingWithBook (int ID) -Methode zu brechen. Und das stimmt. Auf der anderen Seite, wenn Sie das gesamte Buch-Objekt übergeben, geben Sie sich selbst die Möglichkeit, die Interna von doSomethingWithBook (Buch Buch) zu ändern (vielleicht wird es auf der Grundlage eines anderen Feldes in der Zukunft suchen wollen), ohne eine der ( möglicherweise zahlreiche) Orte, die du doSomethingWithBook genannt hast. Ich würde argumentieren, dass Letzteres dir mehr hilft.
Im Fall der Anfrage würde ich eine andere Antwort geben, da ich ein Request-Objekt als eng mit einer bestimmten Art von Schnittstelle (Web) verbunden betrachten würde und daher die Verwendung dieses Objekts einschränken möchte. Eine Frage, die ich mir gerne selbst stelle: Wenn ich diese Webanwendung in eine Befehlszeilenanwendung umwandeln möchte, wie viele Klassen müssten sich ändern? Wenn ich den Request übergebe, "infiziert" das mehr Klassen mit webspezifischer Logik.
Schwächere Konnektivität wird bevorzugt, es sei denn, es gibt spezielle Gründe. Wenn Sie die Buch-ID nur an die Suchmethode übergeben, können Sie die Buch-Schnittstelle ändern, ohne befürchten zu müssen, dass sie sich auf andere Funktionen auswirkt. Zu einem späteren Zeitpunkt werden Sie vielleicht feststellen, dass Sie genau den gleichen Job mit einer URL außerhalb des Request-Handlers ausführen müssen, um unnötige Abhängigkeit von der Anfrage zu vermeiden. Beachten Sie jedoch, dass, wenn Sie häufig do_smth(request.getRequestURL())
aufrufen, es ziemlich nervig werden kann.
Dies steht im Zusammenhang mit dem Demeter-Gesetz , das grundsätzlich besagt, dass Objekte und Methoden nur genau das erhalten sollen, was sie brauchen anstatt durch ein anderes Objekt zu gehen, um das zu bekommen, was sie wirklich brauchen. Wenn Sie mehrere Felder aus einem Book
in Ihrer Methode verwenden müssen, ist es möglicherweise besser, ein Buch zu nehmen. Aber im Allgemeinen haben Sie weniger Kopplung in einem System, wenn Sie nur auf genau das angewiesen sind, was Sie brauchen.
In beiden Beispielen wäre wahrscheinlich nur die Verwendung der ID oder URL vorzuziehen. Besonders im Fall der URL, wo (wenn Sie die Methode testen möchten) es leicht ist, eine URL zum Testen zu erstellen, aber schwieriger (und völlig unnötig), um eine Anfrage an die Methode zu senden, die dann nur die URL verwendet sowieso. Die Methode wird auch allgemeiner auf andere Situationen als diejenige angewendet, in der Sie ein Anfrageobjekt haben.
Ich würde jeder Methode nur so viel wie nötig geben (also für die zweite Frage: gib ihr einfach request.getRequestURL()
).
Für den ersten würde ich über die Definition beider Methoden nachdenken (aber bevorzugen Sie id
-one, da Sie leicht die ID bekommen können, wenn Sie ein Buch haben, aber nicht umgekehrt).
(Hinweis: Dies ist eine abweichende Ansicht bezüglich der akzeptierten Antwort.)
Nun, es gibt eine implizite Regel im Kontext der Domänenmodellierung. Wenn der Empfänger Aufgaben ausführt, die vom Domänenmodell unabhängig sind, übergeben Sie das Feld. Andernfalls sollten Sie das Objekt übergeben, und die modellspezifische Aktion wird durch den Zugriff des Empfängers auf die ID-Eigenschaft des Objekts 'Buch' explizit gemacht. Am wichtigsten ist jedoch, dass, wenn der Zugriff auf die Eigenschaft jemals über das Zurückgeben der Referenz eines Felds hinausgeht (z. B. bestimmte Aktionen im Eigenschaftenaccessor), Sie NICHT unbedingt alle Instanzen in Ihrem Code verfolgen möchten, in denen Sie die Eigenschaft dereferenziert haben, bevor Sie sie an verschiedene Methoden übergeben .
Weitere Überlegungen sind die Konsequenzen (falls vorhanden) des Zugriffs auf das Feld vor dem Aufruf oder im Empfänger.
Es gibt eigentlich keine Regel, Sie sollten mit den Informationen, die Sie benötigen, einfach sein, in diesem Fall die book.id. Wenn Sie in Betracht ziehen, Ihre Suche in der Zukunft zu erweitern oder zu teilen, können Sie eine überladene Methode zum Akzeptieren eines Buchobjekts verwenden, so dass Sie nach anderen Attributen des Buchobjekts suchen können.
Denken Sie darüber nach, den Code auf lange Sicht zu pflegen. Jede Methode, die Sie bereitstellen, ist eine Methode, die Sie für zukünftige Benutzer unterstützen müssen. Wenn bookId alles ist, was für die vorhersehbare Zukunft benötigt wird, dann würde ich einfach nur das weitergeben: Auf diese Weise kann jeder, der eine bookId hat, Ihre Methode verwenden, und sie wird mächtiger.
Aber wenn es eine gute Chance gibt, dass Sie die Suche möglicherweise umstrukturieren müssen, um einige andere Attribute von Book zu verwenden, geben Sie Buch ein.
Ich stimme den vorherigen Plakaten zu. Ich wollte hinzufügen, dass, wenn Sie mehrere Eigenschaften des Objekts (ID, Titel, Autor) benötigen, dann würde ich empfehlen, das Objekt (oder eine Schnittstelle zu dem Objekt) zu übergeben. Kurze Parameterlisten sind im Allgemeinen vorzuziehen.
Nehmen wir an, es gibt eine Methode, die Buchautoren nach Buch-ID sucht. Was sollte dieser Methode als Parameter übergeben werden - nur book.id (int) oder ganzes Buchobjekt?
Ich gehe davon aus, dass "Buchautoren" ein Attribut eines Buches sind. Daher stelle ich mir so etwas wie die folgende Klasse vor:
%Vor% Bei einem instanziierten Buchobjekt ( aBook
) würde ich, um die Liste der Autoren zu bestimmen, erwarten, dass ich aBook.getAuthors()
aufrufen kann, was keine Parameter erfordert.
Ich würde von der Erstellung von teilweise instanziierten Domänenobjekten abraten. Mit anderen Worten, mit einem bookid
und nach einer Liste von Autoren suchend, würde der Client-Code eher so aussehen:
und weniger so:
%Vor% Die erste Version reduziert die Anzahl der wegwerfbaren Objekte, die vom Client-Code erstellt werden. (In diesem Fall bookQuery
, was kein echtes Buch ist.)
Es macht auch den Code leichter zu lesen - und daher zu pflegen. Dies liegt daran, dass bookQuery
nicht das tut, was der Wartungsprogrammierer erwarten würde. Zum Beispiel würde ich erwarten, dass zwei Bücher mit derselben ID die gleiche Title, Autoren, ISBN usw. haben. Diese Behauptungen würden für bookQuery
und aBook
fehlschlagen.
Drittens minimiert es die Wahrscheinlichkeit, dass Sie eines Tages ein ungültiges (teilweise instanziiertes) Buchobjekt an eine Methode übergeben, die ein echtes Buch erwartet. Dies ist ein Fehler, bei dem der Fehler (in der Methode) weit entfernt von der Ursache (der partiellen Instanziierung) auftreten kann.