Ich schreibe ein Spiel in Typescript und habe beschlossen, mich an die Idee der " schnittstellenbasierten Programmierung " zu halten, bei der Sie Code auf der Grundlage einer Schnittstelle anstelle der Implementierung eines Objekts schreiben.
Ich habe eine gute Anzahl von Schnittstellen und Klassen geschrieben, die sie implementieren, bin dann einen Schritt zurückgetreten und habe festgestellt, dass die Klassen so einfach sind, dass ich die Implementierung wahrscheinlich nie ändern muss, da es wirklich nur einen Weg gibt, das zu tun, was die Klasse tut (bewegt sich Phaser.Sprite
auf eine eingeschränkte Weise, um sich wie ein Panzer zu verhalten).
Dann erinnere ich mich, dass ich vor einigen Jahren über die Idee von YAGNI gelesen habe. Grundsätzlich sollten Sie Ihren Code nicht überentwickeln , um Dinge einzuschließen , die Sie möglicherweise nie verwenden.
Sollte jede Klasse nach den Best Practices eine Schnittstelle implementieren oder auf Klassen beschränken, von denen Sie erwarten, dass sie in Zukunft möglicherweise ausgetauscht werden?
quelle
Antworten:
Der Grund für Schnittstellen liegt darin, dass sie den Polymorphismus vereinfachen. Das heißt, Sie können Instanzen vertraglich senden, anstatt deren tatsächliche Implementierung zu kennen. Beispielsweise können Sie einen "Reader" an eine Methode senden, damit eine solche aufgerufene Methode die "read ()" - Methode verwenden kann. Indem Sie eine Schnittstelle als "Reader" deklarieren, können Sie jedes Objekt an diesen Vertrag anpassen, indem Sie die darin angegebenen Methoden implementieren. Auf diese Weise kann jeder Anrufer davon ausgehen, dass bestimmte Methoden existieren, auch wenn die dem Vertrag zugrunde liegenden Objekte möglicherweise völlig unterschiedlich sind.
Dies entkoppelt den Polymorphismus von einer Basisklasse und ermöglicht es auch zwischen Klassenkettengrenzen, indem ein Vertrag impliziert wird.
Jetzt ... Dies ist nur dann nützlich, wenn mehrere Vererbungsketten auf dieselbe Weise funktionieren müssen oder wenn Sie viele Basisklassen mit allgemeinem Verhalten haben, die Sie an andere Benutzer weitergeben möchten.
Wenn Sie nur EINE Vererbungskette (Basisklasse-> Unterklasse) oder nur die Basis haben oder die zugehörigen Objekte nicht an eine andere Person weitergeben oder generisch verwenden müssen, würden Sie keine Schnittstellenimplementierungen hinzufügen, wie dies dann der Fall ist nutzlos.
quelle
Moves
undShoots
für Ihr Tankbeispiel) für eine einzelne Klasse.Wenn Sie nicht sicher sind, ob Sie die Schnittstellen tatsächlich benötigen, tun Sie dies wahrscheinlich nicht. Dies ist der Kern des YAGNI-Prinzips. Wenn Sie die Implementierung austauschen müssen, führen Sie eine Schnittstelle ein.
quelle
Das Erstellen einer Schnittstelle für jede Klasse ist etwas übertrieben. Aus rein objektorientierter Sicht hat jede Klasse bereits eine Schnittstelle . Eine Schnittstelle ist nichts anderes als die öffentlich zugänglichen Methoden und Datenelemente einer Klasse.
Unter "Schnittstelle" versteht man normalerweise "eine Java-Klasse, die mit dem
interface
Schlüsselwort definiert wurde " oder "eine C ++ - Klasse mit nur öffentlichen, rein virtuellen Funktionen". Dies sind nützliche Abstraktionen, da sie die Schnittstelle einer Klasse von ihrer Implementierung entkoppeln.Verwenden Sie daher gegebenenfalls Schnittstellen.
Wird es mehrere Implementierungen für eine Schnittstelle geben? In diesem Fall kann diese Situation ein Kandidat für das Extrahieren gängiger, öffentlich zugänglicher Methoden in eine Schnittstelle sein.
Übergebe ich Implementierungen einer potenziellen Schnittstelle an andere Module, die das Innenleben meines Moduls nicht kennen sollten? Eine Schnittstelle kann hier nützlich sein, da sie die Größe des Berührungspunkts zwischen Modulen verringert.
Beachten Sie die obigen Wieselwörter: "kann" ein Kandidat sein, "kann" nützlich sein. Es gibt keine feste Regel, die für eine bestimmte Situation "Ja" oder "Nein" sagt.
Davon abgesehen ist es höchstwahrscheinlich übertrieben, eine Schnittstelle für alles zu haben. Wenn Sie dieses Muster sehen, gehen Sie zu weit:
quelle
interface
, es kommt einfach so vor, dass alles in Javainterface
auch seine öffentlich zugängliche Schnittstelle (OO-Konzept) ist.Für neuere Entwickler kann es sehr verlockend sein, Schnittstellen als eine Unannehmlichkeit zu betrachten, die Sie einfach hinzufügen, nur weil Ihnen gesagt wird, dass dies "Best Practice" ist. Wenn Sie sind blind dies zu tun, schmatzt es von Cargo - Kult - Programmierung .
Es gibt eine Reihe sehr guter Gründe, warum Sie Schnittstellen für größere Entwicklungen in Betracht ziehen sollten, anstatt eine Reihe von Klassen zusammenzufassen.
Verspottende Frameworks
Wenn Sie eine mehrschichtige Anwendung testen möchten, ohne Objekte für die verschiedenen Ebenen erstellen zu müssen, sollten Sie zweifellos Mocking-Frameworks verwenden, um die Ebenen zu verspotten. Schnittstellen werden hier häufig verwendet.
Abhängigkeitsspritze
Während sie aufgrund des Aufblähens, das sie hinzufügen, etwas in Ungnade gefallen sind, ist die Idee solide - die Fähigkeit, Konkretionen basierend auf einer Schnittstelle einfach einzutauschen. Das Prinzip findet sich auch in vielen Entwurfsmustern wie dem Fabrikmuster.
Diese Ansätze sind im D von SOLID-Prinzipien zusammengefasst . Das Problem dabei ist, dass Sie Abstraktionen verwenden, keine Konkretionen.
Wie bei den Entwurfsmustern selbst ist es ein Urteilsspruch, wann sie verwendet werden sollen. Der entscheidende Punkt ist, zu verstehen, wie nützlich die Schnittstellen sind, und sie nicht nur in Ihre Klassen zu stecken, weil Sie das Gefühl haben, dass Sie es müssen. Es gibt eine gute Diskussion über die verschiedenen Vorzüge der DIP und YAGNI hier .
quelle