CODE IN MOTION Wie wichtig die Form von Quellcode ist - Beautiful Code Seminar: SS09 Prof Dr. sc. nat. Klaus Bothe Referent: Paul Heisig

Die Seite wird erstellt Nikolas-Stefan Weiß
 
WEITER LESEN
CODE IN MOTION
                 Wie wichtig die Form von Quellcode ist

Beautiful Code
Seminar: SS09
Prof Dr. sc. nat. Klaus Bothe
Referent: Paul Heisig
Struktur
1.    Einführung
     1.   Vorgedanke
     2.   Schöner Code
     3.   DiffMerge
Struktur
2.    Die sieben Säulen schönen Codes
     1.   Buchformat
     2.   Gleiche Funktion – gleiches Aussehen
     3.   Überwindung der Einrückung
     4.   Kommentieren von Code-Blöcken
     5.   Entwirrung von Code-Blöcken
     6.   Aufräumen
     7.   Stilkonform
Struktur
3.    Die sieben Säulen schönen Codes und
      DiffMerge
     1.   Lesbarkeit ohne Highlighting
     2.   Graphisches Vergleichen
     3.   Bugs…
4.    Fazit
     1.   Schöner Code in Motion
     2.   Ein guter Programmierer
1.1. Vorgedanke
 Die Funktion von Quellcode ist determiniert
 Die Form dagegen frei wählbar
 Was ist „schöner Code“?
 Welche Vorteile bringt die Einhaltung
 bestimmter Konventionen?
 Diese Fragen werden am Beispiel der
 DiffMerge Komponente erörtert
“The main point is that every successful piece of
  software has an extended life in which it is
  worked on by a succession of programmers
  and designers....”

                               Bjarne Stroustrup
1.2. Schöner Code
 Funktion ist schnell zu erfassen Æ visuelle
 Syntaxanalys
 Relative Wichtigkeit des Codes über Form
 wahrnehmen
 Fehler werden minimiert
 Einarbeitungszeit wird minimiert
1.3. DiffMerge
 Komponente von Perforce Software zum
 visuellen Vergleichen und Mergen von
 Textdateien
 Viele Sonderfälle
 Wurde über 10 Jahre lang von verschiedenen
 Entwicklern weiterentwickelt
 Daher sind gewisse Grundregeln wichtig
2. Die sieben Säulen schönen Codes

1.   Buchformat
2.   Gleiche Funktion - gleiches Aussehen
3.   Überwindung der Einrückung
4.   Entwirren von Code-Blöcken
5.   Kommentieren von Code Blöcken
6.   Aufräumen
7.   Stilkonform
2.1. Buchformat
 Schmale Spalten
 Code dicht
 Links: Struktur
 Rechts: Details
 80 Zeichen sollten nicht überschritten werden
2.1. Buchformat
  Was passiert hier?
if( bf->end == bf->Lines() && lf1->end == lf1->Lines( ) &&
   lf2->end == lf2->Lines( ) ) return( DD_EOF );
2.1. Buchformat
  Was passiert hier?
if( bf->end == bf->Lines() && lf1->end == lf1->Lines( ) &&
   lf2->end == lf2->Lines( ) ) return( DD_EOF );

  Besser:
if( bf->end == bf->Lines( ) &&
   lf1->end == lf1->Lines( ) &&
   lf2->end == lf2->Lines( ) )
       return( DD_EOF );
2.2. gleiche Funktion – gleiches Aussehen

 Variablen zusammen initialisieren
 Parameter langer Funktionen untereinander
 aufreihen
 && oder || Verzweigungen untereinander
 aufreihen
 this einheitlich verwenden
 Resultat: Mustererkennung beschleunigt
 Lesetempo
2.2. gleiche Funktion – gleiches Aussehen

  Schnell zu erkennen: drei der vier while
  Bedingungen haben gleiche Struktur

while( d.diffs == DD_CONF && ( bf->end != bf->Lines( ) ||
                              lf1->end != lf1->Lines( ) ||
                              lf2->end != lf2->Lines( ) ) )
2.2. gleiche Funktion – gleiches Aussehen

case MS_BASE:                      /* dumping the original */

    if( selbits = selbitTab[ DL_BASE ][ diffDiff ] )
    {
            readFile = bf;
            readFile->SeekLine( bf->start );
            state = MS_LEG1;
            break;
    }

case MS_LEG1:                      /* dumping leg1 */

    if( selbits = selbitTab[ DL_LEG1 ][ diffDiff ] )
    {
            readFile = lf1;
            readFile->SeekLine( lf1->start );
            state = MS_LEG2;
            break;
    }

case MS_LEG2:                      /* dumping leg2 */

    if( selbits = selbitTab[ DL_LEG2 ][ diffDiff ] )
    {
            readFile = lf2;
            readFile->SeekLine( lf2->start );
    }
    state = MS_DIFFDIFF;
    break;
2.3. Überwindung der Einrückung

 Linker Rand gibt Struktur an, rechte Seite die
 Details
 Zu weit nach rechts eingerückter Code ist
 unübersichtlich
 Möglichst nicht mehr als zwei
 Einrückungsebenen
 Schwierig umzusetzen
2.3. Überwindung der Einrückung
    Oft so:

if (foo) {
    if (bar) {
          if (anotherVariable) {
                 // bla
          }
    }
}
2.3. Überwindung der Einrückung
    Oft so:

if (foo) {
    if (bar) {
          if (anotherVariable) {
                 // bla
          }
    }
}

    Besser:

if (!foo) return;
       if (!bar) return;
if (!anotherVariable) return;
// bla
2.4. Kommentieren von Code-
Blöcken
 Code-Blöcke mit Anmerkungen
 Was passiert in dem Block?
 Leerzeichen zwischen Blöcken
 Optimal: 15% leere Zeilen und 25% Zeilen mit
 Anmerkungen
2.5. Entwirrung von Code-Blöcken

 Innerhalb einer Funktion logische Blöcke
 bilden (eine Aufgabe – ein Block)
 Aufgaben der Blöcke soll ersichtlich sein oder
 per Kommentar verdeutlicht sein
 Aufteilung in Minifunktionen
 Klar ersichtliche Informationsweitergabe
 innerhalb der Blöcke
2.6. Aufräumen
 Reduzieren, reduzieren, reduzieren
 Je kleiner der Geltungsbereich von Variablen,
 umso kürzer der Name (z.B. kurze Namen [wie
 i, c] für Variablen mit knappem Geltungsbe-
 reich)
 Lange Variablennamen helfen nur anfänglich,
 stören den Leser aber langfristig Æ nur bei
 globalen Variablen nutzen
 Toten Code nicht auskommentieren, sondern
 entfernen
2.7. Stilkonform
 Codeänderungen sollten dem Originalstil
 konform sein
 Änderungen sollten nicht erkennbar sein
 (dafür sind Versionsverwaltungen besser
 geeignet)
 Konformität nicht nur innerhalb von
 Funktionen, sondern bestenfalls Projektweit
 wahren
3. Die sieben Säulen schönen
Codes und DiffMerge
 Perforce Software hat die sieben Regeln auf
 DiffMerge angewandt
 Ein Beispiel, wie sich dies positiv auf Code
 auswirkt und diesen schön macht
 Code ist dadurch leichter zu verstehen
3.1. Lesbarkeit ohne Highlighting
Breakpoint 3, DiffMerge::DiffDiff (this=0x80e10c0) at diff/diffmerge.cc:510
510             Mode initialMode = d.mode;
(gdb) list 505,515
505             DiffGrid d = diffGrid
506                      [ df1->StartLeg() == 0 ][ df1->StartBase( ) == 0 ]
507                      [ df2->StartLeg() == 0 ][ df2->StartBase( ) == 0 ]
508                      [ df3->StartL1() == 0 ][ df3->StartL2( ) == 0 ];
509
510             Mode initialMode = d.mode;
511
512             // Pre-process rules, typically the outer snake information
513             // contradicts the inner snake, its not perfect, but we use
514             // the length of the snake to determine the best outcome.
515
(gdb) print d
$1 = {mode = CONF, diffs = DD_CONF}
(gdb)
3.2. Graphisches Vergleichen
3.3. Anzahl der Patches pro DiffMerge
Release

       was war zwischen 2004 und 2006 passiert?
3.3. Anzahl der Patches pro DiffMerge
Release

        Anzahl der if-Statements
4. Fazit
 Was ist also Schöner Code in Motion?
4.1. Schöner Code in Motion
 Schöner Code in Motion ist der Code, welcher
 mit minimalstem Aufwand geändert werden
 kann und geändert wird
4.2. Ein guter Programmierer
 Kann gut Programmieren
 Kann schnell fremden Code verstehen
 Kann Code schreiben, den andere gut
 verstehen
Fragen?
Quellen
 Wingerd, L., & Seiwald, C. (2007). Code in Motion. In A.
 Oram, & G. Wilson, Beautiful Code (S. 527-537).
 Beijing, Cambridge, Farnham, Köln, Sebastopol, Taipei,
 Tokyo: O'Reilly.
 Die sieben Säulen schönen Codes. Christopher
 Seiwald. Abgerufen am 13. Mai 2009 von
 http://www.perforce.com/perforce/de/papers/prettycode.
 html
Sie können auch lesen