it-swarm.com.de

Was bringt es, wenn jede Serviceklasse eine Schnittstelle hat?

In der Firma, in der ich arbeite, hat jede Serviceklasse eine entsprechende Schnittstelle.
Ist das notwendig?

Anmerkungen:

  • Die meisten dieser Schnittstellen werden nur von einem einzelne Klasse verwendet
  • Wir erstellen keine öffentliche API

Ist dies bei modernen Verspottungsbibliotheken, die konkrete Klassen verspotten können, und IDEs, die eine Schnittstelle mit etwa zwei Klicks aus einer Klasse extrahieren können, nur ein Überbleibsel aus früheren Zeiten?

111
Bob Roberts

Ihr Unternehmen folgt den Prinzipien von SOLID) und zielt auf eine Schnittstelle anstatt auf eine konkrete Klasse ab. Dadurch wird dem Programm kein Overhead hinzugefügt. Was sie tun, ist eine sehr moderate Menge an zusätzlicher Arbeit, die das Volumen zurückzahlen kann, wenn Die Annahmen, die Sie machen, sind am Ende falsch ... und Sie können nie sagen, welche Annahme das sein wird. Was Sie empfehlen, während etwas weniger Arbeit, kann viele, viele, viele Stunden Refactoring kosten, die gerade gewesen sein könnten Dies geschieht im Voraus, indem einfach die grundlegenden OO Designprinzipien) befolgt werden.

Sie sollten von diesen Jungs lernen und sich glücklich schätzen. Ich wünschte, ich würde in einer solchen Umgebung arbeiten, in der solides Design ein vorrangiges Ziel war.

98
Edward Strange

Angesichts Ihrer Frage gehe ich davon aus, dass die Gründe für dieses Design nicht dokumentiert sind.

Die ungerechtfertigte Verwendung einer Schnittstelle mit einer einzelnen Implementierung ist eindeutig falsch, da dies gegen YAGNI verstößt . Nach meiner Erfahrung war dies auch in Bezug auf die Wartung ziemlich schädlich, hauptsächlich weil Methoden, die eine Schnittstelle implementieren, unnötig öffentlich sein müssen. Nachdem Sie mehr Refactoring Erfahrung gesammelt haben, werden Sie wahrscheinlich lernen, den bescheidenen Charme von privat und Paket privat Zugriffsmodifikatoren zu schätzen, die einen zulassen die Aufmerksamkeit innerhalb einer einzelnen Klasse/eines Pakets zu lenken.

Die undokumentierte gerechtfertigte Verwendung dieser Redewendung ist in meinen Augen ungefähr so ​​schlecht - vor allem, weil sie es einem Betreuer nicht erlaubt, "zu erzählen" gut von schlecht ". Infolgedessen bleibt eine zwischen nicht ganz ansprechenden Optionen. Optionen sind entweder, dass Sie das fragwürdige öffentliche Material unverändert lassen und somit wiederholt die Produktivität jedes Mal verringern, wenn Sie den Code ändern müssen, oder Sie riskante Änderungen vornehmen durch blindes "Zusammenfallen" der Einzelimplementierung in eine leichter zu wartende POJO - sich dem Risiko aussetzen, schmerzhaft zu entdecken, dass dies der falsche Weg ist, dass ein anderer ( Gott bewahre, Remote ) Modul außer Sicht erwartet die Schnittstelle.

Ich habe einige Male "Enthüllungen" durchgemacht, die durch den irrtümlichen Zusammenbruch der Single-Implementation-Schnittstelle verursacht wurden. Jedes Mal war es eine ziemlich lehrreiche Erfahrung, aber ich würde nicht wirklich wieder dorthin wollen. Die Sache ist, dass dies bei späten Tests, bei der Integration oder sogar bei der Benutzerakzeptanz geschieht und das Zurücksetzen/Beheben des Fehlers, der vor langer Zeit in dieser Phase gemacht wurde, ziemlich umständlich ist.


  • Eine Option, die nicht ohne Erwähnung bleiben sollte, besteht darin, zu untersuchen, ob die undokumentierte Verwendung in dem Moment, in dem Sie sie finden, gerechtfertigt ist (und danach zusammenbricht bzw. dokumentiert).

    Für mich war dieser ziemlich kontraproduktiv. Dieser Ansatz zwingt einen im Wesentlichen dazu, umfassende Integrationstests durchzuführen, was wahrscheinlich eine der effizientesten Methoden ist, um einen Fluss zu unterbrechen mitten in einem komplizierten Fix/Refactoring.

    http://i.stack.imgur.com/tBUBG.jpg

Ich konnte die Praktikabilität einfach nicht erkennen ... die Schnittstellen werden eins zu eins wie com.company.service.foo und com.company.service.foo.impl

Im Folgenden geht es darum, wie ich normalerweise mit solchen Fällen umgehe.

  1. Erstellen Sie ein Ticket in Issue-Tracker , wie "PRJ-123 Undokumentierte fragwürdige Verwendung der Schnittstelle mit Einzelimplementierung in Foo/FooImpl ".
    Fügen Sie der Ticketbeschreibung hinzu oder kommentieren Sie eine Erklärung, dass dies die Wartbarkeit beeinträchtigt, und weisen Sie darauf hin, dass dies ohne Dokumentation wie Overengineering aussieht. Fügen Sie einen Kommentar hinzu, der vorschlägt, das Problem zu beheben, indem Sie es in ein POJO "reduzieren", um die Wartbarkeit zu vereinfachen.
  2. Warten Sie einige Zeit, nur für den Fall, dass jemand kommt, um die Dinge zu erklären. Ich würde mindestens ein oder zwei Wochen warten

    • Wenn jemand den Zweck erklärt, a) das auf das Ticket setzen, b) zu Foo javadocs etwas hinzufügen wie Zweck der in Ticket PRJ-123 erläuterten Schnittstelle, c) das schließen Ticket, d) überspringen Sie die nächsten drei Schritte.
    • Andernfalls, ...
  3. Kommen Sie zum Teamleiter oder Manager und fragen Sie, was sie denken würden, wenn ich das Ticket wie vorgeschlagen reparieren würde.
    Wählen Sie einen Berater mit ausreichender Autorität, um den "Schreitest" zu bestehen, falls sich herausstellt, dass die vorgeschlagene Lösung falsch ist.
  4. Reduzieren Sie auf POJO gemäß dem vorgeschlagenen Fix, arrangieren Sie Codeüberprüfung wenn dies möglich ist (in solchen rutschigen Fällen tut es nicht weh, Ihren Rücken zu bedecken).
  5. Warten Sie, bis die Änderung den vollständigen Test bestanden hat, und aktualisieren Sie das Ticket je nach Ergebnis. Fügen Sie die Informationen hinzu, ob die Änderung den Test bestanden hat oder nicht.
  6. Erstellen und bearbeiten Sie ein neues Issue-Tracker-Ticket, um verbleibende ähnliche Fälle basierend auf dem Ergebnis Ihres Pilotentickets zu behandeln (PRJ-123): entweder den Zweck dokumentieren oder zu POJO zusammenbrechen.
84
gnat

Hier ist, wie Adam Bien über diese Frage nachdenken: Service s = new ServiceImpl () - Warum machst du das?

Das ist nicht nur Aufblähen (und das Gegenteil der Idee "Konvention über Konfiguration"), sondern es verursacht echten Schaden:

  1. Stellen Sie sich vor, Sie erhalten eine andere Implementierung (das ist der springende Punkt einer Schnittstelle) - wie würden Sie sie nennen?
  2. Es verdoppelt die Anzahl der Artefakte - und erhöht die "Komplexität" erheblich.
  3. Es ist wirklich lustig, die Javadocs auf der Schnittstelle und dem Gerät zu lesen - eine weitere Redundanz
  4. Die Navigation in IDE ist weniger fließend

und ich stimme ihm zu.

Vielleicht stecken Ihre Mitarbeiter immer noch in der Zeit mit J2EE fest, weil dies bei der Arbeit mit J2EE notwendig war. Vielleicht finden Sie im Internet alte Tutorials über schwere Zeiten in J2EE.

40
Xoke

Bei Java-Schnittstellen geht es nicht nur um Spottbarkeit (obwohl das natürlich ein Faktor ist). Eine Schnittstelle macht einen öffentlichen Auftrag für Ihren Dienst verfügbar, ohne Implementierungsdetails wie private Methoden oder Attribute.

Beachten Sie, dass sich "öffentlich" bei Verwendung interner Dienste (wie in Ihrem Fall) auf die tatsächlichen Benutzer dieser Dienste bezieht, einschließlich - aber nicht beschränkt auf - andere Programmierer und interne Dienste!

20
Andres F.

Ein möglicher Grund für jede Serviceklasse, eine Schnittstelle zu haben, besteht darin, dass die Interaktion mit hoch entwickelten Frameworks (z. B. Spring, JEE) viel einfacher wird. Dies liegt daran, dass Java kann einfach Interceptor-Objekte für Schnittstellen generieren (siehe Java.lang.reflect.Proxy); Dies für konkrete Klassen ist weitaus schwieriger und mit einigen nicht offensichtlichen Einschränkungen beim Arbeiten verbunden Dies gilt in zweifacher Hinsicht, wenn Sie mit OSGi arbeiten, bei dem diese Dienstschnittstellen von einem anderen Klassenlader als die Implementierungen dieser Dienste geladen werden. Dies (zusammen mit der Diensterkennungsstruktur) erzwingt wiederum eine sehr starke Trennung zwischen Jeder Dienst und seine Clients, die Clients buchstäblich können nicht brechen die Abstraktion.

Beachten Sie, dass selbst wenn eine IDE eine Schnittstelle mit einem einzigen Klick aus einer Klasse extrahieren kann, dies nicht bedeutet, dass die Schnittstelle korrekt extrahiert werden muss. Intelligenz wird noch benötigt.

12
Donal Fellows

Es scheint ein Overhead zu sein, Interface anfangs zu verwenden. Später, wenn wir einige Funktionen erweitern müssen, helfen diese Interfaces sehr.

Wenn Sie nur eine konkrete Implementierung durchführen, müssen Sie die Code-Implementierung stark ändern. Wenn Sie jedoch die Schnittstelle verwenden, müssen Sie nur eine neue Klasse hinzufügen, die den Vertrag der Schnittstelle implementiert (und Sie können ein neues Klassenobjekt aus der Referenzvariablen der alten Schnittstelle aufrufen). .

1
kundan bora