OOP: In welchen Situationen ist klassenbasiertes Design besser als schnittstellenbasiertes?

9

Ich habe die Website von JDOM gelesen .

Warum wird die JDOM-API eher in konkreten Klassen als in Schnittstellen definiert?

Jason Hunter fasst die Argumente gegen eine schnittstellenbasierte API für JDOM zusammen:

Mit Schnittstellen wird alles zur Fabrik, Elemente müssen in neue Dokumente "importiert" werden, anstatt nur hinzugefügt zu werden, Funktionen wie die langfristige Serialisierung können nicht garantiert werden, und die Liste geht weiter.

Wir haben eigentlich mit Schnittstellen angefangen. Während unserer Überprüfung vor der Veröffentlichung an einige Kollegen erhielten wir das Feedback, dass wir konkrete Klassen ausprobieren sollten. Wir haben es getan und das Design war viel besser dafür.

Ich bin ein Anfänger Designer. Alle Ratschläge , die ich gehört habe , etwa bis jetzt ist die Beratung vor mit der Gestaltung mit konkreten Klassen.

Möglicherweise sind an bestimmten Stellen konkrete Klassen angebracht. Gibt es häufig auftretende Klassenprobleme, für die die Verwendung konkreter Klassen im Design in Ordnung ist?

Vinoth Kumar CM
quelle
Vielleicht möchten Sie einen Blick darauf werfen
NoChance
Sie können auch die Reihe "Begrenzen Sie Ihre Abstraktionen" lesen
henginy
"Wir haben es getan, und das Design war viel besser dafür." - Wie war es besser?
CodeART
Ähnliche Frage.
RalphChapin

Antworten:

5
  • Durch die Vererbung entstehen Abhängigkeiten von der Implementierung , was ein großes Problem hinsichtlich der Wartbarkeit sein kann. Die Folge davon ist, dass Sie beim Umgang mit Datenübertragungsobjekten , die per Definition fast keine Implementierung enthalten, Vererbungs- und konkrete Klassen sicher verwenden können . Sie können auch die Vererbung konkreter Klassen verwenden, wenn Sie diese Abhängigkeit wünschen. In dieser Situation möchten Sie möglicherweise eine abstrakte Klasse verwenden, die die allgemeinen Methoden (normalerweise Dienstprogrammfunktionen) oben in der Hierarchie enthält.
  • Vergessen Sie bei der Verwendung einer konkreten Klassenhierarchie nicht, das Liskov-Substitutionsprinzip anzuwenden .
  • Es gibt kein Problem bei der Verwendung konkreter Klassen für Clients (dh Klassen, die verwendet werden, keine Klassen, die verwendet werden).
  • IMHO können Sie konkrete Klassen verwenden, bis es Dinge zu ändern gibt. Das Open / Closed-Prinzip fordert Sie auf, Schnittstellen zu verwenden, um eine Kopplung zu vermeiden. In Bezug auf das Prinzip " Sie werden es nicht brauchen" sollten Sie jedoch konkrete Klassen verwenden, bis Sie etwas in der Implementierung ändern müssen. Das Problem ist, dass Sie jeden Kunden Ihrer Klassen ändern müssen, wenn sich zum ersten Mal irgendwo etwas ändert. Während Sie nur ein mögliches Werkzeug haben, um etwas zu tun, können Sie konkrete Klassen IMO verwenden.

[BEARBEITEN] Die JDOM-Website nimmt als Beispiel java.io.File, aber dies ist definitiv ein schnittstellenbasiertes Design, da man eine java.io.File-Instanz so manipulieren kann, als wäre sie nur serialisierbar. In dieser Situation würden nur "Schöpfer" die konkrete Klasse kennen

Matthias Jouan
quelle
Es gibt zwei widersprüchliche Definitionen von "Wertobjekt". Ihre scheint die seltenere zu sein, die auch als "Datenübertragungsobjekt" bezeichnet wird.
Michael Borgwardt
@ MichaelBorgwardt Danke für den Hinweis, da ich nicht nur "Datenübertragungsobjekt" meinte: Ich bearbeite meine Antwort
Matthias Jouan
1
LSP ist wichtig für jede Subtypisierungsbeziehung, Schnittstellenimplementierung sowie Vererbung.
2

Von der JDOM-Site:

Jason (Hunter) gründete das JDOM-Projekt Anfang 2000 zusammen mit Brett McLaughlin

Das heißt, ungefähr zu der Zeit, als Java 1.3 eingeführt wurde. Bei der Java-Entwicklung stand der Reife nichts im Wege - die erfahrensten Entwickler hatten bestenfalls 4 Jahre Zeit, Java zu verwenden. Es gab keine weit verbreiteten IoC-Container, keinen Ruhezustand. Apache Struts hatte gerade erst seinen Anfang genommen.

Das heißt, Jason und Brett haben sich einfach geirrt. Viele Leute haben es noch nicht "verstanden". Wenn sie C ++ - Hintergründe hatten, brauchten Sie keine Schnittstellen in C ++ (nun, sie waren in C ++ vorhanden, aber Sie brauchten sie nicht wirklich, oder?), Warum zum Teufel verwenden Sie sie in Java? Nun, es gibt viele gute Gründe, auf die andere Sie hinweisen können.

Sie haben sich definitiv geirrt

Alles, was mit Schnittstellen gemacht werden kann, kann mit Unterklassen gemacht werden

Java erlaubt keine Mehrfachvererbung von Klassen, aber die Implementierung mehrerer Schnittstellen. Das kann einen echten Unterschied machen.

Matthew Flynn
quelle
2

Denken Sie zunächst daran, dass es in der Softwareentwicklung verschiedene Möglichkeiten gibt, ein Problem zu lösen. Wenn ein Entwickler eine andere Technik als Ihre verwendet, bedeutet dies nicht, dass diese falsch ist.

Einer dieser Fälle sind "Schnittstellen" gegenüber (Basis-) "Klassen". Es gibt Situationen, in denen mit beiden Techniken dasselbe Ziel erreicht werden kann.

Um die Sache noch komplizierter zu machen, gibt es verschiedene Verwendungsmöglichkeiten von Schnittstellen, um nur zu erwähnen:

  • Eine besteht darin, einen "Vertrag" oder eine "Spezifikation" ohne "Implementierung" zu entwerfen.
  • andere, um einer vorhandenen Klasse oder Klassenhierarchie Funktionalität hinzuzufügen
  • Ergänzend zu früheren, um den gemeinsamen Zugriff zwischen verschiedenen Objekten und Technologien zu ermöglichen, z. B. Enterprise Beans, CORBA, COM, WebServices
  • Mehrfachvererbung zu emulieren

Ihre Frage bezieht sich auf den ersten Punkt.

Wenn Sie eine Klassenhierarchie entwickeln möchten, nicht nur eine einzelne Klasse, und mehrere Klassen bestimmte Funktionen gemeinsam nutzen sollen, möchten Sie möglicherweise mit einer Basisklasse beginnen, auch wenn dies mit einer Schnittstelle möglich ist.

Lassen Sie Schnittstellen für die anderen Szenarien.

Ein gutes Beispiel sind Widgets (Steuerelemente) Bibliotheken.

Ich schlage vor, einen Blick auf andere Programmiersprachen zu werfen, wie sie Schnittstellen und Klassen wie PHP, Delphi (Object Pascal), C # verwenden.

Prost.

umlcat
quelle
0

Im Allgemeinen möchten Sie eine Schnittstelle für alles, was als Parameter übergeben oder zurückgegeben wird, damit Sie die Klasse von ihren Abhängigkeiten entkoppeln können.

Wenn wir also nach einer Klasse suchen, geben wir normalerweise keine Ausnahmen weiter. Ich bin kein Java-Entwickler, aber sicherlich in anderen ähnlichen Sprachen habe ich keine für Ausnahmen definierten Schnittstellen gesehen.

jk.
quelle
0

API-Designregeln sind wirklich eine bestimmte Sache. Ich bin mir nicht sicher, ob Sie aus dieser FAQ etwas schließen sollten, wie Sie Ihren täglichen Code gestalten sollen.

Für Ihren regulären Code ist es immer noch richtig, dass Sie die Vererbung von Schnittstellen oder abstrakten Klassen viel häufiger verwenden als die IMO-Vererbung von Vanille.

Um ein gutes Verständnis dieser Regel zu erhalten, müssen Sie sich nicht vom Standpunkt einer abgeleiteten Klasse gegenüber ihrer Oberklasse, sondern vom Standpunkt eines Objekts, das von einem anderen Objekt abhängig ist, platzieren. Es ist fast immer besser, sich auf eine Abstraktion als auf eine konkrete Implementierung zu verlassen, da Sie so eine ganze Reihe verschiedener Klassen als Abhängigkeiten akzeptieren können, wobei Sie sich auf ihren Vertrag und nicht auf ihre Implementierungsdetails verlassen.

Der erste Einsatz hierfür ist oft in Unit - Tests - wenn Sie es wirklich wollen Einheit Test Ihre Klasse in völligen Isolation, was Sie tun , dass gegen gefälschte Implementierungen Ihrer Abhängigkeiten , die von den realen Implementierungen unterscheiden, die in der Produktion eingesetzt werden.

guillaume31
quelle