Meine liebe Hassliste



  • Einrückung, Planks usw. interessieren mich kaum. Wenn ichs nicht lesen kann, lass ich einfach eine automatische Code-Formatierung drüberlaufen.

    Defaultargumente, mhh interessant. Mir ist noch nix nerviges damit untergekommen. Habt ihr ein Beispiel?

    Mich nerven besonders ewiglange Funktionen, vorallem wenn da viel ohne RAII gemacht wird und man immer aufpassen muss. Generell eigentlich alles, mit dem man unnötig viel Zeit verbringen muss, nur weil irgendwer zu doof oder gar faul war. Und wenn es dann bei nem Kunden crasht, der ursprüngliche Entwickler aber schon lange nicht mehr da ist, und ich es debuggen darf ...

    @TravisG: Weils manchmal Spaß macht, sich zu ägern. 😉



  • ...



  • TravisG schrieb:

    Bin ich der einzige, der keine Hassliste für fremden Code hat?

    Ja, könnte sein.

    Fremden Code zu debuggen ist so unglaublich schwieriger als eigenen zu debuggen...
    So unglaublich viel aufwändiger. Faktor 4, wenn der andere extrem gut ist, so gut wie Bashar, Shade oder so.
    Kann aber gerne mal auf 10 oder exorbitant gehen.

    TravisG schrieb:

    Warum soll man sich über sowas aufregen?

    Wir Programmierer regen uns doch nicht auf wegen sowas. Wir können hassen, ohne, daß der Blutdruck steigt. Sonst wären wir alle tot.

    Wenn ich wiedermal als Admin was mache, dann ist es schon fast regelmäßig, daß der Kunde sehr gut vorgebildet ist, wie man mit Rechnern umgeht. Ich mache genau das, was er auch tun würde, nur gebe ich nicht nach 20 Minuten auf, sondern kämpfe mich durch, selbst wenn es 2 Stunden dauert. Wiedermal von MS und Adobe Steine in den Weg gelegt kriegt, die Hardware von der Bezugsstelle taugt nix, der im Unternehmen zwangsweise eingesetze Virenscanner ist dummkonfiguriert...
    Na, und?
    Die ersten Programme hinzukriegen war viel unergiebiger. Die ersten Speicherlöcher in C zu stopfen, allein sie zu erkennen!
    Ich löse also sein Problem. Und er schaut mich mit großen Augen an. Gibt zu, daß er schon drei Fachleute vorher befragt hatte, die aufgegeben hatten.

    Einfach dran bleiben. Und insbesondere so lange fummeln und frickeln, bis ein Geistesblitz kommt. Der kommt nicht von alleine, sundern dadurch, daß man dran bleibt und sich reinvertieft.

    Am Ende habe ich nur gemacht, was der Kunde auch hätte machen können, nur ich rege mich eben nicht auf, sondern frickele mich durch. Und wenn's wieder mal eine besondere Gemeinheit gibt, die ich erkenne, dann lache ich, zeige auf den Bildschirm und lache die Gemeinlinge aus. Letztendlich sichern die Gemeinlinge, Laientreiberprogrammierer und Lügedokumentierer ja auch, daß Informatiker immer mal einen schnellen Euro machen können.



  • volkard schrieb:

    new statt vector weil evtl schneller

    Da vector alles initialisiert, kann unique_ptr<T[]> uU durchaus schneller sein. 🤡



  • Swordfish schrieb:

    hustbaer schrieb:

    * Plenken funktion ( parameter );

    Fällt

    if( !foo ) { bar( 43 ); }
    

    in das Schema?

    Das ist doch hübsch.

    Ich würde schreiben

    if(!foo){
       bar(43);
    }
    

    also antiplenk.

    Kaputt wird es bei

    if (!foo) {
       bar (43);
    }
    

    Ich kann mich nicht entscheiden, wohin mit den Spaces.

    if ( ! foo ) {
       bar ( 43 ) ;
    }
    

    ?
    Nee.

    if( !foo ) {
       bar( 43 );
    }
    

    Nee.

    if( !foo and !bar ) {
       bar( 43 + 5*7 - 3 + pow ( 10 , 3*2 ) );
    }
    

    Nee. Stattdessen stelle ich in der IDE die Schriftart groß, sehr groß, ungemein groß, das würdet Ihr nicht glauben. Für mich ist das der beste Weg.



  • cooky451 schrieb:

    volkard schrieb:

    new statt vector weil evtl schneller

    Da vector alles Initialisiert, kann unique_ptr<T[]> uU durchaus schneller sein. 🤡

    Kennst Du push_back?

    Ok, der Zeiger kann schneller sein. push_back verbrät eine Inkrementierung und eine Fallunterscheidung pro Einfügung, 2 Takte?
    Falls man mit den Daten dann was berechnet, ist es vollkommen Latte, was push_back kostete.

    Und ich bin ein Freund davon, sich selber Container zu schreiben, die halt an das Problem noch besser angemessen sind als die Standardcontainer. Bei vector<T> zum Beispiel habe ich eine Alternativ-Implemetierung Vector<T,size_t>, die intern nicht new benutzt, sondern ein std::array. Manchmal, ganz ganz selten, bläst das ganz gut. Vorstellbar als Container, der zu eriner Schach-Stellung die möglichen Züge aufnimmt. Aber fast immer ist vector echt vollkommen ok und kein zehntel Prozent Performance-Nachteil kann befürchtet werden.

    Wer zerstört im Exception-Fall die Objekte, die per placement-new in den unique_ptr<T[]> gestopft wurden?



  • Du denkst da an den falschen Anwendungsfall. Manchmal will man einfach nur 100 MB Speicher am Stück haben, der dann später beschrieben wird - std::vector fährt da dann erstmal mit einem memset drüber. 😉 Aber ja, die Anwendungsfälle halten sich schon in Grenzen, ist nur etwas, das mir eingefallen ist.



  • cooky451 schrieb:

    Du denkst da an den falschen Anwendungsfall. Manchmal will man einfach nur 100 MB Speicher am Stück haben, der dann später beschrieben wird - std::vector fährt da dann erstmal mit einem memset drüber. 😉 Aber ja, die Anwendungsfälle halten sich schon in Grenzen, ist nur etwas, das mir eingefallen ist.

    Ja, dafür dann den MemoryPool. Apache macht es vor. Wobei der Hauptvorteil davon ist, daß kein Destruktor befragt wird.

    Daß vector aber die 100MB vorher nullen wüprde, ist schlicht falscht.
    vector<char> v(100000000) tut es. Und dann reinkopieren mit v[i++]=c;
    Aber das fast immer bessere
    vector<char> v; nebst v.push_back(c);
    ist davon frei.



  • cooky451 schrieb:

    Du denkst da an den falschen Anwendungsfall. Manchmal will man einfach nur 100 MB Speicher am Stück haben, der dann später beschrieben wird

    Und ohne ihn zu nullen? Dann geht doch push_back perfekt. Wir konstruieren einfach hinein.
    Ähm, ob ich den i++ selber führe oder der vector. Ja, Registerdruck, falls i ind c.size() immer gleich sind. Falls ungleich, ist es schon recht egal.

    Oder DU willst ausnutzen, daß auf Deinem BS der allokierte Speicher schon genullt ist? Nee, so fies bist Du nicht, das weiß ich.



  • Na ja, angenommen du willst 100 MB binäre Daten einfach am Stück in den Speicher schaufeln (aus einer Datei z.B.) - da ließt du doch nicht immer ein byte auf einmal und pushst das dann in der vector? 😃



  • ...



  • Swordfish schrieb:

    volkard schrieb:

    [...]

    Aha. Also

    if(foo()){
        bar(42)
    }
    

    .

    Und noch vier- bis fünfmal [Strg]+[+] drücken bitte.



  • cooky451 schrieb:

    Na ja, angenommen du willst 100 MB binäre Daten einfach am Stück in den Speicher schaufeln (aus einer Datei z.B.) - da ließt du doch nicht immer ein byte auf einmal und pushst das dann in der vector? 😃

    Naja, vielleicht benutzue ich dann Filemapping und fresse gar keinen Speicher weg.
    Aber jo, ein "Container" für nicht konstruierten Speicher, der fehlt irgendwie.



  • if( x < y){
           //...
    } else {
           //...
    }
    

    liest sich beschissen.



    • eigenen vektor definieren, weil er "besser" ist als der Standard
    • wegen Formatierung eine Diskussion anfangen als gäbe es nicht wichtigeres


  • Meine unvollständige Hassliste, sortiert nach Kategorie.

    Ressourcenleck
    - Destruktoren, die mehrere Ressourcen manuell freigeben (weil starkes Anzeichen für Lecks beim Anfordern)

    • delete , delete[] , free , myPrefix_Free
      - Nichtverwendung von Initialisierungslisten
    • destroy() -Methode statt Destruktor
      - Verwendung von nicht-trivialen C-Bibliotheken ohne irgendwelche Wrapper
    • exit

    Undefiniertes Verhalten
    - reservierte Bezeichner (besonders gerne als _INCLUDE_GUARD_H_ )
    - Missachtung von strict aliasing oder alignment
    - falsche Verwendung von union

    • signed Overflow

    Unnötige Gefahr / Obfuscation

    • #define für Konstanten
      - globale/statische Variablen
      - Annahme, dass sizeof(int) == sizeof(long) == 4 etc.
      - C-Casts
      - magische Zahlen
    • int oder unsigned , wenn eigentlich ptrdiff_t oder size_t gemeint ist
      - riesige Klassen in riesigen Dateien
    • strcpy , strlen , atoi , fopen , memcpy usw.
    • s/f/printf
      - geschweifte Blockklammern bei Einzel-Statements weglassen
      - Klassenmember in einem #ifdef (endet immer in kaputtem Build oder undefiniertem Verhalten)
      - Statements in #ifdef
      - Kommaoperator statt Statements

    Voodoo
    - Werte im Destruktor in Nullzustand setzen ( v.clear() , p = nullptr etc.)
    - "safe delete"-Makros oder -Funktions-Templates

    • if (p) { delete p; }
    • inline bei Definition in cpp-Datei
      - lokale Arrays, wo vector oder string besser geeignet wären
    • typedef struct

    Unwissenheit

    • ntohl , ntohs und so
    • struct zur "Serialisierung"
      - Verwendung von std::list , wenn std::vector gemeint ist
    • throw new
      - C-Standard-Header einbinden
      - Spaces zum Einrücken
    • while (!feof(f)) und ähnliche Abenteuer

    In den meisten Projekten finden sich leider die meisten dieser Punkte.



  • Swordfish schrieb:

    hustbaer schrieb:

    * Plenken funktion ( parameter );

    Fällt

    if( !foo ) { bar( 43 ); }
    

    in das Schema?

    Ja.
    Das sind 3 Sachen auf einmal, wobei ich eins vergessen hatte hinzuschreiben: "ifs" wo die bedingte Anweisung (bzw. der Block) in der selben Zeile mit dem "if" steht.

    Also Schritt für Schritt...
    Zwei Zeilen draus machen

    if( !foo )
        bar( 43 );
    

    Plenks entfernen

    if(!foo)
        bar(43);
    

    Fehlendes Leerzeichen nach dem Keyword einfügen

    if (!foo)
        bar(43);
    

    Tadaa 🙂



  • TyRoXx schrieb:

    Ressourcenleck
    - Destruktoren, die mehrere Ressourcen manuell freigeben

    Der Destruktor ist dabei ja nicht das Problem, sondern der (meist nicht Exception-sichere) Konstruktor den man dazu braucht.

    Aber guter Punkt grundsätzlich. Ganz schlimm: Code der fleissig Exceptions verwendet, aber an 1000 Stellen nicht Exception-sicher ist.



  • TyRoXx schrieb:

    - Destruktoren, die mehrere Ressourcen manuell freigeben (weil starkes Anzeichen für Lecks beim Anfordern)

    Sehr schöner Punkt 👍 und immer wieder ein relativ gutes Zeichen für halb verstandenes RAII.

    TyRoXx schrieb:

    Missachtung von strict aliasing

    Da fehlt noch Alignment. Aber wenn jemand speziell für eine Plattform programmiert ist das schon okay denke ich. Strict aliasing scheint eh niemand so richtig zu verstehen.

    TyRoXx schrieb:

    • strcpy , strlen , atoi , fopen , memcpy usw.

    memcpy ist schon okay denke ich. Auch an fopen sehe ich grundsätzlich nichts Falsches, wenn es ordentlich gekapselt ist.

    TyRoXx schrieb:

    - geschweifte Blockklammern bei Einzel-Statements weglassen

    😞 Wie sieht's hiermit aus?

    for (unsigned i = its + 1; --i != 0; )
      if (foo(i) == its)
        return bar(++i), baz(its), i;
    

    TyRoXx schrieb:

    - lokale Arrays, wo vector oder string besser geeignet wären

    Oder std::array? Man sollte die Vorzüge des Stacks nicht so oft missen, finde ich.



  • cooky451 schrieb:

    TyRoXx schrieb:

    • strcpy , strlen , atoi , fopen , memcpy usw.

    memcpy ist schon okay denke ich.

    Mir sind die impliziten Konvertierungen zu void * zu gefährlich.
    Bei std::copy kann der Compiler viel leichter Fehler entdecken.

    cooky451 schrieb:

    Auch an fopen sehe ich grundsätzlich nichts Falsches, wenn es ordentlich gekapselt ist.

    Wie wäre es mit i/o/fstream ?

    cooky451 schrieb:

    TyRoXx schrieb:

    - geschweifte Blockklammern bei Einzel-Statements weglassen

    😞 Wie sieht's hiermit aus?

    for (unsigned i = its + 1; --i != 0; )
      if (foo(i) == its)
        return bar(++i), baz(its), i;
    

    Stimmt, den Kommaoperator habe ich vergessen.

    cooky451 schrieb:

    TyRoXx schrieb:

    - lokale Arrays, wo vector oder string besser geeignet wären

    Oder std::array? Man sollte dir Vorzüge des Stacks nicht so oft missen, finde ich.

    Wenn die Größe wirklich klein und fest ist, kann man std::array verwenden.
    Wenn die Größe variabel und nur selten zu groß für den Stack ist, kann man sich ein small_vector<T, N> -Template schreiben.
    Ansonsten möge man einen dynamischen Standard-Container nehmen.


Anmelden zum Antworten