Inhaltsverzeichnis
Stilrichtlinie
engl. coding style guide
Wo Inhalt ist, fügen sich die Formen von selbst.— Leo Tolstoi, Tagebücher, 1896
Meine Festlegungen für die Gestaltung von C++-Quelltexten. Die hier empfohlenen Schreibweisen haben sich für mich als günstig erwiesen. Merke: Richtlinien sind Empfehlungen, kein Dogma. In begründeten Fällen weiche ich vom Standardschema ab. Einige andere Richtlinien zum Vergleich:
- ISO C++ Core Guidelines. https://github.com/isocpp/CppCoreGuidelines
- Google C++ Style Guide. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
- David Straker: C Style. Prentice Hall (1991). http://syque.com/cstyle/index.htm
Dateiorganisation
Quelltext-Dateinamen enden auf *.cpp, Vorspanndateien (Header) auf *.h. Header erhalten eine Include-Wächter, der sich auf den Namen des Headers bezieht:
//: demo.h : ... Dateikopf-Kommentar #ifndef DEMO_H #define DEMO_H // ... Abhängigkeiten #include <...> // ... Inhalte hier #endif // DEMO_H
Jede Datei, auch Header, bezieht die genutzten Definitionen als #include
-Anweisung mit ein.
Ausnahme: Zirkelbezüge sind durch Forward-Deklaration aufzulösen.
Kommentare
Quellcode sollte soweit wie möglich selbstdokumentierend sein, u.a. durch gut gewählte, "sprechende" Namen für Typen, Funktionen, Variablen und Konstanten. Wiederhole nicht im Kommentar, was schon im Quelltext gesagt ist. Stimmen Quelltext und Kommentar nicht überein, ist vermutlich beides falsch. Erläutere statt dessen, warum der Quelltext so geschrieben wurde:
for (int t = 3; t <= sqrt(double(n))+0.5; t += 2) // in n==t*y ist t<sqrt(n)<y oder n == t*t { if (n%t == 0) return false; }
Auch Hinweise auf Literatur können angegeben werden:
void farey_series(int n) { // Lit.: D.E.Knuth: DAOCP Vol. 1, Faszikel 1.3', "MMIX", (2002), p. 47. ... }
Block-Kommentare /**/
werden nur selten genutzt, vorwiegend zum Deaktivieren kurzer Codesequenzen während der Entwicklungsphase:
//* // Ein Schrägstrich weg bzw. hinzu schaltet den ganzen Block aus / an. ... //*/
Namenskonventionen
Zwiespalt: Deutsche und englische Namen (Schlüsselwörter) im Gemisch wirken komisch.1) Aber: Nutze die Fremdsprache Englisch nur, wenn Du Dir völlig sicher bist — "false friends" sind peinlich. Nutze ein Wörterbuch, frage einen native speaker.
Klassen und Strukturen
Namen von Klassen und Strukturen beginnen mit Großbuchstaben. Der Rest ist klein geschrieben, bei zusammengesetzten Namen UpperCamelCasing.
class Commander { // ... private: int data_; };
Namen nicht öffentlicher Attribute enden mit einem Unterstrich. Weitere Regeln siehe Variablen.
Methoden und Funktionen
Funktionsnamen werden mit Kleinbuchstaben geschrieben, bei zusammengesetzten Namen camelCasing:
bool istPrimzahl(int n);
Entscheidungsfragen sollten mit is…()
, has…()
o.ä. beginnen.
"get"- und "set"-Methoden tragen keine Vorsilbe. Aus dem Aufruf überladener Methoden wird deutlich, was gemeint ist:
int n = std::cout.precision(); // "getter" std::cout.precision(n); // "setter"
Parameternamen sollten "sprechend" sein, weiteres siehe Variablen.
Variablen und Konstanten
Für Variablen werden Kleinbuchstaben verwendet, bei zusammengesetzten Namen camelCasing. Konstanten werden mit Großbuchstaben geschrieben, bei zusammengesetzten Namen mit Unterstrichen. Vermeide Unterstriche am Anfang.
int const MAX = 10; int stauBecken = 1, staubEcken = 4 * stauBecken;
Bei fast gleichen Namen besteht Verwechslungsgefahr, also, wenn möglich, große Sprachdistanz wählen:
staubEcken = 4 * talsperren;
Sprechende Namen werden bevorzugt, aber für lokale Variablen wie Schleifenzaehler sind kurze Namen zu wählen, eine Art "schwäbische" oder eher "schottische" (?) Notation, z.B.
c | Buchstabe (char) |
d | Dezimalbruch (double) |
i | Index (int) |
n | natürliche Zahl (number, int) |
u | vorzeichenlose Zahl (unsigned int) |
p | Zeiger (Pointer) |
s | Zeichenkette (string) |
int sum = 0; for (int n = 1; n < MAX_ANZAHL; ++n) { sum += n; }
ist besser lesbar als
int summeAllerZahlen = 0; for (int natuerlicheZahl = 1; natuerlicheZahl < MAX_ANZAHL; ++natuerlicheZahl) { summeAllerZahlen += natuerlicheZahl; }
Der alleinstehende Kleinbuchstabe l
wird wegen seiner Ähnlichkeit zur Ziffer 1
vermieden, sofern es nicht der direkten Umsetzung mathematischer Formeln wie
$\sigma_{ij} = C_{ijkl} \cdot \varepsilon_{kl}$ dient.
Formatierung
Geschweifte Klammerpaare stehen übereinander, Abschnitte innerhalb des Klammerpaars werden eine Ebene eingerückt (Allman style). Nach meiner Erfahrung sind für Anfänger Blöcke und zusammengehörende Klammern so einfacher erkennbar.
Bevorzugte Editor-Einstellung: Einrückungen erfolgen um zwei Leerzeichen, Tabs werden als Leerzeichen abgespeichert.
class Allman { public: int f(int n) { int sum = 0; for (int i = 0; i <= n; ++i) { sum += i; } return sum; } };
Bei fußgesteuerten Schleifen steht der Kontrollausdruck hinter der schließenden Klammer, nicht darunter:
do { something(); } while (!finished());
Auch Einzelanweisungen von Schleifen und Entscheidungen sind im Klammerblock zu schreiben. Ausnahme: tabellarische Fallunterscheidung.
int istPrimzahl(int n) { if (n < 2) return false; if (n == 2) return true; if (n%2 == 0) return false; // ... }
Leerzeichen dienen der optischen Gliederung innerhalb der Zeile, z.B. vor / nach Operatoren, nach Komma und Semikolon, vor Schleifen- und Entscheidungsbedingungen.
ClangFormat
Vergeude deine kostbare Zeit nicht mit dem "Verschönern" des Quelltextes. Dafür gibt es Werkzeuge.
Mit ClangFormat
werden auch Diskussionen und "Kriege" über die "richtige" Formatierung von Quelltext hinfällig.
Die eigene Gestaltungsrichtlinie online erstellen
und als .clang-format
-Konfigurationsdatei im YAML-Format ablegen:
--- Language: Cpp AlignConsecutiveAssignments: 'true' AlignConsecutiveDeclarations: 'true' AllowShortCaseLabelsOnASingleLine: 'true' AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: 'true' AllowShortLoopsOnASingleLine: 'true' AlwaysBreakTemplateDeclarations: 'true' BreakBeforeBraces: Allman BreakConstructorInitializersBeforeComma: 'true' ConstructorInitializerIndentWidth: 2 SpaceBeforeParens: ControlStatements UseTab: Never ...
Das Werkzeug lässt sich als Kommando ausführen (Beispiel für Windows):
c:\llvm\bin\clang-format -i -style=file MeinQuelltext.cpp
oder im Editor einbinden (Beispiel Notepad++ Menü Run|Run):
c:\llvm\bin\clang-format -i -style=file "$(FULL_CURRENT_PATH)"