Development:Codingstyle

Aus TuxBoxWIKI
Wechseln zu: Navigation, Suche


Review-KandidatDieser Artikel befindet sich derzeit im Reviewprozess. Hilf mit, ihn zu verbessern! Falls du bei weiteren Artikeln helfen willst, findest du hier eine Auswahl offener Artikel.

Der Sourcecode von Neutrino ist inzwischen in die Jahre gekommen. Viele Programmierer haben Hand am Source angelegt. Da es nie Maintainer oder besondere Sourcecode Formatierungsregeln gab, ist der Quellcode von Neutrino, und auch der daraus entstandene Quellcode von Neutrino-HD, in unterschiedlichster Weise formatiert. Dies ist für die Lesbarkeit und für das Verständnis des Quellcodes nicht von Vorteil.

Zustand

Der Source der Neutrino Quellen ist zum größten Teil in C++ geschrieben. Es wird aber auch C-Code verwendet. Da teilweise viele Personen an ein und derselben Datei gearbeitet haben kann es innerhalb ein und der selben Datei die unterschiedlichsten Formatierungen geben.
In den sonstigen Dateien wiederum (Shellscripte z.B.) gibt es keine besonderen Unterschiede in den Styles und Formatierungen.

Strukturierung

Für das Formatieren von C/C++ gibt es leicht unterschiedliche Einrückungsstile. Um die Lesbarkeit des Quellcodes zu verbessern sollten Programmierer die in den diversen Dateien arbeiten sich an bestimmte Standards halten. Dies ist kein absolutes Muss, ist aber sehr zuträglich für das Projekt. In anderen GNU Projekten ist die Einhaltung projektspezifischer Standards wegen der Größe dieser Projekte wiederum Pflicht. So zum Beispiel bei der Linuxkernelentwicklung oder beim KDE Projekt.

Modelines

Mit sogenannten Modelines kann man dem Editor seiner Wahl Bearbeitungsoptionen und Anzeigeoptionen mitgeben, sofern dieser dieses Feature unterstützt. Diese Modelines müssen entweder direkt in den bis zu ersten drei Zeilen oder in der letzten Zeile vorhanden sein, allgemein üblich ist am Beginn der Datei. Da historisch bedingt die ersten Editoren reine Text basierende Programme waren bezieht sich der Syntax in der Regel auf Vi/Vim. Eine Modeline (im Beispiel nur in der ersten Zeile) sieht dann z.B. so aus.

// vim:filetype=c:ai:expandtab:tabstop=4:textwidth=72:
//
// file foo.cpp
// The file foo.cpp implements various helper functions.
//
// include <iostream>
// ...
Erläuterung zu den Modeline Angaben
Modelineargument Erklärung
vim: Start der Modelineanweisungen
filetype=c Angabe des Dateityp, hier C Quelletxt
ai autointend, bei Zeilenumbruch automatisierte Einrückung (funktioniert je nach Editor nicht automatisch)
expandtab automatische Erweiterung von Tabulatoranschlägen mit Leerzeichen
tabstop=4 Anzahl von Zeichen die beim benutzen der Tabulatortaste benutzt werden
textwidth=72 automatisierter Umbruch nach dem 72. Zeichen (Tabs werden aufgelöst)

Die Anweisungen der Modeline beginnen im Beispiel mit vim: und werden immer mit einem Doppelpunkt oder auch Leerzeichen getrennt. Zwischen den Kommentarzeichen und dem Beginn der Modeline muss mindestens ein Leerzeichen sich befinden. Genaueres zum Aufbau der Modelines findet man im Wiki vom Vim.

Quelltextformatierungen

Da an Neutrino wohl fast nur Freiwillige arbeiten, ist so eine Forderung nur schwer umzusetzen. Man kann so etwas aber sehr wohl als erstrebenswertes Optimum ansehen und jeder der mitarbeitet, sollte sich so weit es geht an solche Wunschvorgaben halten.

Als ein guter Kompromiss zwischen Lesbarkeit und Platzbedarf hat sich der Stil 1TBS/K&C („One True Brace Style“ von Kernighan und Ritchie) erwiesen. Kurz und kompakt bedeutet das folgendes:

Beispiel Funktionsdeklaration

  • Die öffnende Klammer einer Funktion steht immer an einem Zeilenanfang.
void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
{
...
}
  • Bei vielen Funktionsübergabeparametern sollten an diesen jeweils möglichst die Zeile umgebrochen werden. Eine Zeile sollte nicht mehr wie 72 Zeichen enthalten.
unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
	unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
	unsigned int *offset, enum xfer_buf_dir dir)
{
...
}

Beispiel Schleifen

  • Schleifen können genauso eingefasst werden. Dies kostet aber relativ viel Platz bei zahlreichen einfachen Aktionen, darum folgende Empfehlung die öffnenden Klammer direkt nach der Bedingung von Schleifen, if...then...else...-Steuerpaaren usw. zu setzen mit der schließenden Klammer vor der nächsten Bedingung. Dieser Stil wird auch in der Kernelentwicklung angewandt und ist sehr gebräuchlich.
if(( hp = gethostbyname( host )) != NULL ) {
	memmove( &taddr->sin_addr, hp->h_addr_list[0], sizeof( taddr->sin_addr ));
	taddr->sin_port = 0;
	taddr->sin_family = AF_INET;
} else if ( inet_aton( host, &taddr->sin_addr ) == 0 ) {
	return -1;
}
  • Das Gegenstück dazu ist, jede Klammer separat in eine Zeile zu setzen was zwar nicht platz sparend ist, aber die Lesbarkeit des Quellcodes welcher logisch zusammen gehört, wird dabei erhöht. Der selbe Quellcode würde dann so aussehen.
if(( hp = gethostbyname( host )) != NULL )
{
	memmove( &taddr->sin_addr, hp->h_addr_list[0], sizeof( taddr->sin_addr ));
	taddr->sin_port = 0;
	taddr->sin_family = AF_INET;
}
else if( inet_aton( host, &taddr->sin_addr ) == 0 )
{
	return -1;
}
  • Letztendlich gilt aber auch hier: Benutzt den Stil den Ihr in der Datei vorfindet!
  • Die Einrückungstiefe (Tabulator) sollte aus vier Zeichen bestehen. Acht Zeichen sind allerdings auch o.k. Innerhalb einer Datei sollte aber immer die selbe Einrückungstiefe benutzt werden.
  • Hier ist zu beachten das je nach verwendeten Editor und dessen Einstellungen unterschiedliche Effekte auftreten können. Die meisten Editoren bieten an eine Tabeinrückung mit der entsprechenden Leerzeichenanzahl aufzufüllen . Kontrolliert Eure Einstellung im Editor.
  • Massives oder sogar vollständiges Verändern von Dateien, nur um die obigen Punkte zu erreichen (z.B. durch Tools wie astyle), sind daher grundsätzlich zu vermeiden! Dadurch geht die komplette Historie zu dieser Datei zwar nicht verloren, wird aber stark beeinträchtigt, so dass z.B. Blame-Tools unter Umständen wenig oder keine brauchbaren Daten liefern könnten. Die Historie ist aber bei der Einkreisung von Programmierfehlern teilweise sehr hilfreich! Es sollten daher nur die Stellen vereinzelt nebenher verändert werden, an denen man gerade Veränderungen durchführen will.

Kommentare

Kommentare sind wichtige Bestandteile des Quellcodes! Nutzt diese Möglichkeit der Informationsweitergabe.

Gemessen an vielen C++ Projekten wie sie zB. auf Openhub (früher Ohloh) analysiert werden, sind durchschnittlich 22% aller Quellcode-Zeilen Kommentare. Für Neutrino-HD liegt dieser Wert nur bei 12% und hat damit eine der niedrigsten Quoten, die offiziell bestätigt sind.

Eine hohe Anzahl von Kommentaren könnte darauf hindeuten, dass der Code gut dokumentiert und organisiert ist, und könnte ein Zeichen für teamfähige Mitglieder, ein hilfreiches und diszipliniertes Entwicklungsteam sein.

Leider sind Kommentare in Neutrino und Neutrino-HD aktuell in der Tat sehr spärlich im Code. Es muss nicht jede Subroutine erklärt werden, aber ein Kommentar zu einer Funktion, der Funktionsweise und deren Rückgabewerte sollte aber selbstverständlich sein.

  • In internationalen Projekten sind Kommentare in Landessprache des Entwickler verpönt! Üblich und eine von jeden Programmierer verstandene Sprache ist Englisch, also bitte alle Kommentare in Englisch verfassen.
  • Kommentare über mehr wie eine Zeile sollten mit /* ... */ eingefasst und einzeilige Kommentare können mit // begonnen werden, üblich ist aber auch wieder die Einfassung mit /* ... */. Kommentare sollten entweder der einzige Inhalt einer Zeile sein oder am Ende einer Codezeile stehen aber niemals mitten im Code (was theoretisch auch geht).
/*
 * draw_line
 * 
 * args:
 * x1    StartCol
 * y1    StartRow
 * x2    EndCol
 * y1    EndRow
 * state LCD_PIXEL_OFF/LCD_PIXEL_ON/LCD_PIXEL_INV
 * 
 */

oder

if ((fd = open(LCD_DEVICE, O_RDWR)) < 0) {
	perror("LCD (" LCD_DEVICE ")"); //giving out an error message
...

folgendes ist auch gebräuchlich

if ((fd = open(LCD_DEVICE, O_RDWR)) < 0) {
	perror("LCD (" LCD_DEVICE ")"); /* giving out an error message */
...

Debugausgaben

Ausgabe von Debugmeldungen sind ein wichtiges Hilfsmittel bei der Entwicklung. Für den normalen Betrieb sind diese Debugausgaben jedoch auf die wichtigsten Meldungen zu minimieren. Gerade hier kann Neutrino-HD noch deutlich verbessert werden. Einfache printf Ausgaben sind für die eigene Entwicklung o.k. sollten aber nicht in ein Versionsverwaltungssystem eingecheckt werden.

Weblinks