Prefix I für ein Interface
-
Ich verstehe nicht wieso man in C# ein Interface speziell auszeichnet. Genauer, ich verstehe nicht, wieso ist es wichtig zu wissen, dass etwas ein Interface ist und keine Klasse.
Für mich ist es nur ein Implementationsdetail, ob jemand eine Klasse, abstrakte Klasse oder ein Interface nimmt und Implementationsdetails sollte man immer vor dem Benutzer verbergen. Wieso sollte es also für jemanden wichtig sein zu wissen, ob er ein Interface oder eine (abstrakte) Klasse benutzt?
In Java muss man die Schlüsselwörter
implements
undextends
benutzen, je nach dem ob es ein Interface oder eine Klasse ist. Aber Java hat kein Präfix I für Interfaces. In C# wird eine Klasse und ein Interface abgeleitet/implementiert durch die gleiche Schreibweise,class Foo : Klasse, InterfaceA, InterfaceB
. Mehrfachvererbung gibt es in C# nicht, also ist der zweite Name nach dem Doppelpunkt immer ein Interface.Ob man ein Interface oder eine Klasse implementiert, der Code verändert sich nicht, bis auf zwei Kleinigkeiten. Wenn man eine Klasse erweitert, dann hat man
base
zur Verfügung, aber nicht bei einem Interface. Ob manbase
zur Verfügung hat oder nicht, kann der Compiler einem sofort mitteilen. Wenn man eine Methode von einer (abstrakten) Basisklasse überschreibt, dann muss man das Schlüsselwortoverride
verwenden. Wenn man es nicht verwendet, meldet der Compiler einen Fehler. Somit braucht man hier nicht auf das Präfix zu vertrauen.Ein Interface hat keinen Ctor, somit kann man auch nicht versehentlich versuchen eine Instanz davon zu erstellen. Das ist das gleiche mit abstrakten Klassen und abstrakte Klassen haben keinen Präfix. Also sollten abstrakte Klassen auch einen Präfix haben. Später im Code kann man ein Interface ganz genau wie eine (abstrakte) Klasse benutzen. Es ist ja auch der Sinn eines Interfaces, man sollte immer den Interfaces Typen verwenden und nicht eine genaue Implementierung.
Es gibt also keinen Punkt im Code an dem man aus verstehen etwas unbeabsichtigt machen könnte, wenn man ein Interface mit einer Klasse verwechselt. Der Code unterscheidet sich nur in der (nicht) Benutzung von
override
und des (nicht) verfügbarenbase
. Beide Fälle deckt der Compiler ab und sind trivial.Wieso wird also ein Implementierungsdetail so propagiert? Gibt es einen Grund, wo es wirklich wichtig ist zu wissen ob ein Typ ein Interface ist und keine Klasse? Wieso haben dann abstrakte Klassen und Strukturen keinen Präfix? Ist der Präfix nur aus historischen Gründen oder weil man keinen besseren Namen für ein List Interface ausdenken kann als
IList
?Wieso macht man es nicht umgekehrt, ein Interface nennt man List und eine Implementierung nennt man
ListImp
? Der Name des Interfaces verwende ich überall im Code, aber den Namen der Implementierung verwende ich nur einmal und dann nie wieder. Oder man nennt die Implementierung nach dem was sie macht. Z.B. ArrayList implementiert List mit einem Array. HashMap implementiert eine Map mit einem Hash. LinkedList implementiert eine Liste als eine verketteten Liste.PS: Vor allem nervt das I wenn man über den Code redet. Dann ist immer die Rede von "Foo implementiert das I-List Interface". Da ist immer eine Pause im Satz, weil man extra einen Buchstaben sagen muss.
-
DEvent schrieb:
Dann ist immer die Rede von "Foo implementiert das I-List Interface". Da ist immer eine Pause im Satz, weil man extra einen Buchstaben sagen muss.
Dann lass doch einfach das I beim Sprechen weg. Jede Sprache hat so ihre Eigenheiten. Verwende nicht so viel Zeit/Buchstaben darauf. Dein Text umfasst etwa 3200 Buchstaben, die reichen fuer 3200 I's. C# ist mir bei manchen Sachen auch ein Raetsel.
-
Notationen ergeben nicht immer Sinn. Eher selten.
-
DEvent schrieb:
PS: Vor allem nervt das I wenn man über den Code redet. Dann ist immer die Rede von "Foo implementiert das I-List Interface". Da ist immer eine Pause im Satz, weil man extra einen Buchstaben sagen muss.
Tipp: Lies den Bezeichner richtig. Foo implementiert das Interface List.
Ansonsten, wie schon gesagt wurde, Notationen sind eine subjektive Angelegenheit. Irgendjemand bei Microsoft hatte wohl das Gefühl, dass es nötig sei. Was solls? Man kann sich darüber zu Tode ärgern oder es einfach aktzeptieren und damit leben.
Übrigens:
DEvent schrieb:
In C# wird eine Klasse und ein Interface abgeleitet/implementiert durch die gleiche Schreibweise,
class Foo : Klasse, InterfaceA, InterfaceB
. Mehrfachvererbung gibt es in C# nicht, also ist der zweite Name nach dem Doppelpunkt immer ein Interface.Was machst du, wenn du
class Foo : Something
hast? Dann ist nicht klar, obSomething
eine Klasse oder ein Interface ist. Aber das nur als Anmerkung, hat mit der restlichen Argumentation nichts zu tunGrüssli
-
Das ist die MS-Antwort auf iPhone und iMac.
-
Das hat doch nichts mit C# und MS zu tun. Ist doch mal wieder so ein typischer MS-Basher Posting. Namenskonventionen haben (und das solltest du wissen) keine technischen Gründe! Man wählt sie aus Geschmacksgründen.
Und als Beweis: in Eclipse (Java) sind alle Interfaces mit einem I-Prefix versehen:
`org.eclipse.core.runtime.IAdaptable
org.eclipse.core.runtime.IAdapterFactory
org.eclipse.help.IContext
`
Die Liste lässt sich beliebig forführen. Dummerweise programmieren wir seit ein paar Jahren auf der OSGi- und Eclipse-Plattform und bei uns gilt seit dem die Regel, mit Eclipse konform zu gehen, und auch unsere eigenen Interfaces mit einem I-Prefix zu versehen.
Und die AspectJ (java) macht das auch:
`org.aspectj.weaver.patterns.ITokenorg.aspectj.weaver.IWeaver`
Aber weißte was? Mir ist das heute egal. Ich habe mich am Anfang auch aufgeregt, aber ich muß diese Namenskonvention akzeptieren. Es ist letztendlich kein Beinbruch. Man kann sich auch über CamelCases u.a. Konventionen aufregen. Am Ende ist es die Entscheidung eines Projektes. Und C# bzw. das .NET-Framework hat nunmal dies Konvention. So ist das halt. Es is total blödsinnig zu sagen, das die Namenskonvention nur beim .NET-Framework so ist. Man sieht an der Java-Welt, das es doch eine verbreitete Praxis ist.
-
Naja, man könnte als Erklärung genausogut sagen, dass die MS Programmierer so traurig waren dass sie jetzt kein C mehr vor alle Klassen schreibe dürfen, dass man ihnen als Trostpflaster das I bei Interfaces gegeben hat
Ist natürlich Unsinn, aber im Endeffekt ist alles nur dahergeraten, solange keiner mit einem Artikel/Interview/Paper von einem an der Entscheidung beteiligten MS Mitarbeiter vorweisen kann.
OK, etwas realistischeres gerate: Man hat oft Fälle wo es für ein Interface genau eine Implementierung gibt, die der "Normalfall" ist. Bzw. die man als "Standardlösung" anbieten möchte. Oft wäre der "natürliche" Name für diese Klasse und der "natürliche" Name für die Klasse dann gleich. "List" ist dafür eh schon ein gutes Beispiel. Nun kann man, wenn beide im selben Namespace leben, dafür aber nicht den selben Namen verwenden. Es immer irgendwie zu machen ist auch furchtbar, also braucht man ein System. Mir bekannte Systeme sind:
* "Abstract" (oder ein anderes Wort ala "Any", "Generic", ...) als Prefix für Interfaces. Ist je nach verwendetem Wort schön verständlich, dafür furchtbar lange "AbstractList<AbstractFile>" -> bäh. Noch ein Nachteil (wenn man als Wort "abstract" wählt): ungünstig für Sprachen wo es eine strikte Trennung zwischen abstrakten Klassen und Interfaces gibt. In C++ gibt es die nicht, in C# oder Java schon. Ein Interface in C# oder Java "AbstractXxx" zu nennen wäre also mehr als nur verwirrend.
* "I" (oder einen anderen Buchstaben - wobei ich noch nie was anderes als "I" gesehen hätte) als Prefix für Interfaces. Im Prinzip dasselbe, nur minimal schlechter verständlich (=für alle ausser Noobs gleich gut verständlich), dafür viel kürzer. "IList<IFile>" -> schon viel besser.
* Irgendwas (Buchstabe oder Wort) als Prefix für Klassen. *schauder*, mehr will ich dazu garnicht schreiben.
* Die Javarianer-Variante: Interfaces heissen einfach nur "List", "File" etc., Implementierungen heissen XxxList/XxxFile, wobei Xxx etwas ist was Aufschluss über die Art/Besonderheiten der Implementierung gibt. Das führt dann zu so eigenartigen Namen wie ArrayList. Was die Interface Namen angeht auch alles schön kurz: "List<File>" -> supi. Allerdings ist nicht klar ersichtlich was nun ein Interface ist und was nicht. Ob das nun ein Nachteil ist oder nicht ist Ansichtssache, darüber will ich mich mal nicht auslassen. Kommt IMO auch stark drauf an, wie gut man ein Framework schon kennt. Wenn ich 95% der wichtigsten Interfaces namentlich kenne, ist es vermutlich egal. Weiterer Nachteil: diese Regelung ist viel "schwammiger" als die "jedes Interface fängt mit I an" Variante. Einige Klassen implementieren mehr als nur ein Interface, und manchmal ist auch nicht 100% klar welches als das "primäre" Interface angesehen werden kann, nach dem die Klasse benannt werden sollte. Zusätzlich führt es zu Problemen wenn Interfaces nachträglich eingeführt werden.
Wenn die ArrayList Klasse zu einem Zeitpunkte geschrieben worden wäre wo es noch kein List Interface gegeben hat, hätte sie sicher einen anderen Namen bekommen - z.B. einfach nur Array oder DynamicArray. Führt man nachträglich das Interface List ein, dann hat die Klasse auf einmal den falschen Namen.Vermutlich gibt es noch weieter Varianten die mehr oder weniger Sinn machen, aber das sind die drei die ich kenne (EDIT: muaha, ich kann zählen, erhlich. Die "Prefix für Klassen" Variante hab ich nach diesem Absatz eingefügt und dann übersehen dass hier "drei" steht .... /EDIT). Von denen hat MS sich halt die "I" Variante ausgesucht, IMO keine ganz dumme Idee.
-
Vielleicht hat man das I in Anlehnung an die COM Objekte (IMesh, IUnkown) übernommen. :p
-------------
"Ist alles Geschmackssache" sagte der Affe und biss in die Seife.Aus "Wie schreibe ich unleserlichen Code":
Ungarische Notation ist die taktische Nuklear-Waffe im Kampf gegen lesbaren Code: benutze sie! Während bereits eine unvollstellbare Menge an Source-Code damit kontaminiert ist, kann nichts anderes einen Wartungs-Ingenieur schneller außer Gefecht setzen als ein wohlüberlegter Angriff mittels Ungarischer Notation. Die folgenden Tipps helfen, die ursprüngliche Absicht der Ungarischen Notation zu unterlaufen:
* Bestehe auf "c", um eine konstante Variable zu kennzeichnen.
* Suche nach Kürzel, die in anderen Sprachen eine andere Bedeutung haben. Bestehe z.B. auf PowerBuilders "l_" und "a_" (local and argument) Präfixe, verwende VB-Style für jeden Kontroll-Typ, auch wenn Du in Java programmierst. Ignoriere die Tatsache, dass sich Mega-Bytes an sichtbaren MFC-Source-Code auch nicht daran hält.
* Verletze das Ungarische Prinzip, dass die am häufigsten verwendeten Variablen nur die wichtigste Information mit sich tragen soll.Bestehe darauf, dass jeder Klassentyp seinen eigenen Präfix bekommt. Erlaube niemanden auf die Idee zu kommen, dass etwas ohne Präfix bedeutet, dass es eine Klasse ist. Unterschätze nicht die Wirkung - ein Scheitern dieser Maßnahme bedeutet, dass der Source Code mit kürzeren Variablennamen überflutet wird, die eine höhere Vokal/Konsonanten-Verhältnis aufweisen. Im schlimmsten Fall kann das dazu führen, dass die ganze Verschleierungs-Technik zusammenbricht und zum spontanen Wiedererscheinen von lesbaren Begriffen im Code führt!
* Verletze das Ungarische Konzept, dass Funktions-Parameter und andere sichtbaren Symbole einen bedeutsamen Namen erhalten sollen. Die Ungarischen Kürzel eignen sich hervorragend, um daraus exzellente temporäre Variablen zu machen.
* Bestehe darauf, dass Deine Ungarischen Kürzel ganz und gar orthogonale Informationen tragen können. Betrachte dazu dieses "Real-World"-Beispiel: "a_crszkvc30LastNameCol". Es beschäftigte eine Team von Wartungs-Ingenieuren fast 3 Tage lang um herauszubekommen, dass dieses Ungetüm von Variablennamen folgendes beschreibt: ein konstanter String, der als Referenz vorliegt, und der die Information einer Datenbank-Spalte vom Typ Varchar[30] mit Namen "LastName" enthält und Bestandteil des Primärschlüssels ist.
* Nutze die Tatsache aus, dass das menschliche Hirn nur 7 Informationen gleichzeitig aufnehmen kann. Damit ergeben sich folgende Eigenschaften für den Source-Code:
o eine einzelne Zuweisung trägt bereits 14 Informationen
o eine einzelne Funktion mit 3 Parametern und Rückgabewert beinhaltet bereits 29 Informationen
o baue den Standard aus: beindrucke das Management und Mitarabeiter mit der Einführung einer aus 5 Zeichen bestehende Wochentag-Angabe wie z.B. "Monam" und "FriPM".
-
Was auch immer der Grund ist, Microsoft verwendet es konsequent im Framework.
Steht auch in den Interface naming conventions.
Wir halten uns auch an die MS naming convention für unseren Code, und dadurch sieht es schon sehr sauber und aufgeräumt aus
-
ich find das fehlende C vor den Klassen schade, aber was solls.
-
Ich würde mich so sehr darüber aufregen, aber es ist ein Implementatierungsdetail, ob ich ein Interface verwende. Was, wenn ich morgen anstelle des Interfaces eine Klasse anbieten? Dann muss man überall das IFoo in Foo umbenennen, was überhaupt nicht nötig wäre.
Die Javarianer-Variante: Interfaces heissen einfach nur "List", "File" etc., Implementierungen heissen XxxList/XxxFile, wobei Xxx etwas ist was Aufschluss über die Art/Besonderheiten der Implementierung gibt. Das führt dann zu so eigenartigen Namen wie ArrayList.
Wieso eigenartig? Du hast das List Interface und du hast eine Listenimplementiering, die auf einem Array beruht. Also ist es ein ArrayList. Eine LinkedList ist eine Liste, die verkettet ist. Besser als wie im .NET Framework, da ist die Beschreibung von IList und List identisch, ich weis nicht wie List das IList Interface implementiert. Im Java Framework ist es nach dem Namen sofort ersichtlich. Wenn du eine Standard-Implementierung hast, ist es besser die Klasse mit "DefaultFoo" oder "FooImp" zu versehen. Die Klasse siehst du im Code nur einmal, das Interface wird aber immer wieder verwendet.
Was die Interface Namen angeht auch alles schön kurz: "List<File>" -> supi. Allerdings ist nicht klar ersichtlich was nun ein Interface ist und was nicht. Ob das nun ein Nachteil ist oder nicht ist Ansichtssache, darüber will ich mich mal nicht auslassen. Kommt IMO auch stark drauf an, wie gut man ein Framework schon kennt. Wenn ich 95% der wichtigsten Interfaces namentlich kenne, ist es vermutlich egal. Weiterer Nachteil: diese Regelung ist viel "schwammiger" als die "jedes Interface fängt mit I an" Variante. Einige Klassen implementieren mehr als nur ein Interface, und manchmal ist auch nicht 100% klar welches als das "primäre" Interface angesehen werden kann, nach dem die Klasse benannt werden sollte. Zusätzlich führt es zu Problemen wenn Interfaces nachträglich eingeführt werden.
Wenn die ArrayList Klasse zu einem Zeitpunkte geschrieben worden wäre wo es noch kein List Interface gegeben hat, hätte sie sicher einen anderen Namen bekommen - z.B. einfach nur Array oder DynamicArray. Führt man nachträglich das Interface List ein, dann hat die Klasse auf einmal den falschen Namen.Man sollte immer nach dem Interface programmieren, erst sollte man das Interface klar definieren und danach sollte man seine Klassen implementieren. Das Java Framework wurde offensichtlich danach implementiert, wärend beim C# Framework man zuerst eine Liste programmiert hat und danach das Interface extrahiert hat. Dann wusste man nicht mehr wie man das Interface nennen sollte und hat aus Faulheit ein I Präfix gewählt. (ist meine Spekulation)
Aus "Clean Code A Handbook of Agile Software Craftmanship, Robert C. Martin"
[...]For example, say you are building an Abstract Factory for the creation of shapes. What should you name them? IShapeFactory and ShapeFactory? I prefer to leave interfaces unadorned. The preceding I, so common in today's legacy wads, is a distraction at best and too much information at worst. I don't want my users knowing that I'm handling them an interface. I just want them to know that it's a ShapeFactory. So If I must encode either the interface or the implementation, I choose the implementation. Calling it ShapeFactoryImp, or even hideous CShapeFactory, is preferable to encoding the interface.
Noch ein paar Zitate:
KRZYSZTOF CWALINA: One of the few prefixes used is “I” for interfaces (as in ICollection), but that is for historical reasons. In retrospect, I think it would have been better to use regular type names. In a majority of the cases developers don’t care that something is an interface and not an abstract class, for example.
BRAD ABRAMS: On the other hand, the “I” prefix on interfaces is a clear recognition of the influence of COM (and Java) on the .NET Framework. COM popularized, even institutionalized, the notation that interfaces begin with “I.” Although we discussed diverging from this historic pattern we decided to carry forward the pattern as so many of our users were already familiar with COM.
JEFFREY RICHTER: Personally, I like the “I” prefix and I wish we had more stuff like this. Little one-character prefixes go a long way toward keeping code terse and yet descriptive. As I said earlier, I use prefixes for my private type fields because I find this very useful.
BRENT RECTOR Note: this is really another application of Hungarian notation (though one without the disadvantages of the notation's use in variable names).
-
DEvent schrieb:
Was, wenn ich morgen anstelle des Interfaces eine Klasse anbieten?
Warum sollte man DAS tun? Dass man eine konkrete implementierung durch ein interface ersetzt ist üblich. Den umgekehrten weg zu gehen ist eher sinnlos.
Abgesehen davon... wenn du den typ des angebotenen objects änderst, dann musst du die bezeichner so oder so ändern. Da spielt das I dann keine rolle. Wenn hingegen das interface sämtliche funktionen deines objects abdeckt, ist ein unbenennen von IList zu List absolut unnötig.
-
DEvent schrieb:
Ich würde mich so sehr darüber aufregen, aber es ist ein Implementatierungsdetail, ob ich ein Interface verwende. Was, wenn ich morgen anstelle des Interfaces eine Klasse anbieten? Dann muss man überall das IFoo in Foo umbenennen, was überhaupt nicht nötig wäre.
1. Frage: Wie oft passiert das?
2. Frage: Wie schnell ist das automatische Name-Refactoring der IDE durch?DEvent schrieb:
Man sollte immer nach dem Interface programmieren, erst sollte man das Interface klar definieren und danach sollte man seine Klassen implementieren. Das Java Framework wurde offensichtlich danach implementiert, wärend beim C# Framework man zuerst eine Liste programmiert hat und danach das Interface extrahiert hat. Dann wusste man nicht mehr wie man das Interface nennen sollte und hat aus Faulheit ein I Präfix gewählt. (ist meine Spekulation)
rofl! Also DEvent wirklich, damit machst du dich ja schlicht nur lächerlich. Das ist keine Spekulation sondern reines und typisches MS-Bashing. Man kann das nämlich grob so zusammenfassen: Java ist ein voll gutes und durchdachtes Framework, während sich Microsoft bei .Net überhaupt nichts gedacht hat!
Und was willst du mit den Zitaten aussagen? Grundsätzlich sollte da wunderbar herauskommen, dass es eben eine subjektive Angelegenheit ist.
Grüssli
-
Die Javarianer-Variante: Interfaces heissen einfach nur "List", "File" etc., Implementierungen heissen XxxList/XxxFile, wobei Xxx etwas ist was Aufschluss über die Art/Besonderheiten der Implementierung gibt. Das führt dann zu so eigenartigen Namen wie ArrayList.
Wieso eigenartig?
Wel aus C und C++ Sicht Liste und Array zwei orthogonale Konzepte sind. Unter Liste versteht man eine verkettete solche. Das verträgt sich nicht mit dem Begriff Array, der ja einen zusammenhängenden Speicherblock beschreibt.
Dadurch verwirrte mich QList aus QT auch zuerst. Das ist aus C++ Sicht nämlich gar keine Liste sondern eine deque.
-
Dravere schrieb:
2. Frage: Wie schnell ist das automatische Name-Refactoring der IDE durch?
3 versionen? 5?
schwer zu sagen wann der letzte client code angepasst wurde. ich würde etwa 2-3 Jahre schätzen...interfaces darf man nicht mehr ändern wenn sie mal fix sind.
-
DEvent schrieb:
Ich verstehe nicht wieso man in C# ein Interface speziell auszeichnet.
Dann frage es in http://www.c-plusplus.net/forum/viewforum-var-f-is-28.html
Genauer, ich verstehe nicht, wieso ist es wichtig zu wissen, dass etwas ein Interface ist und keine Klasse.
Da Du hier gefragt hast: Es hängt von der verwendeten Sprache ab.
-
Artchi schrieb:
Das hat doch nichts mit C# und MS zu tun. Ist doch mal wieder so ein typischer MS-Basher Posting.
Hast du was anderes von unserem Linux-Nerd #1 erwartet?
-
mit einer reinen OO-Sprache ("alles ist ein Objekt ... jedes Objekt ist Mitglied einer Klasse") wäre das nicht passiert.
-
Frag mich bloss, was man bei Generische Komposition machen soll
public interface ISystem<F, B> { F Frontend { get; set; } B Backend { get; set; } void Compute(); } public class DefaultSystem<F, B> : ISystem<F, B> { // Use fucking new Syntax for initialization example: new DefaultSystem() { Frontend = ...}; private F frontend; private B backend; public F Frontend { get { return frontend; } set { frontend = value; } } public B Backend { get { return backend; } set { backend = value; } } public virtual void Compute() { } } public class NormalSystem : DefaultSystem<DefaultFrontend, DefaultBackend> { public NormalSystem() : base() { Frontend = new DefaultFrontend(); Backend = new DefaultBackend(); } public override void Compute() { Frontend.front(); Backend.back(); } } public class ReverseSystem : DefaultSystem<DefaultFrontend, DefaultBackend> { public ReverseSystem() : base() { Frontend = new DefaultFrontend(); Backend = new DefaultBackend(); } public override void Compute() { Backend.back(); Frontend.front(); } } public interface IBackend { void back(); } public class DefaultBackend : IBackend { public void back() { System.Console.WriteLine("It's from Backend"); } } public interface IFrontend { void front(); } public class DefaultFrontend : IFrontend { public void front() { System.Console.WriteLine("It's from Frontend"); } } public class Program { static void Main(string[] args) { var sys1 = new NormalSystem(); var sys2 = new ReverseSystem(); sys1.Compute(); sys2.Compute(); Console.ReadLine(); } }