Das "I"-Prefix bei Interfaces
-
Hallo leute,
ich stelle immer häufiger fest, dass in vielen komponenten das "I"-Prefix bei Interfaces verwendet wird. In .NET scheint es standard zu sein und bei Java habe ich das häufiger in eclipse-komponenten gesehen.
Was hat das überhaupt für einen zweck? Für mich als anwender einer bibliothek ist es doch völlig egal, ob es ein interface, eine klasse oder eine abstrakte klasse ist, auf der ich operationen ausführe; es ist ein typ! Deshalb ist mir der sinn und zweck dieses prefixes schleierhaft. Schon allein das lesen ist ja ekel erregend: "Iiihhh-Collection", "Iiihhh-Comparable" oder so

Was hat das also für einen Zweck? Oder können sich diese leute nicht einfach endgültig von der ungarischen notation verabschieden?
Gruß
mathik
-
Ich finds auch sinnlos. Gluecklicherweise gibts eine ganz einfache Loesung: einfach ignorieren

-
In Java ist ein Interface doch etwas vollkommen anderes als eine Klasse. Von daher find ich es da auch überflüssig. In C# ist es afaik genauso, aber das .NET Framework gibts ja nicht nur für C#, von daher find ich es da sinnvoller, da C++ (wobei hat das CLI C++ richtige interfaces?) dafür keine direkte Sprachunterstützung hat.
Hier kann man mit nem I vor dem Klassennamen direkt sagen, dass es keine eigenständige Klasse ist, sondern eine Schnittstelle darstellen soll.
Bei der ungarischen Notation, wie sie in der Praxis angewandt wird, schreibt man etwas in den Namen das auch schon so da steht, aber ob eine Klasse ein Interface ist steht nicht klar da, das muss man schon aus der Klassendefinition heraus interpretieren. Und von daher finde ich es hier durchaus sinnvoll das durch ein I deutlich zu machen (das weicht von der "echten" Nutzung der ungarischen Notation gar nicht arg ab).
-
@Blue-Tiger
ich versuche es ja, aber wegen diesem doofen "Iiihhh" davor ist das nicht so einfach...
lolz schrieb:
In Java ist ein Interface doch etwas vollkommen anderes als eine Klasse. Von daher find ich es da auch überflüssig. In C# ist es afaik genauso, aber das .NET Framework gibts ja nicht nur für C#, von daher find ich es da sinnvoller, da C++ (wobei hat das CLI C++ richtige interfaces?) dafür keine direkte Sprachunterstützung hat.
Hier kann man mit nem I vor dem Klassennamen direkt sagen, dass es keine eigenständige Klasse ist, sondern eine Schnittstelle darstellen soll.
Bei der ungarischen Notation, wie sie in der Praxis angewandt wird, schreibt man etwas in den Namen das auch schon so da steht, aber ob eine Klasse ein Interface ist steht nicht klar da, das muss man schon aus der Klassendefinition heraus interpretieren. Und von daher finde ich es hier durchaus sinnvoll das durch ein I deutlich zu machen (das weicht von der "echten" Nutzung der ungarischen Notation gar nicht arg ab).ist doch völlig egal, dass es in C++ technisch keine explizite unterscheidung zwischen interfaces und (abstrakten) klassen gibt. in c++ ist ein interface nichts anderes als eine klasse aus "pure-virtual-functions".
nochmal die frage: wo hat es für dich für einen vorteil, wenn du ganz genau weißt, dass das ein interface ist und keine (abstrakte) klasse??
-
in eclipse wurde das so gemacht, weil zu jedem interface eine implementierende klasse mit dem selben namen existiert: IPath <- Path
IMO is diese namensgebung besser als Path <- PathImpl oder DefaultPath
wenn man allerdings keinen namenskonflikt hat (z.B. IActionListener würde nich viel sinn machen wenn man keine IActionListener<-ActionListener klasse hat) kann man sich das I schenken.
-
schlauher als ihr schrieb:
in eclipse wurde das so gemacht, weil zu jedem interface eine implementierende klasse mit dem selben namen existiert: IPath <- Path
IMO is diese namensgebung besser als Path <- PathImpl oder DefaultPath
wenn man allerdings keinen namenskonflikt hat (z.B. IActionListener würde nich viel sinn machen wenn man keine IActionListener<-ActionListener klasse hat) kann man sich das I schenken.Hört sich für mich so an, als ob man da bestimmte Design-Richtlinien aus Prinzip und ohne Verstand befolgt hat, so dass der eigentliche Sinn von Interfaces ad absurdum geführt wurde.

BTW: Nach den Coding Conventions von Sun sollten die Namen von Interfaces in Java möglichst Adjektive sein, während die Namen von Klassen Substantive sein sollten. Das sollte wohl zur Unterscheidung reichen.

-
Offensichtlich gibt es ja einen Unterschied zwischen einem Interface und einer abstrakten Basisklasse. Diesen semantischen Unterschied kann man durch das "I" deutlich machen, um dies schneller zu sehen. Während eine abstrakte Klasse z.B. als Analyseklasse der OOA entstehen kann, sind Interfaces ja eher technische Verbinder zwischen Objekten. Durch die Kennzeichnung kann man den Leser schneller mit der Nase auf diesen Unterschied stossen. Ich finde das daher nicht so schlimm... wobei man es genauso auch durch die Namensgebung der Klasse kennzeichnen kann, es ist dann nur weniger offensichtlich normiert.
-
Marc++us schrieb:
Offensichtlich gibt es ja einen Unterschied zwischen einem Interface und einer abstrakten Basisklasse. Diesen semantischen Unterschied kann man durch das "I" deutlich machen, um dies schneller zu sehen. Während eine abstrakte Klasse z.B. als Analyseklasse der OOA entstehen kann, sind Interfaces ja eher technische Verbinder zwischen Objekten. Durch die Kennzeichnung kann man den Leser schneller mit der Nase auf diesen Unterschied stossen. Ich finde das daher nicht so schlimm... wobei man es genauso auch durch die Namensgebung der Klasse kennzeichnen kann, es ist dann nur weniger offensichtlich normiert.
naja, ich würde eher sagen, dass man in der OOA von typen bzw. fachklassen spricht. wie diese typen letzendlich im entwurf bzw. im programm abgebildet werden (womöglich unter einsatz bestimmter entwurfsmuster) ist dann technologieabhängig, z.b. mit (abstrakten) klassen, interfaces, C-structs, usw.
ich als client einer komponente will doch eigentlich garnicht wissen, ob ich operationen auf einem interface oder auf einer klasse ausführe. ich finde durch das "I"-prefix werden zu viel implementierungsdetails nach außen gegeben und die lesbarkeit gehindert.
-
ich habe fuer jedes interfaces zu meinen implementationen ebenfalls eine normale klasse. ich kann nicht beides gleich benennen, ich mag auch nicht extra verschiedene namespaces dafuer generieren wenn sie eigentlich den gleichen bereich ansprchen, deswegen mach ich den einzigen sinn-unterschied im namen deutlich, naemlich dass das eine eine Classe ist und das andere nur ein Interface.
-
Das tun die Leute mit dem "I"-Prefix doch auch.

-
Gregor schrieb:
schlauher als ihr schrieb:
in eclipse wurde das so gemacht, weil zu jedem interface eine implementierende klasse mit dem selben namen existiert: IPath <- Path
IMO is diese namensgebung besser als Path <- PathImpl oder DefaultPath
wenn man allerdings keinen namenskonflikt hat (z.B. IActionListener würde nich viel sinn machen wenn man keine IActionListener<-ActionListener klasse hat) kann man sich das I schenken.Hört sich für mich so an, als ob man da bestimmte Design-Richtlinien aus Prinzip und ohne Verstand befolgt hat, so dass der eigentliche Sinn von Interfaces ad absurdum geführt wurde.

BTW: Nach den Coding Conventions von Sun sollten die Namen von Interfaces in Java möglichst Adjektive sein, während die Namen von Klassen Substantive sein sollten. Das sollte wohl zur Unterscheidung reichen.

mir ist ehrlich gesagt nicht klar, warum namen von interfaces eher adjektive und vor klassen eher substantive sein sollten. Collection ist ja auch kein adjektiv

interfaces, (abstrakte) klassen, structs usw. sind doch einfach technische konzepte zur abbildung von typen aus der analyse im programm.ich verwende interfaces und (abstrakte) klassen nach dem folgenden prinzip:
1. wenn ich sehe, dass es für eine schnittstelle mehrere unterschiedliche implementierungen gibt bzw. benötigt werden, dann nehme ich ein interface.
2. wenn ich sehe, dass ein paar klassen das gleiche verhalten haben und sich nur in ein paar details unterscheiden, dann mache ich eine abstrakte basisklasse und wende das template-pattern an.
3. ansonsten verwende ich klassen und refaktorisiere diese nach bedarf , falls 1. oder 2. zustrifft.dadurch ist es für die klienten völlig egal und transparent, ob diese nun auf interfaces oder klassen operieren.
-
rapso schrieb:
ich habe fuer jedes interfaces zu meinen implementationen ebenfalls eine normale klasse.
was erhoffst du dir dadurch, indem du das für jede klasse machst? eine klasse hat doch auch eine schnittstelle, nämlich die öffentlichen operationen. der rest ist für die klienten tabu und wird von denen verborgen ("jede klasse sollte wie ein eisberg sein: man sieht nur die spitze")
-
rapso schrieb:
ich habe fuer jedes interfaces zu meinen implementationen ebenfalls eine normale klasse.
Wozu dann ueberhaupt das Interface? Wenn du fuer jedes Interface nur 1 Implementation hast, wozu dann ueberhaupt das Interface? In so einem Fall wuerde ich persoenlich einfach die Implementierung verwenden. Sollte ich spaeter sehen, dass es verschiedene Implementierungen braucht, kann ich das immer noch rausfaktorisieren (das Interface behaelt dann den Namen und die 2 Implementierungen erhalten Namen, die ihre Unterschiede voneinander ausdruecken).
Wenn ich z. B. eine verkettete Liste brauch (und keine Sdt.-Lib haette
), schreib ich erst mal eine Klasse "LinkedList", die genau das implementiert. Und die verwend ich ueberall. Entdeck ich spaeter, dass es an manchen Stellen Sinn machen wuerden, eine LinkedList mit konstanter Zugriffszeit auf beliebige Elemente zu haben, Wird aus "LinkedList" eben ein "List"-Interface, und "LinkedList" und "ArrayList" implementieren das dann.schlauher als ihr schrieb:
in eclipse wurde das so gemacht, weil zu jedem interface eine implementierende klasse mit dem selben namen existiert: IPath <- Path
IMO is diese namensgebung besser als Path <- PathImpl oder DefaultPathGleiche Frage: wozu brauchen die ein Interface, wenn sie doch nur 1 Implementierung haben? Und wenn sie dem Benutzer die Moeglichkeit bieten wollen, eigene Implementierungen zur Verfuegung zu stellen und deswegen Interfaces anbieten, dann ja, dann find ich "DefaultXyz" ist ein sehr guter Name fuer die Standardimplementierung von Xyz.
-
mathik schrieb:
rapso schrieb:
ich habe fuer jedes interfaces zu meinen implementationen ebenfalls eine normale klasse.
was erhoffst du dir dadurch, indem du das für jede klasse machst?
Eine Trennung von Typ und Klasse?
-
finix schrieb:
mathik schrieb:
rapso schrieb:
ich habe fuer jedes interfaces zu meinen implementationen ebenfalls eine normale klasse.
was erhoffst du dir dadurch, indem du das für jede klasse machst?
Eine Trennung von Typ und Klasse?
d.h. deiner meinung nach ist typ=interface und implementierung=klasse??
das ist ja auch korrekt, nur nicht vollständig. eine klasse hat genauso wie ein interface eine schnittstelle: die öffentlichen operationen.wie schon bereits gesagt: ein typ aus der analyse kann technisch durch ein oder mehrere interfaces und (abstrakten) klassen realisiert werden. genauso können ein interface und eine (abstrake) klasse mehrere typen realisieren. für mich sind das somit technische konzepte um typen programmtechnisch abzubilden; evtl. sogar vergleichbar mit for- vs. while-schleifen

deshalb finde ich es übertrieben konsequent für jede klasse ein interface zu erstellen, auch wenn es nur eine implementierung gibt. das verkompliziert den code nur unnötig. außerdem gibt es eine refactoring-operation: "extract-interface", mit der man zu einer klasse durch knopfdruck ein interface generieren kann und alle klienten darauf automatisch angepasst werden.
-
Blue-Tiger schrieb:
schlauher als ihr schrieb:
in eclipse wurde das so gemacht, weil zu jedem interface eine implementierende klasse mit dem selben namen existiert: IPath <- Path
IMO is diese namensgebung besser als Path <- PathImpl oder DefaultPathGleiche Frage: wozu brauchen die ein Interface, wenn sie doch nur 1 Implementierung haben? Und wenn sie dem Benutzer die Moeglichkeit bieten wollen, eigene Implementierungen zur Verfuegung zu stellen und deswegen Interfaces anbieten, dann ja, dann find ich "DefaultXyz" ist ein sehr guter Name fuer die Standardimplementierung von Xyz.
Also ich kann mir das durchaus vorstellen, vor allem, wenn ich bedenke, dass ich gerade System-Resourcen (z.B: eben Path) bzw. Objekte die System-Resourcen verwenden (z.B: Zugriffsobjekte für die Datenbankschicht) in Komponententests mocken möchte. Bei mir geht das teilweise schon so weit, dass ich nur noch die Schnittstelle habe und mir aus dieser (und einigen zusätzlichen Metadaten) die Implementierung generieren lasse.
-
dsf232sdg schrieb:
Blue-Tiger schrieb:
schlauher als ihr schrieb:
in eclipse wurde das so gemacht, weil zu jedem interface eine implementierende klasse mit dem selben namen existiert: IPath <- Path
IMO is diese namensgebung besser als Path <- PathImpl oder DefaultPathGleiche Frage: wozu brauchen die ein Interface, wenn sie doch nur 1 Implementierung haben? Und wenn sie dem Benutzer die Moeglichkeit bieten wollen, eigene Implementierungen zur Verfuegung zu stellen und deswegen Interfaces anbieten, dann ja, dann find ich "DefaultXyz" ist ein sehr guter Name fuer die Standardimplementierung von Xyz.
Also ich kann mir das durchaus vorstellen, vor allem, wenn ich bedenke, dass ich gerade System-Resourcen (z.B: eben Path) bzw. Objekte die System-Resourcen verwenden (z.B: Zugriffsobjekte für die Datenbankschicht) in Komponententests mocken möchte. Bei mir geht das teilweise schon so weit, dass ich nur noch die Schnittstelle habe und mir aus dieser (und einigen zusätzlichen Metadaten) die Implementierung generieren lasse.
Hmm.... ok, die Autogenerierung klingt sinnvoll
Aber warum ists fuer Komponententests sinnvoll, bei nur 1 Implementierung eine Interface/Implementierungstrennung einzufuehren? Ist das nicht unnoetige Komplexitaet?
-
Blue-Tiger schrieb:
Hmm.... ok, die Autogenerierung klingt sinnvoll
Aber warum ists fuer Komponententests sinnvoll, bei nur 1 Implementierung eine Interface/Implementierungstrennung einzufuehren? Ist das nicht unnoetige Komplexitaet?Natürlich lassen sich dadurch die Implementierungen ansich nicht einfacher testen, aber gerade wenn Abhängigkeiten zu anderen Komponenten bestehen, lassen sich diese dann, wenn auch nur beim Testen, ersetzen um eine isolierte Ausführung zu gewährleisten. Mock-Objekte implementieren Schnittstellen, enthalten aber statt Geschäftslogik die notwendige Testlogik (also beispielsweise einige Assertions). Am besten siehst du dir dazu aber die Theorie zu Mock-Objekten an.
-
testbarkeit ist aber immer noch kein argument dafür, für jede klasse ein interface zu machen. mock-objekte können nämlich - zumindest bei java (z.b. mit easymock) - auch für klassen erstellt werden.
mich stört ja auch nicht, dass interfaces für schnittstellen von komponenten verwendet werden, oder dass sie in maßen verwendet werden. mich stört eigentlich nur das "I"-prefix. denn ich will auf typen operieren - diese werden meistens durch interfaces repräsentiert - und deren name ist dann durch dieses "Iiihhh" vermurkst. "PathImpl" oder "DefaultPath" oder "IPath" (steht jedoch für PathImplementation) finde ich besser, da diese durch das interface "Path" an der schnittstelle der komponente sowieso verdeckt werden.
-
mathik schrieb:
testbarkeit ist aber immer noch kein argument dafür, für jede klasse ein interface zu machen. mock-objekte können nämlich - zumindest bei java (z.b. mit easymock) - auch für klassen erstellt werden.
mich stört ja auch nicht, dass interfaces für schnittstellen von komponenten verwendet werden, oder dass sie in maßen verwendet werden. mich stört eigentlich nur das "I"-prefix. denn ich will auf typen operieren - diese werden meistens durch interfaces repräsentiert - und deren name ist dann durch dieses "Iiihhh" vermurkst. "PathImpl" oder "DefaultPath" oder "IPath" (steht jedoch für PathImplementation) finde ich besser, da diese durch das interface "Path" an der schnittstelle der komponente sowieso verdeckt werden.
Ich habe auch nie jemandem empfohlen ein Interface für jede Klasse zu erstellen. Für typische Beans (normale POJOs sind gemeint, nicht diese GUI Beans) - wenn wir schon den Bezug zu Java herstellen - wäre dies sinnlos.
Auch wenn einige meiner Hierachien anfangs nur aus einem Interface und der Implementierung bestehen, verändern sich diese eben mit der Zeit, wobei nicht notwendigerweise eine weitere konkrete Implementierung dazukommen muss. Decorator-Objekte, die den Aufruf modifizieren, und dergleichen (irgendwie also Aspektorientierung für "arme") ergeben sich gerne erst im Lauf der Entwicklung.
Weiters denke ich schon, dass Testbarkeit sehr wohl ein Argument für die Verwendung von Interfaces ist, weil sich auch mit Projekten wie easymock nicht alles mocken lässt.