Ist es eine schlechte Praxis, eine Schnittstelle zum Definieren von Konstanten zu haben?


40

Ich schreibe eine Reihe von Junior-Testklassen in Java. Es gibt verschiedene Konstanten, zum Beispiel Strings, die ich in verschiedenen Testklassen benötige. Ich denke über eine Schnittstelle nach, die sie definiert, und jede Testklasse würde sie implementieren.

Die Vorteile, die ich dort sehe, sind:

  • einfacher Zugriff auf Konstanten: MY_CONSTANTstattThatClass.MY_CONSTANT
  • Jede Konstante ist nur einmal definiert

Ist dieser Ansatz eher eine gute oder eine schlechte Praxis? Ich habe Lust, das Konzept der Schnittstellen ein wenig zu missbrauchen.

Sie können allgemein über Schnittstellen / Konstanten, aber auch über Unit-Tests antworten, wenn es etwas Besonderes gibt.


Die Antwort für "Es ist eine schlechte Praxis, wenn eine Schnittstelle X definiert?", Da X alles ist, was nicht "Methodensignaturen" sind, lautet fast immer "Ja".
T. Sar - Reinstate Monica

Antworten:


79

Joshua Bloch rät in seinem Buch Effective Java davon ab :

Dass eine Klasse einige Konstanten intern verwendet, ist ein Implementierungsdetail. Das Implementieren einer konstanten Schnittstelle führt dazu, dass dieses Implementierungsdetail in die exportierte Klassen-API gelangt. Für die Benutzer einer Klasse ist es unerheblich, dass die Klasse eine konstante Schnittstelle implementiert. Tatsächlich kann es sie sogar verwirren. Schlimmer noch, es stellt eine Verpflichtung dar: Wenn die Klasse in einer zukünftigen Version so geändert wird, dass sie die Konstanten nicht mehr verwenden muss, muss sie dennoch die Schnittstelle implementieren, um die Binärkompatibilität sicherzustellen.

Sie können den gleichen Effekt mit einer normalen Klasse erzielen, die die Konstanten definiert und dann verwendet import static com.example.Constants.*;


13

In unserem Fall tun wir dies, weil die Werte der Konstanten einen Vertrag für Endzustände darstellen, für deren Bereitstellung eine Service-Implementierung erforderlich ist. Durch das Einfügen dieser Konstanten in die Schnittstelle werden die Endzustände als Teil des Vertrags angegeben. Wenn sie von einer Implementierung der Schnittstelle nicht verwendet würden, würde dies nicht funktionieren.

SOMETIMES-Konstanten sind Implementierungsdetails. Manchmal sind sie nicht. Wie üblich muss ein Ingenieur sein Gehirn einsetzen, um zu entscheiden, was zu tun ist, und sich nicht auf ein umfassendes Muster oder eine umfassende Praxis verlassen.


7

Ich denke nicht, dass es eine gute Sache ist, Schnittstellen nur für Konstanten zu haben.

Wenn jedoch eine Schnittstelle, die das Verhalten definiert (Methoden, die Klassen implementieren sollen), Konstanten aufweist, ist dies in Ordnung. Wenn es "einige Implementierungsdetails" in die API verliert, liegt es daran, dass dies so ist, wie es sein sollte. Sie sind auch undicht, dass der Implementierer Foo- und Bar-Methoden implementiert.

Nehmen Sie zum Beispiel das Interface java.awt.Transparency. Es hat die Konstanten OPAQUE, BITMASK und TRANSLUCENT, aber auch die Methode getTransparency ().

Wenn der Designer diese Konstanten dort ablegt, hat er / sie gedacht, dass sie stabil genug sind, um Teil der Schnittstelle zu sein, wie es getTransparency () ist.


2

Denken Sie, es ist ein Standpunkt, der vor allem an Orten beliebt ist, an denen Design nach Vertrag vorherrscht.
Schnittstellen sind Verträge. Konstanten in Interfaces zu platzieren bedeutet, dass jede Klasse, die sich an den Vertrag hält, dem durch die Konstante identifizierten Wert / Konzept zustimmt.


1
Schnittstellen sind öffentliche Aufträge. Konstante WERTE sind private Anliegen, die öffentliche Schnittstelle sollte höchstens ihre Namen preisgeben. Das überlässt man am besten einer abstrakten Klasse.
24.

Beispiele: javax.naming.Context, javax.ims.Session und Hunderte solcher Schnittstellen ...
CMR

2
@jwenting Könnte auch eine öffentliche Schnittstelle "at most expose their names", ohne die Werte offenzulegen ?
CMR

das würde von der programmiersprache abhängen, denke ich. Im Falle von Java, nein.
Jwenting

2

Eine Firma, bei der ich gearbeitet habe, hat die von der Schnittstelle importierten 1 Konstanten stark genutzt. Ich fühle keinen Schaden daraus.

Die Frage, die Sie sich stellen sollten, ist, wie wichtig der Namensraum für Sie ist. Bei Konstanten ist das eigentlich alles, als was eine Klasse fungiert. Wenn Sie Tausende von Konstanten haben, möchten Sie möglicherweise nicht, dass alle diese Konstanten immer verfügbar sind.

Das Coole an Interfaces ist, dass Sie so oder so arbeiten können - bringen Sie alle oder keinen der benötigten Namespaces ein (und greifen Sie explizit darauf zu MyInterface.CONSTANT). Ziemlich dasselbe wie import static MyInterface.*, aber ein bisschen offensichtlicher.


1: Wenn Sie nicht mit Java vertraut sind, meine ich nicht das importSchlüsselwort, ich meine nur das Einbringen überimplements MyConstantsInterface


1

Ich komme aus einem Umfeld, das hauptsächlich durch den "Ada-Weg" und den ".Net-Weg" beeinflusst wird. Ich würde nein sagen, dass es wahrscheinlich nicht am besten ist, Konstanten innerhalb von Interfaces zu deklarieren. Es ist technisch nicht erlaubt in c #.

Der Grund, warum ich nein sage, ist, dass eine Schnittstelle eine Vertragsform ist, die das Verhalten definiert, nicht den Zustand oder die Struktur. Eine Konstante impliziert eine Art Zustand (primitiv) oder einen Aspekt des Zustands (zusammengesetzt oder aggregiert).

Ich kann den Drang verstehen, Standardwerte und vordefinierte Werte für alle Benutzer verfügbar zu machen, die die Schnittstelle implementieren. Der Standardzustand lässt sich jedoch besser in einem abstrakten Objekt oder einer Wertvorlage beschreiben, bei denen die Standardwerte mindestens einen minimalen Kontext aufweisen.

Für eine technische Anleitung: download.oracle.com/javase/1.5.0/docs/guide/language/static-import.html


Das Hinzufügen von mehr Links mit Bezug auf statische Import (1.5): 1. Wikipedia 2. Oracle Text & Tabellen referenzieren @Justinc
Abhijeet

1
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Referenz von Oracle Docs
Abhijeet

1

Nein, es ist keine allgemein schlechte Praxis.

Der Punkt ist, dass Konstanten wie jedes andere Artefakt unter den Regeln der minimalen Sichtbarkeit und der richtigen Abstraktionsstufe eingeführt werden sollten.

Syntax nur verwenden, weil Sie können, ist das eigentliche Problem.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.