TU Berlin

FG Kombinatorische Optimierung und GraphenalgorithmenStyleguide

COGA 5-Wheel

Inhalt des Dokuments

zur Navigation

Programmierregeln

Bei allen Programmieraufgaben sind grundsätzlich die unten aufgeführten Richtlinien einzuhalten.

Es werden keine Programme abgenommen, die nicht den Richtlinien entsprechen. Die allgemeinen Regeln sind eher inhaltlicher Natur und können nicht automatisch überprüft werden. Die weiteren Regeln schränken die zu verwendende Syntax und den Funktionsumfang von Java, der verwendet werden kann, ein. Ihre Einhaltung wird mit dem Tool checkstyle überprüft.

Allgemeine Regeln
Die Programme sind ausführlich auf Englisch kommentiert.
Variablen müssen sinnvolle Namen haben.
Nicht erlaubt ist das Durchbuchstabieren der Variablen von a an! Dadurch wird für uns und euch das Verstehen des Programms enorm erleichtert.
Alle nichttrivialen Code-Fragmente müssen dokumentiert werden.
Das gilt insbesondere für nicht triviale Abbruchbedingungen von Schleifen, wichtige Rechenschritte etc. Diese Kommentare können direkt im Code stehen.
try-catch-Blöcke sind kurz zu halten. 
Macht euch Gedanken darüber, in welchen Codezeilen überhaupt welche Exceptions auftreten können. Nichttriviale Methoden, bei denen sämtliche Anweisungen in einem einzigen riesigen try-catch-Block liegen, sind somit ausdrücklich verboten.
Fehleingaben des Benutzers werden abgefangen und gemeldet.
Es darf dabei keinerlei Fehlermeldung auf der Console (d.h. im xterm) erscheinen.
Es dürfen keine nichttrivialen Programmsegmente in gleicher oder nur geringfügig veränderter Form mehrmals im gesamten Programm auftauchen.
Das anscheinend vielgeliebte fünffache Kopieren des gleichen Codestücks mit anschließenden einfachen Änderungen ist hiermit verboten. Solch Code gehört in eigene Methoden verfrachtet.
Variablen dürfen nur im kleinstmöglichen Scope deklariert werden.
Instanzvariablen (also solche im Klassenscope), die nur vorübergehend in Methoden benutzt werden, sind nicht erlaubt. Das gleiche gilt für Instanzvariablen, die als bloßer Ersatz für die Parameterübergabe eingesetzt werden. Nur durch Parameterübergabe kann nämlich halbwegs transparent werden, welche Informationen eine Methode für ihre Ausführung zwingend benötigt.

Die Konfigurationsdatei für checkstyle 

Mit checkstyle überprüfte Regeln
Benennungen von Variablen, Konstanten, etc.
Namen von Variablen, Methoden und Typen enthalten nur die Zeichen a-z (oder A-Z) und 0-9 und fangen mit einem Buchstaben an.
  • (Lokale, statische) Variablen, Methodenparameter und Methoden fangen mit einem kleinen Buchstaben an. Enthält der Name mehrere Bestandteile werden dafür Großbuchstaben verwendet (CamelCase).
  • Namen von Typen (Klassen, Interfaces, Enums) beginnen mit einem Großbuchstaben.
  • (Lokale) Variablen dürfen keinen Parameter überdecken (d.h. den gleichen Namen haben). Eine Ausnahme bilden Konstruktoren und Setter; das heißt this.value = value ist in diesen Fällen zulässig.
  • Parametervariablen dürfen nicht verändert werden, es ist aber nicht notwendig, sie als final zu deklarieren.
  • Pakete enthalten nur Kleinbuchstaben, die Unterpakete werden mit einem . getrennt und entsprechen genau der Verzeichnisstruktur.
Konstanten
Als Konstante in Java werden sämtliche Bezeichner gewertet, die die Modifizierer final static tragen.
  • Die Namen von Konstanten enthalten nur Großbuchstaben. Mehrere Bestandteile werden mit einem Unterstrich (_) getrennt. Zum Beispiel private final static int MY_VALUE = 3;
  • Alle im Code benutzten Werte müssen als Konstante definiert werden. Eine Ausnahme bilden die Werte -1, 0, 1 und 2.
Klassen
  • Klassen enthalten keine öffentlichen Datenfelder. Es muss begründbar sein, wenn Variablen package private oder protected sind. private ist immer vorzuziehen. Ausnahme: die bei Serialisierung vorgeschriebene Variable serialVersionUID darf public sein.
  • Innerhalb von Klassen werden Deklarationen in folgender Reihenfolge durchgeführt: erst werden statische, dann normale Variablen definiert. Zuerst protected, dann package und zuletzt private. Nach den Variablen folgen die Konstruktoren, anschließend die Methoden.
  • Eigene Exception-Typen (durch Vererbung) dürfen nur final deklarierte Felder enthalten.
  • Interfaces müssen mindestens eine Methode definieren.
  • Alle Konstruktoren von Utility-Klassen (d.h. Klassen, die nur static Methoden haben) müssen private sein.
Größen- und Längenbeschränkungen
Um die Übersichtlichkeit zu gewährleisten, müssen folgende Beschränkungen eingehalten werden:
  • Jede Java-Quellcodedatei darf höchstens 1000 Zeilen enthalten.
  • In jeder Datei wird nur ein einziger Typ (Klasse, Interface) auf der obersten Ebene definiert. Die Datei heißt genau so wie der Typ. Es kann aber innere Klassen geben.
  • Jede Methode darf maximal 120 Zeilen enthalten, dabei werden Leerzeilen mitgezählt.
  • Jede Zeile darf nur 120 Zeichen enthalten.
  • In einer Zeile steht maximal eine Anweisung.
  • Anonyme innere Klassen (z.B. Implementierungen eines ActionListeners) dürfen maximal 30 Zeilen umfassen. Sind sie länger, sollte daraus eine innere oder ggf. sogar äußere Klasse erzeugt werden.
  • Eine Methode darf maximal 7 Parameter haben.
  • for-Schleifen und if-Abfragen werden maximal 3-mal geschachtelt. Kompliziertere Konstrukte werden in eigene Methoden ausgelagert.
  • try-catch-Blöcke werden maximal 2-mal geschachtelt. Dies kann notwendig sein, um Fehler bei Dateioperationen korrekt zu behandeln.
  • Eine Methode enthält maximal 5 return Statements. Häufigere Benutzung von return deutet auf übermäßig komplizierten Code oder einen Designfehler hin.
Einrücken:
  • Bei geschachtelten Blöcken wird jede Ebene um 2 Leerzeichen eingerückt.
Sonstige Formatierungen
Es gibt nicht viele Vorgaben bezüglich der Formatierung des Codes selbst. Wichtig ist hauptsächlich, dass die Formatierung einheitlich ist. Im Folgenden einige Regelungen bezüglich Leerzeichen und Klammerung.
Leerzeichen:
  • Nach unären Operatoren (z.B. dem Prä-Inkrement-Operator ++) wird kein Leerzeichen gesetzt.
  • Vor den Post-Operatoren (++, --) und Semikolons wird kein Leerzeichen gesetzt.
Klammerung:
  • Es sind keine leeren Blöcke erlaubt! ({ } ohne Code und einer zugehörigen Anweisung wie if oder else) Blöcke in Blöcken sind nicht zulässig.

  • Geschweifte Klammern nach if, for, methoden, etc. werden in der gleichen Zeile geschrieben.
  • Analog dazu: else, catch etc. wird nach der schließenden Klammer in der gleichen Zeile geschrieben.
  • Die geschweiften Block-Klammern bei if-Abfragen und Schleifen müssen geschrieben werden, auch wenn nur eine Anweisung folgt.
Kommentare
  • Klassen, Interfaces, Methoden und Variablen, die nicht private sind, werden im JavaDoc-Style kommentiert. (Private Methoden/Variablen die nicht trivial sind, sollten aber auch kommentiert werden!)
  • Getter und Setter müssen nicht kommentiert werden. Wenn sie nicht trivial sind, sollten sie doch kommentiert werden.
  • JavaDocs fangen mit einem ganzen Satz an (inklusive Punkt). Geöffnete HTML-Tags müssen geschlossen werden.
Idiome
Bestimmte Idiome, die theoretisch möglich sind, sollen vermieden werden. Dies verringert die Fehleranfälligkeit von Programmen.
  • Keine überflüssigen ";" (leere Anweisungen)
  • this wird nicht mit null verglichen.
  • Wenn die equals-Methode kovariant überschrieben ist (z.B. als equals( MyObject o )), muss equals( Object o ) ebenfalls überschrieben werden.
  • Die Methoden equals und hashCode müssen beide überschrieben werden (wenn eine überschrieben wird).
  • Strings werden nicht mit == bzw. != verglichen. Wenn String-Variablen mit Konstanten verglichen werden, geschieht dies in der Form "mein String".equals( myStringValue ).
  • Zuweisungen mit Seiteneffekten sind nicht zulässig. Z.B. String s = Integer.toString(i = 1).
  • Innerhalb von for-Schleifen wird die Kontrollvariable (z.B. i) nicht verändert.
  • Boolesche Ausdrücke werden vereinfacht. Ausrücke der Art !false (=true) oder a && true (=a) sind nicht zulässig.
  • switch-Anweisungen müssen einen default:-Bereich haben. Wenn alle Fälle abgedeckt sind, und default niemals auftreten kann, muss eine AssertionError geworfen werden.
  • Wenn clone() überschrieben wird, muss super.clone() aufgerufen werden.
  • Ausnahmen der Typen java.lang.Exception, java.lang.Error und java.lang.RuntimeException werden nicht in einem catch-Block aufgefangen. Sie deuten auf gravierende Fehler hin, die nicht zur Laufzeit des Programms behandelt werden können. Treten spezielle Ausnahmen auf, sollten diese auch spezifisch abgefangen werden.
  • Wenn in einem case-fall ein fall through benutzt wird (d.h. kein break;), muss stattdessen ein Kommentar wie //fall through geschrieben werden.
Spezielle Situationen:
  • finalize() wird nicht überschrieben.
  • Falls Unittests durchgeführt werden, müssen sämtliche Methoden wie tearDown oder setUp korrekt benannt sein. Andernfalls kann es passieren, dass Tests erfolgreich verlaufen, es aber gar nicht sind.

 

Beispiel-Dokumentation mit JavaDoc:

Alle Klassen und Methoden sind auf Englisch nach folgendem Schema zu dokumentieren (zusätzlich zu allen Kommentaren für benutzte Variablen und Programmstücke):

Klassen

Beispiel:

/**
* A christmas tree that always nicely fits into its canvas.
* Can be used just like any other Component.
*/
public class XmasTree
{
...

Vor der Klasse steht also ein mehrzeiliger Kommentar, dessen erste Zeile /** ist und bei dem jede weitere Zeile mit * beginnt. In ein oder mehreren Sätzen sollen dort Sinn und Fähigkeiten der Klasse kurz umrissen werden.

Methoden

Beispiel:

/**
* Compute the volume of a cube with the specified dimensions.
*
* @param h the height of the cube
* @param w the width of the cube
* @param d the depth of the cube
*
* @return the volume of the cube
*
* @exception CubeException if any of the given parameters is negative
*/
public double computeVolume(double h, double w, double d)
throws CubeException
{
...

Es steht direkt vor der Methode ein mehrzeiliger Kommentar, der wieder mit /** und jede weitere Zeile mit beginnt.

Anschließend ein oder mehrere Zeilen, die die Methode kurz beschreiben. Hierhin gehören auch alle Voraussetzungen, die vielleicht erfüllt sein müssen, bevor die Methode aufgerufen werden sollte.

Es folgen Zeilen der Form
  @param Variablenname Beschreibung
für jeden Parameter der Methode.

In ähnlicher Weise kommt nun eine Zeile der Form
  @return Beschreibung
die den Rückgabewert erklärt. Bei void-Methoden steht natürlich keine solche Zeile.

Falls die Methode eine Ausnahme auswerfen kann, muß diese auch dokumentiert werden durch die Zeile
   @exception Exceptionname Bedingungserläuterung
die in Worten angibt, wann eine solche Exception erzeugt wird.

Navigation

Direktzugang

Schnellnavigation zur Seite über Nummerneingabe