Codeformatierung - Max Zeilenlänge?



  • @logging_error: Ich würd nie Die Fehlermeldung im einfach so unter meinen Code mischen. Schlimmstenfalls habe ich sie wie von DEvent vorgeschlagen als Konstanten irgendwo sammeln. Besser noch in eine Klartext-Datei auslagern von wo aus sie in das Programm generiert oder zur Laufzeit geladen werden kann.

    if (fehlerVariableX != 0 || fehlerVariableY != 0)
        logging_error(errorCode, "ERROR_TEXT_30556", variableA, variableB, variableC);
    

    @hustbaers Funktionen: 4-5 Argumente sind too much. 3 gehen noch. 2 sind besser, 1 ist ideal. Im gegebenen Fall seh ich beidesmal systemName und systemKeyName. Klingen ähnlich, werden zusammen benutzt, gehören sicherlich zusammen. -> struct systemNames. Beidesmal zusammen mit einem weiteren Namen. Das werden sicher nicht die einzigen Stellen sein (oder bleiben) wo die alle zusammen benutzt werden -> nächste Struct. Macht 3 und 2 Argumente und deutlich kürzere Zeilen.
    Mal davon abgesehn dass die Benutzung von wstring zum einen und wchar_t C-Style Strings zum anderen in der selben Source stinkt :P. Da war also offenbar jemand zu faul fürs Refactoring, und dann isses auch kein Wunder wenn die Zeilenlängen ausm Ruder laufen.
    JM2C

    @SAP: auch wenns generiert ist, offenbar muss sich den Code hin und wieder ein Entwickler anschauen. => nicht wartbar, Generator fürn Arsch. Kein Wunder dass die so teuer sind, bei den Aufwänden die sie für ihren Code fahren müssen 😛



  • @DEvent:
    Sehe ich ganz anders. Ich finde meine Variante 10x übersichtlicher. Das was richts raussteht, ist Code, den man kaum jemals lesen muss. Zum Verständnis was abgeht, wenn jemand den Code nicht kennt, reicht der Anfang der Zeile, der Teil der auf jedem Schirm Platz hat. Wieso also 13 Zeilen für etwas verschwenden was nur 3 Zeilen braucht? Die 10 Zeilen andere Dinge die ich dadurch mehr auf den Bildschirm bringe, verschaffen wesentlich mehr übersicht, als die uninteressanten Informationen die dadurch rechts rausstehen.

    Ich habe "deine" Variante auch an vielen Stellen, aber eben selektiv dort, wo es Sinn macht.

    Wieso ihr die Strings nicht als String-Konstanten habt, ist so wieso ein Rätsel.

    Weil es unübersichtlich ist, und für dieses Projekt Overkill. Bei Format-Strings führt das bloss dazu, dass man Fehler bei der Übergabe der "Replacement-Objects" macht.

    @pumuckl:
    4-5 Argumente sind zu viel... pfuh... weil?
    Meine Erfahrung aus der Praxis: was du beschreibst klingt in der Theorie nett, aber führt zu extrem unflexiblem Code. Haste schnell structs die drei Dinge zusammenfassen, wovon du dann an einer stelle nur zwei brauchst. Was machste dann? Nochmal auseinanderreissen in zwei structs? Oder in die 3. Variable nen Dummy-Wert reinschreiben? Oder erst wieder die zwei Werte an der Stelle dann ohne Struct ... ? Oder?
    Was du schreibst ist natürlich nicht Unsinn, nur fange ich wesentlich später damit an. Sicher nicht wegen 3-4 Werten die ich an 2-3 Stellen zusammen rumreiche.

    Und nochwas: schreibst du dir für alle API Funktionen (WinAPI oder was auch immer) eigene Wrapper, damit du auf < 3 Parameter kommst? Ich hoffe nicht...
    JM2C



  • hustbaer schrieb:

    Und nochwas: schreibst du dir für alle API Funktionen (WinAPI oder was auch immer) eigene Wrapper, damit du auf < 3 Parameter kommst? Ich hoffe nicht...

    Nicht alle APIs sind so grottig wie die WinAPI 😉



  • Shade Of Mine schrieb:

    hustbaer schrieb:

    Und nochwas: schreibst du dir für alle API Funktionen (WinAPI oder was auch immer) eigene Wrapper, damit du auf < 3 Parameter kommst? Ich hoffe nicht...

    Nicht alle APIs sind so grottig wie die WinAPI 😉

    Aber die meisten 😉



  • DEvent schrieb:

    witte schrieb:

    @DEvent:
    Du hast noch nie was mit SAP zu tun gehabt oder?

    http://s5b.directupload.net/images/100301/xx8vgdnn.jpg

    LOL. Der Developer sollte sofort verdonnert werden solche Funktionen bis ans Lebensende zu nutzten. Grade in C# wo man doch alle Möglichkeiten hat.

    Wie ich das sehe, sind fast alle Parameter als Referenzen. Wieso kann man die nicht in einen Struct oder Class zusammen fassen. Ich denke nicht, dass ein Programmierer wirklich alle überprüfen muss.

    Das ganze stammt sehr wahrscheinlich ursprünglich aus ABAP, da wird ein Funktionsaufruf so formatiert und sieht dann garnicht mehr so schlimm aus.

    call function 'APPL_LOG_WRITE_DB'
        exporting
          object                = gc_bal_object
    *     subobject             = ' '
    *     log_handle            = ' '
    *     update_task           = ' '
        tables
          object_with_lognumber = lt_log_logs
        exceptions
          object_not_found      = 1
          subobject_not_found   = 2
          internal_error        = 3
          others                = 4.
    


  • @alle: Was haltet ihr von einer Limitierung von 60 Zeichen? Lese gerade ein Buch, wo jede Zeile maximal 60 Zeichen enthält (Leerzeichen nicht mitgezählt). Unglaublich aber wahr. Die Seite ist 16 cm breit, davon sind 6 cm frei von Text 😮
    Aber, muss zugeben, liest sich gut... da kann man nichts sagen...



  • Interessante Diskussion; das ist ein Thema, mit dem jeder anders umgeht. In meinem Quellcode habe ich es aufgegeben, auf die Zeilenlänge zu achten. Es ist einfach nicht möglich, 80 Zeichen pro Zeile zu forcieren, wenn man bereits mit jedem namespace oder sonstigen Blöcken 4 Zeichen "verliert". Und ich habe auch in mittleren Projekten gerne mal 4- oder sogar 5-stufige Namensräume (Manche Leute empfinden dies als übertrieben, aber ich mag es aufgeräumt). Früher habe ich dennoch versucht, wenigstens die mehrzeiligen Kommentare konsequent auf 80 Zeichen zu formatieren, was ich aber inzwischen auch aufgegeben habe. Meine jetzigen Regeln:

    • Konsequente Formatierungen sind wichtiger als Zeichenbegrenzungen.
    • Der Tabulator darf nicht benutzt werden oder muss automatisch mit 4 Spaces ersetzt werden.
    • Zeilenumbrüche sind, wenn angebracht, jeweils nach dem Komma anzubringen, wobei dann auf die öffnende Klammer eingerückt wird. Als Beispiel seien folgende Snippets gegeben:
    inline bgr(const value_type &,
                       const value_type &,
                       const value_type &);
    
    static std::map<const std::type_info *,
                                    boost::shared_ptr<pre_gc_rtt_descriptor> > descriptors;
                    // ...
                    pre_gc_rtt_descriptor(const std::type_info &,
                                          nothing (*)(nothing *const));
    
    aimpl.insert(std::pair<std::wstring,
                                   handle<node> >(value->name(), 
                                                  value));
    

    Alternativ dazu rücke ich in seltenen Fällen (etwa bei Zuweisungen an Variablen mit langen Namen) auf der nächsten Zeile 4 Spaces gegenüber dem Anfang ein:

    resource *const res = 
                        secured_set.find(ref)->second;
    
    • Mehrzeilige Kommentare sollten die Zeilenumbrüche immer an ungefähr der gleichen Stelle haben. Das hilft einfach beim Lesen.
    • ...

    Das ist alles Teil meines Coding-Styles und den ziehe ich bei meinem Code sehr konsequent durch (will heissen, ich schreibe keinen Code bevor nicht der alte aufgeräumt ist; bin ich jetzt krank? 🤡) und komme so bei mittleren Projekten an den meisten Stellen nicht über 80 Zeichen pro Zeile hinaus. Aber auf der anderen Seite gibts dann durchaus Files, wo dank Namensräumen der Code erst ab Zeichen 100 beginnt. Aber wenigstens ist dieser dann konsequent auf 100 eingerückt.

    abc.w schrieb:

    @alle: Was haltet ihr von einer Limitierung von 60 Zeichen? Lese gerade ein Buch, wo jede Zeile maximal 60 Zeichen enthält (Leerzeichen nicht mitgezählt). Unglaublich aber wahr. Die Seite ist 16 cm breit, davon sind 6 cm frei von Text 😮
    Aber, muss zugeben, liest sich gut... da kann man nichts sagen...

    Das geht ja noch recht gut. Ich habe früher oft direkt auf einem TI-89 programmiert, dort hast du im Editor 24 Zeichen pro Zeile. Das ist zu wenig 😉

    MfG



  • Weil ich das jetzt schon ein paarmal lese...

    Ich formatiere statt

    aimpl.insert(std::pair<std::wstring,
        handle<node> >(value->name(), 
            value));
    

    es lieber so:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(
           value->name(), 
           value
        )
    );
    

    bzw. hier wuerde ich eher folgendes machen:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(value->name(), value)
    );
    

    ich finde es immer komisch wenn man die schliessende klammer nicht sieht.



  • Shade Of Mine schrieb:

    ich finde es immer komisch wenn man die schliessende klammer nicht sieht.

    Ich finde es noch komischer, wenn die dann aussieht wie ein umgebrochener binärer Operator.

    Anders gesagt: im Grunde sinnvoll, bei <> vermeidenswert.



  • hustbaer schrieb:

    @DEvent:
    Sehe ich ganz anders. Ich finde meine Variante 10x übersichtlicher. Das was richts raussteht, ist Code, den man kaum jemals lesen muss. Zum Verständnis was abgeht, wenn jemand den Code nicht kennt, reicht der Anfang der Zeile, der Teil der auf jedem Schirm Platz hat. Wieso also 13 Zeilen für etwas verschwenden was nur 3 Zeilen braucht? Die 10 Zeilen andere Dinge die ich dadurch mehr auf den Bildschirm bringe, verschaffen wesentlich mehr übersicht, als die uninteressanten Informationen die dadurch rechts rausstehen.

    Wie soll den jemand, der deinen Code nicht kennt, wissen welcher Code Abschnitt wichtig ist und welcher nicht?

    Außerdem, Code, den man nicht regelmäßig zu Gesicht bekommt, neigt dazu vergessen zu werden. Alles Code ist aber wichtig in einem Programm und jede Code Character muss überprüft werden.



  • Shade Of Mine schrieb:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(
           value->name(), 
           value
        )
    );
    

    Woah... sorry wegen der fehlenden konstruktiven Kritik, aber sowas find ich grässlich.



  • TravisG schrieb:

    Shade Of Mine schrieb:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(
           value->name(), 
           value
        )
    );
    

    Woah... sorry wegen der fehlenden konstruktiven Kritik, aber sowas find ich grässlich.

    Ich ebenso. Genauso wie mit den Strings Ist mir wieder ein Rätsel wieso man keine typedefs verwendet.

    aimpl.insert(Mypair(value->name(), value));
    


  • hustbaer schrieb:

    Und nochwas: schreibst du dir für alle API Funktionen (WinAPI oder was auch immer) eigene Wrapper, damit du auf < 3 Parameter kommst? Ich hoffe nicht...
    JM2C

    Jein. Ich benutze die API mit den vielen Parametern nur in einer oder wenns hochkommt zwei Schichten von vielen. Und da nur in möglichst wenigen Klassen. Meist muss ich mir eh Adapter für die APIs bauen, weil ich meine Architektur nicht an der Architektur der APIs ausrichte. Mit diesen Adaptern hab ich dann die Verwendung der API-Funktionen eingegrenzt und quasi Wrapper für die API geschaffen.



  • Hallo /rant/,

    dein Code-Style entspricht in etwa meinem (ich bin doch nicht einzigartig -).



  • DEvent schrieb:

    hustbaer schrieb:

    @DEvent:
    Sehe ich ganz anders. Ich finde meine Variante 10x übersichtlicher. Das was richts raussteht, ist Code, den man kaum jemals lesen muss. Zum Verständnis was abgeht, wenn jemand den Code nicht kennt, reicht der Anfang der Zeile, der Teil der auf jedem Schirm Platz hat. Wieso also 13 Zeilen für etwas verschwenden was nur 3 Zeilen braucht? Die 10 Zeilen andere Dinge die ich dadurch mehr auf den Bildschirm bringe, verschaffen wesentlich mehr übersicht, als die uninteressanten Informationen die dadurch rechts rausstehen.

    Wie soll den jemand, der deinen Code nicht kennt, wissen welcher Code Abschnitt wichtig ist und welcher nicht?

    Außerdem, Code, den man nicht regelmäßig zu Gesicht bekommt, neigt dazu vergessen zu werden. Alles Code ist aber wichtig in einem Programm und jede Code Character muss überprüft werden.

    Naja ich verstecke den Code ja nicht mit irgendeinem magischen Zauber.
    Die Funktionsnamen die am Anfang der Zeile noch sichtbar sind, reichen auch vollkommen aus, damit man weiss was passiert.

    In allen drei Zeilen, ist für jemanden der das komplette Programm vor sich hat, sofort klar, was diese Zeilen tun sollen. So lange also kein Grund besteht, anzunehmen, dass sich genau in einer dieser Zeilen ein Fehler verbirgt, muss man die Parameter nicht checken, da man weiss, welche Parameter übergeben werden sollen.
    Glaub mir bitte einfach, dass das im Kontext vollkommen klar ist.

    Beispiel (erfunden):

    void PrintTableData(Data d, Sink s)
    {
        // ...
        // ...
        for (size_t i = 0; i < lala; i++)
        {
            // ...
            // ...
            s->Print(d[i].irgendwas, d[i].was, d[i].manNichtmehr, lesenKannWeilsAus, demBildschirmRaussteht);
            // ...
        }
        // ...
        // ...
    }
    

    Hier muss ich mir die Parameter zu Print() einfach nicht angucken, um zu "wissen", was Print() wohl machen wird: ein Datenelement aus "d" an die "Sink" schicken, die das dann irgendwo hin "drucken" wird.

    Hier den Print() Aufruf über 5 Zeilen zu ziehen, ist also vollkommen unnötig, weil auch so sofort klar ist, was passiert.

    ----

    Ich lese auch selbst oft Code von anderen Leuten, und im Schnitt finde ich mich schneller zurecht, wenn ich viel gleichzeitig am Bildschirm habe, als wenn viele Funktionsaufrufe über mehrere Zeilen verteilt sind.



  • DEvent schrieb:

    TravisG schrieb:

    Shade Of Mine schrieb:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(
           value->name(), 
           value
        )
    );
    

    Woah... sorry wegen der fehlenden konstruktiven Kritik, aber sowas find ich grässlich.

    Ich ebenso. Genauso wie mit den Strings Ist mir wieder ein Rätsel wieso man keine typedefs verwendet.

    aimpl.insert(Mypair(value->name(), value));
    

    Es gibt viele (gute) Gründe für Typedefs, also bitte nicht falsch verstehen. Ich will nicht Typedefs nicht schlecht reden.
    Zur Abwechslung aber mal ein paar dagegen:

    * Overkill. Nicht jeder "komplizierte" Type, den man 2-3 mal wo braucht, muss gleich getypedeft werden. Kostet bloss sinnlos Zeit.

    * Namen. Oft ist es sau-schwer, passende Namen für Typedefs zu finden. Ich weiss zwar genau was der Typ "eigentlich" ist, aber oft brauche ich viel zu lange, bis mir ein Name einfällt, der mehr hilft als schadet. Schlechte Namen implizieren oft Dinge, die dann gar nicht so sind. Das ist sehr schlecht.

    * Jeder zusätzliche Level-Of-Indirection erschwert das Verständnis, da man ein weiteres Ding nachschlagen muss, bis man zu dem Punkt vorgedrungen ist, wo dann endlich Butter bei die Fische gemacht wird.



  • Shade Of Mine schrieb:

    Ich formatiere statt

    aimpl.insert(std::pair<std::wstring,
        handle<node> >(value->name(), 
            value));
    

    es lieber so:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(
           value->name(), 
           value
        )
    );
    

    bzw. hier wuerde ich eher folgendes machen:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(value->name(), value)
    );
    

    foo-bar! OMG! 😮
    Spätestens jetzt sollte einem klar sein, warum es typedefs und defines gibt.



  • BTW:

    aimpl.insert(std::pair<std::wstring,
        handle<node> >(value->name(), 
            value));
    

    ->

    aimpl.insert(std::pair<std::wstring, handle<node> >(value->name(), value));
    

    ->

    aimpl.insert(std::make_pair(value->name(), value));
    

    welt wieder in ordnung



  • TravisG schrieb:

    Shade Of Mine schrieb:

    aimpl.insert(
        std::pair<
           std::wstring,
           handle<node>
        >(
           value->name(), 
           value
        )
    );
    

    Woah... sorry wegen der fehlenden konstruktiven Kritik, aber sowas find ich grässlich.

    *zustimm*
    ich seh das wie hustbaer 🙂



  • hustbaer schrieb:

    BTW:

    aimpl.insert(std::pair<std::wstring,
        handle<node> >(value->name(), 
            value));
    

    ->

    aimpl.insert(std::pair<std::wstring, handle<node> >(value->name(), value));
    

    Und wieso noch der Leerraum zwischen den beiden > 😕


Anmelden zum Antworten