it-swarm-eu.dev

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

Ich schreibe eine Reihe von Junit-Testklassen in Java. Es gibt mehrere 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_CONSTANT Anstatt von ThatClass.MY_CONSTANT
  • jede Konstante wird nur einmal definiert

Ist dieser Ansatz eher eine gute oder eine schlechte Praxis? Ich denke, dies ist ein bisschen so, als würde man das Konzept der Schnittstellen missbrauchen.

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

45
FabianB

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

Dass eine Klasse einige Konstanten intern verwendet, ist ein Implementierungsdetail. Durch die Implementierung einer konstanten Schnittstelle wird dieses Implementierungsdetail in die exportierte API der Klassen übertragen. Für die Benutzer einer Klasse ist es nicht von Bedeutung, dass die Klasse eine konstante Schnittstelle implementiert. In der Tat 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 import static com.example.Constants.*; Verwenden.

88
matt

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 eine Implementierung der Schnittstelle sie nicht verwendet, wird sie ihre Aufgabe nicht erfüllen.

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

14
user144901

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

Wenn eine Schnittstelle, die das Verhalten definiert (Methoden, die Klassen implementieren, implementieren sollten), Konstanten hat, ist dies in Ordnung. Wenn es "Details eines Implementierers verliert" in die API, liegt es daran, dass es so sein sollte. Sie lecken auch, dass der Implementierer die Methoden .foo() und .bar() implementiert.

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

Wenn der Designer diese Konstanten dort platziert, liegt dies daran, dass er/sie dachte, dass dies stabil genug wäre, um Teil der Schnittstelle zu sein, wie es .getTransparency() ist.

6

Eine Firma, bei der ich gearbeitet habe, hat stark von Schnittstellenimporten Gebrauch gemacht1 Konstanten. Ich fühle keinen Schaden daraus.

Die Frage, die Sie sich stellen sollten, lautet: Wie wichtig ist Ihnen der Namespace? Bei Konstanten ist das wirklich 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 Schnittstellen ist, dass Sie so oder so arbeiten können - bringen Sie alle benötigten oder keine Namespaces ein (und greifen Sie explizit mit MyInterface.CONSTANT Auf diese zu). So ziemlich das Gleiche wie import static MyInterface.*, Aber etwas offensichtlicher.


1: Wenn Sie nicht mit Java vertraut sind, meine ich nicht das Schlüsselwort import, sondern nur das Einfügen über implements MyConstantsInterface

2
Nicole

Ich denke, es ist ein Standpunkt, der vor allem an Orten beliebt ist, an denen Design by Contract vorherrscht.
Schnittstellen sind Verträge. Das Platzieren von Konstanten in Schnittstellen bedeutet, dass jede Klasse, die den Vertrag einhält, dem durch die Konstante angegebenen Wert/Konzept zustimmt.

2
CMR

Nein, es ist keine allgemeine schlechte Praxis.

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

Die eigentliche Verwendung der Syntax ist das eigentliche Problem.

1
oopexpert

Ich komme aus einem Umfeld, das hauptsächlich vom Ada-Weg und vom .Net-Weg beeinflusst wird. Ich würde nein sagen, dass es wahrscheinlich nicht am besten ist, Konstanten innerhalb von Schnittstellen zu deklarieren. In c # ist dies technisch nicht zulässig.

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 begrüßen, jedem, der die Schnittstelle implementiert, Standardeinstellungen und vordefinierte Werte zur Verfügung zu stellen, aber vielleicht würde der Standardstatus besser in einem abstrakten oder Wertobjekt oder einer Vorlage beschrieben, in der die Standardeinstellungen zumindest einen minimalen Kontext haben würden.

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

1
JustinC