Galileo Computing < openbook >
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.


Java ist auch eine Insel von Christian Ullenboom
Buch: Java ist auch eine Insel (Galileo Computing)
gp Kapitel 26 Style-Guide
gp 26.1 Programmierrichtlinien
gp 26.2 Allgemeine Richtlinien
gp 26.3 Quellcode kommentieren
gp 26.3.1 Kommentartypen
gp 26.3.2 Strategischer und taktischer Kommentar
gp 26.3.3 Bemerkungen über JavaDoc
gp 26.3.4 Gotcha-Schlüsselwörter
gp 26.4 Bezeichnernamen
gp 26.4.1 Ungarische Notation
gp 26.4.2 Vorschlag für die Namensgebung
gp 26.5 Formatierung
gp 26.5.1 Einrücken von Programmcode - die Vergangenheit
gp 26.5.2 Verbundene Ausdrücke
gp 26.5.3 Kontrollierter Datenfluss
gp 26.5.4 Funktionen
gp 26.6 Ausdrücke
gp 26.7 Anweisungen
gp 26.7.1 Schleifen
gp 26.7.2 Switch, case und Durchfallen
gp 26.8 Reihenfolge der Eigenschaften in Klassen
gp 26.9 Zugriffsrechte und Zugriffsmethoden
gp 26.9.1 Accessors/Zugriffsmethoden
gp 26.10 Verweise


Galileo Computing

26.5 Formatierungdowntop

Individuelle stilistische Fragen beim Programmieren müssen in den Hintergrund gestellt werden, da es bei Quelltexten in erster Linie um die Lesbarkeit für die gesamte Programmiergemeinschaft geht. Daher sollte genügend Freiraum für die Programmzeilen geschaffen werden, die den Code deutlich hervorheben, aber diesen nicht durch ungeschickte Einrückung verdecken. Es kann von uns nicht verlangt werden, dass wir uns in die ungewöhnliche Einrückung von anderen einarbeiten müssen. Wir verlieren nur wertvolle Zeit, wenn wir uns erst in das ästhetische Empfinden des Programmerstellers einarbeiten müssen. Die richtige Platzierung der Leerzeichen ist also nicht unerheblich. Es müssen immer gewöhnliche Leerzeichen anstatt Tabulatoren verwendet werden. Verschiedene Editoren interpretieren Tabulatorzeichen als unterschiedlich breite Einrückungen. Unser feinfühliges Styling des Texts darf nicht an den verschiedenen Darstellungen der Editoren scheitern. Mittlerweile füllen auch viele Texteditoren beim Druck auf die Tabulatortaste den Freiraum mit Leerzeichen auf. Unter Unix können Tabulatoren mit dem Programm expand durch Leerzeichen ersetzt werden. Eine Tabulatorlänge, die später mit Leerzeichen aufgefüllt wird, sollte zwei, drei oder vier Zeichen betragen. Zwei Leerzeichen seien nahe gelegt. Damit geht der Programmcode nicht zu sehr in die Breite.

Die Zeilenlänge sollte 78 Zeichen nicht überschreiten.


Galileo Computing

26.5.1 Einrücken von Programmcode - die Vergangenheitdowntop

Das Einrücken von Programmcode ist eine sehr individuelle Vorliebe und führt vielfach zu emotionalen Kontroversen, weil jeder meint, seine Art der Einrückung sei die beste. Der Programmierstil ist Ausdruck der eigenen Ästhetik, eines Normstils, aber auch Ergebnis schnellen Tippens oder des Drucks des Auftraggebers. Es zeigt sich glücklicherweise, dass jeder durch seinen eigenen Quellcode am schnellsten navigieren kann. Nur wenn es der Text eines anderen ist, kommt neben der kompakten Formulierung der Programme die oft ungewohnte Art der Einrückung hinzu.

Es gibt einige Programme, die Quelltexte konform einrücken, und das bekannteste für C ist »indent«. Es stützt sich auf drei Einrückungskonventionen, die sich mittlerweile in C beziehungsweise C++ etabliert haben (oder hatten). Auch wenn wir hier eigentlich von Java reden, riskieren wir einen Blick in die Entwicklung von C (selbst auf die Gefahr hin, dass wir verdorben werden):

gp Der Programmierstil von Kernighan, Ritchie (1978) wird in einem ausführlichen Buch über C-Programmierung festgelegt. Heutzutage sehen die Programme antiquiert aus.
gp Harbison und Steele (1984) beschreiben den H&S-Standard, der ein erweiterter K&R-Standard ist. Die modernen C-Compiler kommen dem Standard gut nach, der insbesondere zwischen K&R und ANSI seinen Platz gefunden hat.
gp Das American National Standards Institute formte den ANSI-Standard, der gegenüber H&S noch Erweiterungen aufweist. Zum ersten Mal wird auch die Aufgabe des Präprozessors genauer spezifiziert.
gp Der C++-Standard beschreibt eine Obermenge von ANSI-C. Es gibt immer wieder Verzögerungen in der Standardisierung, und somit existiert die Sprache nur als Beschreibung von AT&T.

Der Blick auf die Entwicklung von C und C++ ist interessant, denn über einen langen Zeitraum lassen sich gut Daten über Programmierstile sammeln und auswerten. Wir profitieren also in den Java-Richtlinien von der Vorarbeit unseres Vorgängers C++.


Galileo Computing

26.5.2 Verbundene Ausdrückedowntop

Die geschweiften Klammern »{}«, die einen Block einschließen, sollten eine Zeile tiefer in der gleichen Spalte stehen. Hier ist mitunter ein Kompromiss zwischen Lesbarkeit und kurzem Code zu schließen. Im Prinzip haben wir mit der Klammer unter dem Schlüsselwort nur zwei Möglichkeiten (exemplarisch an if gezeigt). Eine Variante setzt die Klammer in eine einzelne Zeile. Die traditionelle Unix-Schreibweise setzt die Klammer in dieselbe Zeile wie die erste Anweisung:

if ( Bed )           if( Bed ) 3                  if ( Bed ) { 44 
{ ...                 {                              ...
}                       ...                       }
                      }

Innerhalb von Blöcken sollte jede Anweisung in einer eigenen Zeile stehen. Nur eng verwandte Operationen sollten sich eine Zeile teilen. Als Beispiel sei die case-Anweisung genannt.


Galileo Computing

26.5.3 Kontrollierter Datenfluss downtop

Den Kontrollfluss-Möglichkeiten mit den Schlüsselwörtern if, else, while, for und do sollte ein Block folgen, auch wenn dieser leer ist. Fügen wir dann Zeilen in den Schleifenrumpf ein, kommt es nicht zu semantischen Fehlern. Der Komma-Operator ist in Java schon aus den Anweisungen verschwunden, und es kommt seltener zu Missverständnissen.1 Es wird empfohlen, while-Schleifen, die ihre Arbeit innerhalb der Bedingung erfüllen, nicht einfach mit einem Semikolon abzuschließen, wie

while ( Bedingung );

Besser ist dann schon Folgendes:

while ( Bedingung )                  while ( Bedingung )
{                                      ;
  // Empty !
}

Auf jeden Fall sollte auch eine einzelne abhängige Anweisung nicht in derselben Zeile wie die Bedingung stehen. Ein nicht nachzuahmendes Beispiel ist etwa:

if ( presentCheese.isFullOfHoles() ) reduceHomelessnesOfMice();

Verbinden sich if-Abfragen mit einem else-Teil, könnte ein Block wie folgt aussehen:

if ( Bedingung )           // Kommentar wann ausgeführt
{
}
else if ( Bedingung )      // Kommentar wann noch ausgeführt
{
}
else                       // Kommentar für das, was bleibt
{
}

Galileo Computing

26.5.4 Funktionentoptop

Bei der Funktionsdeklaration sollten wir immer bemüht sein, die Signatur so vollständig wie möglich anzugeben.

Rückgabetyp

In Java wird immer ein Rückgabewert gefordert. Compilieren wir beispielsweise die Zeile

 tst() { }

so ist dies unter C2 völlig korrekt, da Funktionen ohne explizit angegebene Rückgabewerte immer den Ergebnistyp int haben; unter Java erhalten wir aber die Fehlermeldung:

Invalid method declaration; return type required.
 tst()
 ^

Neben der Angabe des Rückgabewerts sollten wir aber auch die Einrückungen und den Einsatz von Leerzeichen beachten. So ist zwischen Funktionsnamen und öffnender Klammer der Parameterliste, sowohl in der Deklaration als auch später im Gebrauch der Funktion, kein Leerzeichen zu setzen. Grundsätzlich sollten wir vermehrt Leerzeichen einsetzen, um die Lesbarkeit zu erhöhen. Nach der öffnenden Klammer ist ein Leerzeichen zu platzieren, ebenso nach jedem trennenden Komma und vor der schließenden Klammer.

Zeilenumbruch

Die Parameter sind, wenn es der Platz erlaubt, in dieselbe Zeile zu schreiben. Reicht der Raum nicht aus, weil zu viele Parameter übergeben werden, ist zunächst einmal zu überlegen, ob nicht ein Designfehler vorliegt und die Signatur ungeschickt gewählt ist. Arbeiten wir konsequent objektorientiert, erübrigen sich vielfach Argumente. Die meisten API-Funktionen von Java besitzen nicht mehr als ein oder zwei Parameter. Gibt es gute Gründe für den Einsatz vieler Parameter, so schreiben wir jeden Parameter in eine eigene Zeile. Die Klammer wird hinter den letzten Parameternamen gesetzt.

Der Ergebnistyp sowie die Sichtbarkeitsstufe sollten zusammen mit dem Funktionsnamen in einer Zeile stehen. Viele Programmierer meinen, der Rückgabewert sollte in einer eigenen Zeile über der Funktionsdeklaration stehen, denn somit sei der Funktionsname besser zu erkennen.3 Andernfalls kann dem eigentlichen Funktionsnamen eine längere Angabe der Sichtbarkeitsstufe (public, protected oder private) sowie ein lang werdender Ergebnistyp vorausgehen. So finden wir etwa einige lange Zeilen in der Funktionsimplementierung (von Sun):

public void addLayoutComponent(Component comp, Object constraints)
private static void testColorValueRange(float r, float g, float b)
public static AdjustmentListener remove(AdjustmentListener l,
                                        AdjustmentListener oldl)

Bei der dritten Zeile sehen wir das Dilemma. Nach dem Kodierungsstil von GNU schwächt sich die Länge der Zeile etwas ab:

public static AdjustmentListener
remove(AdjustmentListener l, AdjustmentListener oldl)

Beide Formulierungen haben ihre Vor- und Nachteile. In der Sun-Variante erblicken wir nach den Schlüsselwörtern public und void, die ja heutzutage immer farblich hervorgehoben sind, den Namen des Rückgabetyps und dann den Namen der Funktion, etwa im ersten Beispiel addLayoutComponent. Unser Auge muss also zuerst über public/private/protected und den Rückgabetyp springen, der wie bei AdjustmentListener lang werden kann, um dann den uns interessierenden Funktionsnamen aufzunehmen. Bei der unteren Variante jedoch kann das Auge immer am linken Rand die Information finden, die es braucht. Doch leider scheint die Argumentation nicht ganz so einfach zu sein, denn benutzen wir zwei Zeilen, ist der Name der Funktion vom darüber liegenden public void etwas verstellt und alles wirkt gedrungen und dicht. Ich empfehle daher die erste Variante, die etwas luftiger ist und den Funktionsnamen mehr in die Mitte rückt. Also:

public static AdjustmentListener remove( AdjustmentListener l,
                                         AdjustmentListener oldl )

Im Gegensatz zu der Schreibweise von Sun steht jedes Argument in einer Zeile, und die Klammern sind mit Leerzeichen etwas freigeräumt.

Nach der Parameterliste sind die geschweiften Klammern des Blocks immer in die nächste Zeile unter den ersten Buchstaben des Funktionsnamens zu schreiben. Beim Durchlaufen des Programmcodes können wir uns besser an den öffnenden Klammern orientieren.

Auf Attribute und Funktionen zugreifen

Der Punkt-Operator für den Zugriff auf Objekt- oder Klassenvariablen beziehungsweise -methoden darf nicht durch Freiraum von dem Klassennamen oder dem Ausdruck für die Objektreferenz oder dem Methoden- beziehungsweise Variablennamen abgetrennt werden. So ist es vernünftiger, anstatt

persons.                whoAmI      .                 myName

die Zeile

persons.whoAmI.myName

zu programmieren. Obwohl der Java-Compiler auch Programmcode mit eingebetteten Kommentaren und Zeilenvorschüben akzeptiert, ist von Konstruktionen wie

persons./* um wen geht es */whoAmI/* ich bin's*/./*mein Name*/myName

dringend abzuraten.






1 C-Programmierer bauen gerne Konstrukte wie :while ( /* Bedingung */) Anweisung1, Anweisung2; Damit versuchen sie geschweifte Klammern zu sparen! Natürlich sind solche Aktionen zu vermeiden!

2 Auch in C++ müssen die Funktionen einen Rückgabetyp vereinbaren.

3 So argumentieren jedenfalls viele Programmierer von GNU.





Copyright (c) Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de