Stilfrage: C als Präfix für Klassen



  • Hallo Kauz01,
    ich schreibe es gerne für dich noch einmal: Mir geht es *nicht* um eine Wertung.
    Ich sprach lediglich von Schwierigkeiten.

    Etwas überspitzt ausgedrückt sagst du: Wer Latein gelernt hat ist in den Denkstrukturen so festgefahren, dass er nie vernünftig programmieren wird.

    Nein. Das sage ich nicht. Weder an- noch überspitzt!
    Was ich sage ist, dass vorhandene und gut ausgeprägte Denkstrukturen schwer zu durchbrechen sind.



  • Original erstellt von volkard:
    Zur Logik gibts auch Stil. Der eine mag eher endliche Autonaten, der andere lieber Rekursion und der dritte leiber wiederholte Anläufe. Der eine mag nur flache lokale Variablen und dafür mehr übergeben, der andere mag gerne Attribute.
    Und auf jeden Fall ist's da ganz unaufgeräumt. Heut ist die Auswertung zu wpc53 gekommen: http://www.geocities.com/acmesofties/wpc.htm
    Von 6 Einsendern haben die Tester drei als falsch erkannt. Der Siegercode ist auch falsch, womit's vier wären. Und daß die anderen beiden korrekt sind, mag ich auch nicht so auf Anhieb glauben, leider kenn ich deren Code nicht.
    Hab mal Code von so nem 3D-Shooter gesehen. Glaub' doom war's. War schrecklich. So das zusammenfummeln der Schleifen und Bedingungen und dann wiedermal unmotiviert break oder goto...
    Leider finden sich da gar keine Regeln. Und Diskussionen über den Stil größerer Codebrocken finden nicht statt.[/QB]

    okay, da hast du auch wieder recht.. immerhin hab ich mich mit euch lange genug drum gesstritten, ob Rekursion sinnvoll ist 😉

    cYa
    DjR

    [ Dieser Beitrag wurde am 25.03.2003 um 13:54 Uhr von DocJunioR editiert. ]



  • OK ich verstehe es immernochnicht. Wenn einem die Firma vorschreibt, ein C vor Klassen zu setzen, OK, dann macht man es. Aber wenn man nicht dazu gezwungen ist, verstehe ich es wirklich nicht. Wenn man z.B. die Konvention Typen groß, Variablen/Funktionen klein einhält, hat man weniger arbeit, der Code ist (aus meiner sicht) leichter zu lesen und es ist nicht so dämlich auszusprechen.

    Peter ist eine "Zeh"-Person. Das ist doch einfach Mist. Peter ist eine Person ist da doch gleich viel angenehmer.

    Allerdings bin ich für ein m_ vor Membern (oder meinet wegen auch ein nachgestelltes _, wie einige es verwenden). Aber vielleicht sollte ich darüber nochmal nachdenken.

    Aber was ist die alternative:

    set_foo(T foo)
    {
       this->foo = foo;
    }
    

    Das ist für mich keine Alternative. Ich finde das seiht einfach nicht übersichtlich aus. (Das ist aber eine Frage des Geschmacks.)

    set_foo(T foo)
    {
       Klassenneame::foo = foo;
    }
    

    Das sieht schon besser aus, bedeutet aber oft viel Tipparbeit. Ein m_ ist praktischer. Ich werd's mal ausprobieren.



  • Der Thread sollte in die FAQ des Trollforums. Leute, so funktioniert das! Man stelle eine Frage wie diese und beobachte endloses aufeinander einhacken 😉



  • Original erstellt von Bashar:
    Der Thread sollte in die FAQ des Trollforums. Leute, so funktioniert das! Man stelle eine Frage wie diese und beobachte endloses aufeinander einhacken 😉

    Naja, ich bin's langsam gewohnt. Ich stelle eben die richtigen Fragen und hab die richtigen kommentare dazu, dass man auf mich losgeht *rofl*
    Naja, ich gebe zu, dass ich mich auch gelegentlich im Ton vergreife.

    Ich gelobe jedoch meinerseits Besserung und werde eine Technik namens "Nachfragen" anwenden, um herauszufinden, ob ich etwas vielleicht falsch aufgefasst hab.. dummsinnig reagieren kann ich ja dann immernoch 🤡

    cYa
    DjR



  • Original erstellt von DocJunioR:
    Ich stelle eben die richtigen Fragen und hab die richtigen kommentare dazu, dass man auf mich losgeht

    Das ist die Definition von Troll.

    Dasnurmalanmerkenwollend ...



  • Respekt, DocJr! Zuerst als "Unregistrierter" eine Frage stellen und dann drauflos trollen!
    *Troll Ehrenauszeichnung überreich*



  • *fg* Hallo Röspekt (wer ist hier unregistriert?).. Ich habe die Frage nicht gestellt - ich hab meine Konventionen ja schon.

    Trolle sind imho Leute, die dämliche Kommentare ablassen und ziemlich sinnlos Leute angreifen. Ich vertrete nur meine Meinung und das meistens auf sachlicher Ebene, Daniel. glaub nicht, dass man das trollen nennen kann...



  • Trolle sind in erster Linie Leute, die solche Threads hier (mit Absicht, will ja keinem was unterstellen;)) erstellen.



  • Original erstellt von Bashar:
    Trolle sind in erster Linie Leute, die solche Threads hier (mit Absicht, will ja keinem was unterstellen;)) erstellen.

    Ich hab mich nur angekratzt gefühlt und verteidigt. können wir den thread jetzt schließen?
    Der Mensch der gefragt hat, hat eh seine Antwort nicht bekommen 😞 - mal abgesehen davon hab ich schon 3 Versuche gestartet das ganze hier zu beenden.

    Edit: bezugnehmed auf den nachfolgenden Post korrigiere ich obige Aussage 😉

    [ Dieser Beitrag wurde am 26.03.2003 um 18:31 Uhr von DocJunioR editiert. ]



  • Die Frage wurde beantwortet. Sie lautete daoch, was spricht gegegen ein C vor Klassenbezeichnungen und was dafür. Es wurden einige "Argument" genannt. Also ist die Frage beantwortet.



  • Argh! 😃 😉

    OK ich verstehe es immernochnicht. Wenn einem die Firma vorschreibt, ein C vor Klassen zu setzen, OK, dann macht man es. Aber wenn man nicht dazu gezwungen ist, verstehe ich es wirklich nicht. Wenn man z.B. die Konvention Typen groß, Variablen/Funktionen klein einhält, hat man weniger arbeit, der Code ist (aus meiner sicht) leichter zu lesen und es ist nicht so dämlich auszusprechen.

    Sind das Deine Argumente?

    Wieso weniger Arbeit. Ein, zwei oder drei Buchstaben mehr Tippen ist keine Arbeit und kostet mich über den Tag aggregiert 3 Minuten (die ich mir aber imho hundertfach einspare, weil ich immer den Typ kenne. Das ist ein ganz persönliches Bedürfnis von mir. Wers nicht hat, ok. Aber ich hab nunmal das starke Verlangen immer auf den ersten Blick zu sehen, ob das Teil ein int ist, oder ein double. Obs ein Zeiger ist oder keiner und sogar 😮 , ob die Objekte in einer List oder einer Map gespeicher sind. Aber das ist wie gesagt MEIN BEDÜRFNIS. Wers nicht hat, dan will ich dazu nicht zwingen - allerdings versteh ich nicht, wie man dieses Bedürfnis nicht haben kann 😉 ).

    Leichter zu lesen. Das ist wie Du selber schreibst Deine Sicht. Sehr subjektiv.

    Das Aussprechen wäre wirklich dämlich. Aber sorry, ich hab noch nie jemanden von ner Klasse "Zeh-Person" reden hören. Ich würd sagen, "Nimm doch die Klasse Person, die ich mal geschrieben hab". Dass die Klasse CPerson heißt, is klar, weil alle meine Klassen mit C anfangen. Oder: "Du kriegst von mir nen Zeiger auf das Haus".

    Ich hab in allen Diskussionen noch nie ein echtes Argument gehört, was schlecht an den Präfixen wär. Das mit dem Lesen ist schlimmstenfalls Gewohnheit, das mit dem Aussprechen geht an der Realität vorbei und das mit dem Mehraufwand ist lächerlich. Also: Es spricht nix dagegen also weiß ich nicht, was dagegen spricht, wenns einer macht, wenn ers subjektiv besser findet. Wenns einer subjektiv schlechter findet, braucht ers nicht machen (außer die Firma schreibts vor). Aber beide Meinungen sind doch gleichwertig, weil gleich subjektiv.

    Ich mein, es gibt Stilfragen, für die gibst echte stichhaltige Argumente (z.B. dass ne Funktion keinen Zeiger zurückgeben sollte, für den sie selber speicher reserviert hat). Aber es gibt auch Stilfragen, die sind geschmackssache. Und über Geschmack, kann man nicht streiten.

    Und übrigens: ich wär ehrlich gesagt mal froh, wenn jemand ein Argument gegen die Präfixe bringen würde, das ich als solches akzeptieren kann. Nur damit ich mal verstehe, warum so viele was gegen sie haben.



  • Original erstellt von kartoffelsack:
    Und übrigens: ich wär ehrlich gesagt mal froh, wenn jemand ein Argument gegen die Präfixe bringen würde, das ich als solches akzeptieren kann. Nur damit ich mal verstehe, warum so viele was gegen sie haben.

    Du lässt ja kein Argument gelten



  • ich sag aber auch warum. Wenns keine anderen gibt ...



  • Eigentlich wollte ich mich ja raushalten, aber...

    Ich hab mal den Thread überflogen und Argumente für und gegen Präfixe gesucht (hab nichts dagegen, wenn diese Liste erweitert wird):

    Dagegen:
    * Ist unnötig und kostet Zeit
    * Ist überholt und veraltet

    Dafür:
    * Typen sind einfacher zu erkennen
    * Der zusätzliche Zeitaufwand ist gering

    Mit einer Wertung halte ich mich zurück



  • Hallo,
    ich finde Shade hat schon mehrfach ein wunderbares Argument genannt. Zumindest in der OOP sollte der Typ eines Objekts nicht im Vordergrund stehen. Im Vordergrund steht sein Verhalten. Wenn ich nun den Typ in den Namen kodiere, verschiebe ich damit das Wesentliche. Außerdem verletzte ich damit eine Form der Kapselung. Schließlich lege ich mich auf den *konkreten* Typ eines Objekts fest. Sollte sich dieser Mal ändern (unter Beibehaltung der Schnittstelle), muss ich auf einmal meine Präfixe ändern.

    Und mal ne ganz andere Sache.
    Wie verwendet man Präfixe im Zusammenhang mit generischem Code?

    PS:
    Nur um mich mal zu outen: Ich verwende auch sehr häufig das Präfix p für Pointer. Was an dieser komischen Programmiersprache C++ liegt, die mich dazu zwingt mal . und mal -> zu verwenden. Mittlerweile habe ich eine IDE die einen Punkt, falls nötig, automatisch in ein -> umwandelt. Meine ps reduzieren sich seit dem drastisch 🙂

    Aber mir geht es eigentlich auch hauptsächlich um ungarische Notationssachen. Also sowas wie ein C vor einer Klasse oder ein lpcwHaus oder lpcstrHaus.

    [ Dieser Beitrag wurde am 27.03.2003 um 12:01 Uhr von HumeSikkins editiert. ]



  • meine IDE sagt mir immer, welchen Typ eine variable hat :p

    aber naja.
    wie Hume schon sagte: bei OOP ist der Typ doch uninteressant.

    Beispiel:

    Int32 i32;
    Int64 i64;
    Int128 i128;

    da ist mir doch egal, ob Int32 jetzt ein typedef auf int ist und ob Int128 eine Klasse für große Zahlen ist.

    ich mach ein
    i128+=3;
    und weiss, dass 3 zu der zahl dazugezählt werden.
    ausserdem sagt mir der name, dass es eine zahl ist.
    wenn man mehr will, dann benütze ich meine IDE dafür 😉

    nungut, Hume hat es schon angesprochen:
    wie siehts bei generischer Programmierung aus?

    OK, std::vectorstd::string kann man
    VecOfStr
    oder so ähnlich nennen.

    ABer was ist bei
    smrt_ptr<ThreadPolicy, RefCountPoilcy, OwnerPolicy>
    wie sieht das aus?

    aber OK. auch da kann man prefixe machen (nur wer die sich dann merkt 😕)
    spThrdSveRingRCTkOwnName; (smart pointer with Thread Save, Ref count using Ring, takes owner policies named Name :D) (sorry, ich konnte nicht anders)

    naja, nun nehmen wir aber mal folgendes:
    du änderst 1 policy, oder den typ einer variablen?
    ok, das hatten wir schon: einfach ein replace über das file laufen lassen...



  • Das mit dem Typ is wenigstens mal ein Argument:

    Hier bin ich aber der Meinung, dass die zusätzliche Information nicht schadet. Sie hindert mich nicht, objektorientiert zu denken, v.a. weil man die Präfixe im Allgemeinen ja nur bei den eingebauten Typen verwendet. Die kommen im Code aber nur auf ganz niedriger Ebene vor. Und auf dieser Ebene is imho die Typinfo wichtig. Trotz allem "Do it as the ints": wenn ich in ner Klasse über ne set-Funktion ein Attribut setze und dieses ist außerhalb des Bereichs, in dem es sein soll, werd ich (wenn auch erst zur Laufzeit) nen aussagekräftigen Fehler bekommen ("Alter kann nicht 1000 sein!"). Wenn ich aber ne short-Variable auf 1000 setz, sagt mir das keiner. Und zur Laufzeit wird das an ganz anderen Stellen zu komischen verhalten führen. Also werd keinen Aufwand scheuen, diesen Fehler von vornherein zu vermeiden. Und ich denke, dass ein shAlter = 100000; eher ins Auge spring als ein Alter = 10000 (wenn man die Konvention kennt), v.a. wenn ich irgendwann auf die Idee komme, dass das Alter auch 10000 sein könnte, weil ich das Alter von Versteinerungen speicher will.

    UND (das hab ich schon mal ausführlich erläutert):
    Ich verwende Präfixe auch bei ausgewählten Klassen.

    z.B.: Container: Welcher Container verwendet wird ist wichtig, da sie sich anders verhalten.
    z.B.: std::string: Weil das doch eher ein "normaler" Typ ist. Wie in vielen anderen Programmiersprachen.
    z.B.: smart-pointer: Weil hier auch das Verhalten wichtig ist.

    Ich hab also z.B. bei einem Container mit Personen (dem aufmerksamen Leser wird nicht entgehen, dass ich "Personen" sage, obwohl ich von Instanzen der Klasse "CPerson" rede). Da gibts zwei wichtige Infos:
    1. Was ist in dem Container: Personen. Also: Bestandzeil des Instanzennamens wird "Personen" sein.
    2. In welchem Container sind die Personen? Hab ich Random-Access, kann ich schnell einfügen, ist das ganze sortiert?
    Wenn ich also ne Liste mit Personen hab, wird das ganze deswegen lstPersonen heißen.

    In Generischem Code, kann ich natürlich kein Präfix verwenden, weil ich die Info nicht hab. Keine Typ-Info kein Präfix.

    Mittlerweile habe ich eine IDE die einen Punkt, falls nötig, automatisch in ein -> umwandelt.

    klingt gut. Welche IDE ist das?

    Leider erwartest Du dann aber von dem, der Deinen Code später weiterentwickelt, dass er auch so ne IDE hat. Das ist genauso, wie wenn Du davon ausgehst, dass der auch nen 21-Zoll-Monitor hat und Dir deswegen keine Gedanken über ewig lange Funktionen machst. Was ist, wenn es . und -> gibt, wie bei smart-Pointern.



  • klingt gut. Welche IDE ist das?

    Visual Assist-Plugin für MSVC 6.

    Was ist, wenn es . und -> gibt, wie bei smart-Pointern.

    Irrelevant. Der Code der *weiß*, dass es sich um einen smart-Pointer handelt, hat dieses Wissen *by design*, braucht kein Präfix und kann beides benutzen.

    Der Code der *nicht wissen muss*, dass es sich um einen smart-Pointer handelt braucht kein Präfix, da er sowieso nur den -> (also die Zeigerschnittstelle) verwendet.

    Ein smart-Pointer ist ein Implementationsdetail. Viele Teile des Code sollen überhaupt nicht wissen müssen ob sie mit einem Smart-Pointer oder einem normalen Pointer arbeiten.

    Hier bin ich aber der Meinung, dass die zusätzliche Information nicht schadet

    Gegenbeispiel. Wir schreiben eine neue Software House 1.0.
    Die Software kann viele Häuser erstellen und man kann dann tolle Sachen damit machen. Schwimmen, laufen, radfahren. Was weiß ich.

    Da wir modern sind und die Software viele verschiedene Häuser dynamisch erzeugen können muss, wird dies über eine Factory realisiert.

    In der Version 1.0 liefert die Factory immer einen Pointer auf ein Haus:

    class House
    {
    public:
        House(...);
        virtual void schwimm();
        virtual void lauf() ;
        virtual void fahrRad() ;
        ...
    };
    
    // Irgendwo anders
    class House;
    class HouseCreator
    {
    public:
        House* makeHouse(const char* houseType);
        //...
    };
    // und überall im Anwendungscode:
    House* h1 = houseCreator.makeHouse("NormalesHaus");
    ...
    House* h2 = houseCreator.makeHouse("HausOhneDach");
    ...
    
    // Präfix-Version
    class CHouse
    {
    public:
        CHouse(...);
        virtual void schwimm();
        virtual void lauf() ;
        virtual void fahrRad() ;
        ...
    };
    
    // Irgendwo anders
    class CHouse;
    class CHouseCreator
    {
    public:
        CHouse* makeHouse(const char* houseType);
        //...
    };
    // und überall im Anwendungscode:
    CHouse* ph1 = houseCreator.makeHouse("NormalesHaus");
    ...
    CHouse* ph2 = houseCreator.makeHouse("HausOhneDach");
    ...
    

    Eines schönen Tages stellen wir fest, dass die Basisklasse (C)House besser ein reines Interface sein sollte (vielleicht weil wir auf eine neue Komponententechnik umsteigen).

    // kein Ctor mehr, alle Methoden abstrakt, keine Daten-Member
    class House
    {
    public:
        virtual void schwimm() = 0;
        virtual void lauf() = 0;
        virtual void fahrRad() = 0;
        ...
    };
    

    Die Änderung ist schnell gemacht. Die Factory und der Anwendungscode können unverändert bleiben.

    Nicht aber in der Präfixvariante:

    // kein Ctor mehr, alle Methoden abstrakt, keine Daten-Member
    class IHouse
    {
    public:
        virtual void schwimm() = 0;
        virtual void lauf() = 0;
        virtual void fahrRad() = 0;
        ...
    };
    

    Hier muss zusätzlich die Factory und der gesamte Anwendungscode geändert werden:

    // Irgendwo anders
    class IHouse;
    class CHouseCreator
    {
    public:
        IHouse* makeHouse(const char* houseType);
        //...
    };
    // und überall im Anwendungscode:
    IHouse* ph1 = houseCreator.makeHouse("NormalesHaus");
    ...
    IHouse* ph2 = houseCreator.makeHouse("HausOhneDach");
    ...
    

    Sicher, mit modernen Umgebungen ist sowas schnell erledigt.
    Aus logischer Sicht ist die Änderung aber völlig unsinnig. Es spielt für die Anwendung überhaupt keine Rolle ob es sich bei House um ein Interface, eine abstrakte oder eine konkrete Klasse handelt. Häuser-Objekt werden sowieso durch die Factory erzeugt. Danach werden sie nur noch verwendet. Und zwar immer gleich. Ob nun IHouse, CHouse oder AHouse (keine Ahnung ob es sowas wie A gibt).

    Ein weiteres Argument gegen ungarische Notation, dass ich immer wieder lese (formuliert von Charles Miller http://fishbowl.pastiche.org/))

    Thirdly, and this is my problem with Hungarian notation in general, it's hard to read. Our eyes don't read words letter by letter, we read by pattern-matching the shapes of words, we only fall back on letter-by-letter in the worst case of not knowing a word at all. IApplication takes longer to read than Application. The extra I at the start changes the shape of the word, and your brain takes longer to parse it.

    I prefer to have code that is easy to read in the general case, and tools that will tell me the supporting information if and when I need it. Hungarian notation is an artifact of a time when the tools weren't good enough to give us this information in any way but by throwing it all in our face at once. Now we have colour-coding, tool-tips and one-keypress navigation available to us, Hungarian notation is a horrendously clumsy anachronism. The information should be available, but not obscuring the code. Which is why I don't use Hungarian notation, but I do use a good, modern IDE.

    <edit>Junge, Junge. Diese Code-Tags </edit>
    <edit>Zitat kompletiert.</edit>

    [ Dieser Beitrag wurde am 27.03.2003 um 13:37 Uhr von HumeSikkins editiert. ]



  • In Deinem Beispiel hast Du recht. Ich kann aber natürlich nur für mich antworten: Da ein Interface und eine Klasse das gleiche Verhalten haben (und rein syntaktisch auch beide "class"en sind) käm ich nie auf die Idee für ne reine Interface-Klasse ein anderes Präfix als für ne konkrete Klasse zu nehmen.
    Ich nehme z.B. ein anderes Präfix für ne Struct, aber hier ist das Verhalten auch anders. Structs sind (bei mir) immer PODs und haben somit ein anderes Verhalten als Klassen.

    Du könnt Ihr jetzt ein Argument dagegen bringen: "bei mir". Bei nem anderen mag es anders sein. Aber wichtig imho ist v.a. dass es projektweit gleich ist. Und wenns die Projektleiter wichtig finden: firmenweit.
    Aber Programmierstile weichen sowieso voneinander ab.

    Das mit dem Lesen zieht nach wie vor nicht. Das ist schlimmstenfalls Gewöhnungssache. Je nachdem, was einen am Code interessiert, ist das Gehirn durchaus in der Lage, die Präfixe auszublenden. Man beachtet ja z.B. auch nur die Verkehrsschilder, die wichtig für einen sind. Das kann Dir jeder Wahrnehmungspsychologe sagen. Wenn ich den Code nur mal schnell durchlesen will um festzustellen, wie das ganze grob arbeitet, beachte ich die Präfixe nicht. Will ichs genau sehen (und bin evtl. auf Fehlersuche) helfen sie mir, weil sie ne Gedächtnisstütze sind. Hier geht es schneller, wenn das Gehirn das parst, als wenn es sich für jede Variable erinnern muss, welcher Typ sie war.

    PS: Ich fänd ne IDE toll, wo (zumindest die eingebauten Typen) irgendwie anders gekennzeichnet sind. Farbe, Symbol am Editorrand, Bubble-Help beim drüberfahren mit der Maus, keine Ahnung wie.
    Leider arbeite ich hier aber mit dem C++Builder. Und da funktioniert bei Projekten > 20 Modulen noch nicht mal das "springen zu Deklaration" oder die Codevervollständigung (zumindest nicht mit einer angemessenen Geschwindkeit < 10 sec).


Anmelden zum Antworten