Dieses Dokument dient hauptsächlich dazu, Delphi-Entwicklern einen Standard zum Schreiben von Quellcode sowie einen Benennungsstandard für Programme und Dateien zur Verfügung zu stellen, damit sie beim Programmieren ein einheitliches Format verwenden können. Auf diese Weise schreibt jeder Programmierer Code, der für andere verständlich ist.
Einrückung bedeutet zwei Leerzeichen zwischen jeder Ebene. Platzieren Sie im Quellcode keine Tabulatorzeichen. Dies liegt daran, dass die Breite des Tabulatorzeichens je nach Einstellungen und Codeverwaltungsdienstprogrammen (Drucken, Dokumentation, Versionskontrolle usw.) variiert.
Deaktivieren Sie mithilfe des Menüs „Extras|Umgebung“ auf der Seite „Allgemein“ des Dialogfelds „Umgebungsoptionen“ die Kontrollkästchen „Tabulatorzeichen verwenden“ und „Optionale Füllung“, damit Tabulatorzeichen nicht gespeichert werden.
Die Ränder sind auf 80 Zeichen eingestellt. Im Allgemeinen überschreitet der Quellcode beim Schreiben eines Wortes nicht den Spielraum, diese Regel ist jedoch flexibler. Wenn möglich, sollten Anweisungen, die länger als eine Zeile sind, mit Kommas oder Operatoren umschlossen werden. Nach einem Zeilenumbruch sollte dieser um zwei Zeichen eingerückt werden.
Die begin-Anweisung muss in einer eigenen Zeile stehen. Beispielsweise ist die erste Zeile unten falsch, die zweite Zeile jedoch korrekt:
for i:=0 to 10 do begin // Falsch, begin und for stehen in derselben Zeile
for i:=0 to 10 do // Ja, in einer anderen Zeile beginnen
beginnen
Ein Sonderfall dieser Regel liegt vor, wenn begin Teil einer else-Anweisung ist, zum Beispiel:
wenn eine Aussage = dann
beginnen
. .
Ende
sonst beginnen
Eine andere Aussage;
Ende;
Hinweis: Die Endanweisung steht immer in einer separaten Zeile. Wenn begin nicht Teil einer else-Anweisung ist, wird die entsprechende end-Anweisung um denselben Betrag eingerückt wie die begin-Anweisung.
Normalerweise verwenden wir Blockkommentare vom Typ „{...}“, um nicht verwendeten Code vorübergehend auskommentieren zu können Kommentare: Wenn Sie Versionen unter Delphi 2.0 nicht unterstützen möchten, können Sie den Kommentar „//“ verwenden.
Zwischen der öffnenden Klammer und dem nächsten Zeichen steht kein Leerzeichen. Ebenso gibt es kein Leerzeichen zwischen der schließenden Klammer und dem vorherigen Zeichen. Das folgende Beispiel zeigt korrekte und falsche Leerzeichen.
CallPRoc( Aparameter ); // Fehler!
CallProc(Aparameter); // Richtig!
Fügen Sie in Anweisungen keine zusätzlichen Klammern ein. Im Quellcode werden Klammern nur dann verwendet, wenn sie wirklich benötigt werden. Die folgenden Beispiele veranschaulichen die richtige und falsche Verwendung:
if (I=42) then // Fehler, die Klammern sind überflüssig
if (I=42) or (J=42) then // Richtig, es müssen Klammern verwendet werden
Reservierte Wörter und Schlüsselwörter in der Object Pascal-Sprache werden immer vollständig in Kleinbuchstaben geschrieben. Das Folgende ist eine Liste der in Delphi 5 reservierten Wörter:
Und | Array | als | asm |
beginnen | Fall | Klasse | const |
Konstrukteur | Zerstörer | Schnittstelle | div |
Tun | bis hinunter | anders | Ende |
außer | Exporte | Datei | Finalisierung |
Endlich | für | Funktion | gehe zu |
Wenn | Durchführung | In | geerbt |
Initialisierung | im Einklang | Schnittstelle | Ist |
Etikett | Bibliothek | Mod | Null |
nicht | Objekt | von | oder |
aus | verpackt | Verfahren | Programm |
Eigentum | erheben | aufzeichnen | wiederholen |
Ressourcenzeichenfolge | Satz | shl | shr |
Zeichenfolge | Dann | Threadvar | Zu |
versuchen | Typ | Einheit | bis |
verwendet | var | während | mit |
xor | Privat | geschützt | öffentlich |
veröffentlicht | automatisiert |
Prozedurnamen sollten zur besseren Lesbarkeit mit einem Großbuchstaben beginnen und gestaffelt sein. Das Folgende ist eine falsche Schreibweise:
Prozedur Dies ist ein schlecht formatierter Routinename;
Ändern Sie es einfach wie folgt:
procedure ThisIsMuchMoreReadableRoutineName;
Parameter desselben Typs sollten nach Möglichkeit gruppiert werden:
procedure Foo(Param1,Param2,Param3:Imteger;Param4:string);
Die Reihenfolge der formalen Parameter hängt hauptsächlich von den Registeraufrufregeln ab. Der am häufigsten verwendete Parameter sollte der erste Parameter sein, geordnet von links nach rechts in der Reihenfolge der Verwendungshäufigkeit. Eingabeparameter stehen vor Ausgabeparametern. Parameter mit großem Bereich sollten vor Parametern mit kleinem Bereich platziert werden. Zum Beispiel:
SomeProc(aPlanet, aContinent, aCountry, aState, aCity).
Einige davon sind Ausnahmen. Beispielsweise ist bei der Ereignisverarbeitung häufig der Sender-Parameter vom Typ TObject der erste Parameter, der übergeben wird.
Um zu verhindern, dass Parameter des Typs „Datensatz“, „Array“, „Kurzzeichenfolge“ oder „Schnittstelle“ durch die Prozedur geändert werden, sollte der formale Parameter mit „Const“ gekennzeichnet sein. Auf diese Weise generiert der Compiler Code auf die effizienteste Weise und stellt sicher, dass die übergebenen Parameter unveränderlich sind.
Wenn erwartet wird, dass andere Parametertypen durch die Prozedur nicht geändert werden, können sie auch als Const markiert werden. Dies hat zwar keinen Einfluss auf die Effizienz, bietet dem Aufrufer der Prozedur aber mehr Informationen.
Lokale Variablen werden innerhalb der Prozedur verwendet. Bei Bedarf sollten die Variablen sofort beim Eintritt in die Prozedur initialisiert werden. Lokale Variablen vom Typ AnsiString werden automatisch mit einer leeren Zeichenfolge initialisiert, lokale Variablen vom Typ interface und dispinterface werden automatisch mit Null initialisiert und lokale Variablen vom Typ Variant und OleVariant werden automatisch mit „Nicht zugewiesen“ initialisiert.
Von der Verwendung globaler Variablen wird generell abgeraten. Manchmal ist es jedoch notwendig. Dennoch sollten globale Variablen auf die Umgebungen beschränkt werden, in denen sie benötigt werden. Beispielsweise kann eine globale Variable nur für den Implementierungsteil der Einheit global sein.
Globale Daten, die von vielen Einheiten verwendet werden, sollten in eine gemeinsame Einheit verschoben und von allen Objekten verwendet werden. Globale Daten können bei der Deklaration direkt auf einen Wert initialisiert werden. Beachten Sie, dass alle globalen Variablen automatisch mit Null initialisiert werden. Initialisieren Sie globale Variablen daher nicht mit Nullwerten wie 0, Null oder Nicht zugewiesen. Mit Null initialisierte globale Variablen belegen keinen Platz in der .EXE-Datei. Mit Null initialisierte Daten werden in einem virtuellen Datensegment gespeichert, und das virtuelle Datensegment reserviert nur Speicher, wenn die Anwendung gestartet wird. Mit einem Wert ungleich Null initialisierte globale Daten belegen Platz in der .EXE-Datei.
Typbezeichner sind reservierte Wörter und sollten ausschließlich in Kleinbuchstaben geschrieben sein. Win32-API-Typen werden häufig vollständig in Großbuchstaben geschrieben und folgen den Regeln für bestimmte Typnamen in Windows.pas oder anderen API-Einheiten. Bei anderen Variablennamen sollte der erste Buchstabe groß geschrieben werden und die anderen Buchstaben abwechselnd geschrieben werden. Hier einige Beispiele:
var
MyString: string; // reservierte Wörter
WindowsHandle: HWND; // Win32-API-Typ
I: Integer; //Typkennung in der Systemeinheit eingeführt
Von der Verwendung des Real-Typs wird abgeraten, da er nur der Kompatibilität mit älterem Pascal-Code vorbehalten ist. Normalerweise sollte Double für Gleitkommazahlen verwendet werden. Double kann vom Prozessor optimiert werden und ist ein von IEEE definiertes Standarddatenformat. Extend kann verwendet werden, wenn eine größere Reichweite als Double erforderlich ist. Extend ist ein Intel-spezifischer Typ und wird von Java nicht unterstützt. Wenn die physische Anzahl der Bytes der Gleitkommavariablen wichtig ist (vielleicht bei Verwendung einer anderen Sprache zum Schreiben der DLL), sollte Single verwendet werden.
Von der Verwendung von Variant und OleVariant wird generell abgeraten. Diese beiden Typen sind jedoch für die Programmierung erforderlich, wenn der Datentyp erst zur Laufzeit bekannt ist (häufig in COM- und Datenbankanwendungen). Wenn Sie COM-Programmierung durchführen, beispielsweise ActiveX-Steuerelemente automatisieren, sollten Sie OleVariant verwenden; für Nicht-COM-Programmierung sollten Sie Variant verwenden. Dies liegt daran, dass Variant die nativen Zeichenfolgen von Delphi effektiv speichern kann, während OleVariant alle Zeichenfolgen in OLE-Zeichenfolgen (dh WideChar-Zeichenfolgen) konvertiert und über keine Referenzzählfunktion verfügt.
In einer if/then/else-Anweisung sollte der wahrscheinlichste Ausführungsfall in die then-Klausel und der unwahrscheinlichere Fall in die else-Klausel eingefügt werden. Um viele if-Anweisungen zu vermeiden, verwenden Sie stattdessen case-Anweisungen. Wenn es mehr als 5 Ebenen gibt, verwenden Sie keine if-Anweisungen. Bitte verwenden Sie stattdessen eine klarere Methode. Verwenden Sie in if-Anweisungen keine zusätzlichen Klammern.
Wenn in einer if-Anweisung mehrere Bedingungen getestet werden müssen, sollten diese von rechts nach links in der Reihenfolge ihrer Rechenkomplexität geordnet werden. Dadurch kann der Code die Kurzschluss-Schätzlogik des Compilers voll ausnutzen. Wenn beispielsweise Bedingung1 schneller als Bedingung2 und Bedingung2 schneller als Bedingung3 ist, sollte die if-Anweisung im Allgemeinen wie folgt aufgebaut sein:
wenn Bedingung1 und Bedingung2 und Bedingung3 dann
Wenn eine hohe Wahrscheinlichkeit besteht, dass Bedingung3 falsch ist, können wir mithilfe der Kurzschluss-Schätzlogik auch Bedingung3 an den Anfang setzen:
wenn Bedingung3 und Bedingung1 und Bedingung2 dann
Die Konstanten für jeden Fall in der case-Anweisung sollten in numerischer oder alphabetischer Reihenfolge angeordnet sein. Die Aktionsanweisung für jede Situation sollte kurz sein und normalerweise nicht mehr als 4 bis 5 Codezeilen umfassen. Wenn die Aktion zu komplex ist, sollte der Code in einer separaten Prozedur oder Funktion platziert werden. Die else-Klausel der Case-Anweisung wird nur für Standardfälle oder zur Fehlererkennung verwendet.
Case-Anweisungen folgen den normalen Einrückungs- und Benennungsregeln.
Es wird empfohlen, die Exit-Prozedur nicht zum Verlassen der while-Schleife zu verwenden. Bei Bedarf sollte eine Schleifenbedingung verwendet werden, um die Schleife zu verlassen. Der gesamte Code, der die While-Schleife initialisiert, sollte sich vor dem While-Eintrag befinden und nicht durch irrelevante Anweisungen getrennt sein. Eventuelle Hilfsarbeiten für den Betrieb sollten unmittelbar nach dem Zyklus durchgeführt werden.
Wenn die Anzahl der Schleifen bestimmt ist, sollte eine for-Anweisung anstelle einer while-Anweisung verwendet werden.
Die Wiederholungsanweisung ähnelt einer While-Schleife und folgt denselben Regeln.
Die with-Anweisung sollte mit Vorsicht verwendet werden. Vermeiden Sie die übermäßige Verwendung von with-Anweisungen, insbesondere wenn Sie mehrere Objekte oder Datensätze innerhalb einer with-Anweisung verwenden. Zum Beispiel:
mit Record1,Record2 tun
Diese Situationen können Programmierer leicht verwirren und das Debuggen erschweren.
Die with-Anweisung folgt auch den Regeln dieses Kapitels für Benennung und Einrückung.
Die Ausnahmebehandlung dient hauptsächlich der Fehlerkorrektur und dem Schutz von Ressourcen. Dies bedeutet, dass überall dort, wo Ressourcen zugewiesen werden, try...finally verwendet werden muss, um sicherzustellen, dass die Ressourcen freigegeben werden. Es gibt jedoch Ausnahmen, wenn Ressourcen im Anfangs-/Endteil der Einheit oder im Konstruktor/Destruktor des Objekts zugewiesen/freigegeben werden.
Wenn möglich, sollte jede Ressourcenzuweisung einer try...finally-Struktur entsprechen. Beispielsweise kann der folgende Code einen Fehler verursachen:
SomeClass1 := TSomeClass.Create;
SomeClass2 := TSomeClass.Create;
versuchen
{ etwas Code machen }
Endlich
SomeClass1.Free;
SomeClass2.Free;
Ende;
Eine sichere Lösung für die oben genannte Ressourcenzuweisung ist:
SomeClass1 := TSomeClass.Create;
versuchen
SomeClass2 := TSomeClass.Create;
versuchen
{ etwas Code machen }
Endlich
SomeClass2.Free;
Ende;
Endlich
SomeClass1.Free;
Ende;
Wenn Sie beim Auftreten einer Ausnahme eine Aufgabe ausführen möchten, können Sie try...exclusive verwenden. Normalerweise besteht keine Notwendigkeit, try... zu verwenden, außer um einfach eine Fehlermeldung anzuzeigen, da das Anwendungsobjekt dies automatisch basierend auf dem Kontext tun kann. Wenn Sie die Standard-Ausnahmebehandlung in der Klausel aktivieren möchten, können Sie die Ausnahme erneut auslösen.
Von der Verwendung von try...exclusive mit einer else-Klausel wird abgeraten, da dadurch alle Ausnahmen blockiert werden, auch solche, auf deren Verarbeitung Sie nicht vorbereitet sind.
Prozedur- und Funktionsnamen sollten aussagekräftig sein. Es ist am besten, dem Namen des Prozesses zum Ausführen einer Aktion das Verb voranzustellen, das die Aktion ausdrückt. Zum Beispiel:
Verfahren FormatHardDrive;
Dem Namen der Prozedur zum Festlegen von Eingabeparameterwerten sollte Set vorangestellt werden, zum Beispiel:
Prozedur SetUserName;
Dem Namen der Prozedur zum Erhalten eines Werts sollte Get vorangestellt werden, zum Beispiel:
Funktion GetUserName:string;
Der Name aller formalen Parameter sollte seinen Zweck zum Ausdruck bringen. Gegebenenfalls wird dem Namen des Formalparameters vorzugsweise der Buchstabe a vorangestellt, zum Beispiel:
procedure SomeProc(aUserName:string; aUserAge:integer);
Das Präfix a ist erforderlich, wenn der Parametername denselben Namen wie ein Klassenattribut oder -feld hat.
Wenn zwei Units Prozeduren mit demselben Namen enthalten und die Prozedur aufgerufen wird, wird tatsächlich die Prozedur in der Unit aufgerufen, die später in der Uses-Klausel erscheint. Um dies zu vermeiden, fügen Sie den gewünschten Einheitennamen vor dem Methodennamen hinzu, zum Beispiel:
SysUtils.FindClose(SR);
oder Windows.FindClose(Handle);
Der Name einer Variablen sollte ihren Zweck ausdrücken. Schleifenkontrollvariablen bestehen häufig aus einzelnen Buchstaben, z. B. I, J oder K. Sie können auch einen aussagekräftigeren Namen verwenden, z. B. UserIndex. Boolesche Variablennamen müssen die Bedeutung der Werte „True“ und „False“ klar angeben.
Lokale Variablen folgen den Namensregeln anderer Variablen.
Globale Variablen beginnen mit einem Großbuchstaben „G“ und folgen den Benennungsregeln anderer Variablen.
Der Name des Aufzählungstyps muss den Zweck der Aufzählung darstellen. Das T-Zeichen muss dem Namen vorangestellt werden, um anzuzeigen, dass es sich um einen Datentyp handelt. Das Präfix der Bezeichnerliste des Aufzählungstyps sollte 2–3 Kleinbuchstaben enthalten, um sie miteinander zu verknüpfen. Zum Beispiel:
TSongType=(stRock, stClassical, stCountry, stAlternative, stHeavyMetal, stRB);
Der Name einer Variableninstanz eines Aufzählungstyps ist derselbe wie der Typ, jedoch ohne das Präfix T. Sie können der Variablen auch einen spezielleren Namen geben, wie zum Beispiel: FavoriteSongTypel, FavoriteSongType2 usw.
Der Name des Array-Typs sollte den Zweck des Arrays ausdrücken. Typnamen müssen mit dem Buchstaben „T“ vorangestellt werden. Wenn Sie einen Zeiger auf einen Array-Typ deklarieren möchten, müssen Sie ihm den Buchstaben P voranstellen und ihn vor der Typdeklaration deklarieren. Zum Beispiel:
Typ
PCycleArray = ^TCycleArray;
TCycleArray=Array[1..100] einer Ganzzahl;
Tatsächlich hat eine Variableninstanz eines Array-Typs denselben Namen wie der Typ, jedoch ohne das Präfix „T“.
Der Name des Datensatztyps sollte den Zweck des Datensatzes zum Ausdruck bringen. Typnamen müssen den Buchstaben T voranstellen. Wenn Sie einen Zeiger auf einen Datensatztyp deklarieren möchten, müssen Sie ihm den Buchstaben P voranstellen und ihn vor der Typdeklaration deklarieren. Zum Beispiel:
Typ
PEmployee = ^TEmployee;
TEmployee=Datensatz
Mitarbeitername: string;
Mitarbeiterrate: Doppelt;
Ende;
Der Name der Klasse sollte den Zweck der Klasse zum Ausdruck bringen. Im Allgemeinen sollte der Buchstabe „T“ vor dem Klassennamen hinzugefügt werden. Wenn es sich um eine Schnittstellenklasse handelt, sollte „I“ vor dem Klassennamen hinzugefügt werden. Der Klassenname der Fehlerausnahmeklasse sollte mit „E“ hinzugefügt werden. und der Klassenreferenztyp (Klassenreferenztyp) sollte vor dem Klassennamen hinzugefügt werden. Fügen Sie „Klasse“ nach dem Namen hinzu. Zum Beispiel:
Typ
TCustomer = class(TObject);
ICustomer = Schnittstelle;
TCustomerClass = Klasse von TCustomer
ECustomerException = class(Exception);
Der Instanzname einer Klasse ist normalerweise derselbe wie der Klassenname, ohne das Präfix „T“.
var
Kunde: TCustomer;
Hinweis: Informationen zur Benennung von Komponenten finden Sie unter „Komponententypen“.
Für die Benennung von Feldern gelten dieselben Regeln wie für Variablen, außer dass das Präfix F hinzugefügt wird, um anzuzeigen, dass es sich um ein Feld handelt.
Alle Felder müssen privat sein. Wenn Sie auf ein Feld außerhalb des Geltungsbereichs einer Klasse zugreifen möchten, können Sie dies mithilfe von Klassenattributen tun.
Für die Benennung von Methoden gelten dieselben Regeln wie für Prozeduren und Funktionen.
Statische Methoden sollten verwendet werden, wenn Sie nicht möchten, dass eine Methode durch abgeleitete Klassen überschrieben wird.
Wenn Sie möchten, dass eine Methode durch abgeleitete Klassen überschrieben wird, sollten Sie virtuelle Methoden verwenden. Wenn eine Klassenmethode direkt oder indirekt von mehreren abgeleiteten Klassen verwendet werden soll, sollten dynamische Methoden (dynamisch) verwendet werden. Wenn eine Klasse beispielsweise eine häufig überschriebene Methode enthält und über 100 abgeleitete Klassen verfügt, sollte die Methode als dynamisch definiert werden, was den Speicheraufwand reduzieren kann.
Wenn eine Klasse Instanzen erstellen soll, verwenden Sie keine abstrakten Methoden. Abstrakte Methoden können nur in Basisklassen verwendet werden, die niemals Instanzen erstellen.
Alle Eigenschaftenzugriffsmethoden sollten im privaten oder geschützten Teil der Klasse definiert werden. Eigenschaftenzugriffsmethoden folgen denselben Regeln wie Prozeduren und Funktionen. Den zum Lesen verwendeten Methoden sollte das Präfix „Get“ vorangestellt werden, den zum Schreiben verwendeten Methoden sollte das Präfix „Set“ vorangestellt werden und sie sollten über einen Parameter namens „Value“ verfügen, dessen Typ mit dem Typ der Eigenschaft übereinstimmt. Zum Beispiel:
TSomeClass = class(TObject)
Privat
fsomeField: Integer;
geschützt
Funktion GetSomeField: Integer;
procedure SetSomeField(Value: Integer);
öffentlich
Eigenschaft SomeField: Integer read GetSomeField write SetSomeField;
Ende;
Obwohl dies nicht erforderlich ist, wird empfohlen, Schreibzugriffsmethoden zu verwenden, um auf Eigenschaften zuzugreifen, die private Felder darstellen.
Eigenschaften dienen als Zugriffsfunktionen für private Felder und folgen denselben Benennungsregeln wie Felder, außer ohne das F-Präfix. Eigenschaftsnamen sollten Substantive und keine Verben sein. Eigenschaften sind Daten und Methoden sind Aktionen. Namen von Array-Eigenschaften sollten im Plural vorliegen, während allgemeine Eigenschaften im Singular stehen sollten.
Die Benennung von Komponenten ähnelt der Benennung von Klassen, außer dass Sie bei Konflikten mit anderen Komponentennamen ein dreistelliges Präfix hinzufügen können, um ein Unternehmen, eine Einzelperson oder eine andere Entität zu identifizieren. Eine Clock-Komponente kann beispielsweise so deklariert werden:
TddgClock = Klasse(TComponent)
Beachten Sie, dass die drei Zeichen des Präfixes Kleinbuchstaben sein müssen.
Der Name der Komponenteninstanz sollte ihre tatsächliche Bedeutung beschreiben können. Die Namenskonvention verwendet hier eine modifizierte ungarische Präfix-Namenskonvention. Der Grund für die Verwendung eines Präfixes anstelle eines Suffixes besteht darin, dass es einfacher ist, im Objektinspektor und Code-Explorer nach dem Namen der Komponente zu suchen als nach dem Typ der Komponente. In diesem Standard besteht der Komponenteninstanzname aus zwei Teilen: dem Präfix und dem Attributbezeichner.
Das Präfix einer Komponente ist meist eine Abkürzung des Komponententyps. Siehe Komponentenpräfixe in der folgenden Tabelle:
Name der Komponentenklasse | Komponentenpräfix |
TActionList, TAction stellt das Listenelement der Aktion dar | Akt |
TButton, TSpeedButton, TBitBtn und andere Schaltflächenklassen | btn |
TCheckBox, TDBCheckBox und andere Kontrollkästchen | chk |
TRadioButton-Optionsfeldklasse | rdo |
TToolBar-Symbolleiste | tb |
Alle Hauptmenüklassen von TMainMenu | mm |
Alle Menüelementklassen von TMainMenuItem | mi |
Alle Popup-Menüklassen von TPopupMenu | Uhr |
Alle Popup-Menüelementklassen von TPopupMenuItem | pmi |
TLabel, TStaticText und andere Beschriftungsklassen, die zur Anzeige verwendet werden | lbl |
TPanel und andere Panel-Klassen | nnl |
TPageControl und andere Seitensteuerungsklassen | pgc |
TEdit, TMaskEdit und andere einzeilige Bearbeitungsfeldklassen | Sommerzeit |
TMemo, TRichEdit und andere mehrzeilige Bearbeitungsfeldklassen | mmo |
TDrawGrid, TStringGrid und andere Rasterklassen | grd |
TAnimate und andere Animationsklassen | ani |
TImageList und andere Bildlistenklassen | il |
TImage und andere Bildklassen | Bild |
TChart-Diagrammklasse | cht |
TComboBox, TDBComboBox und andere Dropdown-Listenfeldklassen | cbo |
TListBox, TDBList und andere Listenfeldklassen | lst |
TTreeView | Fernseher |
TListView | lv |
THotKey | hk |
TSplitter und andere Trennzeichenklassen | spt |
Alle Dialogkomponentenklassen wie TOpenDialog | dlg |
Alle Datentabellenklassen wie TTable | Tabl |
Alle SQL-Abfragekomponenten wie TQuery | qry |
TClientDataSetAlle Elemente des Client-Datensatzes | CDs |
TDataSource | ds |
TDatabase | db |
TSockConnection, TDCOMConnection und andere Verbindungskomponentenklassen | con |
TQuickRep, TFastReport und andere Berichtskomponentenklassen | rpt |
TDDEClientConv, TDDEClientItem und andere DDE-Komponentenklassen | dde |
Alle Kalenderklassen wie TMonthCalendar | cal |
TGroupBox und andere Steuerklassen | grp |
Wie oben gezeigt, stammt das Präfix des Komponententyps aus der Analyse der Typeigenschaften, die die Komponente beschreiben. Normalerweise beschreiben die folgenden Regeln, wie ein Komponententyppräfix definiert wird:
Hinweis: Das Präfix einer Komponente gibt den Typ der Komponente an, ob es sich um eine Schaltfläche, eine Beschriftung usw. handelt. Daher ist es nicht erforderlich, für jede spezielle Komponentenklasse ein Komponentenpräfix zu erstellen TMyButton ist immer noch in Ordnung.
Der Identifikationsname der Komponenteneigenschaft ist eine Beschreibung der Absicht der Komponente. Beispielsweise könnte eine TButton-Komponenteninstanz, die zum Schließen eines Formulars verwendet wird, den Namen btnClose tragen. Eine Instanz der Edit-Name-Komponente kann edName heißen.
Der Name des Formulars oder Dialogtyps sollte den Zweck des Formulars ausdrücken, mit dem Präfix „Tfrm“ für ein Formular oder „Tdlg“ für ein Dialogfeld, gefolgt von einem beschreibenden Namen. Der Name des Formulartyps „Info“ lautet beispielsweise:
TfrmAbout = class(TForm)
Der Typname des Hauptformulars lautet:
TfrmMain = Klasse(TForm)
Der Typname des Kunden-Login-Formulars lautet:
TfrmCustomerEntry = class(TForm)
Der Typname des Anmeldedialogfelds lautet:
TdlgLogin = class(TForm)
Der Name der Formularinstanz ist derselbe wie der entsprechende Typname, jedoch ohne das Präfix T. Der Name des zuvor erwähnten Formulartyps und der Instanz lautet beispielsweise:
Geben Sie den Namen ein | Instanzname |
TfrmAbout | frmAbout |
TfrmMain | frmMain |
TfrmCustomerEntry | frmCustomerEntry |
TdlgLogin | dlgLogin |
Sofern keine besonderen Gründe vorliegen, wird nur das Hauptformular automatisch generiert. Alle anderen Formulare müssen aus der automatisch generierten Liste im Dialogfeld „Projektoptionen“ entfernt werden. Weitere Informationen finden Sie in den folgenden Abschnitten.
Alle Formulareinheiten sollten Instanziierungsfunktionen zum Erstellen, Einrichten, modalen Anzeigen und Freigeben des Formulars enthalten. Diese Funktion gibt das vom Formular zurückgegebene Modusergebnis zurück. An diese Funktion übergebene Parameter folgen den Regeln für die Parameterübergabe. Der Grund für eine solche Kapselung besteht darin, die Wiederverwendung und Wartung von Code zu erleichtern.
Die Variablen des Formulars sollten aus der Einheit entfernt und als lokale Variablen in der Formularinstanziierungsfunktion definiert werden (beachten Sie, dass hierfür das Formular aus der automatisch generierten Liste im Dialogfeld „Projektoptionen“ entfernt werden muss. Bitte sehen Sie sich den vorherigen Inhalt an.
Die folgende Unit-Datei veranschaulicht beispielsweise die Instanziierungsfunktion „GetUserData“.
Unit UserDataFrm;
Schnittstelle
Verwendungsmöglichkeiten
Windows, Nachrichten, SysUtils, Klassen, Grafiken, Steuerelemente, Formulare,
Dialoge, StdCtrls;
Typ
TfrmUserData = class(TForm)
edtUserName: TEdit;
edtUserID: TEdit;
Privat
{Private Erklärungen}
öffentlich
{Öffentliche Erklärungen}
Ende;
Funktion GetUserData(var aUserName: String;var aUserID: Integer): Word;
Durchführung
{$R *.DFM}
Funktion GetUserData(var aUserName: String;var aUserID: Integer): Word;
var
frmUserData: TfrmUserData;
beginnen
frmUserData := TfrmUserData.Create(Application);
frmUserData.Caption:='Benutzerdaten abrufen';
Ergebnis: = frmUserData.ShowModal;
wenn Ergebnis=mrOK dann
beginnen
aUserName := frmUserData.edtUserName.Text;
aUserID := StrToInt(frmUserData.edtUserID.Text);
Ende;
Endlich
frmUserData.Free;
Ende;
Ende;
Ende.
Wenn eine Formularstruktur zu komplex ist, muss sie in einen Hauptformularrahmen und mehrere in den Hauptformularrahmen eingebettete Unterformularrahmen unterteilt werden. wie:
TfrmMainFrame: TfrmInfoFrame, TfrmEditorFrame
Der Hauptzweck der Verwendung von Formularrahmen besteht darin, das Problem der Wiederverwendung von Schnittstellen und Code zu lösen und den Zusammenhalt des Einheitscodes zu verbessern (nach der Teilung ist jeder Formularrahmen eine unabhängige Einheit), wodurch die Qualität der Softwareentwicklung verbessert wird. Sie müssen schnittstellenbezogenen Code (wiederverwendbar) und anwendungsbezogenen Code (nicht wiederverwendbar) extrahieren.
Der Name des Datenmodultyps sollte seinen Zweck zum Ausdruck bringen und mit dem Präfix „Tdm“ gefolgt von einem beschreibenden Namen versehen sein. Der Typname des Kundendatenmoduls lautet beispielsweise:
TdmCustomer = class(TDataModule)
Der Typname des Datenmoduls „Bestellungen“ lautet:
TdmOrder = class(TDataModule)
Der Name einer Datenmodulinstanz sollte mit dem entsprechenden Typnamen identisch sein, jedoch ohne das T-Präfix. Der vorherige Datenmodultyp und der Instanzname lauten beispielsweise wie folgt:
Geben Sie den Namen ein | Instanzname |
TdmCustomer | dmKunde |
TdmOrder | dmOrder |
Es wird empfohlen, strukturierte Dateikopfinformationen in allen Quelldateien, Projektdateien und Unit-Dateien zu verwenden. Ein Dateiheader sollte mindestens die folgenden Informationen enthalten:
{
Copyright @ Year by Authors
}
Projektdateinamen sollten beschreibend sein. Der Projektname von „The Delphi 5 Developer's Guide Bug Manager“ lautet beispielsweise DDGBugs.dpr und der Name eines Systeminformationsprogramms ist SysInfo.dpr.
Der Name der Formulardatei sollte den Zweck des Formulars zum Ausdruck bringen und das Suffix Frm haben. Beispielsweise lautet der Dateiname des About-Formulars AboutFrm.dfm und der Dateiname des Hauptformulars MainFrm.dfm.
Der Name der Datenmoduldatei sollte die Rolle des Datenmoduls ausdrücken und ein DM-Suffix haben. Der Dateiname des Kundendatenmoduls lautet beispielsweise CustomersDM.dfm.
Der Name der Remote-Datenmoduldatei sollte den Zweck des Remote-Datenmoduls zum Ausdruck bringen. Fügen Sie das RDM-Suffix nach dem Namen hinzu. Beispielsweise heißt die Datei für das Remote-Datenmodul „Customers“ CustomersRDM.dfm.
Einheitennamen sollten beschreibend sein. Die Hauptformulareinheit der Anwendung heißt beispielsweise MaimFrm.pas.
Die Uses-Klausel des Abschnitts „Schnittstelle“ sollte nur die Einheiten enthalten, die in diesem Abschnitt erforderlich sind. Schließen Sie keine Einheitennamen ein, die möglicherweise automatisch von Delphi hinzugefügt werden. Die Uses-Klausel des Implementierungsteils sollte nur die für diesen Teil erforderlichen Einheiten und keine zusätzlichen Einheiten enthalten.
Der Abschnitt „Schnittstelle“ sollte nur Deklarationen von Typen, Variablen, Prozeduren und Funktionen enthalten, auf die externe Einheiten zugreifen müssen. Darüber hinaus sollten diese Erklärungen vor dem Abschnitt „Implementierung“ stehen.
Der Implementierungsteil umfasst die Implementierung privater Typen, Variablen, Prozeduren und Funktionen dieser Einheit.
Platzieren Sie keinen zeitaufwändigen Code im Abschnitt „Initialisierung“. Andernfalls wird die Anwendung sehr langsam gestartet.
Stellen Sie sicher, dass Sie alle im Abschnitt „Initialisierung“ zugewiesenen Ressourcen freigeben.
Der Name der Formulareinheitsdatei ist derselbe wie der entsprechende Formularname. Ändern Sie lediglich das Präfix in das Suffix. Der Einheitenname des About-Formulars lautet beispielsweise AboutFrm.pas. Der Unit-Dateiname des Hauptformulars lautet MainFrm.pas.
Der Name der Datenmodul-Einheitsdatei ist derselbe wie der entsprechende Datenmodulname. Der Name der Datenmoduleinheit lautet beispielsweise CustomersDM.pas.
Der Name einer allgemeinen Einheit sollte ihren Zweck zum Ausdruck bringen und mit dem Präfix „u“ versehen werden. Beispielsweise lautet der Name einer praktischen Debugging-Tool-Einheit uDebugUtilities.pas, und der Name der Einheit, die globale Variablen enthält, lautet uCustomerGlobals.pas.
Beachten Sie, dass Unit-Namen innerhalb eines Projekts eindeutig sein müssen. Gemeinsame Einheitennamen dürfen nicht denselben Namen haben.
Komponentenzellen sollten in separaten Pfaden platziert werden, um anzuzeigen, dass sie die Zellen sind, die die Komponente definieren. Sie werden im Allgemeinen nicht im selben Pfad wie das Projekt platziert. Unit-Dateinamen sollten ihren Inhalt ausdrücken.
Weitere Informationen zu den Benennungsstandards für Komponenten finden Sie unter „Benennungsstandards für Komponententypen“.
Eine Komponentenzelle kann nur eine Primärkomponente enthalten, nämlich die Komponente, die in der Komponentenpalette angezeigt wird. In derselben Einheit können auch andere Hilfskomponenten oder Objekte enthalten sein.
Der Komponentenregistrierungsprozess sollte aus der Komponenteneinheit herausgezogen und in einer separaten Einheit untergebracht werden. Mit dieser Registrierungseinheit werden alle Komponenten, Eigenschaftseditoren, Komponenteneditoren, Assistenten usw. registriert.
Die Komponentenregistrierung sollte im Designpaket erfolgen. Daher sollten Registrierungseinheiten im Entwurfszeitpaket und nicht im Laufzeitpaket enthalten sein. Es wird empfohlen, die Registrierungseinheit wie folgt zu benennen:
xxxReg.pas
Unter diesen wird das Zeichenpräfix xxx verwendet, um den Namen des Komponentenpakets oder des Unternehmens, der Einzelperson oder einer anderen Entität zu identifizieren. Die Registrierungseinheit heißt beispielsweise xxxReg.pas.
Das Laufzeitpaket sollte nur die erforderlichen Einheiten enthalten. Diese Elemente des Eigenschafteneditors und Komponenteneditors sollten im Entwurfszeitpaket platziert werden. Registrierungseinheiten sollten ebenfalls im Paket für die Designphase enthalten sein.
Die Paketbenennung folgt dem folgenden Muster:
dcliiiDescvvCn.pkg – Designpaket
iiiDescvvCn.pkg – Laufzeitpaket
Darunter stellt iii ein 2-3-stelliges Präfix dar, das zur Identifizierung von Unternehmen, Personen oder anderen Dingen verwendet wird, die identifiziert werden müssen. Es ist optional, vv stellt die Versionsnummer des dar Sie können das Paket entsprechend Ihren Anforderungen auswählen. Das Präfix „dcl“ gibt ein Design-Time-Paket an. Ohne dieses Präfix gibt der Buchstabe „Cn“ den Compiler-Typ und die Compiler-Versionsnummer an. Delphi5=D5, Delphi4=D4, CBuilder3=C3....
Beachten Sie, dass lib oder std im Paketnamen angibt, ob es sich um ein Entwurfszeitpaket bzw. ein Laufzeitpaket handelt. Zum Beispiel:
dclrbStdComPSD5.pkg – Delphi 5-Entwurfszeitpaket
rbStdCompsD5.pkg – Delphi 5-Laufzeitpaket
Obwohl die meisten Tools zur automatischen Codeformatierung Ihnen dabei helfen können, das Format des Quellprogramms neu zu ordnen und die Groß- und Kleinschreibung reservierter Wörter und Bezeichner zu aktualisieren, ist es am besten, dies vor der Verwendung der Versionskontrolle zu tun. Wenn Sie die Versionskontrolle bereits verwendet haben, wird empfohlen, dies nicht zu tun. Es ist nicht einfach, automatische Codeformatierungstools zu verwenden. Selbst wenn noch ein Leerzeichen vorhanden ist, geht das Versionskontrolltool davon aus, dass die Zeile geändert wurde, was zu Änderungen in der Programmverwaltung führt.