Code Convention

Im Laufe seiner Tätigkeit als Softwareentwickler trifft man auf unterschiedlichste Stile in der Notation von Quellcode. Arbeitet man als Teil eines Teams an einem Projekt mit, ob als Angestellter oder Freiberufler, ist man eventuell an Stil-Konventionen gebunden und die Frage nach dem eigenen Stil stellt sich nicht. Hat man jedoch keine festen Vorgaben oder verfolgt eigene Projekte, ist es sinnvoll über eigene Richtlinien nachzudenken. In verschiedenen Projekten und Programmiersprachen traf ich stets auf unterschiedliche Gegebenheiten (manchmal auch nur Kraut und Rüben) und mir wurde klar, dass ich mir bisher über dieses Thema kaum Gedanken gemacht hatte, was ich nun nachhole.

Folgende Punkte klärt meine Konvention:

  1. Wahl von Bezeichnern
  2. This für Member
  3. Klammersetzung

Diese Punkte werden nun im Einzelnen besprochen.

1.Wahl von Bezeichnern

Ein bekanntes System für die Gestaltung von Bezeichnern für Variablen ist die Ungarische Notation: Es gibt sie in zwei Ausprägungen Systems Hungarian und Apps Hungarian. Bei ersterem wird der physische Datentyp im Bezeichner als Präfix vermerkt: Eine boolsche Variable heißt dann beispielsweise bVar (b = bool). Die zweite Variante bringt dagegen den logischen Datentyp in den Bezeichner ein. Für einen Zeiger wird z.bsp. p als Präfix notiert (p = pointer): pElement . Weitere Präfixe, die man als Entwickler schon öfter gesehen hat sind z.bsp: c = Counter, h = Handle, f = Flag.
Systems Hungarian ist aus einer Missinterpretation der ungarischen Notation entstanden – wohl bei Microsoft. Den physischen Datentyp einer Variablen im Bezeichner zu vermerken, gibt keinen Hinweis auf den Verwendungszweck der Variablen. Zudem ist es richtig aufwändig bei der Änderung des Datentyps immer auch den Namen des Bezeichners zu verändern. Vergisst man das, hat man sofort eine Inkonsistenz in der Notation. Weiterhin stellt sich die Frage, welches Kürzel verwendet man für eigene Typen wie Klassen, Strukturen etc. Und bei dynamischer Bindung, die den exakten Datentyp erst zur Laufzeit ermittelt ist dieser Ansatz ebenso wenig zu gebrauchen. Ich werde diese Konvention nicht anwenden.
Die eigentliche Idee der ungarischen Notation findet sich in Apps Hungarian wieder. Anflüge davon findet man in vielen (vor allem älteren) Projekten. Für mich stellt sich dabei jedoch folgende Frage: Wie offiziell sind die Präfixe und wie konsequent werden sie von Entwicklern angewandt? Nutzt ein Programmierer den Präfix cnt statt c für eine Zählvariable ist das noch naheliegend, aber kann jeder Entwickler von jedem Präfix in unbekanntem Code auf den logischen Typ schließen, so dass die Notation tatsächlich einen Mehrwert hat?
Anstatt von Kürzeln und Präfixen habe ich mich entschieden längere Bezeichner zu vergeben, die den Zweck der Variablen (meist) im Namen tragen. Der phyische Datentyp wird dabei nicht vermerkt.

Bezeichner für Klassen oder Methoden werden meistens ausführlich und beschreibend gewählt. Die .Net Richtlinie von Microsoft besagt hierzu: „Do favor readability over brevity“Lesbarkeit ist das Wichtigste. Auch ich wähle gern Bezeichner die praktisch sind z.Bsp. im Zusammenspiel mit Autovervollständigung. Es ist übersichtlich wenn Variablen schick in der alphabetisch geordneten Dropdown-Liste beieinander gelistet sind. Ein Beispiel: In einer Klasse sind mehrer Zählervariablen definiert: windowCount, messageCount, appsCount. Die Lesbarkeit ist bei diesen Bezeichnern gegeben. Die alternativen Bezeichner countWindow, countMessage, countApps sind weniger intuitiv gewählt, würden aber durch Autovervollständigung untereinander aufgeführt, was einen guten Überblick über die Zählervariablen gibt. Trotz dieses Vorteils lege ich die Priorität für meine Konvention auf die Lesbarkeit. Eine Übersicht zu Klassenmembern erhält man ebenso schnell über ein ordentlich definiertes Interface.

Under_score or CamelCase? Meine Recherchen im Netz haben ergeben – Es ist Geschmackssache. Ebenso wie es heißblütige Verfechter des Unterstriches gibt, findet man viele Entwickler, die CamelCase in Bezeichnern den Vorzug geben. Die Verwendung beider Systeme kann man aktuell in der Softwareentwicklung mit 50/50 angeben (Stand: Juli 2013). Meine Entscheidung fällt für CamelCase. Der Unterstrich zum Trennen von Teilen eines Bezeichners mutet (meiner Meinung nach) kryptisch und altmodisch an. In Bezeichnern für Klassen oder Methoden findet der Unterstrich generell kaum Verwendung. Deshalb sehe ich die kontinuierliche Anwendung von CamelCase als sinnvollere Methode an. Einziger Nachteil aus meiner Sicht: Bezeichner mit enthaltenen Abkürzungen wie TCPPort. CamelCase wirkt in diesem Fall auf den ersten Blick schlecht lesbar. Aber kontinuierliche Anwendung bedeutet, dass ich über diesen Fall hinwegschaue.

2.This für Member

Wie macht man den Zugriff auf Member (Variablen, Methoden) gut kenntlich? Generell lassen sich Member in ihrem Namespace bzw. Klasse direkt durch ihren Bezeichner ansprechen. Auf den ersten Blick sieht man im Code jedoch nicht direkt ob nicht doch eine lokale Variable oder lokal definierte Methode aufgerufen wird. Abhilfe schafft hier das Schlüsselwort this. Es steht in vielen Programmiersprachen bereit, um explizit auf Member des aktuellen Kontextes zu verweisen: this->mapCount (C++), this.mapCount (Java), self.mapCount (Python). Ein Argument für die Verwendung von this ist die gute, eindeutige Lesbarkeit des Codes. Als Argument dagegen wird die Aufblähung des Codes durch das zusätzliche this-> genannt. Ich sehe die Lesbarkeit hier im Vorteil und verwende daher konsequent this zur Referenzierung von Membern in meinem Code.

3.Klammersetzung

Ein wichtiges Grundprinzip von Programmiersprachen ist die Sturkturierung des Codes in Blöcke, um Gültigkeitsbereiche zu definieren. Meist werden dazu Klammern verwendet (Bekannte Ausnahme Python: Hier werden Blöcke durch Einrückung definiert). Obgleich, das Setzen Dieser für den Compiler von logischer Bedeutung ist, kann man Klammern im Code flexibel notieren was Abstände, Einrückung, Leerzeichen etc. angeht. Das hat lediglich einen Effekt auf das Erscheinungsbild des Codes und dessen Lesbarkeit. Hier stehen sich sehr kompakte Notationen mit ausschweifenderen lesbareren Varianten gegenüber. Analog zu meinen vorigen Konventionen gebe ich auch hier der Lesbarkeit den Vorrang. Ich finde folgende Notationen gut lesbar:

if (i == 1)    // 1 Leerzeichen nach der Anweisung, Leerzeichen zwischen den Operanden und Operator
{
}
else              // öffnende Klammer immer unter der Anweisung nicht dahinter
{
}

for (int i = 0; i < 1; i++)
{
}

// Das ist ein Kommentar über eine Zeile 

/* Das ist ein Kommentar
     über mehrere Zeilen
*/

Oft kommen mir folgenden Notationsvarianten unter:

for(int i=0; i<1; i++) {
}

So eng und kompakt geschrieben leidet die Lesbarkeit meiner Meinung nach stark, weswegen ich die obere Variante vorziehe.
Möchte man in seinen Projekten stets Einheitlichkeit und Lesbarkeit seiner Code-Notation garantieren kann die Anwendung eines Code Beautifiers hilfreich sein. Beispiel: Artistic Style (Selbst nicht getestet, wird aber oft empfohlen).

Ich denke ganz gleich für welche Konventionen bei der Notation man sich entscheidet, das wichtigste ist die Konsequenz und Einhaltung in der täglichen Ausführung. Viel Spaß beim Coden.

Autor:    Michael Keutel | 28.04.2013