Benennung der Schnittstelle in Java [geschlossen]

324

Die meisten OO-Sprachen stellen ihren Schnittstellennamen ein Großbuchstaben I voran. Warum macht Java das nicht? Was war der Grund dafür, diese Konvention nicht zu befolgen?

Um zu demonstrieren, was ich meine, hätte ich in Java zwei Möglichkeiten, wenn ich eine Benutzeroberfläche und eine Benutzerimplementierung haben wollte:

  1. Klasse = Benutzer, Schnittstelle = Benutzerschnittstelle
  2. Klasse = UserImpl, Schnittstelle = Benutzer

Wo in den meisten Sprachen:

Klasse = Benutzer, Schnittstelle = IUser

Nun könnten Sie argumentieren, dass Sie immer einen aussagekräftigen Namen für die Benutzerimplementierung auswählen könnten und das Problem verschwindet, aber Java drängt auf einen POJO-Ansatz und die meisten IOC-Container verwenden DynamicProxies in großem Umfang. Diese beiden Dinge zusammen bedeuten, dass Sie viele Schnittstellen mit einer einzigen POJO-Implementierung haben.

Ich denke, meine Frage läuft darauf hinaus: "Lohnt es sich, die umfassendere Namenskonvention für Schnittstellen zu befolgen, insbesondere angesichts der Richtung, in die Java Frameworks zu gehen scheinen?"

Allain Lalonde
quelle
61
"Wo in den meisten Sprachen"? Welche Sprachen außer den .Net?
WDS
2
Unterschiedliche Sprachgemeinschaften haben unterschiedliche Namenskonventionen, und dies gilt seit langem. Herauszufinden, wie die Namenskonventionen entstanden sind, ist manchmal im Wesentlichen Folkloreforschung.
David Thornley
4
Eclipse ist ein bedeutender Ausreißer, der Java mit Namen im IFoo-Stil verwendet. wiki.eclipse.org/Naming_Conventions
David Leonard
2
Wenn Sie einen Blick auf Namen von Schnittstellen in Android SDK (Java als auch) nehmen, werden Sie sehen , dass sie am Ende einer Schnittstelle Namenskonvention der mit Wort Schnittstelle verwendet, wie NetworkInterface, DialogInterfaceetc.
sandalone
21
Wie kann diese Frage "als nicht konstruktiv geschlossen" werden, wenn sie so beliebt und für so viele Menschen von Interesse ist?
Inor

Antworten:

329

Ich bevorzuge es, kein Präfix für Schnittstellen zu verwenden:

  • Das Präfix beeinträchtigt die Lesbarkeit.

  • Die Verwendung von Schnittstellen in Clients ist die beste Standardmethode zum Programmieren. Daher sollten die Namen der Schnittstellen so kurz und angenehm wie möglich sein. Das Implementieren von Klassen sollte hässlicher sein, um von ihrer Verwendung abzuraten.

  • Beim Wechsel von einer abstrakten Klasse zu einer Schnittstelle impliziert eine Codierungskonvention mit Präfix I das Umbenennen aller Vorkommen der Klasse - nicht gut!

Sternenblau
quelle
12
Stimme voll und ganz zu. Ein weiterer Schlüssel, den Sie eingeben müssen, wenn Sie die automatische Vervollständigung verwenden. Viele Dateien beginnen mit einem I.
Kalecser
85
Jede anständige IDE erleichtert das Ändern des Codes in der von Ihnen beschriebenen Weise. Außerdem bin ich mir ziemlich sicher, dass Ihre Clients beim Wechsel von einer abstrakten Klasse zu einer Schnittstelle ohnehin neu kompilieren müssen.
Allain Lalonde
63
Super spät hier, aber: Es spielt keine Rolle , überhaupt , wenn ein IDE macht einfach , die Namen etwas zu ändern. Code, der eine Instanz eines Typs verwendet, sollte sich niemals darum kümmern, ob dieser Typ eine Schnittstelle oder eine Klasse ist oder was. Daher ist es sinnlos und schädlich für das Verständnis, ein solches Detail im Namen des Typs offenzulegen. Auf die Art und den Vertrag kommt es an!
ColinD
11
Außerdem, wenn Sie den Weg von IFoo gehen, sollte es nicht CFoo für die Implementierung sein und natürlich würde eine Methode bei einem Fehler ein EFoo auslösen.
Robin
57
"Das Präfix schadet der Lesbarkeit" ist rein subjektiv. Wie die meisten Namenskonventionen. Es ist wichtiger, dass sich Ihr Team darauf einigt, was zu tun ist, damit die Codebasis konsistent ist.
Dreadwail
121

Gibt es wirklich einen Unterschied zwischen:

class User implements IUser

und

class UserImpl implements User

Wenn es nur um Namenskonventionen geht?

Persönlich bevorzuge ich vorhergehenden NICHT die Schnittstelle , Iwie ich will an die Schnittstelle zu Codierung und ich denke , dass in Bezug auf die Namenskonvention wichtiger sein. Wenn Sie die Schnittstelle aufrufen, muss IUserjeder Verbraucher dieser Klasse wissen, dass es sich um eine Schnittstelle handelt IUser. Wenn Sie die Klasse aufrufen, UserImplwissen nur die Klasse und Ihr DI-Container über das ImplTeil Bescheid, und die Verbraucher wissen nur, dass sie mit einem arbeiten User.

Andererseits war die Zeit, die ich verwenden musste, Implweil sich kein besserer Name anbietet, selten, weil die Implementierung entsprechend der Implementierung benannt wird, weil es dort wichtig ist, z

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO
tddmonkey
quelle
Ich denke, Sie möchten wissen, dass es sich um ein DAO handelt, da dies die allgemeine Funktionalität beschreibt, ohne dass die Klasse geöffnet werden muss. Wenn ich die Klassendateien in einem Projekt durchschaue, ist es einfach, alle DAOs zu sehen, indem ich nach * DAO
Patrick
6
DAO ist ein bekanntes Muster für den Datenbankzugriff. Wenn Sie also das Muster im Namen haben, können Sie leicht erkennen, was die Klasse tut, indem Sie sich nur den Namen ansehen. PS Es wäre besser, die Kamelnotation genau zu befolgen ("AccountDao"), wie in mina.apache.org/changes-between-2x-and-1x.html
Esko Luontola
4
@marker, es ist nicht so, als hätte man ein I, um eine Schnittstelle anzuzeigen. DAO teilt Ihnen mit, dass die Klasse oder Schnittstelle ein Objekt für den Zugriff auf Kontodaten ist, wie es das Objekt tut. Ein I zu haben sagt dir, dass es eine Schnittstelle ist, die nichts mit dem Objekt selbst zu tun hat, sondern mit der Semantik der Sprache
tddmonkey
Während Sie es präsentieren, ist das Präfix vs Suffix.
Andrei Rînea
3
@Andrei: Nein, es ist Semantik ("DAO") vs. unnötige Dekoration eines Sprachartefakts ("I" wie in der Schnittstelle; eine Tatsache, die im Code sowieso "Schnittstelle IFoo ..." erwähnt wird)
Dirk
75

Es kann mehrere Gründe geben, warum Java die IUser-Konvention im Allgemeinen nicht verwendet.

  1. Ein Teil des objektorientierten Ansatzes besteht darin, dass Sie nicht wissen müssen, ob der Client eine Schnittstelle oder eine Implementierungsklasse verwendet. Selbst wenn List eine Schnittstelle und String eine tatsächliche Klasse ist, wird möglicherweise eine Methode an beide übergeben. Es ist nicht sinnvoll, die Schnittstellen visuell zu unterscheiden.

  2. Im Allgemeinen bevorzugen wir die Verwendung von Schnittstellen im Client-Code (z. B. List gegenüber ArrayList). Es ist also nicht sinnvoll, die Schnittstellen als Ausnahmen hervorzuheben.

  3. Die Java-Namenskonvention bevorzugt längere Namen mit tatsächlichen Bedeutungen gegenüber Präfixen im ungarischen Stil. Damit dieser Code so gut wie möglich lesbar ist: Eine Liste repräsentiert eine Liste, und ein Benutzer repräsentiert einen Benutzer - keinen IUser.

Avi
quelle
72

Es gibt auch eine andere Konvention, die von vielen Open-Source-Projekten einschließlich Spring verwendet wird.

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

Ich persönlich mag das Präfix "I" nicht aus dem einfachen Grund, dass es eine optionale Konvention ist. Wenn ich dies übernehme, bedeutet IIOPConnection dann eine Schnittstelle für IOPConnection? Was ist, wenn die Klasse nicht das Präfix "I" hat? Weiß ich dann, dass es sich nicht um eine Schnittstelle handelt? Die Antwort hier lautet "Nein", da Konventionen nicht immer befolgt werden und ihre Überwachung mehr Arbeit schafft, als die Konvention selbst spart.

ng.
quelle
Ich mag das, da es Ihnen auch hilft, Schnittstellen für externe Abhängigkeiten zu verwenden, anstatt die Klassen zu koppeln.
Matt Briggs
47

Wie in einem anderen Poster bereits erwähnt, ist es normalerweise vorzuziehen, dass Schnittstellen Funktionen und keine Typen definieren. Ich würde dazu neigen, so etwas wie einen "Benutzer" nicht zu "implementieren", und deshalb ist "IUser" in der hier beschriebenen Weise oft nicht wirklich notwendig. Ich sehe Klassen oft als Substantive und Schnittstellen als Adjektive:

class Number implements Comparable{...}  
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}

Manchmal macht ein Adjektiv keinen Sinn, aber ich würde im Allgemeinen immer noch Schnittstellen verwenden, um Verhalten, Aktionen, Funktionen, Eigenschaften usw. zu modellieren, nicht Typen.

Wenn Sie wirklich nur einen Benutzer erstellen und ihn als Benutzer bezeichnen würden, was bringt es dann, auch eine IUser-Oberfläche zu haben? Und wenn Sie einige verschiedene Benutzertypen haben, die eine gemeinsame Schnittstelle implementieren müssen, was erspart Ihnen das Anhängen eines "I" an die Schnittstelle bei der Auswahl der Namen der Implementierungen?

Ich denke, ein realistischeres Beispiel wäre, dass einige Benutzertypen sich bei einer bestimmten API anmelden müssen. Wir könnten eine Anmeldeschnittstelle definieren und dann eine übergeordnete Klasse "Benutzer" mit den Klassen SuperUser, DefaultUser, AdminUser, AdministrativeContact usw. haben, von denen einige die Anmeldeschnittstelle (Anmeldefähig?) Nach Bedarf implementieren oder nicht.

nairbv
quelle
Ich denke, die Beispiele, die Sie zur Unterstützung von "Schnittstellen als Adjektive" bereitstellen, sind verzerrt, da diese Schnittstellen eher Mix-Ins (oder Eigenschaften) ähneln sollen. Somit sind Schnittstellen sowohl für Adjektive als auch für Substantive gut - aber wahrscheinlich nicht für indefinite transitive verbs 8 ^ P
Stevel
Dies könnte sich in den letzten Jahren geändert haben. Das Orakel-Dokument. erlaubt Schnittstellen als Typen: [link] docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html
karlihnos
38

Bob Lee sagte einmal in einer Präsentation:

Was bringt eine Schnittstelle, wenn Sie nur eine Implementierung haben?

Sie beginnen also mit einer Implementierung, dh ohne Schnittstelle. Später entscheiden Sie, dass hier eine Schnittstelle erforderlich ist, und konvertieren Ihre Klasse in eine Schnittstelle.

dann wird klar: Ihre ursprüngliche Klasse hieß Benutzer. Ihre Schnittstelle heißt jetzt Benutzer. Vielleicht haben Sie ein UserProdImpl und ein UserTestImpl. Wenn Sie Ihre Anwendung gut entworfen haben, bleibt jede Klasse (mit Ausnahme derjenigen, die den Benutzer instanziieren) unverändert und merkt nicht, dass sie plötzlich eine Schnittstelle erhalten.

so wird es klar -> Schnittstelle Benutzerimplementierung UserImpl.

Andreas Petersson
quelle
18
Die Verwendung von Schnittstellen hilft bei der testgetriebenen Entwicklung. Wir sind auf zahlreiche Probleme ohne Domain-Modell und Tests gestoßen, weil wir uns entschieden haben, KEINE Schnittstellen zu verwenden. Ein Freund von mir zitierte einmal: "Alles ist eine Schnittstelle, es wird Sie auf lange Sicht retten."
Hooknc
4
Verspottende und einfache Proxy-Unterstützung. Ich bin mir sicher, dass es auch andere Gründe gibt, Schnittstellen bereitzustellen.
MetroidFan2002
3
Wie ich kürzlich einem Kollegen sagte, kostet es nichts, jetzt eine Schnittstelle einzuführen, aber Sie können später viel Zeit sparen.
tddmonkey
2
Wenn Sie in naher Zukunft andere Implementierungen haben könnten, wäre eine Schnittstelle ein Plus.
Stef
3
Ich mag das Argument "Ich könnte in Zukunft ein anderes Gerät brauchen" nicht. Ich bevorzuge einen YAGNI-Ansatz: Planen Sie keine Dinge, die noch nicht geschehen sind.
David Lavender
24

In C # ist es

public class AdminForumUser : UserBase, IUser

Java würde sagen

public class AdminForumUser extends User implements ForumUserInterface

Aus diesem Grund denke ich, dass Konventionen in Java für Schnittstellen nicht annähernd so wichtig sind, da es einen expliziten Unterschied zwischen Vererbung und Schnittstellenimplementierung gibt. Ich würde sagen, wählen Sie einfach eine beliebige Namenskonvention, solange Sie konsistent sind und etwas verwenden, um den Leuten zu zeigen, dass dies Schnittstellen sind. Ich habe seit ein paar Jahren kein Java mehr gemacht, aber alle Schnittstellen befinden sich nur in einem eigenen Verzeichnis, und das war die Konvention. Hatte nie wirklich Probleme damit.

Matt Briggs
quelle
22
Vielleicht bin ich ein schlechter Java-Codierer, aber ich bevorzuge den C # -Stil. Das bedeutet, dass alle Schnittstellen mit dem Präfix 'I' beginnen :)
Davs
7
Ich bin mir nicht sicher, woher Sie und andere diese angebliche Konvention beziehen. Es ist nicht in den Java-Bibliotheken ersichtlich ...
ChiefTwoPencils
6

Nach meiner Erfahrung gilt die "I" -Konvention für Schnittstellen, die einen Vertrag für eine Klasse bereitstellen sollen, insbesondere wenn die Schnittstelle selbst kein abstrakter Begriff der Klasse ist.

In Ihrem Fall würde ich beispielsweise nur erwarten, IUserob der einzige Benutzer, den Sie jemals haben möchten, der ist User. Wenn Sie verschiedene Arten von Benutzern haben planen - NoviceUser, ExpertUserusw. - ich würde erwarten , dass eine sehen UserSchnittstelle (und vielleicht eine AbstractUserKlasse, die implementiert einige gemeinsame Funktionalität, wie get/setName()).

Ich würde auch Schnittstellen erwarten , die Fähigkeiten definieren - Comparable, Iterableusw. - zu so genannt zu werden, und nicht wie IComparableoder IIterable.

David Koelle
quelle
Wenn der einzige Benutzer, den Sie jemals haben möchten, Benutzer ist, warum nicht einfach Benutzer anstelle der Benutzeroberfläche verwenden?
Carighan
3
In einigen Client / Server-Architekturen muss die Client-Seite die Schnittstellen kennen, ohne dass die Server-Implementierungen im Schwergewicht erforderlich sind.
David Koelle
5

Nach guten OO-Prinzipien sollte Ihr Code (soweit praktikabel / möglich) eher von Abstraktionen als von konkreten Klassen abhängen. Zum Beispiel ist es im Allgemeinen besser, eine Methode wie diese zu schreiben:

public void doSomething(Collection someStuff) {
    ...
}

als das:

public void doSomething(Vector someStuff) {
    ...
}

Wenn Sie dieser Idee folgen, ist Ihr Code meiner Meinung nach besser lesbar, wenn Sie Schnittstellennamen wie "Benutzer" und "Bankkonto" (z. B.) anstelle von "IUser", "Benutzerschnittstelle" oder anderen Variationen angeben.

Die einzigen Codebits, die sich um die tatsächlichen konkreten Klassen kümmern sollten, sind die Stellen, an denen die konkreten Klassen erstellt werden. Alles andere sollte über die Schnittstellen geschrieben werden.

Wenn Sie dies tun, sollten die "hässlichen" konkreten Klassennamen wie "UserImpl" sicher vor dem Rest des Codes verborgen sein, der fröhlich mit den "netten" Schnittstellennamen fortfahren kann.

KarstenF
quelle
Aber warum sollten Sie sich die Mühe machen, für jede Klasse in Ihrem Programm eine passende Schnittstelle zu erstellen, wenn Sie nur Schnittstellen für ein oder zwei Dinge benötigen?
LegendLength
3

= v = Das Präfix "I" wird auch im Wicket-Framework verwendet, an das ich mich schnell gewöhnt habe. Im Allgemeinen begrüße ich jede Konvention, die umständliche Java-Klassennamen verkürzt. Es ist jedoch problematisch, dass in den Verzeichnissen und im Javadoc alles unter "I" alphabetisch sortiert ist.

Die Wicket-Codierungspraxis ähnelt der von Swing, da viele Steuerungs- / Widget-Instanzen als anonyme innere Klassen mit Inline-Methodendeklarationen erstellt werden. Ärgerlicherweise unterscheidet es sich um 180 ° von Swing darin, dass Swing ein Präfix ("J") für die implementierenden Klassen verwendet.

Das Suffix "Impl" ist eine knappe Abkürzung und lässt sich nicht gut internationalisieren. Wenn wir nur wenigstens mit "Imp" gegangen wären, wäre es niedlicher (und kürzer). "Impl" wird für IOC verwendet, insbesondere für Spring, also bleiben wir vorerst dabei. Es wird jedoch ein bisschen schizo nach 3 verschiedenen Konventionen in drei verschiedenen Teilen einer Codebasis.

Jym Dyer
quelle
0

Ist dies eine umfassendere Namenskonvention im eigentlichen Sinne? Ich bin eher auf der C ++ - Seite und nicht wirklich auf Java und Nachkommen. Wie viele Sprachgemeinschaften verwenden die I-Konvention?

Wenn Sie hier eine sprachunabhängige Namenskonvention für Shop-Standards haben, verwenden Sie diese. Wenn nicht, befolgen Sie die Namenskonvention für Sprachen.

David Thornley
quelle