Das Einfügen statischer Elemente in eine Schnittstelle (und das Implementieren dieser Schnittstelle) ist eine schlechte Praxis, und es gibt sogar einen Namen dafür, das Antipattern für konstante Schnittstellen , siehe Effective Java , Punkt 17:
Das konstante Schnittstellenmuster ist eine schlechte Verwendung von Schnittstellen . Dass eine Klasse einige Konstanten intern verwendet, ist ein Implementierungsdetail. Durch die Implementierung einer konstanten Schnittstelle wird dieses Implementierungsdetail in die exportierte API der Klasse ü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. Wenn eine nicht endgültige Klasse eine konstante Schnittstelle implementiert, werden die Namespaces aller Unterklassen durch die Konstanten in der Schnittstelle verschmutzt.
In den Java-Plattformbibliotheken gibt es mehrere konstante Schnittstellen, z java.io.ObjectStreamConstants
. Diese Schnittstellen sollten als Anomalien betrachtet und nicht emuliert werden.
Um einige Fallstricke der konstanten Schnittstelle zu vermeiden (da Sie nicht verhindern können, dass Benutzer sie implementieren), sollte eine geeignete Klasse mit einem privaten Konstruktor bevorzugt werden (Beispiel aus Wikipedia entlehnt ):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
Verwenden Sie einen statischen Import (seit Java 5), um auf die Konstanten zuzugreifen, ohne sie vollständig qualifizieren zu müssen (dh ohne ihnen den Klassennamen voranstellen zu müssen ):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
Wer auch immer diese Hypothese aufgestellt hat, wie auch immer ein Guru sein mag, hat sie auf der Grundlage der Notwendigkeit erfunden, weiterhin schlechte Gewohnheiten und Praktiken effizient umzusetzen. Die Hypothese basiert auf der Förderung der Gültigkeit schlechter Software-Design-Gewohnheiten.
Ich habe hier eine Gegenargumentation gegen diese Hypothese geschrieben: Was ist der beste Weg, um Konstanten in Java zu implementieren? Erklärung der Grundlosigkeit dieser Hypothese.
Diese Frage war 10 Jahre lang offen geblieben, bis sie innerhalb von zwei Stunden geschlossen wurde, nachdem ich meine Gründe für die Berichtigung dieser Hypothese veröffentlicht hatte, wodurch die Unwilligkeit zur Debatte durch diejenigen entlarvt wurde, die an dieser fehlgeleiteten Hypothese festhielten.
Dies sind die Punkte, die ich gegen die Hypothese ausgesprochen habe
Die Grundlage für diese Hypothese ist die Notwendigkeit von Methoden und EINSCHRÄNKENDEN Regeln, um mit den Auswirkungen schlechter Softwaregewohnheiten und -methoden fertig zu werden.
Die Befürworter des Gefühls " Das konstante Schnittstellenmuster ist eine schlechte Verwendung von Schnittstellen" können keine anderen Gründe als die angeben, die durch die Notwendigkeit verursacht werden, mit den Auswirkungen dieser schlechten Gewohnheiten und Praktiken umzugehen.
Lösen Sie das grundlegende Problem.
Und warum nutzen Sie dann nicht alle Sprachfunktionen der Java-Sprachstruktur und nutzen sie nach Belieben. Keine Jacken erforderlich. Warum Regeln erfinden, um Ihren ineffektiven Lebensstil zu verbarrikadieren, um effektivere Lebensstile zu diskriminieren und zu belasten?
Das grundlegende Problem
ist Informationsorganisation. Informationen, die den Prozess vermitteln, und das Verhalten dieser Informationen sollten zuerst zusammen mit den sogenannten Geschäftsregeln verstanden werden, bevor Lösungen für den Prozess entwickelt oder ergänzt werden. Eine solche Methode der Informationsorganisation wurde vor einigen Jahrzehnten als Datennormalisierung bezeichnet.
Dann ist nur das Engineering einer Lösung möglich, da die Ausrichtung der Granularität und Modularität der Komponenten einer Lösung mit der Granularität und Modularität der Komponenten der Informationen die optimale Strategie ist.
Es gibt zwei oder drei wesentliche Hindernisse für die Organisation von Informationen.
Die mangelnde Wahrnehmung für die Notwendigkeit der "Normalisierung" des Datenmodells.
Die Aussagen von EF Codd zur Datennormalisierung sind fehlerhaft, fehlerhaft und mehrdeutig.
Die neueste Modeerscheinung, die sich als agiles Engineering tarnt, ist die falsche Vorstellung, dass man die Organisation von Modulen nicht im Voraus planen und konditionieren sollte, da man sie jederzeit umgestalten kann. Als Ausrede wird Refactoring und kontinuierlicher Wandel verwendet, ohne durch zukünftige Entdeckungen behindert zu werden. Wesentliche Entdeckungen des Verhaltens von Prozessinformationen sind dann, indem Buchhaltungstricks verwendet werden, um Gewinne und Assetisierung zu verzögern, weshalb wesentliche Kenntnisse und deren Behandlung jetzt als nicht erforderlich angesehen werden.
Die Verwendung von Schnittstellenkonstanten ist eine gute Praxis.
Machen Sie sich keine Regeln und stellen Sie keine Fatwa dagegen auf, nur weil Sie Ihre Ad-hoc-Programmiergewohnheiten lieben.
Verbieten Sie den Waffenbesitz nicht mit dem Grund, dass es Menschen gibt, die entweder nicht wissen, wie man mit Waffen umgeht, oder die dazu neigen, Waffen zu missbrauchen.
Wenn die Regeln, die Sie zusammenstellen, für Programmieranfänger gedacht sind, die nicht professionell codieren können und zu denen Sie sich selbst zählen, sagen Sie dies - deklarieren Sie Ihre Fatwa nicht als für ordnungsgemäß normalisierte Datenmodelle anwendbar.
Eine dumme Argumentation - Interfaces sollten von den Flundern der Java-Sprache nicht so verwendet werden?
Es ist mir egal, was die ursprünglichen Absichten der Gründerväter für die US-Verfassung hatten. Die ungeschriebenen, nicht kodifizierten Absichten sind mir egal. Mir ist nur wichtig, was in der schriftlichen Verfassung literarisch kodifiziert ist und wie ich sie für das effektive Funktionieren der Gesellschaft nutzen kann.
Ich kümmere mich nur darum, was mir die Java-Sprach- / Plattformspezifikationen erlauben, und ich beabsichtige, sie voll auszunutzen, um mir ein Medium zu bieten, mit dem ich meine Softwarelösungen effizient und effektiv ausdrücken kann. Keine Jacken erforderlich.
Die Verwendung von Enum-Konstanten ist eigentlich eine schreckliche Praxis.
Es ist erforderlich, zusätzlichen Code zu schreiben, um Parameter dem Wert zuzuordnen. Die Tatsache, dass die Gründer von Java keine Parameter-Wert-Zuordnung bereitgestellt haben, ohne dass Sie geschrieben haben, dass der Zuordnungscode Enum-Konstanten demonstriert, ist eine ebenso unbeabsichtigte Verwendung der Java-Sprache.
Insbesondere, da Sie nicht dazu ermutigt werden, Ihre Parameter zu normalisieren und zu komponieren, besteht der falsche Eindruck, dass in einen Enum-Beutel gemischte Parameter zur gleichen Dimension gehören.
Konstanten sind API-Verträge
Vergiss das nicht. Wenn Sie Ihr Datenmodell entworfen und normalisiert haben und es Konstanten enthält, sind diese Konstanten Verträge. Wenn Sie Ihr Datenmodell nicht normalisiert haben, sollten Sie sich an die Anweisungen halten, wie man restriktives Codieren praktiziert, um mit dieser schlechten Angewohnheit umzugehen.
Daher sind Schnittstellen eine perfekte Möglichkeit, den Vertrag von Constants umzusetzen.
Eine seltsame Vermutung - Was ist, wenn die Schnittstelle versehentlich implementiert wird?
Jep. Jeder könnte versehentlich eine Schnittstelle versehentlich implementieren. Solch unbeabsichtigten Programmierern wird nichts im Wege stehen.
Entwerfen und normalisieren Sie Ihr Datenmodell gegen Leckagen
Platzieren Sie keine restriktiven Dekrete, um vermutete schlechte Praktiken zu schützen, die dazu führen, dass nicht kontrahierte / streunende Parameter in die API gelangen. Lösen Sie das grundlegende Problem, anstatt die Schnittstellenkonstanten dafür verantwortlich zu machen.
Die Nichtverwendung einer IDE ist eine schlechte Praxis
Eine normal funktionierende und EFFEKTIVE Programmiererin ist nicht da, um zu beweisen, wie lange sie unter Wasser bleiben kann, wie weit sie bei glühender Hitze oder nassen Gewittern gehen kann. Sie soll ein effizientes Werkzeug wie ein Auto oder einen Bus oder zumindest ein Fahrrad verwenden, um ihre 10 Meilen täglich zur Arbeit zu bringen.
Legen Sie keine Einschränkungen für andere Programmierer fest, nur weil Sie von der Programmierung ohne IDE besessen sind.
Einige Frameworks sollen Programmierern helfen, weiterhin schlechte Gewohnheiten effizient zu üben.
OSGI ist ein solcher Rahmen. Und so ist auch das Dekret gegen Schnittstellenkonstanten.
Daher die schlüssige Antwort ...
Schnittstellenkonstanten sind eine effektive und effiziente Möglichkeit, gut gestaltete und normalisierte Komponenten eines Datenmodells in Contract einzufügen.
Schnittstellenkonstanten in einer entsprechend benannten privaten Schnittstelle, die in einer Klassendatei verschachtelt ist, sind auch eine gute Vorgehensweise, um alle Ihre privaten Konstanten zu gruppieren, anstatt sie über die gesamte Datei zu verteilen.
quelle
Ich bin jetzt mehrmals auf diese alte Frage gestoßen und die akzeptierte Antwort verwirrt mich immer noch. Nach langem Nachdenken denke ich, dass diese Frage weiter geklärt werden kann.
Warum Schnittstellenkonstante verwenden?
Vergleichen Sie sie einfach:
vs.
Gleiche Verwendung. Viel weniger Code.
Schlechte Praxis?
Ich denke, die Antwort von @Pascal Thivent hat die falsche Betonung, hier ist meine Version davon:
Das Zitat von Effective Java geht davon aus, dass die konstante Schnittstelle von anderen implementiert wird, was meiner Meinung nach nicht passieren sollte (und auch nicht passieren wird).
Wenn Sie eine konstante Schnittstelle mit dem Namen "So etwas" erstellen
Constants
, sollte diese von niemandem implementiert werden. (obwohl technisch möglich, was hier das einzige Problem ist)In der Standardbibliothek wird dies nicht passieren
Die Standardbibliothek kann sich keinen möglichen Missbrauch des Designs leisten, sodass Sie dort einfach keinen sehen.
Allerdings , für die täglichen Projekte des normalen Entwicklers, mit Konstanten Schnittstelle viel einfacher ist , weil man sich keine Sorgen machen braucht über
static
,final
,empty constructor
, etc, und es wird kein schlechtes Design - Problem verursachen. Der einzige Nachteil, den ich mir vorstellen kann, ist, dass es immer noch den Namen "Schnittstelle" hat, aber nichts weiter.Unendliche Debatte
Am Ende denke ich, dass jeder nur aus Büchern zitiert und seinen Ständen Meinungen und Rechtfertigungen gibt. Keine Ausnahme für mich. Vielleicht liegt die Entscheidung immer noch bei den Entwicklern jedes Projekts. Verwenden Sie es einfach, wenn Sie sich wohl fühlen. Das Beste, was wir tun können, ist, es während des gesamten Projekts konsistent zu machen .
quelle
public
kann auch weggelassen werden, da es sich um eine Schnittstelle handelt, sodass diedouble PI = 3.14159;
Verwendung vonConstants.PI
die Klasse nicht benötigt, um dieConstants
Schnittstelle zu implementieren . Ich denke, Interface-Ansatz ist viel sauberer in Bezug auf die Nutzung, IMHOJoshua Bloch, "Effektives Java - Programmiersprachenhandbuch":
quelle
Sie sind nützlich, wenn Sie gemeinsame Konstanten haben, die in Klassen verwendet werden, die die Schnittstelle implementieren.
Hier ist ein Beispiel: http://www.javapractices.com/topic/TopicAction.do?Id=32
Beachten Sie jedoch, dass die empfohlene Vorgehensweise darin besteht, statische Importe anstelle von Konstanten in Schnittstellen zu verwenden. Hier ist eine Referenz: http://www.javapractices.com/topic/TopicAction.do?Id=195
quelle
Es gibt Antworten, die sehr vernünftig sind.
Aber ich habe einige Gedanken zu dieser Frage. (kann falsch sein)
Meiner Meinung nach sollten die Felder in einer Schnittstelle keine Konstanten für das gesamte Projekt sein, sie sind nur Mittel für die Schnittstelle und die Schnittstellen erweitern sie und die Klassen, die diese Schnittstellen implementieren oder in enger Beziehung zu ihnen stehen. Sie sollten in einem bestimmten Bereich verwendet werden, der nicht global ist.
quelle
Zwei Punkte zur Schnittstelle:
Eine Schnittstelle beschreibt eine Teilmenge dessen, was ein Objekt, das es implementiert, tun kann. (Dies ist die Intuition)
Eine Schnittstelle beschreibt allgemeine Konstanten, gefolgt von Objekten, die sie implementieren.
Ich denke also, wenn die Konstantenschnittstelle nicht für globale Konstanten verwendet wird , ist dies akzeptabel:
implements
das (und natürlich diese allgemeinen Konstanten bei der Implementierung verwenden).Beispiel:
In diesem Beispiel:
Circle implements Drawable
wissen Sie sofort, dass diesCircle
wahrscheinlich den in definierten Konstanten entsprichtDrawable
, sonst müssen sie einen schlechteren Namen wählen als die gutenPI
und wurdenGOLDEN_RATIO
bereits vergeben!Drawable
Objekte entsprechen dem spezifischenPI
undGOLDEN_RATIO
definierten inDrawable
, es kann Objekte geben, die nichtDrawable
mit unterschiedlicher Genauigkeit von pi und goldenem Schnitt sind.quelle
Die
javax.swing.SwingConstants
Schnittstelle ist ein Beispiel mit statischen Feldern, die in den Swing-Klassen verwendet werden. Dies ermöglicht es Ihnen, so etwas einfach zu verwendenthis.add(LINE_START, swingcomponent);
this.add(this.LINE_START, swingcomponent);
oderthis.add(SwingComponents.LINE_START, swingcomponent);
Diese Schnittstelle hat jedoch keine Methoden ...
quelle
Ich bin auf diese Frage gestoßen und dachte, ich würde etwas hinzufügen, das nicht erwähnt wurde. Im Allgemeinen stimme ich Pascals Antwort hier zu . Ich denke jedoch nicht, dass Konstanten auf einer Schnittstelle "immer" ein Antimuster sind.
Wenn beispielsweise die von Ihnen definierten Konstanten Teil eines Vertrags für diese Schnittstelle sind, ist die Schnittstelle meiner Meinung nach ein großartiger Ort für die Konstanten. In einigen Fällen ist es einfach nicht angebracht, Ihre Parameter privat zu validieren, ohne den Vertrag den Benutzern Ihrer Implementierung zugänglich zu machen. Ohne einen öffentlich zugänglichen Vertrag können Benutzer nur raten, womit Sie validieren, ohne die Klasse zu dekompilieren und Ihren Code zu lesen.
Wenn Sie also eine Schnittstelle implementieren und die Schnittstelle die Konstanten enthält, die Sie zur Sicherstellung Ihrer Verträge verwenden (z. B. ganzzahlige Bereiche), kann ein Benutzer Ihrer Klasse sicher sein, dass er die Schnittstelleninstanz korrekt verwendet, indem er die Konstanten in der Schnittstelle vergleicht sich. Dies wäre unmöglich, wenn die Konstanten für Ihre Implementierung privat wären oder Ihre Implementierung paketprivat wäre oder so.
quelle
Ich verwende Schnittstellenkonstanten, wenn ich mit gemeinsam genutzten Konstanten zwischen Klassen arbeite.
Die Gruppierung ist ein großer Vorteil, insbesondere bei einer großen Anzahl von Konstanten.
Zur Verwendung verketten Sie sie einfach miteinander:
quelle
Quelle: Java Developer Tools Codierungsstil
quelle