Sauberes Programmieren // Varibeln mit Prefix



  • Original erstellt von dEUs:
    Der Präfix soll ja keine exakte aussage machen. Präfix str nehm ich zb bei char, TCHAR, XYZCHAR*, CString, std::string ... Es ist also unmöglich, genau zu wissen, welcher Typ das jetzt ist, aber es gibt demjenigen, der den Code überfliegt, wenigstens nen Anhaltspunkt.**

    Demzufolge: 'Derjenige, der den Code überfliegt'[1] wird mit einem

    strName += iOtherName;
    

    _nichts_ anfangen können.

    1. Nehmen wir an, strName sei ein char* und iOtherName sei ein int. Ich möchte also die ersten iOtherName Zeichen über-/zurückspringen.
    2. Nehmen wir an, iOtherName sei ein int und strName sei eine Instanz einer Stringklasse, die den 'Verkettungsoperator +=' auch für ints überlädt, weil das im Programm häufig gebraucht wird.
    3. Nehmen wir an, iOtherName sei eine Instanz einer Klasse, die mit 'beliebig langen' natürlichen Zahlen rechnet; sie enthält einen Umwandlungsoperator für den Typen von strName, zB einen std::string.
      uswusf.

    _Das_ hilft niemanden.

    [1]: Wieso sollte jemand Code überfliegen wollen. Auf jeden Fall nicht um ihn zu verstehen, denn dann würde er ihn lesen.



  • intruder:
    für ne Klasse nen Prefix zu erfinden ist ja auch sehr unsinnig .. die Namen der einzelnen Klasse sollte ja schon genug sagen denke ich ..
    Was ich jedoch beführworten würde ist die verwendung von prefixen bei .. variablen

    du provozierst doch absichtlich, oder? du wirst doch nicht ernsthaft glauben, dass hier jemand vorgeschlagen hat, vor einen klassennamen ein praefix zu tun. bei der UN geht es darum, den objektnamen einen praefix zu geben, um den typ zu erahnen. klassen sind typen.
    "fuer ne klasse nen prefix zu erfinden" heisst also, den praefix den namen der instanzen der klasse voranzustellen, nicht dem klassennamen.
    manche machen C fuer classe und T fuer POD, aber daran aendert sich auch nix, wenn es millionen klassen gibt. und meist machen das auch nur mfcler und pascaller, also niemand, an dem man sich zu stark orientieren sollte.



  • Original erstellt von Shade Of Mine:
    und irgendwann weisst du, dass du die variable foo brauchst, aber du weisst nicht welches prefix sie hat. wars jetzt ein iFoo, uFoo, uiFoo, nFoo, unFoo?
    und bei functions pointer wirds ja nur noch lustig.

    hmm das ist doch kein argument... das ist genau das selbe problem wenn du keine UN machst und einfach vergessen hast was für ein typ die variable hatte oder ob sie nun lenght oder size geheissen hat...

    ich denke nur, dass wenn man konsistente namen wählt das ganze verständlich genug sein sollte und dannstören die ständigen p i und weis ich das alles vor den variablebnnamen.



  • Original erstellt von japro:
    hmm das ist doch kein argument... das ist genau das selbe problem wenn du keine UN machst und einfach vergessen hast was für ein typ die variable hatte oder ob sie nun lenght oder size geheissen hat...

    nicht ganz.
    stell dir vor du hast 2 projekte am laufen.
    im Projekt 1 wird zwischen unsigned int und int unterschieden -> ui und i als prefix, bei Projekt 2 ist es immer i.

    nun bist du voll vertieft im projekt und weisst jetzt nicht ob du iSumme oder uiSumme nehmen musst. du weisst aber sehr wohl dass Summe ein unsigned int, oder zumindest int. das kann dir ja eigentlich egal sein wenn du schreibst (und oft ist es egal ob du jetzt nen unsigned, signed, long, short verwendest):

    cout<<"die Summe betraegt"<<Summe;

    OK du denkst bei 2 projekten geht das noch - stimmt. Aber du wirst nicht nur 2 Projekte haben sondern unzählige. und irgendwann wirst du alte projekte aufarbeiten müssen und dann kann es sein dass sich die UN ändert.

    und wenn man den namen der variable vergessen hat, dann hilft einem die UN auch nicht.



  • Ich hab den Thread nur mehr oder weniger überflogen und will jetzt einfach mal meine Meinung zu dem Thema hier äussern:

    Ich finde präfixe blöd. Gerade wenn man Programmierhilfen verwendet die vielleicht alle member auflisten, dann kann ich davon ausgehen, dass die dinger nach Namen sondern nach typ sortiert sind. Macht die Suche ned grade gemütlicher. Allerdings muss ich sagen, dass die Dokumentation des Typs innerhalb des Variablennamens durchaus sinn macht.

    Ich persönlich verwende Suffixe für diesen Zweck. Ich hänge an Variablennamen meistens getrennt durch einen underscore ('_') den Typ (wenn er kurz ist wie z.B. "int") oder eine Verkürzung des typs (wenn es sich um Klassennamen wie TStringList oder so handelt) an.

    Meines erachtens hat - egal in welcher Form - das dokumentieren des Datentyps bei Variabeln erhebliche Vorteile. Um mal einige der wichtigsten zu nennen:

    • Wenn einer den Quelltext liest, muss er sich nicht immer fragen "was war das noch gleich für ein Typ?" und in den Deklarationen nachschauen.
    • Oben Genanntes gilt auch bei Fragen nach Überlauf oder ähnlichem, da man ja den bereich durch den Datentyp (z.B. int) gleich mitdokumentiert hat.
    • Ändert ein Datentyp, ändert der Variablenname. das hat zur Folge, dass man die Namen anpassen muss. Kann ein nachteil sein, hat aber den Vorteil, dass man gleich überall - ohne etwas zu vergessen - überprüfen kann ob dann überhaupt noch gültig ist, was man da geschrieben hat.
    • Prä-/Suffixe bieten eine gedankenstütze sowohl beim lesen als auch beim codieren.

    Klar bedeuten Prä-/Suffixe Schreibarbeit. Allerdings denke ich ist es hier wie mit dem Formatieren von Quellen eine Stilfrage. Das Formatieren von Quellen bedeutet auch schreibarbeit, man gewinnt allerdings damit mehr Übersicht und das Ganze programm lässt sich einfacher lesen.

    Ich hab hier lesen müssen dass es mit C++ egal sei, welchen typ man nehme vonwegen Templates und so. Und überhaupt prüfe der Compiler ob gültig sei was man schreibt.
    Das ist fertiger Unfug! Solange C++ der Schweinesprache C entstammt, solange besitzt C++ die gleichen fahrlässigen probleme wie C da lösen Templates auch nichts. Würde man obiges Argument bei Ada oder Pascal oder anderen streng typerisierten Sprachen anführen müsste ich recht geben. Nicht aber bei C(++).

    Was dokumentiert denn besser? Wenn ich schreibe

    /* im Header:*/
    int variableA = 0xFFFF;
    char variableB = 0xFF;
    
    /* Implemenitert wird: */
    {
        ...
        variableB = variableA;
        ...
    }
    

    oder wenn ich schreibe

    /* im Header:*/
    int variableA_int = 0xFFFF;
    char variableB_char = 0xFF;
    
    /* Implemenitert wird: */
    {
        ...
        variableB_char = variableA_int;
        ...
    }
    

    Beim ersten Beispiel kann man - ohne der Kenntnisse der Datentypen - die Risiken der Zuweisung nicht abschätzen. Der Compiler stört sich schon gar nicht dran. Bei der zweiten kommt jedem blinden die Zuweisung mehr als merkwürdig vor und zumindest wird er sich bewusst, was das überhaupt für folgen hat.

    Ähnliches gilt für Pointer oder mehrfach pointer. Es ist doch sicher interessant zu wissen ob denn nun ein Zeiger nur ein Zeigerszeiger ist oder ob er ein Zeiger ist? Auch hier lässt sich dank der suffix/präfix vergabe bestimmen, wie weit der Weg zum Wert auf den Gezeigt wird ist (durch das Anhängen/Voranstellen von entsprechend vielen 'p' oder was auch immer)

    so, nun weiss ichnicht mehr was ich noch schreiben wollte. Aber ich denke das reicht auch mal soweit.

    Das ist vorläufig alles was ich dazu zu sagen habe.

    -junix



  • Es ist eigentlich scheiß egal, hauptsache man hält sich konstant an einen Stil.



  • Original erstellt von Shade Of Mine:
    nun bist du voll vertieft im projekt und weisst jetzt nicht ob du iSumme oder uiSumme nehmen musst.

    Deshalb sollte man konsequent die gleichen präfixe benutzen. Also unsigned int und int werden immer als ui bzw. i bezeichnet... Egal ob unterschieden wird oder nicht. (wobei ich mich sowieso frage wieso du unterschiedliche typen verwendest wenns ja eh nicht drauf an kommt?)

    -junix



  • Was ist denn nun passiert? Ich war 5 Tage im Urlaub und schon ist OOP out oder wie?

    Ein Zeiger auf eine Basisklasse kann auf alle abgeleiteten zeigen. Damit ist das Konvept des statischen Typen, den ich in einen Variablenname packen kann dahin (Man könnte den Namen aus der vtable zurückgewinnen ... :)).

    Original erstellt von junix:

    • Wenn einer den Quelltext liest, muss er sich nicht immer fragen "was war das noch gleich für ein Typ?" und in den Deklarationen nachschauen.

    Das muss er sowieso, wenn der Code so kaputt ist, dass man weder an dem Namen noch am Verwendungszweck (3 Zeilen davor und 3 Zeilen danach) erkennen kann. Alternativ könnte er den Quelltext neu schreiben.

    Oben Genanntes gilt auch bei Fragen nach Überlauf oder ähnlichem, da man ja den bereich durch den Datentyp (z.B. int) gleich mitdokumentiert hat.

    Überläufe sind lästige Low-Level-Probleme, die man nicht lokal sondern irgendwo zusammengefasst kontrollieren möchte (Signale und Exceptions).

    Ändert ein Datentyp, ändert der Variablenname. das hat zur Folge, dass man die Namen anpassen muss. Kann ein nachteil sein, hat aber den Vorteil, dass man gleich überall - ohne etwas zu vergessen - überprüfen kann ob dann überhaupt noch gültig ist, was man da geschrieben hat.

    Dafür hätte ich ehrlich gesagt Suchen&Ersetzten angewendet. Auf das ganze Projekt, vermutlich.

    Prä-/Suffixe bieten eine gedankenstütze sowohl beim lesen als auch beim codieren.

    Sie lenken vom Wesentlichen ab.

    Ich hab hier lesen müssen dass es mit C++ egal sei, welchen typ man nehme vonwegen Templates und so.

    Nein. Du musstest nichts lesen.

    Und überhaupt prüfe der Compiler ob gültig sei was man schreibt.
    Das ist fertiger Unfug!

    Huch? Ein Compiler prüft nicht, was in ihn reingefüttert wird? Wie will er sonst Code erzeugen, wenn er den Quelltext nicht prüft?

    Würde man obiges Argument bei Ada oder Pascal oder anderen streng typerisierten Sprachen anführen müsste ich recht geben.

    Pascal ist nicht sehr streng getypt. Strenger als C, ja. Aber wenn sich verschiedene Integertypeninstanzen einander zuweisen lassen, so ist das nicht streng getypt. YMMV.

    Der Compiler stört sich schon gar nicht dran.

    Eine Warnung kann er dir sicher produzieren (Manchmal sind Warnungen sinnvoll).



  • So ganz läßt sich auch bei unter C++ der Nutzen einer Präfix-Notation nicht absprechen.

    Nehmen wir als schönes abschreckendes Beispiel einen VCL-Dialog mit dem C++-Builder, wo 8 Checkboxen, 3 Listboxen und 8 Editfelder im Dialog stehen.

    Wie nennen wir die Dinger nun?

    Ich finde es dort sehr hilfreich, wenn man die Memberobjekte mit entsprechenden Kürzeln wie lb, edt, chkbx usw am Anfang kennzeichnet. Gerade weil Dialogklassen im Regelfall nicht sonderlich designed sind, und weil sie auch nie so gut verinnerlicht sind. Da komme ich nun her und will bei einem fremden Dialog bei einer bestimmten Auswahl noch eine Checkbox sperren. Da ist es deutlich hilfreich, wenn man am Namen auch den Typ des Dialogelements erkennt. Und das lb, edt, chkbx ist wohl durchaus UN.

    Bei solchen Sachen hat man nämlich Abweichungen:
    😉 es gibt im Regelfall sehr viele Memberobjekte, mehr als in normalen Workerklassen
    😉 Dialogklassen sind als Hilfsklassen nicht so im Brennpunkt wie andere Dinge, so daß verschiedene Leute hingreifen und man sich nicht mehr so gut an Details erinnert

    Mir ist diese 100%-Verinnerlichung von Guru-Regeln nicht ganz geheuer. Zum einen, weil die Gurus die Namensregeln alle paar Jahre ändern (man denke nur an die Wanderung des _ durch die Namen von Memberobjekten). Heute ziehen alle mit, Heerscharen von Freiwilligen codieren die OS-Quelltexte um damit sie den Guru-Regeln entsprechen, und 2004 kommen die Jungs mit einer neuen Regel, wie üblich mit Kommentaren, warum dies nun auf einmal viel besser ist. Und wieder gibt es zahllose Verfechter dieser neuen Regel, und alle Leute schreiben ihren Code um.

    Ganz klar, die UN ist unter C++ tot, was man ja auch an aktuellen Code-Beispielen von MS sieht. Unter C hat es durchaus gute Gründe für solche Regeln. Aber irgendwo ziehen sich die Leute halt auch die Hose mit Beißzangen an:

    Ein UNler würde schreiben:

    CustomerData cdtaCurrentCustomerData;
    

    und ein moderner C++-OOPler:

    CustomerData currentCustomerData;
    

    Wow. Da liegen natürlich Welten dazwischen... 🙂 ich für meinen Teil erkenne aber auch bei den heute empfohlenen Namensgebungen für Objekte immer noch einen Algorithmus, dessen sich letztlich auch die UN bedient hat. Nur waren dort die Bezeichner kürzer.



  • Es geht doch bei der UN nur um Basistypen. Bei eigenen Objekten ist es natürlich out.



  • bei den dialogen stimme ich dir zu. da heissen die dinger bei mir auch gern
    sliderH und sliderW oder editH und editW. und sind vom typ Slider oder Edit(box). da empfindet man das aber nicht wirklich also "variablentyp mit einbauen", sondern die objekte heissen ja auch umgangssprachlich so: man muss den hoehen-slider nehmen, um die hoehe zu veraendern. den aktuellen wert sieht man in der hoehen-editbox.
    aber nicht (klassiche UN): ich addiere die beiden summand-zahlen um auf die summe-zahl zu kommen.

    [ Dieser Beitrag wurde am 05.03.2003 um 14:10 Uhr von PeterTheMaster editiert. ]



  • Original erstellt von PeterTheMaster:
    bei den dialogen stimme ich dir zu. da heissen die dinger bei mir auch gern
    sliderH und sliderW oder editH und editW.

    Ja, aber auch bei anderen Variablen ist es ganz hilfreich einen Präfix zu verwenden. Woher willst du z.B. nach 2 wochen noch wissen von welchem typ z.B. die Variable hausnummer in deinem Adressprogramm war? int, unsigned, short, char oder vielleicht sogar ein string? Man sollte IMHO zumindest kennzeichnen worum es sich handelt. Und sei es, dass man closeFlag schreibt anstatt bClose oder testStr anstatt strTest. Ich finde es bei Class-Members auch einfach schöner ein m_ davor zu setzen und das p vor dem Pointer halte ich für ziemlich sinnvoll...



  • Original erstellt von Daniel E.:
    Was ist denn nun passiert? Ich war 5 Tage im Urlaub und schon ist OOP out oder wie?

    Was hat die Namensgebung mit OOP zu tun?

    Original erstellt von Daniel E.:
    Das muss er sowieso, wenn der Code so kaputt ist, dass man weder an dem Namen noch am Verwendungszweck (3 Zeilen davor und 3 Zeilen danach) erkennen kann

    Den Verwendungszweck "Produkt aus zwei zahlen errechnen" verrät dir noch nichts über die Grössen der verwendeten Datentypen würd ich mal behaupten oder?

    Original erstellt von Daniel E.:
    Überläufe sind lästige Low-Level-Probleme, die man nicht lokal sondern irgendwo zusammengefasst kontrollieren möchte (Signale und Exceptions).

    Und doch sind es die ach so lästigen low-level Probleme die einem am Meisten Ärger bereiten können. Klar möchte man die Überläufe zusammengefasst kontrollieren können nur gibt dir C(++) da keine Mittel für mit und remember: wir sprechen hier von C(++) und nicht von Ada, Eiffel oder so...

    Original erstellt von Daniel E.:
    Dafür hätte ich ehrlich gesagt Suchen&Ersetzten angewendet. Auf das ganze Projekt, vermutlich.

    Hmmm wieso wunderst du dich dass OOP out sei, wenn dus gar nicht verwendest? Wenn du durch ein ganzes Projekt und nicht nur innerhalb einer Klasse einen Variablennamen ersetzen musst, dann hast du irgendwie nicht sehr objekt orientiert gearbeitet. D'accord?

    Original erstellt von Daniel E.:
    Sie lenken vom Wesentlichen ab.

    Ich denke die Typerisierung ist doch sehr wichtig. Zumal zum beispiel bei der Fehlersuche nichts als korrekt angenommen werden sollte...

    Original erstellt von Daniel E.:
    Nein. Du musstest nichts lesen.

    Wieso kommentierst du das was keines Kommentars bedarf? Wenn ich mich über die Meinungen hier informieren wollte musste ich das lesen.

    Original erstellt von Daniel E.:
    Huch? Ein Compiler prüft nicht, was in ihn reingefüttert wird? Wie will er sonst Code erzeugen, wenn er den Quelltext nicht prüft?

    Er prüft die Typenkonversionen nicht. Er kann zwar - bei bedarf - Warnungen ausprinten, wenn man aber ein SDK mitcompilen muss kann es gut sein, dass dann einige tausend warnungen alleine aus dem Framework etc. daherkommen. Dann neigt man nur Naturgemäss shcon dazu diese Warnungen gar nicht mehr zu beachten.

    Original erstellt von Daniel E.:
    Pascal ist nicht sehr streng getypt. Strenger als C, ja. Aber wenn sich verschiedene Integertypeninstanzen einander zuweisen lassen, so ist das nicht streng getypt

    Tschuldige, ich hab mich falsch ausgedrückt. Ada ist streng typerisiert. Pascal steht irgendwo dazwischen. Immerhin kannst du da nicht einfach einem BYTE einen Integerwert zuweisen. Das reicht doch schonmal?

    Original erstellt von Daniel E.:
    (Manchmal sind Warnungen sinnvoll).

    Alle Warnungen sind sinnvoll solange sie sich auf den eigenen Source beziehen in dem man auch dafür sorgen kann dass sie verschwinden.

    Original erstellt von Marc++us:
    Mir ist diese 100%-Verinnerlichung von Guru-Regeln nicht ganz geheuer.

    Kann ich nur zustimmen. Guru-Regeln sind - in meinen Augen - nur dazu gut, eine Richtung vorzugeben. Man sollte sich allerdings im Rahmen des vernünftigen und nicht sklavisch dran halten. Guru Regeln dienen meines Erachtens dazu, jemandem die "sichere Seite" zu zeigen, der sich nicht in der Lage fühlt, die Konsequenzen seines Handelns abzuschätzen.

    Original erstellt von Marc++us:
    Ein UNler würde schreiben:
    CustomerData cdtaCurrentCustomerData

    Ne, ich würde hier schreiben "CustomerData CurrentCustomer_CustData" oder so in der Art.

    -junix



  • Ich wüsste nicht wieso ich while( b_running ) statt while( running ) schreiben sollte. Running könnte auch ein int oder so sein. Das interessiert doch aber garnicht. Jedenfalls nicht beim Lesen. Und beim Schreiben sollte man schon wissen womit man da rumhantiert.

    Ein pObjekt könnte bei mir schonmal vorkommen. Aber nur wenn es von Bedeutung ist, dass es sich um einen Zeiger handelt. Und das ist es meistens nicht.

    Wenn man sich nicht gerade durch seitenlange Funktionen kämpfen muss, sieht man ohnehin auf einen Blick um welchen Typ es sich handelt.

    Ne, ich würde hier schreiben "CustomerData CurrentCustomer_CustData" oder so in der Art.

    Um Gottes Willen...

    [ Dieser Beitrag wurde am 05.03.2003 um 15:17 Uhr von DrGreenthumb editiert. ]



  • Original erstellt von DrGreenthumb:
    Ein pObjekt könnte bei mir schonmal vorkommen. Aber nur wenn es von Bedeutung ist, dass es sich um einen Zeiger handelt. Und das ist es meistens nicht.

    Um Gottes willen...

    Das heisst also du schreibst nicht konsequent "pObjekt" sondern einfach nach belieben? Dann würd ich auch ganz auf Prä-/Suffixe verzichten. Wozu selber jedesmal drüber nachdenken ob ein "p" hier wohl angebracht wäre oder nicht? Und - noch schlimmer - dem Lesenden zumuten dass er deine Entscheidung nachvollziehen kann?

    Ausserdem: Wieso interessiert dich das nicht was running denn genau ist? Wann liest du bitte den Quellcode? Dann wenn du
    a) einen Source-Audit durchführst
    b) einen Fehler suchst

    In beiden Fällen ist der Typ von running ebenso interessant wie beim codieren.

    -junix



  • Original erstellt von PeterTheMaster:
    bei den dialogen stimme ich dir zu. da heissen die dinger bei mir auch gern
    sliderH und sliderW oder editH und editW.

    Du übersiehst aber die grundsätzliche Gefahr bei dieser Diskussion: hier schreiben Leute "verwendet niemals Präfixe, weil die Gurus das auch nicht machen und veraltet ist". Wir verbreiten hier fundamental wirkende Pauschalaussagen, obwohl es begründete Ausnahmen (die auf praktischen Erwägungen und Überlegungen beruhen) davon gibt.

    Unterschätz mal nicht die Bedeutung die es hat, wenn hier eine solche Aussage als "das macht man immer so" steht...



  • gibt es sowieso jemand vor, wie man zu schreiben hat



  • Original erstellt von junix:
    Das heisst also du schreibst nicht konsequent "pObjekt" sondern einfach nach belieben?

    hmm.. Ja.. Nein, nicht nach belieben. Wobei ich ehrlich gesagt nicht immer ganz konsequent bin, aber davon mal abgesehen.

    Player* player = new Player();
    Würde ich nie pPlayer nennen, weil player ohnehin immer ein Zeiger ist und überall auch so behandelt wird.

    Player p1, p2;
    Player* pPlayer = &player1;
    Da sieht das anders aus. pPlayer ist halt nur ein Zeiger auf den eigentlichen Player.

    Aber dieses Zeiger-Gedöns ist ein Spezialfall.Generell kennzeichne ich die Variablen nicht. Ich hatte bisher weder bei eigenem, noch bei Fremdcode das Bedürfnis dazu.

    Und der Quelltext ist einfach hübscher 😉



  • Hallo,
    komisch. Ist Daniel E. hier der einzige der sowas wie "Definitionen so spät wie möglich", "Namen so lokal wie möglich" oder "kurze Funktionen" berücksichtigt?

    Wenn ich in einem C++ Programm erst 700 Zeilen und drei Dateien früher feststellen kann, was ein Objekt für einen Typ hat, dann ist das für mich kein Zeichen dafür, dass mir die UN helfen würde sondern vielmehr dafür, dass der Code kaputt ist.

    @Marc++us
    Seit wann geht es denn generell um Präfixe? Ich dachte es geht um die UN. Und die ist im Zusammenhang mit C++ tot. Mehr habe ich auch nie gesagt.



  • Original erstellt von HumeSikkins:
    Seit wann geht es denn generell um Präfixe? Ich dachte es geht um die UN. Und die ist im Zusammenhang mit C++ tot. Mehr habe ich auch nie gesagt.

    Naja, das Thema lautet "Sauberes Programmieren // Variablen mit Prefix"... Da liegt es doch nahe nicht nur über UN sondern über den generellen Sinn/Unsinn von Präfixen zu reden... 😃


Anmelden zum Antworten