Eine Frage des Stils?



  • Nexus: Ich hab meine Attributsnamen ohne Schnickschnack. Wenn ich mal nen Parameter mit demselben Namen hab, bekommt der nen Unterstrich angehängt. Find ich schön, weil man den Parameter nur genau einmal braucht, nämlich zum Setzen des Attributs.



  • Nexus schrieb:

    volkard schrieb:

    Da ist kritisch anzumerken, daß my in der Literatur eigentlich nur bei Anfängeranfängerbüchern genommen wird.

    Wirklich? Das wäre mir weder aufgefallen noch habe ich davon gehört. "CKlasse" und so, okay. Aber "my" als Präfix? Allerdings muss ich sagen, dass ich wohl zu wenig Anfängerbücher kenne, um das gut beurteilen zu können. Danke jedenfalls für den Hinweis.

    Und was hälst Du von
    "mein" als Präfix?

    class Person
    {
       int meinAlter;
       int meineGroesse;
       ...
    }
    

    Zucken Dir jetzt die Lachmuskeln?
    Gib es zu, die Mundwinkel sind zuerst hochgerutscht beim Lesen, dann runter beim Erkennen, und dieser Satz läßt sie wieder hochrutschen, weil ich so frech bin.



  • Also my_ meide ich wie der Teufel das Weihwasser. Aber nicht nur weil es, genau wie m_ , in Anfängerbüchern vorkommt, sondern weil ich beruflich auch viel mit Perl zu tun habe, und da ist my das Schlüsselwort um eine Variable zu definieren.

    Generell empfinde ich nicht nur m_ sondern auch alle Anderen Präfixe als hässlich, wenn sie einen Unterstrich voraussetzen.

    Ich bevorzuge sprechende Namen, bei Funktionen und Variablen; Das erste Wort klein, folgende Groß.
    Bei Definitionen wie Klassen, Structs und Templates das erste Wort auch groß. Hier allerdings mit C, S oder T als Präfix. (Denn da eignen sie sich hervorragend um klare Unterscheidungen zu erhalten.)

    Für Funktionsparameter habe ich mal die Vorgabe aus den Programmierrichtlinien eines früheren Arbeitgebers übernommen. Dort wurden alle Argumente mit einem kleinen a (wie "Argument") begonnen, und Übernahmen von Argumenten mit einem kleinen x (wie "eXtended"). Das finde ich zwar nicht sonderlich hübsch, es ist aber ganz praktisch.

    Der obige Code würde bei mir damit in etwa so aussehen:

    class CAuto
    {
    private:
      double preis;
    
    public:
      CAuto(double aPreis) : preis(aPreis) { }
      void setPreis (double aPreis)
        {
          double xPreis = normalizeLumpSum(aPreis);
          preis = xPreis;
        }
    };
    

    Achja: Und wie man sieht verwende ich den GNU-Stil in leicht abgewandelter Form, der kommt auch noch von besagten Richtlinien.

    Unterm Strich ist es keine echte Stil- sondern nur Geschmacksfrage. Als schlechten Stil würde ich es nur empfinden, wenn Notationen und Stile in einem Projekt gemischt sind. (Aber zumindest für den Stil gibts ja astyle. ;))



  • @ volkard: Deutsche Bezeichner wähle ich grundsätzlich nicht. Und ja, deine Posts sind ab und zu recht amüsant 🙂

    Yamakuzure schrieb:

    Ich bevorzuge sprechende Namen, bei Funktionen und Variablen; Das erste Wort klein, folgende Groß.

    Bis hier dachte ich: Ah, ein typischer Anti-UNler, der mehr Wert auf semantische als formale Aussagekraft legt.

    Yamakuzure schrieb:

    Bei Definitionen wie Klassen, Structs und Templates das erste Wort auch groß. Hier allerdings mit C, S oder T als Präfix. (Denn da eignen sie sich hervorragend um klare Unterscheidungen zu erhalten.)

    Hier musste ich die Schublade dann doch wieder wechseln. Um mal einige Dinge kritisch zu hinterfragen und dich zum Nachdenken anzuregen:

    • Warum die Unterscheidung zwischen struct und class ? Ich habe das Gefühl, du orientierst dich zu stark an Schlüsselwörtern.
    • Wäre nicht z.B. auch ein I für Interface angebracht? Das ist oft nämlich weiter von statusbehafteten class -Klassen entfernt als eine Struktur.
    • Warum T für Templates? Templates sind an den spitzen Klammern eindeutig zu erkennen.
    • Wie unterscheidest du struct und class , wenn es sich um Templates handelt?
    • Was machst du mit Typedefs?


  • Nexus schrieb:

    knivil schrieb:

    Namenskonventionen haben nix mit Polymorphie zu tun.

    Einheitliche Namen hingegen schon. Darauf basiert die ganze Funktionsüberladung oder das Duck-Typing bei Templates. ADL ist ein weiteres Beispiel.

    Prototyping lässt grüßen.



  • Meine Antworten in kursiv, okay?

    Nexus schrieb:

    • Warum die Unterscheidung zwischen struct und class ? Ich habe das Gefühl, du orientierst dich zu stark an Schlüsselwörtern.
      Es gibt Programme, bei denen ich eine globale Ansammlung von Umgebungswerten (aka Environment) brauche. Das sind meist kleine Programme, die sich im Wesentlichen auf den C-Kern beschränken. Hier benutze ich Structs in der Tat als eben solche, auch wenn struct nur ein Alias für class ist. Die C-Fans in meiner Firma kommen damit außerdem besser klar.
    • Wäre nicht z.B. auch ein I für Interface angebracht? Das ist oft nämlich weiter von statusbehafteten class -Klassen entfernt als eine Struktur.
      Interace? Ich verwende manchmal Interface-Klassen, und die haben ein C wie Class.
    • Warum T für Templates? Templates sind an den spitzen Klammern eindeutig zu erkennen.
      Weil die Header genauso heißen, aber keine spitzen Klammern haben können.
    • Wie unterscheidest du struct und class , wenn es sich um Templates handelt?
      Nur Klassen-Templates bekommen das T. Entschuldige bitte, die Einschränkung habe ich vergessen zu erwähnen. Templated structs und Funktionen sind Structs und Methoden. Bei Structs verwende ich sie allerdings eh nur für TMP, und da haben sie Funktionscharakter und werden auch so benannt.
    • Was machst du mit Typedefs?
      Oh, die hatte ich vergessen. Also Außerhalb geschlossener Strukturen bekommen typedefs einfach sprechende Namen wie andere Typen auch, innerhalb geschlossener Strukturen sinds meist nicht-reservierte Abkürzungen mit einem Unterstrich davor. Ich weiß, das ist böse, grausam, und darf man nicht machen. Aber die Angewohnheit ist fast 20 Jahre alt (bei typedefs) und ich kanns mir irgendwie nicht abgewöhnen... 😞

    Achja: Und ja, ich bin da wirklich _ziemlich_ Schlüsselwort verhaftet, aber ja nicht ausschließlich.

    Fast vergessen: Endlich mal jemand, der nachfragt, wenn was komisch klingt. Dankeschön!



  • knivil schrieb:

    Polymorphie lässt grüßen

    Namenskonventionen haben nix mit Polymorphie zu tun.

    An der Stelle habe ich mich wohl ein bisschen ungenau/falsch ausgedrückt.

    Ich meinte eher, dass Frameworks einen bestimmten Stil vorschreiben. Wenn man verschiedene Frameworks einsetzt, kommt es zu verschiedenen Schreibweisen innerhalb eines Projektes. Dies fällt bei Vererbung besonders auf. Ein Beispiel:

    #include <gtkmm/main.h>
    #include <gtkmm/window.h>
    #include <gtkmm/button.h>
    #include <iostream>
    
    class SpecialButton : public Gtk::Button
    {
    public:
    	bool getState() {return state;};
    	void setState(bool state) {this->state = state;};
    protected:
    	virtual void on_clicked();
    private:
    	bool state;
    };
    
    void SpecialButton::on_clicked()
    {
    	std::cout << "SpecialButton Clicked\t State: " << state << std::endl;
    	state = !state;
    }
    
    int main(int argc, char* argv[])
    {
    	Gtk::Main kit(argc, argv);
    
    	SpecialButton button;
    	button.setState(false);
    	button.set_label("SpecialButton.");
    
    	Gtk::Window window;
    	window.set_title("Der Titel...");
    	window.set_border_width(10);
    	window.add(button);
    	window.show_all_children();
    
    	Gtk::Main::run(window);
     return 0;
    }
    

    Wie man sieht schreibe ich meine Methodennamen in der Regel zusammen und fange mit einem kleinen Buchstaben an. Um nun in der neuen Klasse SpecialButton die click-Methode zu überschreiben muss ich on_click schreiben und nicht onClick . Die restlichen Methoden (in diesem Falle Setter und Getter für den State) kann ich wieder in der für mich üblichen Schreibweise schreiben.

    P.S.: Ich hoffe man sieht, dass das Beispiel aus der Luft gegriffen ist. 😉



  • Yamakuzure, danke für die Erörterung. Gut, einmal andere Argumente für die UN als "ich hab das mal irgendwo gesehen und finde es noch praktisch" zu hören. 🙂

    Ich selbst benutze struct auch für andere Dinge als class – nämlich Datenbündel, Funktoren und Metafunktionen. Allerdings habe ich persönlich bisher nicht die Notwendigkeit verspürt, diese mit "S" oder "C" zu kennzeichnen. Schlimmer wäre es jetzt gewesen, wenn du struct und class nahezu gleich einsetzt, aber die Bezeichner doch trennst (die Schlüsselwörter selbst unterscheiden sich ja nur in der Default-Sichtbarkeit). Das "I" für Interface verwenden gewisse Leute, um neben formalen (Schlüsselwort) auch semantische Fälle von Klassen zu unterscheiden. Ist natürlich auch ein Streitfall, zumal es Zwischenstufen gibt. Um ganz konsequent zu sein, müsste z.B. man auch Enum-Typen speziell präfixen. Zumindest ist die Auswahl von class und struct als sonderbehandelte Typen mehr oder weniger willkürlich (auch wenn diese natürlich einen Grossteil der Fälle ausmachen).

    Zu den Klassentemplates: Ich sehe diese mehr als eine Art konfigurierbare Klassen an. Bei vollständiger Angabe der Template-Argumente erzeugst du schliesslich Klassen daraus. Von daher finde ich den semantischen Unterschied nicht derart gross, dass ich zwei verschiedene Präfixe wählen würde. Zum Beispiel kann es gut sein, dass du für eine Klasse plötzlich eine austauschbare Komponente einbaust (z.B. Typ oder Policy), und dann eigentlich unnötigerweise Bezeichner und Dateinamen refactoren musst. Unter Umständen schreibst du sogar ein Typedef für eine häufig benutzte Instanziierung, das dann wie die vorherige Klasse benutzt werden kann. Obwohl sich für den Benutzer dadurch nichts ändert, benötigt er ein anderes Präfix (oder keins mehr), was für Verwirrung sorgen kann.

    Ausserdem ist es oft gar nicht relevant, ob es sich um eine Klasse handelt. Bei cout << 2 * number << endl; soll das Doppelte von number ausgegeben werden. Ob es sich dabei um double oder MyDouble handelt, ist unwichtig. Wichtig ist, dass der Typ die Multiplikation und Ausgabe unterstützt. Wenn Methoden aufgerufen werden, siehst du ja auch gleich an der Syntax, dass es sich um eine Klasse handelt. Du distanzierst dich halt mit dem "C" in vielen Fällen von anderen Typen, obwohl der tatsächliche Abstand gar nicht so gross ist.

    Was ich persönlich am schlimmsten finde: Ungarische Notation zwingt dich in C++ zur Inkonsistenz. Du kannst Klassentypen nicht durchgehend mit "C" präfixen. Spätestens wenn du Abstraktionsmechanismen verwendest, seien das zum Beispiel Typedefs oder Templates, musst du darauf verzichten. Aber das "C" nur manchmal hinzuschreiben – wann genau, ist wiederum kontrovers – entfernt sich vom ursprünglichen Gedanken, Klassentypen schnell im Code zu erkennen und reduziert die tatsächlichen Vorteile dieser Namenskonvention.



  • Ah, da war ich wohl nicht deutlich genug.

    Also die Klasse heißt, zum Beispiel "CMeineKlasse". Aber ob eine Instanz nun "foo", "bluBB", oder "CmyFoo" heißt, ist mir wurscht. (Obwohl ich ja schon sagte, dass ich sprechende Namen ohne Präfixe verwende.)

    Oder um es auf dein Beispiel zu transponieren: "Ob es sich dabei um double oder* C ** MyDouble handelt, ist unwichtig.*"

    Was ich nicht verstehe ist dein letzter Absatz. Wieso ungarische Notation? Einzig ein Missverständnis, ich könnte Variablen anstatt Typen gemeint haben, sei eine mögliche Erklärung. Siehe mein obiges Beispiel über CAuto , Instanzen könnten zum Beispiel heißen " autoA " oder " porscheBlau " oder " gelberFord ". Aber ganz sicher nichts mit irgendeinem Typenpräfix (aka UN) davor.



  • Yamakuzure schrieb:

    Was ich nicht verstehe ist dein letzter Absatz. Wieso ungarische Notation? Einzig ein Missverständnis, ich könnte Variablen anstatt Typen gemeint haben, sei eine mögliche Erklärung.

    Nein, ich hab schon verstanden, dass du Typen meinst. Vielleicht war "UN" zu spezifisch, ich bezog mich auf Präfixe in Abhängigkeit des Typen (oder der Art von Typ wie z.B. class ) im Allgemeinen. Mein letzter Absatz richtet sich gegen das "C" vor Klassen, aber kann so mehr oder weniger verallgemeinert werden.



  • Ich probiere in letzter Zeit auch unterschiedliche Stile aus.
    Angefangen habe ich mit dem üblichen UpperCamelCase für Klassennamen, lowerCamelCase für Variablen- und Methodennamen und keinerlei Prä- oder Suffix für Klassenattribute - dafür aber Getter und Setter der Form getXX und setXX.

    Inzwischen habe ich mich an die von mir verwendeten Bibliotheken angepasst (also boost, Standardbibliothek, etc.) und verwende generell Unterstriche zur Unterteilung der Klassennamen und sonst nur Kleinbuchstaben (außer in Makros). Dazu haben Getter und Setter bei mir jetzt den gleichen Namen und sind entsprechend überladen. Das macht es natürlich nötig die Klassenattribute anders zu bennenen, weswegen ich, nachdem ich für kurze Zeit mit dem unleserlichen _ Suffix gearbeitet habe (ptr_->(), sieht grässlich aus), zum m_ Präfix übergegangen bin.

    Momentan bin ich ganz zufrieden mit der Lösung, da es sich gut in STL, etc. einfügt und auch angenehm zu lesen ist (mMn). Gleichzeitig denke ich mir so häufiger gute Namen aus, da man ja doch nicht so viele Unterstriche haben möchte.
    Die STL hat ja auch kein "dynamic_array" sondern einfach nur "vector". 😉

    Alles was nur in die Nähe von Microsofts Ungarischer Notation (im Gegensatz zur echten UN) geht, vermeide ich.



  • @beenzy: Tja, dann solltest du dich aber vom "m_"-Präfix verabschieden, denn der ist ein Teil der Microsoft'schen Abwandlung der Hungarian Notation. 😉

    @nexus: Oh, ich glaube es liegt da doch ein Problemchen vor. Du bezogst dich auf Präfixe in Abhängigkeit des Typen, und ich verwende keine Typen-abhängige Präfixe.

    Deinen Einwand aus dem vorherigen Post über die Refaktorisierung wenn doch generalisiert werden muss, sehe ich ein wenig Anders. Für genau so etwas sind Komposition und Aggregation da. Wenn ich einen Grundtypen verändern muss, war mein Design falsch, und ich bin selber Schuld. Egal wie die Typen heißen. 😉

    Nochmal: " class CFoo { }; " ist eine Typdeklaration/Definition. " CFoo einFoo; " ist eine Objektinstanziierung und etwas völlig Anderes. Denn CFoo kann nicht typenabhängig sein, da "CFoo" der Typ ist. Darüber hinaus müsste es laut ungarischer Notation " grFoo; " heißen, für "Group", was auf alle Verbünde wie Structs, Records und Klassen verwendet wird.

    Du siehst, es handelt sich um den Versuch, Äpfel mit Birnen zu vergleichen.

    Letztendlich verstehe ich deine Vehemenz nicht. Schließlich ist "Das Wesentliche ist, einheitlich zu bleiben." eine Aussage von dir, und ich bleibe stur einheitlich. Oder bist du angefressen, weil ich implizit dein "my"-Präfix für mich als untauglich gebrandmarkt habe?

    So. Der Vollständigkeithalber hier drei hilfreiche Links:



  • Yamakuzure schrieb:

    @
    Nochmal: " class CFoo { }; " ist eine Typdeklaration/Definition.

    Der Punkt ist aber dass das C ein "arten Bezeichnung" ist. Es sagt CFoo ist eine Klasse. Du schliesst also aus dass es ein typedef oder eine struct oder ein enum, etc. ist.

    Das ist genau das selbe wie iNum oder sName.



  • Yamakuzure schrieb:

    Oh, ich glaube es liegt da doch ein Problemchen vor. Du bezogst dich auf Präfixe in Abhängigkeit des Typen, und ich verwende keine Typen-abhängige Präfixe.

    Doch. Du benennst aber nicht Variablen nach ihren Typen, sondern Typen nach der Kategorie von Typen, der sie angehören (z.B. struct oder class oder was anderes).

    Yamakuzure schrieb:

    Deinen Einwand aus dem vorherigen Post über die Refaktorisierung wenn doch generalisiert werden muss, sehe ich ein wenig Anders. Für genau so etwas sind Komposition und Aggregation da. Wenn ich einen Grundtypen verändern muss, war mein Design falsch, und ich bin selber Schuld.

    Das Design muss doch nicht falsch sein, nur weil man plötzlich neue Features hinzufügt.

    Yamakuzure schrieb:

    Nochmal: " class CFoo { }; " ist eine Typdeklaration/Definition. " CFoo einFoo; " ist eine Objektinstanziierung und etwas völlig Anderes.

    Danke, so viel verstehe ich auch noch von C++. Wir reden aber aneinander vorbei. Ich habe wie gesagt schon verstanden, dass du keine Variablen nach Typen benennst.

    Yamakuzure schrieb:

    Letztendlich verstehe ich deine Vehemenz nicht. Schließlich ist "Das Wesentliche ist, einheitlich zu bleiben." eine Aussage von dir, und ich bleibe stur einheitlich. Oder bist du angefressen, weil ich implizit dein "my"-Präfix für mich als untauglich gebrandmarkt habe?

    Warum plötzlich so feindselig? Ich habe weder meine Ansicht als absolut hingestellt, noch gesagt, dass du deinen Stil ändern solltest. Ich habe lediglich Probleme von "C" angesprochen, auf die du aber nie konkret eingegangen bist.



  • @beenzy: Tja, dann solltest du dich aber vom "m_"-Präfix verabschieden, denn der ist ein Teil der Microsoft'schen Abwandlung der Hungarian Notation. 😉

    Ja, da hast du Recht. Aber wie soll ich meine Membervariablen dann nennen? Ich habe eigentlich nicht wirklich Lust mir da jedes Mal groß was auszudenken, nur damit sie nicht so heißen wie die Getter/Setter.

    Und ist m_ wirklich eine Abwandlung der Microsoft'schen UN? "m" steht doch nur für "member" oder "my" und kennzeichnet doch nur, dass die Variable eine Membervariable ist und nicht, welchen Typ sie hat (ich schreibe ja nicht "m_ipszVar").

    Denn CFoo kann nicht typenabhängig sein, da "CFoo" der Typ ist.

    Mh, so ganz verstehe ich den Sinn dahinter nicht.
    Die Anzahl an eingebauten Datentypen ist in C++ nicht sonderlich groß, wieso muss ich mich dann bei einer Objektinstanzierung noch darauf hinweisen, dass ich eine Klasse/Struct instanziere?


Anmelden zum Antworten