Programmierkurs: Delphi: Programmierstil
Der (richtige) Programmierstil
BearbeitenWie schon am Anfang des Buches beschrieben, unterscheidet Pascal nicht zwischen Groß- und Kleinschreibung. Ebenso ist es dem Compiler egal, wie viele Leerzeichen oder Tabulatoren man zwischen die einzelnen Schlüsselwörter, Rechenzeichen oder Ähnliches setzt, genauso wie man ein Programm auch komplett in einer Zeile unterbringen könnte.
Der Programmtext sollte jedoch sauber strukturiert sein und man sollte sich dabei an einige Regeln halten. Dies dient dazu, den Code später einfacher warten zu können. Falls man im Team arbeitet ist so auch sichergestellt, dass sich andere im Code schneller zurecht finden.
Hierfür haben sich einige Regeln eingebürgert, die nach Möglichkeit von jedem angewandt werden sollten.
Allgemeine Regeln
BearbeitenEinrückung
BearbeitenUm bestimmte Zusammenhänge, wie zum Beispiel Anweisungsblöcke, im Quelltext kenntlich zu machen, rückt man die Zeilen ein. Dabei sollten keine Tabulatoren sondern Leerzeichen verwendet werden, damit der Text auf jedem Rechner gleich aussieht. Standard sind 2 Leerzeichen je Ebene.
Seitenrand
BearbeitenGelegentlich wird man auch mal einen Programmtext ausdrucken wollen. Hierfür ist der rechte Seitenrand auf 80 einzustellen. Erkennbar ist dies über eine durchgezogene Linie im Editor. Wenn möglich, sollte diese Linie nicht überschrieben werden.
Kommentare
BearbeitenFür Kommentare sollte man hauptsächlich die geschweiften Klammern { }
verwenden. Den anderen Kommentarblock (* *)
sollte man nur verwenden, um Programmabschnitte vorübergehend aus dem Programm auszuschließen (auszukommentieren). Kommentare mittels //
bitte ausschließlich für einzeilige Kommentare verwenden.
Compilerdirektiven
BearbeitenDirektiven werden immer in geschweifte Klammern gesetzt, wobei die Compileranweisung in Großbuchstaben geschrieben wird. Beim Einrücken gelten die gleichen Regeln wie oben.
Anweisungsblöcke
BearbeitenBei Anweisungsblöcken zwischen begin
und end
stehen diese beiden Schlüsselwörter jeweils auf einer eigenen Zeile. Anweisungen wie if ... then begin
oder while ... do begin
sollten vermieden werden. begin
und end
stehen immer auf der gleichen Ebene wie die zugehörige If- oder Schleifenabfrage:
if ... then begin ... end;
Klammern
BearbeitenNach einer geöffneten Klammer und vor der geschlossenen Klammer stehen keine Leerzeichen. Bei Klammern zur Parameterübergabe an Funktionen, Prozeduren und Methoden kein Leerzeichen zwischen dem Namen und der geöffneten Klammer verwenden. Dies gilt auch für die eckigen Klammer zur Angabe eines Index. Klammern nur angeben, wenn diese auch notwendig sind!
Writeln ( txt ); // falsch Writeln (txt); // falsch Writeln( txt ); // falsch Writeln(txt); // die einzig richtige Variante x := a * ( b + c ); // falsch x := a * (b + c); // richtig x := (a * b); // falsch, unnötige Klammer x := a * b; // richtig i[1] := x; // richtig
Interpunktion
BearbeitenSemikola sowie der Punkt hinter dem letzten end
stehen ohne Leerzeichen direkt hinter dem letzten Zeichen der Anweisung. Sie schließen die Zeile ab, danach folgt ein Zeilenumbruch, sprich: jede Anweisung steht auf einer eigenen Zeile. Ausnahme: Direktiven hinter der Deklaration von Funktionen.
Writeln('Zeilenende hinter Semikolon!'); Writeln('Nächste Anweisung.');
aber:
function Stellenanzahl(Zahl: Integer): Integer; forward; procedure HilfeAusgeben; overload; procedure HilfeAusgeben(Text: string); overload;
Vor Kommata zur Trennung von Parametern oder in anderen Auflistungen steht kein Leerzeichen, aber dahinter. Dasselbe gilt für Doppelpunkte bei der Deklaration von Variablen oder Parametern.
var x: Integer; a: array[0..2, 0..2] of Byte; { ... } x := Pos(chr, zeichenkette); a[0, 1] := 32;
Rechenoperatoren werden immer von Leerzeichen umschlossen.
Operatoren
BearbeitenMit Ausnahme der unären Operatoren @
und ^
stehen vor und nach Operatoren immer Leerzeichen. Hierzu zählt auch der Zuweisungsoperator :=
.
z := x+y; // falsch z := x + y; // richtig a := @Funktion; // richtig p := Zeiger^; // richtig
Reservierte Wörter
BearbeitenDiese Wörter gehören fest zum Sprachumfang von Pascal/Delphi. Sie werden unter neueren Delphi-Versionen standardmäßig dunkelblau und fett hervorgehoben, unter Lazarus und älteren Delphi-Versionen schwarz und fett. Diese Wörter werden immer kleingeschrieben.
Beispiele:
program const
aber auch:
string
Routinen und Methoden
BearbeitenNamensvergabe
BearbeitenNamen von Prozeduren und Funktionen (=Routinen) sowie Methoden sollten immer großgeschrieben sein. Falls sich der Name aus mehreren Wörtern zusammensetzt, beginnt jedes neue Wort ebenso mit einem Großbuchstaben. Der Name sollte so sinnvoll gewählt sein, dass man daraus bereits die Aufgabe der Routine ableiten kann. Um dies zu erreichen, empfiehlt es sich, ein entsprechendes Verb im Namen unterzubringen. Bei Routinen, die Werte von Variablen ändern, wird das Wort Set (oder deutsch Setze) davorgeschrieben. Bei Routinen, die Werte auslesen, steht das Wort Get bzw. Hole davor.
procedure Hilfe; // falsch, Aufgabe nicht ganz eindeutig procedure HilfeAnzeigen; // richtig procedure ausgabedateispeichernundschliessen; // falsch, nur Kleinbuchstaben procedure AusgabedateiSpeichernUndSchliessen; // richtig procedure SetzeTextfarbe; function HolePersonalnr: Integer;
Parameter
BearbeitenDie Bezeichnung von Parametern sollte ebenfalls so gewählt werden, dass man auf den ersten Blick den Zweck erkennen kann. Der Name wird auch groß geschrieben. Nach Möglichkeit sollte ihm ein großes A vorangestellt werden, um einen Parameter von Variablen und Klasseneigenschaften unterscheiden zu können.
Bei der Reihenfolge sollten die allgemeineren Parameter weiter links stehen, die spezielleren rechts, z.B. Ort, Straße, Hausnummer. Zusammengehörige Parameter sollten dabei nebeneinander stehen. Genauso sollten, wenn möglich, Parameter gleichen Typs zusammengefasst werden:
procedure ZeichnePunkt(R, F: Integer; L: TColor); // falsch, Zweck der Parameter nicht erkennbar procedure ZeichnePunkt(Y: Integer; AFarbe: TColor; X: Integer); // falsch, unsinnige Reihenfolge procedure ZeichnePunkt(X, Y: Integer; AFarbe: TColor); // richtig
Parameter vom Typ Record, Array oder ShortString sollten als konstante Parameter deklariert werden, falls deren Wert in der Routine nicht geändert wird. Dies erhöht die Geschwindigkeit des Programms, da der Inhalt der Parameter nicht lokal kopiert wird. Bei anderen Parametertypen ist dies ebenfalls möglich, bringt aber keinen Geschwindigkeitsvorteil.
Variablen
BearbeitenVariablen sollte ein Name gegeben werden, der ihren Zweck erkenntlich macht. Sie sollten ebenfalls grundsätzlich großgeschrieben werden. Bei Zählern und Indizes besteht der Name meist nur aus einem Buchstaben: z.B. I, J, K. Boolische Variablen sollten einen Namen haben, bei dem die Bedeutung der Werte True und False sofort klar ist.
var Wort: Boolean; // falsch, Bedeutung von True und False nicht zu erkennen WortGeaendert: Boolean; // richtig
Variablen werden jede auf einer eigenen Zeile deklariert (wie im Beispiel oben). Es sollten nicht mehrere Variablen gleichen Typs zusammengefasst werden.
Sie sollten es dringend vermeiden, globale Variablen zu benutzen. Falls Sie Variablen global benutzen müssen, dann schränken Sie dies so weit wie möglich ein. Deklarieren Sie z.B. eine solche Variable im Implementation-Teil einer Unit und nicht im Interface-Teil.
Typen
BearbeitenTypen sollten so geschrieben werden, wie sie deklariert wurden. string
ist z.B. ein reserviertes Wort und wird demnach auch als Typ klein geschrieben. Viele Typen aus der Windows-Schnittstelle sind vollständig in Großbuchstaben deklariert und sollten dann auch dementsprechend verwendet werden, z.B. HWND oder WPARAM. Andere von Delphi mitgelieferte Typen beginnen mit einem Großbuchstaben, z.B. Integer oder Char.
Typen, die Sie selbst anlegen, stellen Sie bitte ein großes T voran, bei Zeigertypen ein großes P. Ansonsten gilt die gleiche Schreibweise wie bei Variablen. Auch hier achten Sie bitte darauf, dass der Typ einen zweckmäßigen Namen erhält.
Gleitkommazahlen
BearbeitenBenutzen Sie bitte hauptsächlich den Typ Double, hierfür sind alle Prozessoren ausgelegt. Real existiert nur noch um mit älteren Programmen kompatibel zu sein, in Delphi ist Real derzeit gleichbedeutend mit Double. Single sollten Sie nur verwenden, wenn Ihnen der Speicherbedarf der entsprechenden Variable wichtig ist. Extended ist ein Sonderformat von Intel und könnte beim Datenaustausch zwischen verschiedenen Rechnern zu Problemen führen. Sie sollten Extended daher nur verwenden, wenn Sie auf die erweiterte Genauigkeit angewiesen sind und Werte dieses Typs möglichst nicht in Dateien speichern, die für einen Datenaustausch verwendet werden.
Aufzählungen
BearbeitenGeben Sie bitte Aufzählungen einen Namen, der dem Zweck des Typs entspricht. Die Bezeichner der Positionen benennen Sie so, dass die ersten zwei oder drei Buchstaben (kleingeschrieben) den Typ der Aufzählung wiedergeben:
TMitarbeiterArt = (maAngestellter, maLeitenderAngestellter, maVorstand);
Eine Variable vom Typ Aufzählung wird genau wie der Typ benannt, lediglich das führende T lässt man weg. Benötigt man mehrere Variablen eines Typs, kann man diese entweder durchnummerieren oder erweitert den Namen um einen passenden Begriff.
Varianten
BearbeitenVerwenden Sie Varianten so sparsam wie möglich. Varianten sind nicht die bevorzugte Art, Daten unbekannten Typs zu konvertieren. Benutzen Sie stattdessen Zeiger und Typumwandlungen. Bei COM- und Datenbankapplikationen werden Sie vermutlich nicht umhin kommen, Varianten zu verwenden. Sie sollten in diesem Falle den Typ OleVariant nur bei COM-Anwendungen (z.B. ActiveX-Komponenten) verwenden und ansonsten den Typ Variant.
Arrays und Records
BearbeitenWie auch schon zuvor, sollte auch der Name von Arrays und Records sinnvoll zu deren Verwendungszweck vergeben werden. Auch vor diese Typbezeichner wird ein T gesetzt (bzw. P bei Zeigern). Ähnlich wie bei Aufzählungen, sollten Sie auch bei Variablen eines Array- bzw. Record-Typs den gleichen Namen nur ohne führendes T verwenden, falls möglich.
Anweisungen
BearbeitenIf-Anweisungen
BearbeitenBei Verzweigungen mit if sollten die wahrscheinlichsten Anweisungen nach dem then stehen, die seltender eintretenden Bedingungen nach dem else.
Wenn irgend möglich, sollten Sie vermeiden, mehrere If-Abfragen nacheinander zu schreiben. Verwenden Sie statt dessen die Verzweigung mittels case. Ebenso vermeiden Sie es bitte, If-Abfragen in mehr als fünf Ebenen zu verschachteln. Klammern bitte nur verwenden, wenn diese auch benötigt werden!
In Delphi gibt es die Möglichkeit, Bedingungsabfragen bereits nach der ersten falschen Bedingung abbrechen zu lassen. Dies spart in der Ausführung der Anwendung etwas an Zeit. Um diesen Zeitvorteil weiter auszubauen, sollte man die Abfragen sortieren. Dabei kann man von links nach rechts die Abfragen tätigen, die am wahrscheinlichsten auf "false" lauten werden. Eine weitere Möglichkeit ist, die am schnellsten zu berechnenden Bedingungen am weitesten nach links zu stellen.
Für gewöhnlich stehen die Bedingungen nebeneinander. Sollten dies zu viele werden, können sie auch untereinander geschrieben werden. Dabei sind sie linksbündig zu formatieren:
if Bedingung1 and Bedingung2 and Bedingung3 then ... if Bedingung1 and Bedingung2 and Bedingung3 then ...
Wenn sich die auszuführende Anweisung nach dem then oder else über mehrere Zeilen erstreckt (zum Beispiel, weil sie am Zeilenende umgebrochen werden muss, oder weil Kommentare vorangesetzt werden), bitte alles zwischen begin
und end
einfassen:
{ Falsch } if x = 1 then // Hier passiert was Writeln(x); { Richtig } if x = 1 then begin // Hier passiert was Writeln(x); end; { Falsch } if x = 1 then Writeln('Dies ist ein sehr langer Text, der ' + 'am Zeilenende umgebrochen wurde, ' + 'damit er auf Ausdrucken immer noch ' + 'lesbar erscheint.'); { Richtig } if x = 1 then begin Writeln('Dies ist ein sehr langer Text, der ' + 'am Zeilenende umgebrochen wurde, ' + 'damit er auf Ausdrucken immer noch ' + 'lesbar erscheint.'); end;
Das Schlüsselwort else sollte immer den gleichen Einzug erhalten wie if.
Case-Anweisungen
BearbeitenDie einzelnen Unterscheidungsmöglichkeiten einer Case-Verzweigung sollten numerisch, alphabetisch oder (bei anderen Aufzählungstypen) in der Reihenfolge ihrer Deklaration abgefragt werden.
Die Anweisungen, die den Abfragen folgen, sollten möglichst kurz und einfach gehalten werden, da der Programmtext sonst schnell unübersichtlich wird. Empfehlenswert sind vier bis fünf Zeilen, diese sollten immer zwischen begin
und end
stehen (auch bei einzelnen Zeilen). Größere Anweisungsfolgen am besten in eigene Routinen auslagern.
Den Else-Abschnitt sollten Sie nur verwenden, wenn Sie ein gültiges Default-Verhalten festlegen können.
Alle Abschnitte einer Case-Verzweigung sollen eingerückt werden. Das else steht auf der gleichen Höhe wie das case. Bei größeren Case-Blöcken, die einen Else-Abschnitt enthalten, sollte man das else zum besseren Überblick mit einem Kommentar versehen, um es eindeutig dem Case-Abschnitt zuzuordnen.
case Wert of Bedingung: begin ... end; else { case } ... end;
While-, For- und Repeat-Schleifen
BearbeitenWenn Sie eine Schleife verlassen wollen, vermeiden Sie bitte die Anweisung Exit. Schleifen sollten immer über die Prüfbedingung beendet werden. Alle Variablen, die Sie innerhalb einer Schleife verwenden, sollten Sie direkt davor initialisieren und (wenn nötig) direkt anschließend wieder bereinigen. So stellt man sicher, dass man nichts vergisst.
With-Anweisungen
BearbeitenWith-Anweisungen sollten Sie nur sehr selten einsetzen, wenn Sie zum Beispiel mit einem sehr umfangreichen Record arbeiten. Ansonsten verwenden Sie bitte die Form Variable.Element
in Ihrem Programm. Obwohl es möglich ist, verwenden Sie bitte nie mehrere Records in einer With-Anweisung, wie z.B. with Record1, Record2 do
Fehlerbehandlung
BearbeitenVerwenden Sie die Funktion der Fehlerbehandlung so sparsam wie möglich. Prüfen Sie stattdessen die benötigten Daten vor der Verwendung auf Korrektheit.
Die Fehlerbehandlung sollte immer dann eingesetzt werden, wenn Speicherbereiche zugewiesen werden, um diese nach dem Auftreten einer Exception sauber wieder freizugeben.
Zur Fehlerbehandlung verwendet man gewöhnlich try...finally
. Bei Speicherzuweisungen sollte man recht großzügig mit der Anzahl der Blöcke sein und nach jeder Zuweisung einen neuen Block beginnen.
Klasse1 := TKlasse1.Create; Klasse2 := TKlasse2.Create; try { ... } finally Klasse1.Free; Klasse2.Free; end;
besser:
Klasse1 := TKlasse1.Create; try Klasse2 := TKlasse2.Create; try { ... } finally Klasse2.Free; end; finally Klasse1.Free; end;
Da try...finally
den Fehler nicht abschließend behandelt sondern erneut auslöst, sollte man diesen Block in try...except
verschachteln oder ausschließlich diese Art der Fehlerbehandlung verwenden.
Klassen
BearbeitenDer Name einer Klasse beginnt immer mit einem T, da es sich hierbei um einen Typ handelt. Der Rest des Namens sollte dem Zweck der Klasse entsprechen. Bei mehreren Wörtern im Namen beginnt jedes Wort mit einem Großbuchstaben. Die dazugehörige Variable trägt den gleichen Namen wie die Klasse, nur ohne führendes T. Falls Sie weitere Variablen einer Klasse benötigen, können Sie diese nummerieren oder Sie verwenden weitere zusätzliche Begriffe im Namen der Variablen.
Felder
BearbeitenFelder werden wie Variablen benannt, sollten jedoch mit einem F beginnen. Damit sind sie eindeutig von anderen Variablen zu unterscheiden. Weiterhin sollten Felder immer als private deklariert werden. Falls Sie die Daten von außerhalb der Klasse ändern möchten, erstellen Sie eine Methode oder Eigenschaft für diesen Zweck.
Ebenso wie Variablen sollten Felder jedes auf seiner eigenen Zeile deklariert werden. Bitte keine Felder gleichen Typs zusammenfassen.
Methoden
BearbeitenMethoden benennen Sie wie Prozeduren und Funktionen.
Deklarieren Sie eine Methode als static, wenn diese in Nachkommenklassen nicht überschrieben werden sollen. Im Gegensatz dazu deklarieren Sie eine Methode als virtual, wenn sie ausdrücklich überschrieben werden soll. Verwenden Sie hierfür nicht dynamic! Deklarieren Sie eine Methode nur in Basisklassen als abstract, die niemals direkt verwendet werden.
Methoden zum Zugriff auf Eigenschaften werden immer als private oder protected deklariert. Die Methoden zum Lesen der Eigenschaften beginnen mit Get (bzw. deutsch Hole), die Methoden zum Schreiben der Eigenschaft mit Set (bzw. Setze). Der Parameter der Methode zum Schreiben des Wertes heißt Value.
Eigenschaften
BearbeitenEigenschaften, die auf private Felder zugreifen, werden wie das Feld benannt, nur ohne führendes F. Verwenden Sie für den Namen bitte nur Substantive, keine Verben. Eigenschaften mit Index sollten dabei in der Mehrzahl stehen, sonst Einzahl:
property Farbe: TColor read FFarbe write FFarbe; property Adressen[1..10]: TAdresse read HoleAdresse write SetzeAdresse;
Eigenschaften, die im Objektinspektor von Delphi angezeigt werden sollen, deklarieren Sie als published, sonst als public.
Quelle: frei nach „Delphi 4 Developer's Guide Coding Standards Document“
Inhaltsverzeichnis |