Unterabschnitte

Programmierstil

Allgemeines

Ein einheitlicher Programmierstil erhöht die Lesbarkeit von Programmen und fördert damit die Transparenz und die Wiederverwendbarkeit von Modulen. Aus diesem Grund werden für libCUI Programme ein paar Hinweise gegeben, wie der Quelltext strukturiert sein sollte.

Diese Hinweise sind weder vollständig noch erheben sie den Anspruch darauf, der Weisheit letzter Schluss zu sein. Vielmehr ist einiges davon Geschmacksache und es bleibt dem Programmierer überlassen, ob er sich daran hält oder nicht.

In dem Augenblick allerdings, in dem Code zur Bibliothek hinzugefügt werden soll (die Mithilfe daran ist jederzeit sehr willkommen), sind diese Hinweise als Richtlinien zu verstehen auf deren Einhaltung bestanden wird. Denn, um die Pflege der hinzugefügten Komponenten zu gewährleisten, ist es erforderlich, dass der Code nicht nur für den ursprünglichen Autor verständlich ist.

Im übrigen ist diese Aufzählung keineswegs vollständig. Falls jemand weiter Hinweise zur Verbesserung der Code-Qualität liefern kann, werden seine Anmerkungen gerne angenommen und ggf. hier hinzugefügt.

Formatierung

Einrückungen

Einrückungen werden mit dem Tabulatorzeichen und nicht mit Leerzeichen vorgenommen. Der Grund liegt darin, dass viele Editoren und Entwicklungsumgebungen den Programmierer bei der Formatierung des Quelltextes unterstützen (manchmal sogar eine Formatierung erzwingen) und dabei in der Regel immer Tabulator-Zeichen verwenden.

Wird dann an anderer Stelle mit Leerzeichen gearbeitet, dann fällt das Problem auf den ersten Blick nicht auf. In der Ansicht eines anderen Editors (mit anderen Tabulatoreinstellungen) sieht der Quelltext dann aber wie Kraut und Rüben aus, was zu vermeiden ist, indem konsequent mit Tabulatoren gearbeitet wird.

Programmblöcke

Programmblöcke werden in geschweifte Klammern eingeschlossen, wobei die Schreibweise bevorzugt wird, bei der die Klammern übereinander stehen. Also:

   if (MyFlag == TRUE)
   {
      /* do something */
   }
   else
   {
      /* do something else */
   }

an Stelle von:

   if (MyFlag == TRUE) {
      /* do something */
   }
   else {
      /* do something else */
   }

Ausdrücke

In Ausdrücken werden Operatoren, Zahlen und Variablen durch Leerzeichen voneinander getrennt. Das macht den Quelltext auch in Editoren lesbar, die nicht über Syntax- Hervorhebung verfügen. Also:

   result = 3 * (x / 4);

an Stelle von:

   result = 3*(x/4);

Funktionsnamen

Funktionsnamen werden innerhalb der libCUI in Pascal-Case angegeben. Dabei werden semantische Einheiten des Namens durch Großbuchstaben hervorgerufen. Sie enthalten keine Unterstriche.

Beispiele: ''WindowClose'' oder ''EditNew''.

Zudem wird dem Namen der Name des Moduls in dem die Funktion implementiert wurde vorangestellt. Die Funktion ''EditNew'' findet sich beispielsweise im Programmmodul (Source-Datei) ''edit.c'' wider. Bei sehr langen Modulnamen kann das natürlich entsprechend gekürzt werden.

Funktionen, die nicht an andere Module exportiert werden (lokale Funktionen des Moduls) werden mit dem Schlüsselwort ''static'' versehen. Das vermeidet Namenskonflikte, erhöht die Kapselung der Funktion in einem Modul. Zudem kann schon der Compiler auf nicht verwendeten Code hinweisen.

Variablen

Globale Variablen werden in Großbuchstaben geschrieben, wobei ebenfalls die Pascal-Case Notation zum Einsatz kommt. Dabei werden semantische Einheiten des Namens durch Großbuchstaben hervorgerufen. Auch sie enthalten keine Unterstriche.

Lokale Variablen und Funktionsparameter dagegen werden in Kleinbuchstaben geschrieben. Optional kann hier der Unterstrich zur Hervorhebung der Lesbarkeit verwendet werden.

Globale Variablen, die nur innerhalb des Moduls sichtbar sind (Regelfall), erhalten zudem das Schlüsselwort ''static''.

Beispiel:

static int MyFlag;

void SwitchItOn(int flag_state)
{
   MyFlag = flag_state;
}

Struktur eines Moduls

Jede Fensterklasse sollte in einer eigenen Source-Datei implementiert werden. Damit erhält man ein Modul pro Fensterklasse.

Innerhalb des Moduls ergibt sich dann der folgende Aufbau:

1. Einbindung von Header-Dateien und Definitionen 2. Typdefinition der Instanzdaten 3. Prototypen lokaler Funktionen 4. Globale Variablen 5. Hook-Funktionen 6. Funktion zum Anlegen der Fensterklasse 7. Zugriffsfunktionen auf die Fensterinstanz 8. Lokale Hilfsfunktionen

Bei Dialogen und anderen Fenstern, die Daten mit anderen Modulen austauschen müssen, kann (und muss) die Typdefinietion der Instanzdaten in der Header-Datei des Moduls erfolgen.

Holger Bruenjes 2016-12-12