Das "I"-Prefix bei Interfaces



  • Blue-Tiger schrieb:

    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.

    Kleine Anmerkung noch zu dieser Aussage:
    So generell würde ich das auch nicht sagen, denn gerade beim Beispiel Path kann das meiner Meinung nach zu unnötiger Verwirrung führen. Bei DefaultPath und Path als Typen würde ich intuitiv nicht darauf schließen, dass das eine das andere implementiert. Wenn man es übersetzt, wird es vielleicht deutlicher, dass man ihnen unterschiedliche Bedeutungen zuschreibt: Standardpfad und Pfad.



  • sdf82742sf schrieb:

    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.

    das ist ja auch ein vernünftiges vorgehen. ich mach es ja auch nicht anders. 😉

    sdf82742sf schrieb:

    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.

    auf jeden fall. nur wie gesagt, ich finde es übertrieben für jede klasse ein interface zu erstellen. aber du machst das ja auch anscheinend nicht.

    BTW: mich stört ja immer noch dieses "Iihh"-prefix... wer hat das erfunden? 😃



  • mathik schrieb:

    BTW: mich stört ja immer noch dieses "Iihh"-prefix... wer hat das erfunden? 😃

    Ich nehme an, dass das ein Überbleibsel aus der ungarischen Notation sein wird. Der Hintergedanke dabei ist meiner Meinung nach einfach nachzuvollziehen, da es gerade in größeren Projekten wie Eclipse nicht egal ist ob der Typ eine Klasse, eine abstrakte Klasse oder ein Interface ist. Grundprinzip ist ja, dass man immer gegen Interfaces programmieren soll und um das einfach überprüfen zu können dient das "I"-Präfix um Interfaces von den restlichen Typen schnell unterscheiden zu können. Ich würde zwar leitenden Entwicklern nicht widersprechen, wenn sie mir diese Namenskonvention vorschreiben, da ich sie eben, wie bereits erwähnt, nachvollziehen kann, von selbst aus halte ich sie aber auch nicht ein (sofern ich nicht gerade C# programmiere, denn dann natürlich schon).



  • Da I-Präfix wird auch von MS für die COM-Specs benutzt. COM-Interfaces fangen auch mit I an. Hat halt IBM für Eclipse mit übernommen.



  • Blue-Tiger schrieb:

    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?

    ein interface ist eine reine schnittstellenbeschreibung bzw schnittstelle, sie enthaellt keine interna z.b. inlinefunktionen, member, friends etc. die fuer die anwender der klasse nicht noetig sind.

    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 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")

    diese abstrahierung von schnittstelle und implementierung macht man um zu ermoeglichen die implementierung zu aendern ohne das interface aendern zu muessen. das waere rein theoretisch auch machbar wenn man die klassenbeschreibung der implementierung weitergibt, jedoch ist es einfach sauberer eine schnittstellendefinition auf beiden seiten zu haben, sodass sich auf der einen seite jemand um die interner kuemmern kann, waehrend die andere seite die schnittstelle verwendet ohne das ungewollte abhaengigkeiten entstehen die mittels der implementierungs-header moeglich sind.



  • Artchi schrieb:

    Da I-Präfix wird auch von MS für die COM-Specs benutzt. COM-Interfaces fangen auch mit I an. Hat halt IBM für Eclipse mit übernommen.

    also ist microsoft wieder schuld!? die können sich wohl nicht endgültig von deren ungarischen notation verabschieden, obwohl bei den .NET coding style guides folgendes zu finden ist:

    - Do not use Hungarian notation
    - Do not prefix enums, classes, or delegates with any letter

    und dann steht:

    - Do prefix interfaces names with “I”

    😃 😃 😃

    @rapso
    interfaces sind ja auch schön und gut und man verwendet besser mehr von denen als zu wenig. für jede klasse ein interface zu erzeugen, auch wenn diese nur innerhalb der komponente verwendet wird und sonst keiner kennt, finde ich einfach übertrieben und verkompliziert einfach unnötig den code.



  • mathik schrieb:

    interfaces sind ja auch schön und gut und man verwendet besser mehr von denen als zu wenig. für jede klasse ein interface zu erzeugen, auch wenn diese nur innerhalb der komponente verwendet wird und sonst keiner kennt, finde ich einfach übertrieben und verkompliziert einfach unnötig den code.

    fuer jede fuer die es moeglicherweise alternativ implementierungen geben kann wird es gemacht, das ist auch sinnig.



  • rapso schrieb:

    mathik schrieb:

    interfaces sind ja auch schön und gut und man verwendet besser mehr von denen als zu wenig. für jede klasse ein interface zu erzeugen, auch wenn diese nur innerhalb der komponente verwendet wird und sonst keiner kennt, finde ich einfach übertrieben und verkompliziert einfach unnötig den code.

    fuer jede fuer die es moeglicherweise alternativ implementierungen geben kann wird es gemacht, das ist auch sinnig.

    d.h. nun doch nicht für jede klasse!? 🙂

    solche begründungen, wie "weil es in zukunft vielleicht benötigt wird" finde ich jedoch gefährlich. bei agiler entwicklung soll man ja möglichst alles so einfach wie möglich halten und bei bedarf refaktorisieren. man sollte also nicht zu weit in die zukunft schauen.



  • mathik schrieb:

    bei agiler entwicklung soll man ja möglichst alles so einfach wie möglich halten und bei bedarf refaktorisieren. man sollte also nicht zu weit in die zukunft schauen.

    Wenn man allerdings von XP ausgeht, als agile Entwicklungsmethode, fängt man ohnehin beim Testen an - Testen scheint irgendwie mein Steckenpferd zu sein - und da arbeite ich eben von vornherein lieber mit "leichtgewichtigen" Schnittstellen als "schwergewichtigen" Implementierungen, sozusagen salop formuliert.



  • dsf24534sd schrieb:

    mathik schrieb:

    bei agiler entwicklung soll man ja möglichst alles so einfach wie möglich halten und bei bedarf refaktorisieren. man sollte also nicht zu weit in die zukunft schauen.

    Wenn man allerdings von XP ausgeht, als agile Entwicklungsmethode, fängt man ohnehin beim Testen an - Testen scheint irgendwie mein Steckenpferd zu sein - und da arbeite ich eben von vornherein lieber mit "leichtgewichtigen" Schnittstellen als "schwergewichtigen" Implementierungen, sozusagen salop formuliert.

    Aber du siehst doch gar nicht ob der Typ jetzt "schwergewichtig" oder "leichtg." ist. Du siehst doch in beiden Fällen nur die public-Methoden.

    Ah jetzt versteh ich. Mal ein Beispiel:

    Iterable i = new MeineListe();
    Comparable c = new MeineListe();
    MeineListe ml = new MeineListe();
    

    Bei i siehst du nur den Teil von Iterable und bei c siehst du nur den Teil von Comparable. Bei ml aber siehst du beide Schnittstellen und zusätzliche von der Klasse MeineListe.

    Na gut, aber was bringt es mir zu wissen ob Iterable und Comparable Interfaces sind? Eigentlich doch nichts.

    Was bringt es mir jetzt eine IMeineListe zu haben?

    IMeineListe ia = new MeineListe();
    IMeineListe ib = new MeineListeTest();
    

    Ist das gleiche wie:

    MeineListe mla = new MeineListe();
    MeineListe mlb = new MeineListeTest();
    

    In beiden Fällen sehe ich die Schnittstelle der Klasse MeineListe.



  • DEvent schrieb:

    Aber du siehst doch gar nicht ob der Typ jetzt "schwergewichtig" oder "leichtg." ist. Du siehst doch in beiden Fällen nur die public-Methoden. [...] Na gut, aber was bringt es mir zu wissen ob Iterable und Comparable Interfaces sind? Eigentlich doch nichts.

    Die transitiven Abhängigkeiten, die eine konkrete Implementierung zwangsweise mit sich zieht, sind jene, die den Typ "schwergewichtig" machen, nicht die öffentliche Schnittstelle. Insofern macht es sehr wohl einen Unterschied ob es sich beim Typ um ein Interface oder eine Klasse handelt.



  • Ja, wenn die Klasse eine Implementierung hat, haste Recht. Aber Klassen können auch pure virtual sein.

    class A
    {
    public:
       virtual void foo() = 0;
    };
    

    Absolut keine Abhängigkeit zu irgendwelchen externen Typen. Was bringt es mir jetzt, wenn ich daraus ein "Interface" mache? Es ist doch schon ein Interface.

    Übrigens, wartet mal ab, was C++2009 bringt, da wird es die sogenannten Concepts geben. Das wird auch eine weitere Variante von Schnittstellen-Vorgaben/-Vereinbarungen sein. In dem Fall zwar auf Templates zugeschnitten, aber es zeigt, das was man Ende will, das gleiche ist.



  • Artchi schrieb:

    Ja, wenn die Klasse eine Implementierung hat, haste Recht. Aber Klassen können auch pure virtual sein.

    class A
    {
    public:
       virtual void foo() = 0;
    };
    

    Absolut keine Abhängigkeit zu irgendwelchen externen Typen. Was bringt es mir jetzt, wenn ich daraus ein "Interface" mache? Es ist doch schon ein Interface.

    Ganz ehrlich, ich habe kein Interesse an einer Diskussion "Interfaces vs rein-virtuellen Klassen", insofern schließe ich mich einfach deiner eigenen Aussage aus: "Es ist doch schon ein Interface". Ich bezog mich bei meinen Aussagen auf eine generelle Terminologie, die eben nicht auf eine einzige Sprache eingeschränkt ist , und nachdem C++ ja keine Interfaces kennt, ist dieses Konstrukt für mich quasi ein Interface. Dadurch ergibt sich auch, dass sich unsere Aussagen eher decken als widersprechen.



  • df23sdg schrieb:

    DEvent schrieb:

    Aber du siehst doch gar nicht ob der Typ jetzt "schwergewichtig" oder "leichtg." ist. Du siehst doch in beiden Fällen nur die public-Methoden. [...] Na gut, aber was bringt es mir zu wissen ob Iterable und Comparable Interfaces sind? Eigentlich doch nichts.

    Die transitiven Abhängigkeiten, die eine konkrete Implementierung zwangsweise mit sich zieht, sind jene, die den Typ "schwergewichtig" machen, nicht die öffentliche Schnittstelle. Insofern macht es sehr wohl einen Unterschied ob es sich beim Typ um ein Interface oder eine Klasse handelt.

    in C++ ja, da man dort immer das header benötigt! das I-prefix verwendet dort aber zum glück kaum einer, außer bei MS-sachen wie COM.

    hier gehts aber viel mehr um java und .net.
    und dort siehst du die abhängigkeiten nicht, sofern du nur den zwischencode und die dazugehörige doku hast (mehr braucht man auch nicht bei auslieferung einer komponente). somit es in java oder .net völlig egal ob es eine klasse oder interface ist. du siehst in beiden fällen nur die öffentlichen methoden.



  • in C++ ja, da man dort immer das header benötigt!

    Aber auch eine Header-Datei ist letztendlich auch nur "leichtgewichtig" (was auch immer das damit zutun hat, aber ich benutze mal eure Begrifflichkeit). Denn in der Header steht nur die Beschreibung der Funktionssignaturen und welche Klasse es gibt. Die Implementierung ist doch auch (wie in anderen Sprachen) in einer binären Library "versteckt". Nimm mal mein obiges Beispiel: es ist nur eine Beschreibung, wie Interface A aussieht. Mehr nicht. Damit habe ich eine Abstraktion auf seeehr starker weise.



  • mathik schrieb:

    df23sdg schrieb:

    DEvent schrieb:

    Aber du siehst doch gar nicht ob der Typ jetzt "schwergewichtig" oder "leichtg." ist. Du siehst doch in beiden Fällen nur die public-Methoden. [...] Na gut, aber was bringt es mir zu wissen ob Iterable und Comparable Interfaces sind? Eigentlich doch nichts.

    Die transitiven Abhängigkeiten, die eine konkrete Implementierung zwangsweise mit sich zieht, sind jene, die den Typ "schwergewichtig" machen, nicht die öffentliche Schnittstelle. Insofern macht es sehr wohl einen Unterschied ob es sich beim Typ um ein Interface oder eine Klasse handelt.

    in C++ ja, da man dort immer das header benötigt! das I-prefix verwendet dort aber zum glück kaum einer, außer bei MS-sachen wie COM.

    hier gehts aber viel mehr um java und .net.
    und dort siehst du die abhängigkeiten nicht, sofern du nur den zwischencode und die dazugehörige doku hast (mehr braucht man auch nicht bei auslieferung einer komponente). somit es in java oder .net völlig egal ob es eine klasse oder interface ist. du siehst in beiden fällen nur die öffentlichen methoden.

    Die öffentliche Schnittstelle ist doch für transitive Abhängigkeiten (fast vollkommen) egal. Abhängigkeiten lassen sich durch Kapselung nicht auflösen, nur durch Abstraktion. Folgendes Beispiel soll das verdeutlichen:

    public interface HttpServer {
    
        public void start() throws IOException;
    
        public void stop() throws IOException;
    
    }
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    
    public class Jdk6HttpServer implements HttpServer {
    
        private static final Log log = LogFactory.getLog(HttpServer.class);
    
        /** JDK6 HttpServer, an den sämtliche Anfragen delegiert werden */
        private com.sun.net.httpserver.HttpServer httpServer;
    
        public void start() throws IOException {
            // ...
        }
    
        public void stop() throws IOException {
            // ...
        }
    
    }
    

    Auch wenn die öffentliche Schnittstelle der Klasse Jdk6HttpServer nicht darauf schließen lässt bringt diese Klasse immense (zugegebenermaßen bewusst inszenierte) Abhängigkeiten mit sich, nämlich Java 6 und commons-logging. Die Schnittstelle hingegen hängt gerade mal von der Klasse IOException ab. Natürlich würde in diesem Beispiel kaum jemand kein Interface verwenden, aber auch bei sonstigen alltäglicheren Klassen enstehen schnell Abhängigkeiten. In diesem Beispiel wirken sich die Abhängigkeiten natürlich extrem aus, nachdem man ganze Bibliotheken benötigt um diese zu erfüllen, aber es können auch schon Abhängigkeiten zu anderen Modulen des Projekts unerwünscht sein. Ansätze wie Dependency Injection feiern derzeit nicht umsonst Hochkonjunktur.



  • dsf3246dsf schrieb:

    Die öffentliche Schnittstelle ist doch für transitive Abhängigkeiten (fast vollkommen) egal. Abhängigkeiten lassen sich durch Kapselung nicht auflösen, nur durch Abstraktion. Folgendes Beispiel soll das verdeutlichen:

    public interface HttpServer {
    
        public void start() throws IOException;
    
        public void stop() throws IOException;
    
    }
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    
    public class Jdk6HttpServer implements HttpServer {
    
        private static final Log log = LogFactory.getLog(HttpServer.class);
    
        /** JDK6 HttpServer, an den sämtliche Anfragen delegiert werden */
        private com.sun.net.httpserver.HttpServer httpServer;
    
        public void start() throws IOException {
            // ...
        }
    
        public void stop() throws IOException {
            // ...
        }
    
    }
    

    Auch wenn die öffentliche Schnittstelle der Klasse Jdk6HttpServer nicht darauf schließen lässt bringt diese Klasse immense (zugegebenermaßen bewusst inszenierte) Abhängigkeiten mit sich, nämlich Java 6 und commons-logging. Die Schnittstelle hingegen hängt gerade mal von der Klasse IOException ab. Natürlich würde in diesem Beispiel kaum jemand kein Interface verwenden, aber auch bei sonstigen alltäglicheren Klassen enstehen schnell Abhängigkeiten. In diesem Beispiel wirken sich die Abhängigkeiten natürlich extrem aus, nachdem man ganze Bibliotheken benötigt um diese zu erfüllen, aber es können auch schon Abhängigkeiten zu anderen Modulen des Projekts unerwünscht sein. Ansätze wie Dependency Injection feiern derzeit nicht umsonst Hochkonjunktur.

    das ist in der tat ein beispiel, wo man sowieso ein interface verwenden würde.
    aber auch bei diesem beispiel würde man in den IDE nur "start" und "stop" sehen. dass dort abhängigkeiten zu log4j und anderen bibliotheken existieren siehst du in der IDE nicht. wie gesagt, in sehr vielen fällen ist eine trennung von interface und klasse sinnvoll, insbesondere bei typen aus der analyse. irgendwelche "helper-klassen" aufzuteilen halte ich nicht für sinnvoll.

    BTW: eigentlich habe ich mich auch nicht darüber beschwert, dass zu viele interfaces verwendet werden. ich habe mich nur über das I-prefix beschwert 🙂



  • Artchi schrieb:

    Ja, wenn die Klasse eine Implementierung hat, haste Recht. Aber Klassen können auch pure virtual sein.

    class A
    {
    public:
       virtual void foo() = 0;
    };
    

    [...]

    Aber auch eine Header-Datei ist letztendlich auch nur "leichtgewichtig" (was auch immer das damit zutun hat, aber ich benutze mal eure Begrifflichkeit). Denn in der Header steht nur die Beschreibung der Funktionssignaturen und welche Klasse es gibt. Die Implementierung ist doch auch (wie in anderen Sprachen) in einer binären Library "versteckt". Nimm mal mein obiges Beispiel: es ist nur eine Beschreibung, wie Interface A aussieht. Mehr nicht. Damit habe ich eine Abstraktion auf seeehr starker weise.

    Dein Interface/rein virtuelle Klasse/was auch immer mit dem Namen A ist doch nur so lange "leicht" wie du es so lässt. Aber was machst du jetzt mit der Implementierung?
    Ich dachte man hätte sich im Thread darauf geeinigt, dass man in C++ das I davor schreibt damit man für die Implementierungsklasse den richtigen Namen benutzen kann. Also bei deinem Beispiel ein IA für die öffentliche Schnittstelle die leicht ist und keine abhängigkeiten hat und A welche die Implementierung beinhaltet.



  • mathik schrieb:

    rapso schrieb:

    mathik schrieb:

    interfaces sind ja auch schön und gut und man verwendet besser mehr von denen als zu wenig. für jede klasse ein interface zu erzeugen, auch wenn diese nur innerhalb der komponente verwendet wird und sonst keiner kennt, finde ich einfach übertrieben und verkompliziert einfach unnötig den code.

    fuer jede fuer die es moeglicherweise alternativ implementierungen geben kann wird es gemacht, das ist auch sinnig.

    d.h. nun doch nicht für jede klasse!? 🙂

    das hab ich nie gesagt. lies nochmal.

    solche begründungen, wie "weil es in zukunft vielleicht benötigt wird" finde ich jedoch gefährlich. bei agiler entwicklung soll man ja möglichst alles so einfach wie möglich halten und bei bedarf refaktorisieren. man sollte also nicht zu weit in die zukunft schauen.

    mit der zeit lernt man planvoll zu arbeiten, sodass die wenigen griffe weniger zeit beantspruchen als spaeteres refractoring, ansonsten laesst man es.



  • Marc++us schrieb:

    Das tun die Leute mit dem "I"-Prefix doch auch. 😉

    die tun das wie ich? 😕


Anmelden zum Antworten