Sauberes Programmieren // Varibeln mit Prefix



  • @Hume: hier gehts ja nicht nur um Variablen innerhalb eines Blocks sondern auch um Membervariablen, etc.?

    @kingruedi: scherzkeks. Das ist genau das was zum Beispiel Marc++us sagen wollte (glaub ich zumindest) und was ich auch zu sagen versuchte (in meinen letzten oder vorletzten post):
    Regeln sollten nicht sklavisch sondern mit Verstand eingehalten werden.

    Original erstellt von Daniel E.:
    [...Beschreibung des Basisklassendilemma...]

    Eigentlich kein Problem. Der Zeiger an sich zeigt ganz klar auf ein Objekt das den Typen der Basisklasse besitzt (ob nun als letztes Element der Hierarchie oder ned sei dahin gestellt). Damit das Objekt dann tatsächlich nicht mehr z.B. auf CObject sondern auf CButton (oder so) zeigt, ist ein Cast erforderlich. Man kann also sagen, dass der Ergebniszeiger des Casts nicht mehr den Typen CObject sondern CButton hat.

    Original erstellt von Daniel E.:
    Keine genormten. Praktisch kann ich das.

    Praktisch kann man alles... es ist nur eine Frage ob der Aufwand vertretbar ist oder nicht. Und das bischen mehr schreiben da sman da auf sich nimmt, das fällt sowieso kaum ins gewicht wenn man sich die "Lines of Code" pro Tag-Statistik ansieht.

    Original erstellt von Daniel E.:
    Vermutlich. Aber nehmen wir mal an (Achtung, unrealistisch), ich hätte an verschiedenen Stellen im Programm int verwendet und möchte zentral auf long umstellen.

    Wie du bereits gesagt hast... dieses beispiel ist an den Haaren herbeigezogen und findet keinen Platz in der Praxis.

    Original erstellt von Daniel E.:
    Wie soll er sonst herausfinden, ob sie gültig war?

    Benimm dich nicht schwierig (: Du weisst genau, dass ich damit meinte dass er nicht prüft ob ein long einem char zugewiesen wurde oder ned (: (ausser du stellst den Warnlevel hoch)

    Original erstellt von Daniel E.:
    [...pascal und Typensicherheit...]Für was?

    Um damit typensicherer zu sein als C(++) und so viele Fehler schon mal auszuschliessen?

    Original erstellt von Daniel E.:
    Finde ich nicht: 'if (a = b) 9;' ist absolut legal und mein Compiler warnt.

    Ein scheussliches Konstrukt. Ausserdem wollen vermutlich die wenigsten leute prüfen ob eine Zuweisung erfolgreich ausgeführt wurde. In den meisten Fällen ist das einfach nur ein typischer Fehler. (weshalb auch "possibly incorrect assignment" gewarnt wird.)

    -junix



  • Original erstellt von junix:
    Der Zeiger an sich zeigt ganz klar auf ein Objekt das den Typen der Basisklasse besitzt

    Das hier passende Buzzword ist Vererbung. Ich zB habe von meiner Mutter geerbt und trotzdem bin ich eine, von meiner Mutter unterscheidbare, Person.

    es ist nur eine Frage ob der Aufwand vertretbar ist oder nicht.

    Der Aufwand offfensichtlich nicht korrekte Programme auszuliefern ist nicht vertretbar.

    Wie du bereits gesagt hast... dieses beispiel ist an den Haaren herbeigezogen und findet keinen Platz in der Praxis.

    Nett, dass ich so etwas immer wieder zu portieren habe, weil eine Person mit Tunnelblick davon überzeugt war, man könnte sich darauf verlassen, dass ein int 32 Bit habe ...

    Du weisst genau, dass ich damit meinte dass er nicht prüft ob ein long einem char zugewiesen wurde

    Natürlich überprüft er das. Er überprüft nicht, ob der long-Wert zufällig nicht im char-Bereich darstellbar ist. Das darf der Programmierer gerne tun; er kann sogar viel mehr. Er kann zB _beweisen_, dass dieser Fall nicht eintritt (Compiler können das auch können).

    Um damit typensicherer zu sein als C(++) und so viele Fehler schon mal auszuschliessen?

    Also folgt aus typensicher automatisch, dass man viele Fehler ausschließt? Kaum. Fehler ausschließen tut der Programmierer indem er keine Fehler in seinen Quelltext schreibt. Das er nicht immer sagen kann, ob das ein Fehler ist oder nicht, ist eher minder interessant, weil sich Fehlerabwesenheit sowieso nicht beweisen lässt.

    Ausserdem wollen vermutlich die wenigsten leute prüfen ob eine Zuweisung erfolgreich ausgeführt wurde.

    Dieses Konstrukt prüft ob der Ausdruck 'a = b' einen Wert '!= false' zurückliefert. Für hinreichend normale Typen wird also schlicht getestet, ob 'b != 0'.

    Wenn der Compiler mit einer Art Datenbank für sinnlose Anwendungsfälle ankommt und mir verbietet, was ich zu tun habe, halte ich das für Schrott. Ich kenne das Problem, das ich lösen will vermutlich besser als der Compiler.



  • Original erstellt von MaSTaH:
    Bei Funktionen kenne ich keinen der UN verwendet (Warum auch, wichtige Funktionen sollte man sowieso kurz mal im Code kommentieren wenn Zeit ist)

    Bei Variablen ist UN nicht gut zu verwenden (Warum auch, wichtige Variablen sollte man sowieso kurz mal im Code kommentiere wenn Zeit ist)

    Wenn ich funktionen nicht kennzeichnen muss, warum dann variablen?
    was bringt es mir zu wissen dass ich zahl ein int ist wenn ich nicht weiss was Summe() zurück gibt?

    ich kann ja in der doku nachsehen. Aber hey: das kann ich bei Variablen auch...
    und Wenn eine Funktion Summe heisst, dann gibt sie eine Zahl zurück - ob das jetzt double ist oder int ist doch erstmal egal... der compiler warnt mich schon wenn ich nen double an nen int zuweise.



  • hui, was haben wir da auch eine hübsche Funktion, hört sich der Name nicht toll an: accumulate (um im Standard zu bleiben)
    Wie heißt nochmal der Header? algorithm, nicht?
    na denn, probieren wir mal aus:
    accumulate (a, b, c, d) wird mich der Compiler eh warenen, wenn da was falsch ist...
    hm so in einer Zeile sieh das aber doof aus, da nehm ich doch lieber das d heraus und tu es davor
    d = accumulate (a, b, c);

    Ne Bitte Leute, wozu sind den Dokus da? Zum wegschauen? A!!! hilfe eine Doku!!! erdrück mich nicht!!!! Wenn ein Programmierer das nicht aushält, braucht er gar nicht erst zu programmieren. Und ich denke, das kann man auch auf weitere Lebensbereiche ausdehnen[1]
    accumulate ist sogar ne Template Funktion, da

    sind die Typen der Variablen eh egal

    Haha.[2]
    Ich bin ganz klar gegen die UN, aber auch nur, wenn Programmierer[3] endlich lernen in Dokus nachzuschlagen, und nicht auf ihr Halbwissen[4] vertrauen und Buggy Code schreiben.
    Ich hab schon Seiten vorher mal gesagt, dass dieser Thread verschoben gehört. Und das sag ich jetzt nochmal, vielleicht gibt es ja jemanden, der seine Meinung langsam[5] ändert.

    PS. accumulate befindet sich im Standard-Header numeric, erwartet 2 Vorwärtsiteratoren [anf,end), und einen int als 3. Argument (Startwert), und addiert zu diesem int alle Werte in [anf,end) und gibt die Summe zurück. Das Prädikat (+=) ist austauschbar

    (1) Auf Deutsch: Es geht nicht nur Programmierern so.
    (2) Ausdruck des Mitleids
    (3) Achtung, Verallgemeinerung!
    (4) Das soll keine Anspielung gegen HumeSikkins sein, eher das Gegenteil
    (5) Nach 5 weiteren Seiten sinnloser Diskussion



  • 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.

    Und was ist, wenn da steht

    while(running)
    {
    --running;
    //...
    }

    Da isses dann schon interessant. Und mir jedesmal überlegen zu müssen, obs an der Stelle interessant is? Na, dann schreib ich lieber überall b_running. Und wenn da i_running steht und ich denk mir drei Wochen später, dass es da ein bool auch getan hätte, dann find ichs schon gut, wenn ich gezwungen bin jedes running einzeln zu ändern, weil ich mir dann den Code auf jeden fall nochmal angucke (sorry, ich mach nie sucher - ersetzen ohne mich an jeder Stelle einzeln fragen zu lassen.
    Die Lesbarkeit wird durch die Präfixe auch nicht gestört. Kommt immer drauf an, was einen gerade interessiert - ich kann beim lesen die Präfixe durchaus gedanklich ausblenden. Und niemand hat gesagt, dass die Variablen hinter den Präfixen keinen aussagekräfigen Namen haben sollten.

    Hab ganz weit vorne geschrieben, ich mach itrp für iterator auf Pointer. Da wurd ich dann gefragt, woher man weiß, dass es keine Pointer auf nen Iterator ist. Ganz einfach: ich würde dann pitr schreiben. Und wenn ich itrpPersonen tippe, hab ich 4 Buchstaben lang Zeit, dass mir einfällt, dass itrpPersonen->SetName() keinen Sinn macht.

    Das Argument, dass man nich für jede Klasse ein Präfix erfinden kann zieht nicht, weils hier noch keiner verlangt hat. Interessant sind sie v.a. bei eingebauten Typen, Zeigern etc. Ich mach aber für manche Klassen ne Ausnahme: veciNumbers ist ein std::vector<int> und stiNumbers ist ein set<int>. Jetzt werden manche sagen, das das totaler Quatsch sei, weil man dann die Container nicht mehr einfach austauschen kann etc. Aber für mich ist ein vector mit Nummern etwas vollig anderes als ein set, weil das eine sortiert, das andere nicht sortiert ist (und auch die meisten Member-Methoden sind anders).

    std::sort(Numbers);

    Geht nicht? hm. Bei
    std::sort(stiNumbers);
    seh ich aber sofort, warum.

    Anderes Beispiel:

    Hausnummer

    Frage? Was für ein Typ ist das? Ein int? ha, es gibt auch Hausnummern wie 3a oder so. Es ist ein fundamentaler Unterschied ob die Hausnummer ein string oder ein int ist - und beides mag je nach Anwendung sinnvoll sein und mit einem kurzen Blick in den Code nicht einfach festzustellen.

    Ratschläge wie "wenn die Funktion kurz ist, siehts Dus doch sowieso sofort" sind völlig an der Realität vorbei imho. Ja, schön, ich mach kurze Funktionen. Aber meine Member-Variablen sind nunmal an ner ganz anderen Stelle definiert.

    Machs wie in Java, zählt nicht. In Java gibts keine Zeiger es ist sowieso alles ne Klasse. Mein CKlasse mag vielen sinnlos erscheinen. Aber ich schreib nunmal lieber CKartoffelsack Kartoffelsack statt Kartoffelsack kartoffelsack. Wie viele Gurus haben schon gesagt, dass es blöd wäre, wenn ein Bezeichner groß geschrieben was anderes ist, als der gleiche klein geschrieben.

    Übrigens find ich das Argument, man sollte die Typinfo hinten, nicht vorne machen wegen der Sortierung bei einer Autovervollständigung eigentlich ganz gut.

    Aber im Grunde ist das alles Geschmacksache und kein Mensch verlangt, sich exakt an die UN von MS zu halten (die hat sich bestimmt auch mal geändert). Aber eigene - d.h. wenigstens Projektweite, noch toller aber firmenweite - durchgängige Notation sollte man haben. Und sich dabei an die UN anzulehnen mag manchen als kein Vorteil erscheinen, aber ein schlagkräftiges Argument, was dagegen spricht, hab ich noch nicht gelesen. Außer der Tipparbeit, aber das is irgendwie lächerlich. Zumindest so lang man sich bei

    for_each(vector<map<std::string*, sort_predicate> >::iterator itrRun(Namen.begin()),
             vector<map<std::string*, sort_predicate> >::iterator itrRun(Namen.end()), 
    machIrgendwas);
    

    nen Wolf tippt (ohne UN und Präfixe).



  • Original erstellt von <pfui teufel>:
    Mastah, woher hast du den Code? 😡

    Von hier 😃



  • Original erstellt von kartoffelsack:
    **Und was ist, wenn da steht

    while(running)
    {
    --running;
    //...
    }

    Da isses dann schon interessant.**

    Keineswegs. Wenn irgend ein Verrückter hier 'running' als 'bool' definiert hat, so hat er einiges fundamental falsch verstanden, in erster Linie mal die Schleifen (also etwas potentiell mehrfach [!=potentiell 1x] auszuführen).

    Und wenn da i_running steht und ich denk mir drei Wochen später, dass es da ein bool auch getan hätte, dann find ichs schon gut, wenn ich gezwungen bin jedes running einzeln zu ändern, weil ich mir dann den Code auf jeden fall nochmal angucke

    Die Abwesenheit eines 'i_' hindert dich daran, Quelltext zu lesen? Interessant.

    Kommt immer drauf an, was einen gerade interessiert - ich kann beim lesen die Präfixe durchaus gedanklich ausblenden.

    Man schreibt also etwas hin, um es gedanklich auszublenden? Tricky.

    Und niemand hat gesagt, dass die Variablen hinter den Präfixen keinen aussagekräfigen Namen haben sollten.

    Stimmt. Muss man das so machen?

    std::sort(Numbers);

    Geht nicht? hm. Bei
    std::sort(stiNumbers);
    seh ich aber sofort, warum.

    Der Compiler sieht das auch. Und der glaubt dem Namen nicht.

    Hausnummer

    Frage? Was für ein Typ ist das? Ein int? ha, es gibt auch Hausnummern wie 3a oder so.

    Das trifft sich gut, weil 0x3a ist ein int :).

    Es ist ein fundamentaler Unterschied ob die Hausnummer ein string oder ein int ist - und beides mag je nach Anwendung sinnvoll sein und mit einem kurzen Blick in den Code nicht einfach festzustellen.

    Es ist kein großer Unterschied. Es ist praktisch sogar absolut uninteressant, denn ich möchte ja bekanntermaßen auf Hausnummern operieren, nicht auf ints, nicht auf Strings.

    Abstrakt. Man beschreibt im Computer meistens etwas abstrakt. So auch hier. Ich kann Hausnummern vergleichen, zusammenzählen, ausgeben, ohne dass ich wissen muss, ob Hausnummern intern Integer, Strings oder blaue Schildchen sind.

    Aber meine Member-Variablen sind nunmal an ner ganz anderen Stelle definiert.

    Ja, man muss lesen. Das ist immer so. Bei jedem Funktionsaufruf muss man die Argumente raussuchen (wie oben schon ausfürlich erklärt wurde).

    In Java gibts keine Zeiger

    Zeiger sind ein Konzept, die zB zum Laufen über Felder geeignet sind. Ob man sie Iterator oder Zeiger nennt ist absolut irrelevant. Darum ist auch dein Beispiel mit der itrp-Notation nicht treffend.

    Übrigens find ich das Argument, man sollte die Typinfo hinten, nicht vorne machen wegen der Sortierung bei einer Autovervollständigung eigentlich ganz gut.

    Dann hätte man es doch gleich weglassen können.

    Und sich dabei an die UN anzulehnen mag manchen als kein Vorteil erscheinen, aber ein schlagkräftiges Argument, was dagegen spricht, hab ich noch nicht gelesen.

    ?
    Es wurde gesagt, dass
    a) es dem Gedanken der Objektorientierung zuwieder läuft
    b) hiermit Konzepte (Name und Typ) vermengt werden, was doch ein erster Schritt zur Abstraktion wäre
    c) keine Zusatzinformationen vermittelt werden
    d) Kommunikation über den Quelltext unmöglich gemacht wird
    e) es Mehraufwand für Leser und Programmier ist
    f) zT falsche 'Informationen' geliefert werden
    g) es zum Schlampen anregt
    h) es Compiler gibt

    Dagegen wurde gesagt, dass
    a) man ohne Notation keinen Quelltext lesen könne
    b) kein Zusatzaufwand ist (Begründung fehlt)
    c) der Typ extrem wichtig ist
    e) man keine Dokumentation lesen sollte

    Der interessierte Leser möge sich die Argumentationen auf der Zunge zergehen lassen.



  • Original erstellt von Shade Of Mine:
    **Bei Variablen ist UN nicht gut zu verwenden (Warum auch, wichtige Variablen sollte man sowieso kurz mal im Code kommentiere wenn Zeit ist)

    Wenn ich funktionen nicht kennzeichnen muss, warum dann variablen?
    was bringt es mir zu wissen dass ich zahl ein int ist wenn ich nicht weiss was Summe() zurück gibt?

    ich kann ja in der doku nachsehen. Aber hey: das kann ich bei Variablen auch...
    und Wenn eine Funktion Summe heisst, dann gibt sie eine Zahl zurück - ob das jetzt double ist oder int ist doch erstmal egal... der compiler warnt mich schon wenn ich nen double an nen int zuweise.**

    Der einfache Grund dafür, warum ich es bei Variablen mache und bei Funktionen nicht: Bei Variablen finde ich es übersichtlicher (da kann man jetzt eigener Meinung sein oder nicht). Bei Funktionen sieht es einfach nur Schei$$e aus und versaut eher die Übersicht, da man diese auch dokumentieren kann. Aber: Wer dokumentiert den bitte jede Variable??? Also ich weiß durch die Präfixe und den Namen immer was gemeint ist. Ich finde es einfach nur schade, dass hier einige wenige Leute meinen ihr Style sei der einzig wahre und es gibt nix besseres. Wenn jemand 50 gotos in 60 Zeilen code hat dann lohnt sich solch eine lange Diskussion, aber bitte: Wir diskutieren hier seit 6 Seiten und 3 Tagen über die Benennung von variablen... 😉



  • Original erstellt von kartoffelsack:
    Na, dann schreib ich lieber überall b_running. Und wenn da i_running steht und ich denk mir drei Wochen später, dass es da ein bool auch getan hätte, dann find ichs schon gut, wenn ich gezwungen bin jedes running einzeln zu ändern, weil ich mir dann den Code auf jeden fall nochmal angucke (sorry, ich mach nie sucher - ersetzen ohne mich an jeder Stelle einzeln fragen zu lassen.

    schon mal probiert so 6000-10000 zeilen durchzugehen?
    wer zahlt dir diese arbeitszeit?

    also mein chef würd mich blöd anschauen wenn ich ihm sage: ich hab ne halbe stunde lange variablen umbenannt.

    und wenn das ganze häufiger vorkommt na dann gute nacht.



  • Original erstellt von MaSTaH:
    Der einfache Grund dafür, warum ich es bei Variablen mache und bei Funktionen nicht: Bei Variablen finde ich es übersichtlicher (da kann man jetzt eigener Meinung sein oder nicht). Bei Funktionen sieht es einfach nur Schei$$e aus und versaut eher die Übersicht, da man diese auch dokumentieren kann. Aber: Wer dokumentiert den bitte jede Variable???

    jede variable die sich nicht selbs dokumentiert wird kurz beschrieben.
    genauso bei funktionen.

    verstehst du das dilemma?
    variablen werden anders behandelt als funktionen. das macht doch keinen sinn.

    warum ist es OK für ne funktion in der doku nachzuschlagen, aber für ne variable ist n bisschen scrollen zuviel?



  • Es ist praktisch sogar absolut uninteressant, denn ich möchte ja bekanntermaßen auf Hausnummern operieren

    ja, ok, Du hast also ne Klasse Hausnummer. NUR: in dieser Hausnummer hast Du eine Membervariable und das ist ein int, ein string oder k.a. was. Und es geht hier um den Fall, dass Du mit PODs arbeitest. Und auf irgendeiner Ebene hast Du keine Objekte mehr sondern Variablen von eingebauten Typen. Abgesehen davon würde zumindest ich meine Klassenstruktur nicht so feinteilig machen und eine Klasse Adresse bauen. In der gäbs dann ein Member "Hausnummer" als POD oder String. Addieren brauch ich nicht bei ner Adressverwaltung.

    Keineswegs. Wenn irgend ein Verrückter hier 'running' als 'bool' definiert hat, so hat er einiges fundamental falsch verstanden, in erster Linie mal die Schleifen (also etwas potentiell mehrfach [!=potentiell 1x] auszuführen).

    Aber das ist genau der Punkt. Die Praxis zeigt, dass jeder mal so ein verrückter ist. Vielleicht hat er gedacht, ah, ich hab doch da ne Varible, wie hieß die nochmal? Running oder, tippts ein, geht davon aus, dass es ein int is und schon hat er den Salat. Würd er Prefixes verwenden, hätt er iRunning geschrieben und der Compiler hätts ihm um die Ohren gehauen.
    Und wenn er den Müll trotzdem baut, is die Chance recht gut, dass er beim späteren Überfliegen stutzig wird, wenn er --bRunning sieht.

    Die Abwesenheit eines 'i_' hindert dich daran, Quelltext zu lesen? Interessant.

    Nein, hindern tut sie mich nicht, aber ansonsten zwingt mich der Compiler dazu. Und das ist ein Unterschied. Ich denk ich bin nicht der einzige, der hin und wieder ne kleine schnelle Änderung machen will, die sich dann als doch nicht so klein herausstellt

    Zeiger sind ein Konzept, die zB zum Laufen über Felder geeignet sind. Ob man sie Iterator oder Zeiger nennt ist absolut irrelevant.

    Zeiger sind viel mehr als ein Konzept zum Laufen über Felder. Du schreibst 'z.B.' aber bei den anderen Punkten kannst Du ihn nicht mit nem Iterator vergleichen.
    Das Kopierverhalten einer Instanz, eines Zeigers, und verschiedener Smart-Pointer ist vollkommen verschieden. Und mein Beispiel bezieht sich auf eine "Irgendwas" auf "irgendwas" auf POD-Konstruktion. Wobei Du irgendwas mit Zeiger, Smartpointer oder Iterator ersetzen darfst. Klar krieg ich nen Compiler-Fehler, wenn ich falsch dereferenziere aber - und deswegen hab ich das Beispiel mit dem Iterator gebracht - diese Fehlermeldung ist schlichtweg scheiße! Sie ist, je nachdem, was für eine Template-Spezialisierung mein Iterator ist, locker mal ein paar Zeilen lang mit den haut mir hunder verschachtelte '<'s um die Ohren. Sowas erschreckt mich. Da krieg ich Angst. Das will ich garnicht sehn 😞

    > a) es dem Gedanken der Objektorientierung zuwieder läuft

    Wurde vielleicht gesagt. Aber nicht begründet. Zumindest nicht so, dass ich es mit meinem persönlichen Verständnis von Objektorientierung verstehe.

    b) hiermit Konzepte (Name und Typ) vermengt werden, was doch ein erster Schritt zur Abstraktion wäre

    Was ich nicht sehe, da bei POD-Typen diese Abstraktion nicht machbar ist und bei den paar Objekten, bei denen ich ein Präfix verwende der Typ wichtig ist (eine map ist etwas konzeptuell anderes als ein Vector)

    c) keine Zusatzinformationen vermittelt werden

    Doch, der Typ.

    d) Kommunikation über den Quelltext unmöglich gemacht wird

    Hä? Wieso? Ich hab geschrieben, dass man seinen Variablen trotzdem noch vernünftige Namen geben soll. Wenn ich ein iRunning hab, und mit nem Kollegen spreche, dann sag ich trotzdem: "Das Proggi kackt ab, wenn Running kleiner als 10 wird"

    e) es Mehraufwand für Leser und Programmier ist

    Zu vernachlässigen (s. punkt h). Sorry, ich tippe recht schnell.

    f) zT falsche 'Informationen' geliefert werden

    Wann, wieso?

    g) es zum Schlampen anregt

    ????????????????????????????

    h) es Compiler gibt

    Es ist definitv ein größerer Mehraufwand, mir nen Fehler vom Compiler melden zu lassen, als den Fehler aufgrund der Notation gleich garnicht zu machen.

    > a) man ohne Notation keinen Quelltext lesen könne

    Der Meinung bin ich z.B. nicht. Nur tu ich persönlich mich schwerer, da ich zuviel in den deklarationen nachlesen muss, was mich stört.

    b) kein Zusatzaufwand ist (Begründung fehlt)

    Kein nennenswerter.
    Wie gesagt: ich tippe verdammt schnell

    c) der Typ extrem wichtig ist

    Ich hab ein paar Beispiele gebracht, wo er imho wichtig ist (ich wiederhol mich auch gern: verschiedene Smart-Pointer-Implementationen).

    e) man keine Dokumentation lesen sollte

    Hab ich nirgens gelesen. Aber sorry, ich kenne nicht viele Projekte, wo die Doku immer so exakt auf dem neuesten Stand - und noch dazu fehlerfrei - ist, dass das klappt. Außer natürlich vielleicht fertige Projekte. Ich hab in der Doku meiner STL schon ein paar Fehler gefunden.

    PS.: Ich liebe übrigens endlose Grundsatzdiskussionen 😉



  • schon mal probiert so 6000-10000 zeilen durchzugehen?
    wer zahlt dir diese arbeitszeit?

    So breit verstreut sind meine PODs normalerweise nicht. Man ändert ja auch selten ne Schnittstelle.
    Aber selbst wenn: Wie oft wird denn die Variable benutzt in den 10000 Zeilen. Mit Sucher-Ersetzen und einzelnen Abfragen is das ne Sache von maximal Minuten. Und mein Chef überprüft meinen Fortschritt nicht halbstündlich.

    jede variable die sich nicht selbs dokumentiert wird kurz beschrieben.
    genauso bei funktionen.
    verstehst du das dilemma?
    variablen werden anders behandelt als funktionen. das macht doch keinen sinn.

    Klar. Aber die halbe Stunde umbenennen spar ich mir leicht wieder rein, wenn ich bei ner Variable anhand ihres Vorkommens 5 Zeilen weiter oben im gleichen Fenster sehe, welchen Typ denn das Ding hat, anstatt wenn ich in den Header zur Klassendeklaration gehe nachgucke (zwischen den vielen Beschreibeungen 😉 ), zurückgehe, das Telefon klingelt und ich danach nochmal nachgucken muss.

    verstehst du das dilemma?
    variablen werden anders behandelt als funktionen. das macht doch keinen sinn.
    warum ist es OK für ne funktion in der doku nachzuschlagen, aber für ne variable ist n bisschen scrollen zuviel?

    Das Dilemma versteh ich, akzeptiere ich aber. Aus mehreren Gründen: - Funktions-Deklarationen (also Schnittstellen) ändere ich seltener, und benutz ich im gesamten Projekt häufiger. Das is eher was, was in mein Langzeitgedächtnis kommt.
    - Ebenfalls ästhetische Gründe (ja, die sind wirklich subjektiv)
    - Funktionen sind i.A. besser Dokumentiert als Variablen (v.a. wenn es sich um öffentliche Schnittstellen handelt).



  • Original erstellt von kartoffelsack:
    Und auf irgendeiner Ebene hast Du keine Objekte mehr sondern Variablen von eingebauten Typen.

    Das scheint der springende Punkt zu sein. Ich denke nicht, dass die künstlichen Unterschiede zwischen eingebauten und selbstgebautren Typen so groß ist, dass man unterscheiden muss. Nehmen wir doch mal ne Klasse BigInteger.

    Vielleicht hat er gedacht, ah, ich hab doch da ne Varible, wie hieß die nochmal? Running oder

    Oder running? Oder run? Oder Run? Und schlägst nach.

    Und wenn er den Müll trotzdem baut, is die Chance recht gut, dass er beim späteren Überfliegen stutzig wird, wenn er --bRunning sieht.

    Kommt halt auch den bool an. Es gibt noch genug Leute, die irgendwo ein '#define BOOL int' haben :(. Wie geht man bei so etwas eigentlich um? Jedes Typedef bekommt sein eigenes Präfix? Oder sind typedefs keine PODs mehr?

    ich bin nicht der einzige, der hin und wieder ne kleine schnelle Änderung machen will, die sich dann als doch nicht so klein herausstellt

    Eben. Darum mehrkt man immer recht schnell, das es sinnvoll ist, den Quelltext durchzulesen ...

    Das Kopierverhalten einer Instanz, eines Zeigers, und verschiedener Smart-Pointer ist vollkommen verschieden.

    Natürlich. Die Kopiersemantik eines Zeigers ist aber doch definiert, die eines Smartzeigers musst Du selbst definieren.

    Sie ist, je nachdem, was für eine Template-Spezialisierung mein Iterator ist, locker mal ein paar Zeilen lang mit den haut mir hunder verschachtelte '<'s um die Ohren.

    Woher soll der Compiler wissen, dass Du die kurze Version bevorzugst?

    [Es ist nicht mal so schwer sich aus seinen typedefs maschinell ein sed-Programm (oder so) zu schnitzten, dass die Ausgabe nachbearbeitet.]

    > a) es dem Gedanken der Objektorientierung zuwieder läuft

    Wurde vielleicht gesagt. Aber nicht begründet. Zumindest nicht so, dass ich es mit meinem persönlichen Verständnis von Objektorientierung verstehe.

    Das ist schade. Also nochmal:

    Polymorphie: Ich deklariere einen Zeiger auf eine Basisklasse und lasse ihn auf verschiedene abgeleitete Klassen zeigen? Welches Präfix? Was ist, wenn ich auf ein Array zeige? Dann wenden wir eben keine Präfixe an! Eben :).

    Was ich nicht sehe, da bei POD-Typen diese Abstraktion nicht machbar ist

    Auch PODs abstrahieren. ZB dieser wunderschöne POD aus netdb.h.

    struct  hostent {
                 char    *h_name;        /* official name of host */
                 char    **h_aliases;    /* alias list */
                 int     h_addrtype;     /* host address type */
                 int     h_length;       /* length of address */
                 char    **h_addr_list;  /* list of addresses from name server */
         };
    

    Sogar eingebaute Typen abstrahieren. Schlimmstenfalls die viel bemühten Elektronen aus der Siliziumschicht.

    und bei den paar Objekten, bei denen ich ein Präfix verwende der Typ wichtig ist (eine map ist etwas konzeptuell anderes als ein Vector)

    Eine map ist auch konzeptionell etwas anderes als ein CORBA-Interface. Und darum soll ich sie mit Präfixen versehen?

    c) keine Zusatzinformationen vermittelt werden

    Doch, der Typ

    ... ist keine Zusatzinformation, sondern eine Information, die ich nachschlagen kann.

    Wenn ich ein iRunning hab, und mit nem Kollegen spreche, dann sag ich trotzdem: "Das Proggi kackt ab, wenn Running kleiner als 10 wird"

    Und der Kollege antwortet 'i, o, u, ö, ä, p, r oder sder-Running'? :).

    e) es Mehraufwand für Leser und Programmier ist

    Zu vernachlässigen (s. punkt h). Sorry, ich tippe recht schnell.

    Ich auch. Aber ich finde es gut, wenn im Quelltext das drinnsteht, was mir unbekannt ist, und woüber ich denken soll. Das ist genau so unnütz wie wenn der Autor mir seine Sokengröße oder sein Geburtstag im Quelltext vermittelt. Das interessiert mich nur in begründeten Ausnahmefällen.

    f) zT falsche 'Informationen' geliefert werden

    Wann, wieso?

    Wenn jemand (ein Verrücker :)) mal nur den Typ und den Variablen nicht ändert.

    g) es zum Schlampen anregt

    ????????????????????????????

    Wie war das mit den multiplen Satzzeichen ... 🙂

    Jemand, der keine kurzen Funktionen schreiben kann hat noch ganz andere Lücken, oder: Wieso sollte ich kurze Funktionen schreiben, wenn ich doch alle Informationen aus einer Zeile gewinnen kann?

    Es ist definitv ein größerer Mehraufwand, mir nen Fehler vom Compiler melden zu lassen, als den Fehler aufgrund der Notation gleich garnicht zu machen.

    Sicher. Es ist toll keine Fehler zu machen.

    Der Meinung bin ich z.B. nicht. Nur tu ich persönlich mich schwerer, da ich zuviel in den deklarationen nachlesen muss, was mich stört.

    Wenn Du meinst, dass es für dich eine Arbeitsverminderung ist, tue das. Aber für mich bedeutet es Mehraufwand.

    Ich hab ein paar Beispiele gebracht, wo er imho wichtig ist (ich wiederhol mich auch gern: verschiedene Smart-Pointer-Implementationen).

    Vielleicht könnte man sogar sagen, dass es zu wichtig ist, um in einer Notation aufzutauchen ("Namen sind Schall und Rauch" -- volkard).

    ich kenne nicht viele Projekte, wo die Doku immer so exakt auf dem neuesten Stand - und noch dazu fehlerfrei - ist, dass das klappt.

    Hauptsache mit der Variablennotation klappt's? 🙂

    Ich liebe übrigens endlose Grundsatzdiskussionen 😉

    Ob Du es glaubst oder nicht: Ich auch :).



  • @kartoffelsack
    f)

    Wann, wieso?

    class base { /*...*/ }; class derive : public base { /*...*/ };
    //...
    base *pbVar; //pb == pointer auf base
    derive x;
    pbVar=&x; //ui
    

    g)

    Es ist definitv ein größerer Mehraufwand, mir nen Fehler vom Compiler melden zu lassen, als den Fehler aufgrund der Notation gleich garnicht zu machen.

    Wobei du auch den Aufwand der Notation beachten solltest.

    NUR: in dieser Hausnummer hast Du eine Membervariable und das ist ein int, ein string oder k.a. was.

    ja, ka. was, dass ist genau der Punkt, wenn ich mit einer Hausnummer arbeite, dann ist es mir egal, wie die Klasse intern aufgebaut ist, dann interessiert mich nur die Schnitstelle und da benutzt man ja wohl selbst als UN Freak (merkwürdiger Weise, wie Shade und ich bereits angedeutet haben) keine UNotation und erreicht also keinen Vorteil und falls ich mich dann doch mit dem Innenleben der Klasse befassen muss, dann kann ich mir auch nochmal die deklaration ansehen bzw. sehe eh durch den Quellcode was das für ein Typ ist (machmal arbeite ich auch mit 2 Editor Fenstern, einmal schau ich mir die deklaration und dann die Implementierung an, dadurch hab ich sicher weniger Zeitverlust, als durch das merken und benutzen eine Notation, die auf geheimnisvollen Abkürzungen basiert).

    Würd er Prefixes verwenden, hätt er iRunning geschrieben und der Compiler hätts ihm um die Ohren gehauen.

    Wie gesagt, der Compiler weiss uach ohne Prefix, welchen Typ die Variable hat

    Nein, hindern tut sie mich nicht, aber ansonsten zwingt mich der Compiler dazu.

    Also dient UN dir dazu, dass du Quellcode liest, in dem du dir mehr Arbeit machst

    e)/h)

    Zu vernachlässigen

    du sagst selber, dass du gezwungen bist den gewsammten Quellcode dadurch zu lesen, bei marginalen Änderungen und deswegen ist der Aufwand wohl doch größer. Nebenbei bemerkt hat es wohl nichts damit zu tun, wie schnell du etwas tippen und wie schnell du etwas lesen kannst

    Klar. Aber die halbe Stunde umbenennen spar ich mir leicht wieder rein, wenn ich bei ner Variable anhand ihres Vorkommens 5 Zeilen weiter oben im gleichen Fenster sehe, welchen Typ denn das Ding hat, anstatt wenn ich in den Header zur Klassendeklaration gehe nachgucke (zwischen den vielen Beschreibeungen 😉 ), zurückgehe, das Telefon klingelt und ich danach nochmal nachgucken muss.

    Also ich kann wie gesagt auch 2 Editor Fenster nehmen, in einem ist die Deklaration im anderen der Code (der Emacs bietet zB. ein Feature zu aufteilen des Bildschirms, bei anderen IDEs/Editoren wird es sowas wohl auch geben)

    Das Dilemma versteh ich, akzeptiere ich aber. Aus mehreren Gründen: - Funktions-Deklarationen (also Schnittstellen) ändere ich seltener, und benutz ich im gesamten Projekt häufiger. Das is eher was, was in mein Langzeitgedächtnis kommt.

    Also ich komm oft mit der Argument Reihenfolge durcheinander, wobei mir da je nachdem eh keine UN hilft, wenn Argumente den gleichen Typ haben 🙂 und am Anfang des Projektes passiert es mir oft, dass ich viel umbaue (manchmal auch noch deutlich später). Also wenn du UN benutzt, damit du mehr Code liest, versteh ich nicht, wieso das für Funktionen nicht benutzt werden sollte (gerade wenn Funktionen heufiger verwendet werden, liest du doch mehr Code) und wenn du UN benutzt um leichter mit den Typen umzugehen frag ich mich, warum du bei Funktionen, die du ja wie du selber sagst heufiger benutzt dir die Arbeit nicht leichter machen willst. Das du dir vielleicht die Argumente einer Funktion gut merken kann, glaub ich dir, aber es gibt auch Funktionen die man seltener benutzt oä. ich glaub nicht, dass du 100 Funktionen auswendig kannst, ich muss regelmäßig in die Doku nochmal gucken

    @Mastha

    Also ich weiß durch die Präfixe und den Namen immer was gemeint ist.

    und was trägt der Präfix dazu bei? Also ich versuche Variablen immer so zu benennen, dass klar ist, was diese Variablen sollen.

    Ich finde es einfach nur schade, dass hier einige wenige Leute meinen ihr Style sei der einzig wahre und es gibt nix besseres.

    Nein, es geht hier nicht darum, dass mein Stiel der beste ist, sondern das UN Sinnlos ist, komm jetzt bitte nicht auf die Tour, dann brauchen wir ja gar nicht diskutieren 🙄



  • Oder running? Oder run? Oder Run? Und schlägst nach.

    Ne ich bin mir fast sicher. Ich schlage nicht nach. Und da mir der Compiler nen Fehler meldet, wenn ich mich getäuscht hab, bin ich auf der sicheren Seite.

    Kommt halt auch den bool an. Es gibt noch genug Leute, die irgendwo ein '#define BOOL int' haben . Wie geht man bei so etwas eigentlich um? Jedes Typedef bekommt sein eigenes Präfix? Oder sind typedefs keine PODs mehr?

    defines erkenn ich, weil sie GROSS geschrieben sind. Außerdem muss ich mich jetzt outen: ich mag typedefs nicht. Warum? Weil ich nicht weiß, welcher Typ dahinter steht. Ich arbeite da gerade an nem Projekt. Da muss ich mich durch 3 typedefs durchkämpfen bis ich weiß, dass die ID ein __int64 ist. Schrecklich. ID steht im Namen. Das reicht mir. Ich brauch kein typedef für ID. Ich seh das übrigens ähnlich mit size_type aus der stl (jetzt fallt Ihr über mich her): Wenn ich die Größe von nem Container speicher will, dann heißt die Variable (jetzt mal ohne Prefix): SizeOfAutos. Da interessiert es mich nicht, das der Typ size_type ist. Es interessiert mich aber hin und wieder schon, was das für ein "echter" Typ is. Z.B. wenn mich der Compiler warnt, dass ich signed und unsigned-Integers vergleiche.

    Eben. Darum mehrkt man immer recht schnell, das es sinnvoll ist, den Quelltext durchzulesen ...

    Ja aber entweder sagt mir der Compiler "hey, lies den Code durch" oder das Proggie stürzt irgenwo komisch ab.

    Die Kopiersemantik eines Zeigers ist aber doch definiert, die eines Smartzeigers musst Du selbst definieren.

    Ja und deswegen möchte ich wissen, ob das Teil ein std::auto_ptr oder ein boost::smart_pointer is. Und zwar auf den ersten Blick, da wo er verwendet wird. Damit ich gleich auf garkeine dummen Gedanken komme.

    Woher soll der Compiler wissen, dass Du die kurze Version bevorzugst?
    [Es ist nicht mal so schwer sich aus seinen typedefs maschinell ein sed-Programm (oder so) zu schnitzten, dass die Ausgabe nachbearbeitet.]

    hm ich denk es geht den meisten so. Weil mit den langen kann man eigentlich nie was anfangen. Wie geht das mit dem sed-Programm?

    Also nochmal:
    Polymorphie: Ich deklariere einen Zeiger auf eine Basisklasse und lasse ihn auf verschiedene abgeleitete Klassen zeigen? Welches Präfix? Was ist, wenn ich auf ein Array zeige? Dann wenden wir eben keine Präfixe an! Eben .

    Also nochmal: ich - und soweit ich hier gelesen habe auch alle anderen Präfix-Anhänger, verwende keine Präfixe für Klassen (bei mir von ein Paar ausnahmen abgesehen). Und wenn ich ne Klasse Fahrzeug hab und ein pFahrzeug auf ein Auto zeigen lassen will, heißt dieser Zeiger selbstverständlich pFahrzeug.

    Auch PODs abstrahieren. ZB dieser wunderschöne POD aus netdb.h.

    Ich meine mit PODs eingebaute Typen. Sorry für meine falsche Verwendung. Structs sind für mich Klassen (wie für den Compiler auch).

    Doch, der Typ

    ... ist keine Zusatzinformation, sondern eine Information, die ich nachschlagen kann.

    hm, ich will IMMER wissen, mit welchem Typ ich arbeite (und bei Templates will ich wissen, dass ich mit einem Beliebigen arbeite). Vielleicht würd ich mich dran gewöhnen, wenn ich die Info nicht immer hätte, aber in meinen Projekten hab ich die Info immer parat und das find ich gut so.

    Und der Kollege antwortet 'i, o, u, ö, ä, p, r oder sder-Running'?

    Vielleicht sagt er: das Running is doch ein bool, Du Idiot! Das hat er sich aber sicher eher gemerkt, wenn ers dauern gelesen hat im Code.

    Wenn jemand (ein Verrücker ) mal nur den Typ und den Variablen nicht ändert.

    Komisch, aber dieser Fehler ist mir wirklich noch nie passiert. Weil ich weiß ich muss es ändern sonst wird alles scheiße.

    "Namen sind Schall und Rauch"

    Gut, dann mach ich jetzt aus meinem strHausnummer ein z.

    Hauptsache mit der Variablennotation klappt's?

    Klappt bei mir ganz gut. Aber meine Doxygen doku is auch immer auf dem aktuellsten Stand. Nur nicht immer erzeugt oder neue Module werden beim Erzeugen nicht erfasst. Und je dichter was am Code steht, desto eher isses aussagekräfitg.

    b Du es glaubst oder nicht: Ich auch

    Na das kann ja heiter werden 😃 😉



  • pbVar=&x; //ui

    derived IST EIN base. Das is völlig ok. (oder überseh ich da grad ne Falle 😕 ). Nur die Namensgebung Var und x is halt scheiße.

    dass ist genau der Punkt, wenn ich mit einer Hausnummer arbeite,

    Ich hab gesagt, dass ich nich mit ner Klasse Hausnummer arbeite. Die operatoren, die mir string, unsigned oder int zur verfügung stellen (<<, = und ==) reichen mir vollkommen. Fällt mir nicht ein bei ner Adressverwaltung ne Klasse Hausnummer zu schreiben. Kritisiert mich dafür, aber nicht für das Präfix des Attributs der Klasse "Adresse"

    Wobei du auch den Aufwand der Notation beachten solltest.

    Welchen Aufwand denn? Dass der Tippaufwand nicht zählt, sind wir uns ja wohl einig. Und dass das ändern länger dauert, weil man sich den Code durchgucken MUSS seh ich als Vorteil (man überlegt sich außerdem dann vielleicht vorher schon genauer, welcher Typ sinnvoll ist).

    Also dient UN dir dazu, dass du Quellcode liest, in dem du dir mehr Arbeit machst

    Strenge Typisierung zwingt mich auch zu etwas, was mir mehr Arbeit macht. In der Hoffnung, dass es mir danach umso mehr Arbeit erspart.

    Also ich kann wie gesagt auch 2 Editor Fenster nehmen, in einem ist die Deklaration im anderen der Code (der Emacs bietet zB. ein Feature zu aufteilen des Bildschirms, bei anderen IDEs/Editoren wird es sowas wohl auch geben)

    Ich hab zwei Monitore, x Fenster offen und die IDE ordnet mir - leider - nicht automatisch .h und .cpp nebeneinander an. Außerdem will ich ja evtl nicht nur den eigenen Header sonder auch noch drei Header von Klassen, die ich grad verwende offen haben.

    Also wenn du UN benutzt, damit du mehr Code liest, versteh ich nicht, wieso das für Funktionen nicht benutzt werden sollte (gerade wenn Funktionen heufiger verwendet werden, liest du doch mehr Code) und wen...

    Hab auch schon oft drüber nachgedacht, ob ich die Typinfos auch in die Funktionen aufnehmen soll (und wenn ich ganz ehrlich bin, mach ichs auch meist ein p rein (oh, oh), wenn ich nen Pointer kriege. Also GetpFahrzeug("Mercedes") ). Warum ich mich immer dagegen entscheide? Kann ich nich so wirklich durchgängig erklären - zumindest nicht mehr als ich schon hab. Is ne Unstimmigkeit? Na und. Besser den Vorteil nur bei nem - streng abgegrenzten - Teil als garnicht.

    sondern das UN Sinnlos ist

    Vielleicht, warum es manche/viele für sinnlos halten.



  • wenn man jetzt nur UN bei Builtin Typen hat, dann rentiert sich das ganze irgendwie nicht, oder?

    Builtin Typen hab ich nur ganz unten. Der meiste Code hat mit denen relativ wenig zu tun.

    ausserdem sollen sich Klassen wie normale Typen verhalten, so hat mans mir zumindestens beigebracht. warum sollte ich nun trennen?

    mein Compiler gibt mir übrigens ne fehlermeldung aus, wenn ich --running schreibe obwohl running ein bool ist...

    was bringts mir also? wenn ich nen fehler mache sagts mir der compiler.

    warum magst du denn typedefs nicht? die sind eine sehr nützliche einrichtung.

    Ja und deswegen möchte ich wissen, ob das Teil ein std::auto_ptr oder ein boost::smart_pointer is. Und zwar auf den ersten Blick, da wo er verwendet wird. Damit ich gleich auf garkeine dummen Gedanken komme.

    also doch prefixe bei objekten??
    na dann gute nacht...



  • Original erstellt von kartoffelsack:
    ich mag typedefs nicht. Warum? Weil ich nicht weiß, welcher Typ dahinter steht.

    Das ist doch der Sinn der Sache. Du weißt, dass es sich um ähnliche Typen handelt. Näherer Informationen uninteressant. Findest Du zB auch stdint.h in C böse, weil ich mir da einen passenden 16-Bit-Integer raussuchen kann?

    Da interessiert es mich nicht, das der Typ size_type ist.

    Eben. Der Typ ist nicht interessant :).

    Es interessiert mich aber hin und wieder schon, was das für ein "echter" Typ is

    ... und wenn es zur Abwechslung mal kein 'echter Typ' ist (sondern eine Compilererweiterung).

    Ja und deswegen möchte ich wissen, ob das Teil ein std::auto_ptr oder ein boost::smart_pointer is

    Womit ich ja wissen müsste, wie diese Dinger intern aufgebaut sind. Das alles auf ein (vielleicht 3-zeichen-langen) Präfix zu reduzieren ist doch etwas waghalsig.

    Wie geht das mit dem sed- Programm?

    Einfach Spezielles suchen und ersetzten: 'basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> >' durch 'string' zB. Sich die typedefs maschinell erzeugen zu lassen ist doch recht kompliziert, wenn man mit Funktionszeigern arbeiten will.

    [Soweit ich seh' lässt sich so etwas schön in den Emacs integrieren.]

    ich will IMMER wissen, mit welchem Typ ich arbeite

    Ich nicht. Mich interesieren (wie schon öfters gesagt) die abstrakten Schnittstellen ('ich kann Addieren'). Ob dabei nun intern 2 Assemblerbefehle generiert werden, die dann intern in 0.007 Mikrosekunden verwenden ist mir als Hochsprachenprogrammierer egal.

    [Synchronisation von Nemen und Code] Komisch, aber dieser Fehler ist mir wirklich noch nie passiert.

    Was an seiner Existenz nichts ändert.

    > "Namen sind Schall und Rauch"
    Gut, dann mach ich jetzt aus meinem strHausnummer ein z.

    Ändert an der Programmsemantik nichts.

    derived IST EIN base.

    'typeid (base) == typeid (derived)'?

    Gleichheit ist insgesamt etwas komisch, nicht nur, was Computer anbetrifft ('das Gleiche' vs 'das Selbe').

    Strenge Typisierung zwingt mich auch zu etwas, was mir mehr Arbeit macht.

    ZB? (Mehr Tippaufwand gilt nicht :))



  • Original erstellt von Daniel E.:
    ZB? (Mehr Tippaufwand gilt nicht :))

    Basis klassen getue und new einsatzt (smart pointer) könnte man sich sparen

    aber auf der anderen seite spart typenstrengeheit arbeit(debug) und laufzeit(IMHO)



  • Eine Basisklasse hat mit Typenprüfung ähnlich viel zu tun, wie Smart-Pointer: nichts. Wenigstens sind mir keine Smart-Pointer in Ada vorgekommen und 'Basis klassen getue' meine ich auch schon in Python gesehen zu haben.


Anmelden zum Antworten