Wie benennt Ihr Interface-Klassen?



  • wisst ihr eigentlich, dass (D)evil 15 Jahre alt ist? 😮 😮



  • Also so generell würde ich bei einer Hierarchie den Namen von oben nach unten länger werden lassen, also ganz oben schonmal "Button" bzw "button" hinpacken. Bei der mittleren Ebene kommt's halt drauf an, was sie von der oberen unterscheidet, sonst halt "SpecificButton" bzw "spec_button" und dadrunter halt "DefButton" bzw "default_button".

    Kurze Nebenfrage: Wie benennst du längere Variablen eigentlich? Nur aus Interesse 🙂



  • @wissender:

    Wisst ihr eigentlich, dass (D)Evil 15 Jahre alt ist? 😮 😮

    Wenn es so wäre, würde es dann ein Problem für dich darstellen?

    Kurze Nebenfrage: Wie benennst du längere Variablen eigentlich? Nur aus Interesse

    Wen meinst de?

    Gerade dann, wenn man Schnittstellen für Parameter benutzen sollte.

    namespace interface = mylib::interface;
    interface::button inst(interface::button::my_enum_val1);
    

    Na ok hast recht ^^ Wird doch relativ lang ...



  • (D)Evil schrieb:

    Kurze Nebenfrage: Wie benennst du längere Variablen eigentlich? Nur aus Interesse

    Wen meinst de?

    Meinte Artchi, weil er seine Klassen irgendwie nach dem Stil benennt, wie ich meine Variablen 🤡



  • @badestrand! Ich habe hauptsächlich lange Variablennamen, wenn ich z.B. für einen Button eine spezielle Implementierung habe:

    class button : public base_button
    {
          native::native_component<button, base_panel, rect_t> *button_impl;
          rect_t rect;
          dimension_t dim;
          std::string name;
    };
    

    Aber ansonst heißen meine Variablen, ganz normal. Zu lange Variablen mache ich einfach kurz (schneide sie ab oder sowas).
    Bei lokalen temporären Variablen, gehe ich meistens noch radikaler vor:

    layout_ptr fl(new flow_layout());
    get_root_panel().set_layout(fl);
    

    @devil! Ja, ich mache ja z.B. sowas:

    void foo(mylib::interface::button b);
    

    In einem Header, wo man using namespace vermeiden sollte, wäre das nicht schön.

    Aber:

    namespace interf = mylib::interface;
    void foo(interf::button b);
    

    wäre eine gute Lösung. Gute Idee devil! 🙂



  • (D)evil schrieb:

    Wenn es so wäre, würde es dann ein Problem für dich darstellen?

    Nein, im Gegenteil! Ich habe mich nur gewundert, als ich erfahren habe, dass du 15 Jahre alt bist. Ich hätte dich wesentlich älter eingeschätzt. 😉



  • ich persönlich mach keinen unterschied in der benennung zwischen interfaces, abstrakten klassen und konkreten klassen, da es für die verwendung keine rolle spielt. wenn man ausversehen versuchen sollte, eine instanz eines interfaces zu erzeugen, gibt einem der compiler schon früh genug einen auf die finger.

    ich mags halt nicht, wenn in den signaturen meiner methoden son präfix gerümpel auftaucht 😃



  • So, jetzt muss ich mich auch mal einmischen. Die Idee mit den Namensbereichen hat natürlich seinen Reiz, ich halte sie trotzdem für nicht sehr gut. Namensbereiche sollten IMHO *thematisch* gruppieren. Ich verwende in C++ eigentlich durchgängig dieselbe Praxis wie in anderen Umgebungen (.NET, Java) auch, also die Konvention firmenname::projektname als Präfix für alle Namensbereiche. Der Firmenname kann manchmal weggelassen werden. Namensbereiche haben damit nur zwei Ziele:

    1. Namenskonflikte verhindern!
    2. (Eventuell) Objekte leichter auffindbar machen.

    Ich denke, ein Namensbereich namens interface hilft da nicht (zumal einige alte Compiler immer noch Probleme mit zu vielen verschachtelten Namensbereichen haben).

    Was lange Namen betrifft: Wo ist das Problem? Wenn ein langer Name nötig ist, um den Zweck einer Methode (o.ä.) ausreichend zu beschreiben, dann wird eben ein langer Name verwendet. In einem aktuellen Projekt (nicht C++) habe ich z.B. eine Klasse namens 'ActionDataSourceControl' und eine Methode namens 'CreateConditionGroupForFields'. Allerdings haben lokale Variablen bei mir eigentlich immer kurze Namen, oft nur einen einzigen Buchstaben. Für kurze Methoden ist das überhaupt kein Problem, bei längeren Methoden verkleinere ich den Gültigkeitsbereich der Variable so weit wie möglich). Außerdem bestehen lokale Variablen bei mir oft aus den Anfangsbuchstaben. Eine lokale Instanz der obenstehenden Klasse könnte bei mir z.B. 'adsc' heißen.

    Ansonsten halte ich es wie Archie: Ich verwende konsistent die Benennung, die die STL und Boost vorgeben, also alles Kleinbuchstaben und Unterstrich als Trenner. Das ist zwar keine schöne Konvention (zumindest für öffentliche Schnittstellen), aber Konsistenz ist hier m.E. wichtiger.

    Zum Schluss noch einen Satz zur eigentlichen Fragestellung: Ich halte die verwendete Konvention für gut. Aus 'button_base' ist zwar nicht erkennbar, ob es sich um eine Schnittstelle oder eine abstrakte Basisklasse handelt, aber das soll es IMHO auch gar nicht (zumal C++ technisch sowieso nicht zwischen den beiden unterscheiden kann).



  • warum so viele leute probleme mit langen klassen- und methodennamen haben, kann ich ehrlich gesagt immer noch nicht nachvollziehen. lange, beschreibende namen sorgen für sehr viel mehr übersicht, als es die verwendung kurzer namen zum zwecke der "übersichtlichkeit" im code je erreichen könnte.

    Glyph *paragraph = new Paragraph;
    DocumentLayoutContentController *controller
      = new DocumentLayoutContentController( Layout::PLAIN );
    controller->addGlyph( paragraph );
    
    // find ich z.b. wesentlich übersichtlicher als
    
    glyph *p = new para;
    ctrl_doclay *ctrl = new ctrl_doclay( consts::L_PLAIN );
    ctrl->add( p );
    

    (das war ein leicht angepasstes reales beispiel ^^)



  • von den ganzen unterstrichen in dem code krieg ich noch augenkrebs. Das ist ja schrecklich. Wie kann man soetwas nur übersichtlicher finden???



  • Konrad Rudolph schrieb:

    So, jetzt muss ich mich auch mal einmischen. Die Idee mit den Namensbereichen hat natürlich seinen Reiz, ich halte sie trotzdem für nicht sehr gut. Namensbereiche sollten IMHO *thematisch* gruppieren. Ich verwende in C++ eigentlich durchgängig dieselbe Praxis wie in anderen Umgebungen (.NET, Java) auch, also die Konvention firmenname::projektname als Präfix für alle Namensbereiche. Der Firmenname kann manchmal weggelassen werden. Namensbereiche haben damit nur zwei Ziele:

    1. Namenskonflikte verhindern!
    2. (Eventuell) Objekte leichter auffindbar machen.

    Ich denke, ein Namensbereich namens interface hilft da nicht (zumal einige alte Compiler immer noch Probleme mit zu vielen verschachtelten Namensbereichen haben).

    👍 Ich dachte schon ich bin der einzige der das komisch findet



  • Konrad Rudolph schrieb:

    So, jetzt muss ich mich auch mal einmischen.

    Ich bitte darum! 🙂

    Konrad Rudolph schrieb:

    Namensbereiche haben damit nur zwei Ziele:

    1. Namenskonflikte verhindern!
    2. (Eventuell) Objekte leichter auffindbar machen.

    Ja, beides kann der Namespace interface erfüllen. Auch thematisch erfüllt er seinen Zweck. Klar, es kommt darauf an, was thematisiert werden soll. Ich muß ehrlich sagen, das in unserem aktuellen Java-Projekt, sich die Kräfte durchgesetzt haben, für jeden Pups ein Package anzulegen. Da würde ich am liebsten um mich schlagen:

    de.firma.mylib.option
    de.firma.mylib.option.core
    de.firma.mylib.option.model
    de.firma.mylib.option.model.internal
    de.firma.mylib.option.ui
    de.firma.mylib.option.ui.internal
    de.firma.mylib.option.util
    

    Und es ist kein Ende abzusehen. Zumal option nur ein Thema von ca. 30 ist. 😡

    Da gehe ich mit dir konform, das sowas nicht ausarten darf.

    Konrad Rudolph schrieb:

    Ich denke, ein Namensbereich namens interface hilft da nicht (zumal einige alte Compiler immer noch Probleme mit zu vielen verschachtelten Namensbereichen haben).

    OK, in meiner Lib interessieren mich zu alte Compiler nicht. Die schliesse ich sogar absichtlich aus. Ich finde, man darf ein gewisses Mass an Konformität erwrten.

    Konrad Rudolph schrieb:

    Was lange Namen betrifft: Wo ist das Problem? Wenn ein langer Name nötig ist, um den Zweck einer Methode (o.ä.) ausreichend zu beschreiben, dann wird eben ein langer Name verwendet. In einem aktuellen Projekt (nicht C++) habe ich z.B. eine Klasse namens 'ActionDataSourceControl' und eine Methode namens 'CreateConditionGroupForFields'.

    Gegen aussagekräftige Namen habe ich nicht. Aber dein Methodenbeispiel, würde mich mal interessieren. Ich schätz es sieht ca. so aus:

    ConditionGroup CreateConditionGroupForFields(Fields f);
    

    Da muß ich sagen, finde ich es unnötig lang. So wäre es kürzbar, und trotzdem verständlich:

    ConditionGroup CreateConditionGroup(Fields f);
    

    Der Übergabeparameter kann schon aussagen, das was ich "für" machen soll. Ich sehe öffters solche doppelt-gemoppelt-Bezeichner. Dabei gibt die Signatur-Syntax schon vieles her.

    Klar, sowas ist dagegen einfach unschön:

    ConditionGroup CrtCndtonGrp(Fields f);
    

    😉

    Konrad Rudolph schrieb:

    Ansonsten halte ich es wie Archie: Ich verwende konsistent die Benennung, die die STL und Boost vorgeben, also alles Kleinbuchstaben und Unterstrich als Trenner. Das ist zwar keine schöne Konvention (zumindest für öffentliche Schnittstellen), aber Konsistenz ist hier m.E. wichtiger.

    *zustimm* Das CamelCase von Java finde ich pers. auch schöner. Aber wenn ich ausgiebig die C++-Stdlib und Boost benutze, halte ich mich an deren Konventionen. Denn in Java richte ich mich auch nach der Sun-Konvention, egal obs mir gefällt oder nicht.

    Konrad Rudolph schrieb:

    Zum Schluss noch einen Satz zur eigentlichen Fragestellung: Ich halte die verwendete Konvention für gut. Aus 'button_base' ist zwar nicht erkennbar, ob es sich um eine Schnittstelle oder eine abstrakte Basisklasse handelt, aber das soll es IMHO auch gar nicht (zumal C++ technisch sowieso nicht zwischen den beiden unterscheiden kann).

    Stimmt, haste Recht. Technisch gesehen ist es in C++ egal ob es abstrakt oder ein "Interface" ist.



  • thordk schrieb:

    warum so viele leute probleme mit langen klassen- und methodennamen haben, kann ich ehrlich gesagt immer noch nicht nachvollziehen. lange, beschreibende namen sorgen für sehr viel mehr übersicht, als es die verwendung kurzer namen zum zwecke der "übersichtlichkeit" im code je erreichen könnte.

    Glyph *paragraph = new Paragraph;
    DocumentLayoutContentController *controller
      = new DocumentLayoutContentController( Layout::PLAIN );
    controller->addGlyph( paragraph );
    
    // find ich z.b. wesentlich übersichtlicher als
    
    glyph *p = new para;
    ctrl_doclay *ctrl = new ctrl_doclay( consts::L_PLAIN );
    ctrl->add( p );
    

    (das war ein leicht angepasstes reales beispiel ^^)

    ctrl anstatt Controller finde ich für eine Variable i.O. Zumal ctrl auch noch auf jeder (englischen) Tastatur drauf steht, und jeder wissen sollte was es heißen könnte. 😉

    Im Ernst, solche Zerstückelungen mache ich pers. hauptsächlich bei Variablen und dann meistens nur bei temporären.

    ctrl_doclay als Typname würde ich so auch nicht machen. Höchstens bei privaten lokalen Klassen, die nicht nach draussen dringen. Alles was vor dem User versteckt ist, kürze ich gerne. Alles was der User benutzen muß, versuche ich kurz zu halten. Aber nicht in dem versuche Buchstaben weg zu lassen.

    Anstatt TreeListView finde ich z.B. TreeList i.O., wenn es in einem View-Namespace ist. Wenn es ein TreeListModel gibt, sollte man evtl. einen Model-Namespace überlegen. Wobei TreeListView auch schon recht kurz ist. Nur noch mehr Wörter dürften nicht rein. StuecklistenTreeListView finde ich schon har an der Grenze! Noch ein Wort, und ich würde die Kriese kriegen. 😉



  • Artchi schrieb:

    Konrad Rudolph schrieb:

    Was lange Namen betrifft: Wo ist das Problem? Wenn ein langer Name nötig ist, um den Zweck einer Methode (o.ä.) ausreichend zu beschreiben, dann wird eben ein langer Name verwendet. In einem aktuellen Projekt (nicht C++) habe ich z.B. eine Klasse namens 'ActionDataSourceControl' und eine Methode namens 'CreateConditionGroupForFields'.

    Gegen aussagekräftige Namen habe ich nicht. Aber dein Methodenbeispiel, würde mich mal interessieren. Ich schätz es sieht ca. so aus:

    ConditionGroup CreateConditionGroupForFields(Fields f);
    

    Da muß ich sagen, finde ich es unnötig lang. So wäre es kürzbar, und trotzdem verständlich:

    ConditionGroup CreateConditionGroup(Fields f);
    

    Der Übergabeparameter kann schon aussagen, das was ich "für" machen soll. Ich sehe öffters solche doppelt-gemoppelt-Bezeichner. Dabei gibt die Signatur-Syntax schon vieles her.

    Da gebe ich Dir vollommen recht. Leider sieht die Signatur vollkommen anders aus als von Dir vermutet:

    public static void CreateConditionGroupForFields(
        WizardBase dialog,
        StepBase step
    );
    

    Hier schreit ja erst einmal alles nach schlechtem Design. Leider gibt es dafür recht gute Gründe. 'WizardBase' ist eine (Dialog-)Basisklasse aus einem anderen Projekt. Die Methode mit dem Monsternamen befindet sich in einer statischen Helper-Klasse und stellt quasi ein Mixin dar. Eine Member-Methode wäre hier konzeptuell besser gewesen, kommt aber leider nicht in Frage, weil die Vererbungshierarchie sonst ausgeartet wäre (na ja, um genau zu sein ist fehlende Planung Schuld, es wäre einiges Refactoring notwendig gewesen, um das nachträglich zu korrigieren). Bei der im Namen genannten 'ConditionGroup' handelt es sich um ein UI-Konzept aus der Anwendung. Die 'Fields' sind Teil der 'StepBase'-Klasse (nicht ganz korrekt, aber nahe genug). Elemente der Klasse 'Field' direkt zu übergeben ist leider auch nicht möglich, weil diese nicht direkt existieren sondern durch diese Methode erst extrahiert werden.

    => Aber im Prinzip hattest Du schon recht: Dieser umständliche Name kompensiert in großem Maße für ein schlechtes Design.

    *zustimm* Das CamelCase von Java finde ich pers. auch schöner.

    *brr*. CamelCase ist für mich persönlich das schlimmste überhaupt; es stört den Lesefluss. Herfried Wagner hat das recht anschaulich erläutert (runterscrollen bis „Probleme der Camel Case-Konvention“).

    Ich bevorzuge aus diesem Grund für öffentliche Schnittstellen die PascalCase-Konvention. Aber wie Du auch sagtest: Ich halte mich an die „lokalen Gepflogenheiten“, d.h. in Java verwende ich z.B. ebenfalls CamelCase.



  • die in dem artikel erläuterten probleme betreffen aber auch ausschließlich die betrachtete sprache und nicht java, die sprache, welche camel case populär gemacht hat.

    public int foo;
    public foo();
    
    //...
    
    this.foo = 0; // ist *immer* eindeutig
    foo = 0; // ebenso
    foo(); // und zwar deshalb
    foo() = 0; // und weil sowas falsche syntax wäre ;)
    


  • thordk schrieb:

    die in dem artikel erläuterten probleme betreffen aber auch ausschließlich die betrachtete sprache und nicht java, die sprache, welche camel case populär gemacht hat.

    ACK. In Java gelten *diese* Bedenken so nicht. Die anderen Bedenken bezüglich der Lesbarkeit und des Schriftbilds aber schon und die sind meiner Erfahrung nach nicht unerheblich, was sich aber nur auf subjektiven Eindrücken begründet.



  • Was ich an Camel-Case schön finde: Dadurch gibt es jetzt vier Stile, mit denen man Code-Arten voneinander abgrenzen kann. Z.B.

    class PascalCamel
    {
    public:
        void kissMyCamel()
        {
            camel_hunches = TWO_HUNCHES;
        }
    
    protected:
        enum Hunches
        {
            ONE_HUNCH,
            TWO_HUNCHES
        };
    
    private:
        int camel_hunches; // Nachgeguckt, hunch->Höcker :)
    };
    

    Damit kann man auf einen Blick sehen, um was es sich handelt, ähnlich wie Makros oder Konstanten meist GROß geschrieben werden. Ansonsten würde ich nicht so recht damit zurecht kommen:

    class default_button // einmal Klasse
    {
    };
    default_button my_btn;
    
    // oder aber
    button default_button; // diesmal Variablen-Bezeichner
    
    // oder auch
    button* default_button( int nr );
    

    Klar, man erkennt es aus dem Kontext, aber ich finde es angenehmer, sie auch vom Erscheinungsbild unterscheiden zu können.


Anmelden zum Antworten