Delphi-PRAXiS
Seite 1 von 12  1 2311     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Mein Delphi-Style (https://www.delphipraxis.net/134200-mein-delphi-style.html)

Dipl Phys Ernst Winter 17. Mai 2009 18:41


Mein Delphi-Style
 
Dipl. Physiker Ernst Winter: Mein Stil von Delphi Programmen
Der Compiler unterscheidet nicht zwischen Groß- und Kleinbuchstaben, er überliest eingefügte Leerzeichen, Zeilenumbrüche und Leerzeilen, ihm sind vom Benutzer vergebenen Namen gleichgültig. Das ergibt eine große Variabilität für den richtigen, das heißt compilierbaren Code. Alles was damit zusammenhängt bezeichnen wir als den Stil der Delphi-Programmierung. Es gibt für den Stil keine verbindlichen Regeln, jeder sollte seinen Stil nach seinen eigenen Kriterien entwickeln und ihn nicht unmotiviert ändern.

Für mich kann das einzige Kriterium nur die Lesbarkeit des Programmcodes sein!

Das beginnt bei der Vergabe der Namen für die Bezeichner, Verwendung strukturierter Datentypen und endet mit der optischen Trennung von Code und Kommentaren in einem kompakten Quelltext.
Programmcode ist besser zu verstehen, wenn möglicht viel davon gleichzeitig auf dem Bildschirm zu sehen ist. Die Gurus der Strukturierten Programmierung forderten einmal, dass eine Prozedur vollständig auf den Bildschirm passt. Ich schreibe daher möglichst kompakten Code.

Prinzipielles: Schreibweise der Morpheme (Wörter)
Erster Grundsatz: Im ganzen Programm ist nur eine Schreibweise für jedes Wort zu verwenden. Daraus folgt unmittelbar:
Zweiter Grundsatz: Die Schreibweise der von Delphi vergebenen Wörter ist beizubehalten.
Das betrifft zunächst die durchgängige Kleinschreibung aller Schlüsselwörter. Ich verwende ein Programm DelphiText, um diese beiden Grundsätze abzusichern.
Die Schreibweise der von mir vergebenen Namen ist durch kleingeschriebene Präfixe und InfixCaps gekennzeichnet.

Konventionen zur Namensbildung
Allgemein sind wir uns über die Verwendung von ’selbsterklärenden’ Bezeichnern einig. Das Problem ist nur welche wir erklären müssen.

Namen von Variablen
Naturwissenschaftliche Disziplinen leben wesentlich von ihrer Symbolik. Mathematik, Physik, Chemie und Technik könnten wir ohne symbolische Bezeichnung ihrer Größen kaum verstehen. Dabei haben sich in den einzelnen Disziplinen weitgehend einheitliche Symbole eingebürgert. Mitunter werden zur Klassifizierung der Symbole verschiedene Alphabete verwendet, z.B. in der Mathematik griechische Buchstaben für Winkel, deutsche Buchstaben für Vektoren, fette Buchstaben für Matrizen... Programmiersprachen sind jedoch an ein einziges Alphabet gebunden, an Stelle verschiedener Alphabete können Präfixe verwendet werden.
Die Algorithmen der Programme aus Mathematik, Physik oder Technik entnehmen wir entsprechenden Lehrbüchern oder Monographien. In ihnen stehen Symbole und keine selbsterklärenden Bezeichner!
Wir sollten die dort verwendeten Symbole nicht mit der Forderung nach ’Selbserklärung’ verunstalten, das verwischt nur den Zusammenhang zwischen Algorithmus aus dem Buch und unseren Code.
Ein Beispiel:
Delphi-Quellcode:
for intZaehler:= intAnfangZeile to intEndeZeile do arrBildfeld[intZeile, intZaehler]:=...
bzw. aus der DP:
Delphi-Quellcode:
for iFor:= ...
Welch ein redundanter Schwachsinn! Offenbar an einen geistig Behinderten gerichtet. So etwas habe ich in keinem Mathematikbuch gefunden, selbst wenn es Programme enthält.
Der in der Mathematik übliche Bezeichnungsweise einer Matrix Bik folgend schreibe ich
Delphi-Quellcode:
for i:= ia to ie do
  for k:= ka to ke do B[i, k]:=...
mit Zeilenindex i und Spaltenindex k in den Grenzen ia, ie und ka, ke.
Da ist doch wohl alles erklärt! Der Code wird kompakter, übersichtlicher und besser lesbar.

Für die kurzlebigen Namen lokaler Variable, deren Gültigkeitsbereich eine Prozedur ist, die oft vollständig auf den Bildschirm passt, verwende ich einem oder maximal zwei Buchstaben. Dabei folge ich der aus FORTRAN stammenden Konvention, dass Namen für Integer-Variable mit den Buchstaben i, j, k, l, m oder n anfangen.
Für den Index der Elemente von Vektoren wird vorzugsweise i verwendet, in Matrizen (immer!) i für den Zeilenindex und k für den Spaltenindex. Namen lokaler Stringvariable beginnen mit dem Buchstaben s.
Damit sind typkennzeichnende Präfixe nach der Ungarischen Notation nahezu überflüssig. Ich halte jedoch für vorteilhaft:
is für boolean, da man eine Boolean-Variable als Bedingung verwenden kann.
p Pointer
T Typ, von Borland eingeführt, eine großgeschriebene Ausnahme.

Ich bilde die Namen von Variablen, deren Gültigkeitsbereiches mehrere Prozeduren umfasst, nach dem Prinzip von Adelstiteln: Je länger eine Variable lebt bzw. je größer ihr Gültigkeitsbereich ist, umso länger und 'selbsterklärender' wird im allgemeinen ihr Name.
In Globale Namen verwende ich InfixCaps, wobei ich einfache Variable kleingeschrieben beginne z. B. iMax und xMax (Anfangsbuchstaben nach der FORTRAN Konvention). Großgeschrieben beginnen Namen von Datenstrukturen (Felder, Records, Files).
Globale Namen von Zahlenstrings bilde ich mit angehängten 'Str' aus ihrer Zahlenvariablen: z.B. XStr für die Stringdarstellung des Werts der Variablen x, beispielsweise gebildet mit Str(x:6:2, XStr).

Namen von Komponenten
Die Namen der Komponenten stehen nicht in den Büchern, sie sollten wir selbsterklärend bilden.
Nach dem Vorschlag von Adrian Vogler (in “Komponenten und Delphi“ Tewi-Verlag 1996) bilde ich den Namen mit einem Präfix für den Typ:
btn Button
lbl Label-Komponente, die vom Programm zur Datenausgabe benutzt werden,
edt Edit-Komponente,
me MaskEdit-Komponente,
mn Menü-Item,
pa Panel,
tab Table, dazu mit
src die zugehörige Datasource,
dahinter steht mit InfixCaps ihre Verwendung.
Beispiele:
Buttons; btnOk, btnAbbruch, btnEnde...
Editierfelder: edtName, meDatum, meX, meX0, meYMin,...
Label: lblName, lblDatum, lblX, lblX0, lblYMin,... zur Anzeige von Werten.
Label, die vom Programm nicht verändert werden, behalten die von Delphi gemachten Vorgaben: Label1...

Verwendung von strukturierten Typen
Pascal wurde von N. Wirth entwickelt, um Studenten die Strukturierung von Daten zu lehren. Ein guter Stil nutzt die entsprechenden Möglichkeiten, um zusammenzuhalte was zusammengehört. Beispiele:
1. Komplexe Zahlen nicht in unabhängigen Variablen
Delphi-Quellcode:
pre, pim, zre, zim : extended;
sondern mit einem Typ
Delphi-Quellcode:
[pre]TKomp= record Re, Im: extended end;
P, z: TKomp;[/pre]
2. Die Punkte zur Beschreibung eines Körpers sind nicht in drei voneinander unabhängigen Arrays
Delphi-Quellcode:
X, Y, Z: array[1..nMax] of extended;
zu speichern, sondern mit einem Feld des Typs
Delphi-Quellcode:
TPunkt= Record x, y, z: extended end;
TKoerper= array[1..nMax] of TPunkt;
3. Interpolation mit Splinefunktionen: Die Stützstellen und die Koeffizienten der Approximationsfunktionen nicht in unabhängigen Feldern
Delphi-Quellcode:
X, Y: array[0..nMax] of extended;          // Stützpunkte
A, B, C, D: array[0..nMax-1] of extended;   // Koeffizienten
sondern mit den Typen
Delphi-Quellcode:
TPkt= record x, y: extended end;
TKoeff= record a, b, c, d: extended end;
Stp: array[0..nMax] of TPkt;
Koeff: array[0..nMax-1] of TKoeff;
Kompakter Quelltext
Verwendung von Leerzeichen

Abgesehen vom Einrücken werden Leerzeichen zur Verdeutlichung von Aufzählungen und zum Umranden von Operatoren verwendet.
Ich setze ein Leerzeichen nach jedem Komma und Semikolon.
Bei der Umrandung von OPeratoren beachte ich die Gleichwertigkeit der beiden Seiten links und rechts des Operators:
Kann man sie (ohne Syntaxfehler) nicht vertauschen, so betone ich das, indem ich nur ein Leerzeichen hinter dem Operator setze:
Delphi-Quellcode:
  const
     eps= 1e-8;
  typ
     TArr3= array[1..3] of extended;
  var
     i, k: integer;
  begin
     k:= kMax;
Bei Vergleichen und arithmetischen Operatoren betone ich die Gleichheit der Seiten, indem ich kein oder gegebenenfalls ein Leerzeichen vor und nach dem Operator setze.
In arithmetischen Ausdrücken hebe ich die Termstruktur hervor, indem ich ’+’ und ’–’ mit Leerzeichen umrande (Ausnahme: Indexausdrücke), aber nicht ’*’ und ’/’..
Delphi-Quellcode:
  y:= a[3]*Power(x, 3) + a[2]*x*x + a[1]*x + a[0];
Verwendung von Leerzeilen und Zeilenumbrüchen
Ich verwende Leerzeilen nur zur Trennung der Unitabschnitte und der Prozeduren im Implementationsabschnitt. (Da ist einiges von den Delphivorgaben zu löschen).
Kompakter Code trennt eine Anweisung nur, wenn sie nicht auf eine Zeile passt. Wieso sollte sie sich besser lesen lassen, wenn ich sie auf mehrere Zeilen verteile? Die Trennung erfolgt immer vor oder hinter einem Schlüsselwort, wobei ich Trennungen zwischen zwei Schlüsselwörtern vermeide: Beispiele:
Delphi-Quellcode:
  if k=kMax then A[k]:= A[k-1]/A[k]
  if a=0 then Result:= 0 else if a>0 then Result:= 1 else Result:= -1;
  if Sender=mnPrintGraphOben then h:= ro            // 'Drucken|Graph oben'
                             else h:= rm;           // 'Drucken|Graph unten'                      
  for k:= 0 to kMax do A[k]:= 0;
  for i:= 1 to iMax do begin temp:= A[i]; A[i]:= B[i]; B[i]:= temp end;
  for i:= 2 to m do begin
    for k:= 1 to i-1 do B[i]:= B[i] - A[r(i,k)]*B[k];
    B[i]:= B[i]/Abs(A[r(i,i)]) end;
  with Image1.Canvas do begin
    MoveTo(DL, D0 - Round(sy*(F(xMin)-yMin)));
    for i:= 0 to 320 do begin
      x:= xMin + i*dx;
      LineTo(DL + 2*i, D0 - Round(sy*(F(x)-yMin))) end end;
Nach ’begin’ wird 2 Zeichen weiter eingerückt, mit jedem ’end’ wird 2 Zeichen ausgerückt
Diese Schreibweise vermeidet die Zeilen auf denen nur ein ’begin’ steht und die völlig unnützen Treppen, deren Zeilen nur ein ’end’ enthalten.
Kommentare
Zu jeder Programmdatei und zu jeder eingefügten selbstständigen Unit gehört ein zusammenfassender Kommentar mit einer kurzen Beschreibung und einer Signatur mit Namen des Entwicklers und dem Datum der Entwicklung.
Ich schreibe diesen Kommentar hinter die Zeile mit der Programm- bzw. Unit deklaration.
Bei den zu einem Formular gehörenden Units können wir auf diesen Kommentar verzichten, da die visuelle Ansicht des Formulares die Aufgabe am besten beschreibt.

Kommentare zum Code dürfen diesen nicht zerreißen. Ich verwende //-Kommentare, die ich rechtsbündig auf dem Bildschirm platziere. Links steht dann entsprechend eingerückt der Code und rechts davon die zugehörigen Kommentare.
Kommentiert wird der Zusammenhang zwischen Code und Anwendung, nicht die Syntax! Wenn da Unklarheiten bestehen, schau ich in die Online-Hilfe.
Eine abschließende Bemerkung
Die Namensbildung und die Verwendung von strukturierten Typen beeinflussen die Lesbarkeit eines Programms mehr als die mehr formellen Aspekte der Verwendung von Leerzeichen und Zeilenumbrüchen.

Satty67 17. Mai 2009 18:54

Re: Mein Delphi-Style
 
Ich hab' nach Jahren auch meinen Stil gefunden. Tatsächlich sind es Kleinigkeiten, die mich bei fremden Code mehr irritieren als man denken sollte.

folgendes:
Delphi-Quellcode:
Var
  i : Integer;
Begin
  While i >= 0 Do
  Begin
    Dec(i);
  End;
End;
lese ich deutlich schwerer (ist jetzt ein einfaches Beispiel), als meinen eigenen Stil:
Delphi-Quellcode:
var
  i : Integer;
begin
  while i >= 0 do begin
    dec(i);
  end;
end;
Die Großen Buchstaben am Wortanfang von Schlüsselwörtern und die andere Block-Bildung lenken mich ständig vom eigentlichen Inhalt ab. Wenn der fremde Code kompliziert ist, ist meistens mein erster Schritt, die Schreibweise an meinen Stil anzupassen, damit ich ihn schneller/besser verstehe.

alleinherrscher 17. Mai 2009 18:57

Re: Mein Delphi-Style
 
Zitat:

Welch ein redundanter Schwachsinn! Offenbar an einen geistig Behinderten gerichtet. So etwas habe ich in keinem Mathematikbuch gefunden, selbst wenn es Programme enthält.
Sehr geehrter Herr "Dipl. Physiker" Ernst Winter, ich finde solche Äußerungen sollten unterhalb ihres diplomierten Niveaus liegen!

Und: Ein hoch auf ihre Mathematikbücher!

mkinzler 17. Mai 2009 19:00

Re: Mein Delphi-Style
 
Also bei den Blöcken sehe ich das gerade anders herum: Befinden sich begin und end auf selber Ebene ist der Block imho besser erkennbar

Die Muhkuh 17. Mai 2009 19:03

Re: Mein Delphi-Style
 
Hallo Ernst,

den unteren Quellcode kann man nicht mehr lesen, wenn man diesen Stil nicht gewohnt ist.

Es gibt von Haus aus einen Styleguide, der alles abdeckt und welchen man wunderbar lesen kann. Natürlich muss man sich nicht an alles halten, aber Dein letzter Codeausschnitt ist, in meinen Augen, Schwachfug. Es steht teils zu viel in einer Zeile, in welcher auch noch Leerzeichen fehlen, welche die Übersichtlichkeit erhöhen.

Wenn ich diesen Code in einem Thread sehen würde, würde mir die Lust am Helfen, ehrlich gesagt, vergehen. Persönlich, und viele andere auch, würden sowas vorziehen:

Delphi-Quellcode:
if k = kMax then
  A[k] := A[k-1] / A[k];

if a = 0 then
  Result := 0 
else
if a > 0 then
  Result := 1 
else
  Result := -1;
 
if Sender = mnPrintGraphOben then
  h := ro          
else
  h := rm;          

for k := 0 to kMax do
  A[k]:= 0;
 
for i := 1 to iMax do
begin
  temp := A[i];
  A[i] := B[i];
  B[i] := temp
end;

for i := 2 to m do
begin
  for k := 1 to i - 1 do
    B[i] := B[i] - A[r(i,k)] * B[k];

  B[i] := B[i] / Abs(A[r(i,i)])
end;

with Image1.Canvas do
begin
  MoveTo(DL, D0 - Round(sy * (F(xMin) - yMin)));

  for i := 0 to 320 do
  begin
    x := xMin + i * dx;
    LineTo(DL + 2 * i, D0 - Round(sy * (F(x) - yMin)))
  end;
end;
Desweiteren sind auch einige Variablen nicht geschickt gewählt. Die Stelle mit dem "h := ro" bzw. "h := rm" wüsste ich auf Anhieb nicht, was das bedeuten soll. Hier sind auf jeden Fall bessere Bezeichner zu wählen.

Die ungarische Notation, die Du ansprichst, ist nicht von Nöten, auch nicht die von Dir genannten Ausnahmen. Bezeichner sollten sprechend sein und der Name sollte zwingend auf dessen Typ schließen.

Eine Variable Zaehler bräuchte man wohl nie iZaehler nennen, genauso wenig wie man eine Variable IsAvailable bIsAvailable nennen würde. Es geht einfach schon hervor, um welchen Typ es sich handelt. Falls nicht, steht wohl ein Refactoring an.

Ich würde Dir das Buch Clean Code empfehlen:

http://www.amazon.de/exec/obidos/ASIN/3826655486/delphipraxis-21

Dort stehen viele Tipps und Anregungen drin, wie man seinen Code sauber hält. Natürlich ist es kein muss, dass man sich daran hält, aber man bekommt viele gute Tipps, die einem wirklich helfen.

Ich will Dir keines Falls zu Nahe treten, jeder hat seinen eigenen Stil, mit dem er programmiert. Wenn man aber Code massentauglich machen will, sollte man sich an einem gut lesbaren Codestil orientieren.

Zitat:

Kommentare zum Code dürfen diesen nicht zerreißen. Ich verwende //-Kommentare, die ich rechtsbündig auf dem Bildschirm platziere. Links steht dann entsprechend eingerückt der Code und rechts davon die zugehörigen Kommentare.
Kommentiert wird der Zusammenhang zwischen Code und Anwendung, nicht die Syntax! Wenn da Unklarheiten bestehen, schau ich in die Online-Hilfe.
Dem stimme ich Dir zu, Kommentare sollten nicht zerreißen, deswegen bringt man auch nur dort welche an, wo sie von Nöten sind. In sauberem Code ist das kaum der Fall, da der Code für sich spricht.

Satty67 17. Mai 2009 19:03

Re: Mein Delphi-Style
 
@mkinzler:

Ist er auch!

Aber es ist auch nicht die Logik, die mich solche Blöcke schwerer lesen lässt, sondern Jahre der eigenen anderen Schreibweise.

himitsu 17. Mai 2009 19:05

Re: Mein Delphi-Style
 
Zitat:

Zitat von mkinzler
Also bei den Blöcken sehe ich das gerade anders herum: Befinden sich begin und end auf selber Ebene ist der Block imho besser erkennbar

dank einer "ordentlichen" Einrückung hab ich eigentlich kein Problem damit und finde es ach "schöner", wenn begin auf der selben Zeile wie der "Vergleich" ist.

Die Muhkuh 17. Mai 2009 19:06

Re: Mein Delphi-Style
 
Zitat:

Zitat von himitsu
Zitat:

Zitat von mkinzler
Also bei den Blöcken sehe ich das gerade anders herum: Befinden sich begin und end auf selber Ebene ist der Block imho besser erkennbar

dank einer "ordentlichen" Einrückung hab ich eigentlich kein Problem damit und finde es ach "schöner", wenn begin auf der selben Zeile wie der "Vergleich" ist.

Solange nach dem Begin ein Zeilenumbruch erfolgt, ist beides gut lesbar.

DeddyH 17. Mai 2009 19:06

Re: Mein Delphi-Style
 
Zitat:

Delphi-Quellcode:
if k=kMax then A[k]:= A[k-1]/A[k]
  if a=0 then Result:= 0 else if a>0 then Result:= 1 else Result:= -1;
  if Sender=mnPrintGraphOben then h:= ro            // 'Drucken|Graph oben'
                             else h:= rm;           // 'Drucken|Graph unten'                      
  for k:= 0 to kMax do A[k]:= 0;
  for i:= 1 to iMax do begin temp:= A[i]; A[i]:= B[i]; B[i]:= temp end;
  for i:= 2 to m do begin
    for k:= 1 to i-1 do B[i]:= B[i] - A[r(i,k)]*B[k];
    B[i]:= B[i]/Abs(A[r(i,i)]) end;
  with Image1.Canvas do begin
    MoveTo(DL, D0 - Round(sy*(F(xMin)-yMin)));
    for i:= 0 to 320 do begin
      x:= xMin + i*dx;
      LineTo(DL + 2*i, D0 - Round(sy*(F(x)-yMin))) end end;

Ohne persönlich werden zu wollen: wenn hier jemand ein Problem hat und solch einen Code postet, ist mein erster Gedanke "damit hätte ich auch ein Problem". Das ist für Außenstehende nicht auf Anhieb durchschaubar und hat nichts mit "Geistig Behinderten" zu tun.

mirage228 17. Mai 2009 19:11

Re: Mein Delphi-Style
 
Delphi-Quellcode:
if k=kMax then A[k]:= A[k-1]/A[k]
  if a=0 then Result:= 0 else if a>0 then Result:= 1 else Result:= -1;
  if Sender=mnPrintGraphOben then h:= ro            // 'Drucken|Graph oben'
                             else h:= rm;           // 'Drucken|Graph unten'                      
  for k:= 0 to kMax do A[k]:= 0;
  for i:= 1 to iMax do begin temp:= A[i]; A[i]:= B[i]; B[i]:= temp end;
  for i:= 2 to m do begin
    for k:= 1 to i-1 do B[i]:= B[i] - A[r(i,k)]*B[k];
    B[i]:= B[i]/Abs(A[r(i,i)]) end;
  with Image1.Canvas do begin
    MoveTo(DL, D0 - Round(sy*(F(xMin)-yMin)));
    for i:= 0 to 320 do begin
      x:= xMin + i*dx;
      LineTo(DL + 2*i, D0 - Round(sy*(F(x)-yMin))) end end;
Also über den Code-Stil kann man wohl streiten, obwohl ich es eher so machen würde wie Die Muhkuh ;)
Als erstes würde ich diesen Code jedoch ausführlicher kommentieren, gerade wenn es auf irgendwelche Logik u.dgl. ankommt. Das erspart immer noch die meiste Zeit, wenn man sich später wieder in einen Code einarbeiten muss. Ich habe in einigen meiner Projekten einige ziemlich komplexe Methodengefüge, die selbst bei bestem Stil ohne zusätzliche Kommentare nicht auf Anhieb zu verstehen sind...


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:45 Uhr.
Seite 1 von 12  1 2311     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz