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_CONSTANT
stattThatClass.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.
java
design
programming-practices
constants
FabianB
quelle
quelle
Antworten:
Joshua Bloch rät in seinem Buch Effective Java davon ab :
Sie können den gleichen Effekt mit einer normalen Klasse erzielen, die die Konstanten definiert und dann verwendet
import static com.example.Constants.*;
quelle
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.
quelle
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.
quelle
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.
quelle
"at most expose their names"
, ohne die Werte offenzulegen ?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 wieimport static MyInterface.*
, aber ein bisschen offensichtlicher.1: Wenn Sie nicht mit Java vertraut sind, meine ich nicht das
import
Schlüsselwort, ich meine nur das Einbringen überimplements MyConstantsInterface
quelle
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
quelle
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 DocsNein, 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.
quelle