Soll ich Schnittstellen für Datenübertragungsobjekte erstellen?
19
Ist es eine gute oder eine schlechte Idee, eine Schnittstelle für Datenübertragungsobjekte zu erstellen? Vorausgesetzt, das Objekt ist normalerweise veränderlich.
Obwohl mein Beispiel in Java ist, sollte es auf jede andere Sprache anwendbar sein, die ähnliche Konzepte hat.
Die allgemeine Antwort lautet " Nein" , da Sie niemals Code hinzufügen sollten, ohne einen bestimmten, konkreten Grund dafür zu haben, und es gibt keinen allgemeinen Grund für eine solche Schnittstelle.
Abgesehen davon kann es manchmal einen guten Grund geben. Aber in allen Fällen, die ich gesehen habe, waren diese Schnittstellen teilweise und deckten nur eine oder einige Eigenschaften ab, die von mehreren Klassen geteilt wurden, die ich polymporphisch verwenden wollte, ohne ihnen eine gemeinsame Superklasse zu geben. Typische Kandidaten sind eine IdEigenschaft, die in einer Art Registrierung verwendet werden soll, oder eine NameEigenschaft, die dem Benutzer angezeigt werden soll. Es kann jedoch in jedem Fall nützlich sein, wenn Sie möchten, dass Code mit allem, was ein X XSourceenthält , umgehen kann. Erstellen Sie einfach eine Schnittstelle, die die getX(und nur bei Bedarf die setX) Methoden enthält.
Aber eine separate Schnittstelle für jede Modellklasse, die alle Eigenschaften enthält? Ich kann mir keinen guten Grund dafür vorstellen. Ein schlechter Grund wäre ein schlecht entworfenes Framework, das dies erfordert. Entity EJBs haben genau das getan, wenn ich mich richtig erinnere. Zum Glück waren sie so schlecht, dass sie nie viel Bodenhaftung erlangten und seit EJB 3.0 veraltet sind
Anmerkung: Vermeiden Sie es, den Begriff "Wertobjekt" zu verwenden, um Java-Beans mit nur trivialen Gettern und Setters zu beschreiben. Dies steht im Widerspruch zur allgemeineren Definition von Wertobjekt als etwas ohne Identität, das normalerweise unveränderlich ist. Ein besserer Begriff wäre DTO oder Modellklasse - obwohl im letzteren Fall anzumerken ist, dass anämische Domänenmodelle als Antipattern betrachtet werden.
"Anämische Domänenmodelle gelten als Antimuster" - von Martin Fowler, der in der PEAA zugibt, dass er Menschen kennt, die jahrzehntelang so "sehr erfolgreich" gearbeitet haben. Ich schlage daher vor, dass weniger ein Anti-Pattern als vielmehr ein Nicht-wie-Fowler-gerne-arbeitet. Trotzdem gute Antwort, +1.
pdr
4
@pdr: Fowler mag den Begriff geprägt haben, aber er ist keineswegs der einzige, der sie als Antimuster ansieht. Ich glaube nicht, dass jemand, der OO wirklich verstanden hat, der Meinung ist, dass es eine gute Idee ist, domänenspezifische Logik aus dem Domänenmodell herauszuhalten.
Michael Borgwardt
Danke für die Termkorrektur, DTO war das Wort, nach dem ich letzte Nacht gesucht habe, aber ich konnte mich nicht an mein Leben erinnern. Durch das Ändern des Namens wurde das Design sinnvoller.
Archimedes Trajano
@pdr Ich denke, der beste Weg, es auszudrücken, ist, dass es ein Antimuster im Kontext der OO-Programmierung ist. Es gibt viele andere Paradigmen, bei denen es vollkommen in Ordnung ist, und Sie könnten auf diese Weise sogar erfolgreich in einer OO-Sprache arbeiten (es wäre einfach nicht besonders objektorientiert).
Daniel B
3
@MichaelBorgwardt: Da stimme ich zu, er ist nicht allein. Aber es gibt auch keine Leute, die anderer Meinung sind. Wenn Sie gesagt hätten, dass "anämische Domänenmodelle von manchen als Antimuster angesehen werden", hätte ich nichts gesagt. Ehrlich gesagt denke ich, dass Ihre gesamte Antwort ohne den letzten Absatz sowieso besser wäre. Die erste Hälfte hätte einen besseren Kommentar abgegeben; Die zweite Hälfte bietet nichts zu dieser Frage.
pdr
2
Das Erstellen der Benutzeroberfläche ist in Ordnung, aber NICHT so, wie Ihr Beispiel funktioniert. Sie sollten den Setter von der Schnittstelle entfernen, und es wird in Ordnung sein:
interfaceValueObject{String getName();};
Dies ermöglicht viele verschiedene Implementierungen davon, wie Name aus der Datenbank abgerufen werden kann ... Setter sollte in verschiedenen Schnittstelle sein.
Schnittstellen definieren einen Vertrag zwischen den Klassen, die die Schnittstellen implementieren, und ihren Clients. Sie werden als Abstraktionsmechanismus verwendet, damit Clients "Dinge mit einem bestimmten Verhalten" manipulieren können.
Die allgemeine Antwort auf die Frage "Soll ich diese Schnittstelle erstellen und verwenden?" ist: Ja, wenn Sie ein (ein einziges) Konzept zuordnen können, das für Ihre Kunden semantisch relevant ist.
Zum Beispiel ist Comparable eine gute Schnittstelle, weil es erklärt, dass Dinge dank einer ihrer Methoden verglichen werden können und ich als Kunde daran interessiert bin, mit vergleichbaren Objekten umzugehen (zB um sie zu sortieren). A contrario, Coolstuff ist keine gute Schnittstelle , wenn Sie die kühlen Objekte zugeben (in der Tat nicht ein bestimmtes Verhalten haben, können Sie eine Software vorstellen , in der mit kühlem Umgang Objekte macht Sinn, weil sie ein gemeinsames Verhalten wie zum Beispiel eines BeCool Methode).
In Ihrem speziellen Fall glaube ich, dass Ihre Schnittstelle unbrauchbar ist. Wer wird es wie und wann nutzen? Sie können nicht für jeden der veränderlichen Werte eine Schnittstelle erstellen. Fragen Sie sich also, welche relevante und interessante Eigenschaft Ihren Methoden zugrunde liegt.
Wenn Sie es mit Objekten zu tun haben möchten, auf die alle ihre veränderlichen Werte mit verschiedenen Methoden zugreifen können, werfen Sie einen Blick auf den Begriff Java Bean und darauf, wie Sie Ihre Klassen dazu zwingen können, ihre Konventionen zu übernehmen.
Wie Michael sagte, fügen Sie keine Schnittstelle hinzu, es sei denn, Sie haben einen bestimmten Bedarf dafür.
Testen ist ein Beispiel für einen guten Grund. Obwohl ich echte Kollaborateure bevorzuge, wenn es sich nur um "Wertobjekte" handelt, wie Sie sie nennen, müssen Sie für eine echte Komponententestisolation möglicherweise ein gefälschtes Objekt zum Testen erstellen. In diesem Fall ist eine Schnittstelle sehr hilfreich.
Schnittstellen waren für die Verwendung von spöttischen Frameworks seit Ewigkeiten nicht mehr erforderlich.
Michael Borgwardt
Klingt so, als würden Sie Monkeypatching befürworten. Ich war mit Moles in C # auf diesem Weg und es ist nicht schön. Besser, wenn möglich, die Mitarbeiter hinzuzuziehen.
Jhewlett
1
Obwohl die beiden Verspottungs-Frameworks, die ich mit Mockito und easyMock verwende, die letzten Klassen nicht verspotten können, wenn sie unveränderlich sind.
Archimedes Trajano
1
Wenn Sie möchten, dass dieses Objekt in Zukunft eine Art Feldvalidierung erhält, sollten Sie sie in einem frühen Stadium einkapseln.
Das 'Interface for Value Object' ist das, was ich benutze, um einen Accessor zu nennen.
Ich habe verschiedene Richtlinien bezüglich der Zugriffsanforderungen erlebt. Einige Leute befürworten, wann immer möglich, andere verbieten, die Menge des zu schreibenden Codes zu reduzieren.
Einige Verweise für Accessoren (oder direkte Verwendung von Werten) lauten wie folgt:
Mit Accessors kann die Art der Wertspeicherung später geändert werden
Accessors ermöglicht das Hinzufügen eines Zugriffsprotokolls, wenn Sie Ihre Software debuggen möchten (wenn Sie einen Protokollaufruf in einer einzelnen Methode hinzufügen, erfassen Sie jede Wertänderung).
Accessoren entsprechen eher der Objektprogrammierung, da jede Variable von Methoden gekapselt wird
Accessors reduzieren die Code-Expressivität (mehr SLOC für das gleiche Ergebnis)
Accessors benötigt etwas CPU
Ich persönlich empfehle, die Anzahl der Accessoren zu verringern und sie zu verwenden, wenn Sie erwarten, dass der Setter (setName) später zu mehr als einer einfachen Beeinträchtigung wird.
Diese Art von Wertobjekt ist ziemlich niedrig. Ich würde vorschlagen, es in eine von zwei Richtungen zu verschieben: (1) das Wertobjekt unveränderlich zu machen, das heißt, wie ein realer Wert , oder (2) die Veränderbarkeit zu einer übergeordneten domänenorientierten Geschäftsfunktion zu erhöhen, was bedeutet, dass wir herausstellen sollten Schnittstellen im Sinne domänenrelevanter Funktionseinheiten.
Das Erstellen der Benutzeroberfläche ist in Ordnung, aber NICHT so, wie Ihr Beispiel funktioniert. Sie sollten den Setter von der Schnittstelle entfernen, und es wird in Ordnung sein:
Dies ermöglicht viele verschiedene Implementierungen davon, wie Name aus der Datenbank abgerufen werden kann ... Setter sollte in verschiedenen Schnittstelle sein.
quelle
Schnittstellen definieren einen Vertrag zwischen den Klassen, die die Schnittstellen implementieren, und ihren Clients. Sie werden als Abstraktionsmechanismus verwendet, damit Clients "Dinge mit einem bestimmten Verhalten" manipulieren können.
Die allgemeine Antwort auf die Frage "Soll ich diese Schnittstelle erstellen und verwenden?" ist: Ja, wenn Sie ein (ein einziges) Konzept zuordnen können, das für Ihre Kunden semantisch relevant ist.
Zum Beispiel ist Comparable eine gute Schnittstelle, weil es erklärt, dass Dinge dank einer ihrer Methoden verglichen werden können und ich als Kunde daran interessiert bin, mit vergleichbaren Objekten umzugehen (zB um sie zu sortieren). A contrario, Coolstuff ist keine gute Schnittstelle , wenn Sie die kühlen Objekte zugeben (in der Tat nicht ein bestimmtes Verhalten haben, können Sie eine Software vorstellen , in der mit kühlem Umgang Objekte macht Sinn, weil sie ein gemeinsames Verhalten wie zum Beispiel eines BeCool Methode).
In Ihrem speziellen Fall glaube ich, dass Ihre Schnittstelle unbrauchbar ist. Wer wird es wie und wann nutzen? Sie können nicht für jeden der veränderlichen Werte eine Schnittstelle erstellen. Fragen Sie sich also, welche relevante und interessante Eigenschaft Ihren Methoden zugrunde liegt.
Wenn Sie es mit Objekten zu tun haben möchten, auf die alle ihre veränderlichen Werte mit verschiedenen Methoden zugreifen können, werfen Sie einen Blick auf den Begriff Java Bean und darauf, wie Sie Ihre Klassen dazu zwingen können, ihre Konventionen zu übernehmen.
quelle
Wie Michael sagte, fügen Sie keine Schnittstelle hinzu, es sei denn, Sie haben einen bestimmten Bedarf dafür.
Testen ist ein Beispiel für einen guten Grund. Obwohl ich echte Kollaborateure bevorzuge, wenn es sich nur um "Wertobjekte" handelt, wie Sie sie nennen, müssen Sie für eine echte Komponententestisolation möglicherweise ein gefälschtes Objekt zum Testen erstellen. In diesem Fall ist eine Schnittstelle sehr hilfreich.
quelle
Wenn Sie möchten, dass dieses Objekt in Zukunft eine Art Feldvalidierung erhält, sollten Sie sie in einem frühen Stadium einkapseln.
quelle
Das 'Interface for Value Object' ist das, was ich benutze, um einen Accessor zu nennen.
Ich habe verschiedene Richtlinien bezüglich der Zugriffsanforderungen erlebt. Einige Leute befürworten, wann immer möglich, andere verbieten, die Menge des zu schreibenden Codes zu reduzieren.
Einige Verweise für Accessoren (oder direkte Verwendung von Werten) lauten wie folgt:
Ich persönlich empfehle, die Anzahl der Accessoren zu verringern und sie zu verwenden, wenn Sie erwarten, dass der Setter (setName) später zu mehr als einer einfachen Beeinträchtigung wird.
quelle
Diese Art von Wertobjekt ist ziemlich niedrig. Ich würde vorschlagen, es in eine von zwei Richtungen zu verschieben: (1) das Wertobjekt unveränderlich zu machen, das heißt, wie ein realer Wert , oder (2) die Veränderbarkeit zu einer übergeordneten domänenorientierten Geschäftsfunktion zu erhöhen, was bedeutet, dass wir herausstellen sollten Schnittstellen im Sinne domänenrelevanter Funktionseinheiten.
quelle