Code-Konventionen
Verbindliche Coding-Standards für die WvdS FPC RAD Suite.
Namenskonventionen
Typen
| Kategorie | Präfix | Beispiel |
| Klasse | TWvdS* | TWvdSBuildConfig, TWvdSProjectManager |
| Interface | IWvdS* | IWvdSLogger, IWvdSParser |
| Record | TWvdS* | TWvdSBuildResult, TWvdSToolPath |
| Enum | TWvdS* | TWvdSProjectType, TWvdSBuildStatus |
| Exception | EWvdS* | EWvdSFileNotFound, EWvdSParseError |
| Callback | TWvdS* | TWvdSBuildCallback, TWvdSProgressHandler |
Externe
API-Typen (VSCode, Node.js) behalten ihre originalen Namen.
Unit-Namen
Microsoft-Stil Namespaces mit WvdS-Präfix:
WvdS.{Domain}.{Layer}.pas
Beispiele:
WvdS.Build.Models.pas
WvdS.Build.Service.pas
WvdS.Projects.SettingsDialog.pas
WvdS.VSCode.Commands.pas
Layer-Suffixe
| Suffix | Inhalt | Beispiel |
| .Models | Records, Enums, Typen | WvdS.Build.Models |
| .Service | Geschäftslogik | WvdS.Build.Service |
| .Dialog | WebView-Dialoge | WvdS.Projects.SettingsDialog |
| .Provider | VSCode API Wrapper | WvdS.Designer.EditorProvider |
Variablen und Parameter
| Kategorie | Präfix | Beispiel |
| Private Felder | F | FProjectPath, FConfig |
| Parameter | A | APath, AOptions, ACallback |
| Lokale Variablen | Kein | Result, I, Config |
Resourcestrings
Präfix nach Feature:
| Präfix | Feature |
| rsCore* | Core Extension |
| rsBuild* | Build Extension |
| rsProject* | Projects Extension |
| rsDesigner* | UI Designer |
| rsPreview* | UI Preview |
| rsMeta* | UI Meta |
| rsPackaging* | Packaging |
| rsTool* | Toolchain |
Code-Struktur
Unit-Aufbau
unit WvdS.{Feature}.{Layer};
{$mode objfpc}{$H+}
interface
uses
// 1. System Units
SysUtils, Classes,
// 2. WvdS Common
WvdS.System, WvdS.Collections,
// 3. Feature-spezifisch
WvdS.{Feature}.Models;
type
// Typ-Definitionen
function PublicFunction(const AParam: string): Boolean;
procedure PublicProcedure(AValue: Integer);
implementation
uses
// Private Uses (nur hier benötigte Units)
WvdS.VSCode.Strings;
// Private Typen und Variablen
type
TInternalHelper = class
end;
var
InternalState: TObject;
// Implementierungen
function PublicFunction(const AParam: string): Boolean;
begin
// ...
end;
procedure PublicProcedure(AValue: Integer);
begin
// ...
end;
initialization
// Initialisierung
finalization
// Aufräumen
end.
Klassen-Aufbau
type
TWvdSExampleClass = class(TObject)
private
FName: string;
FValue: Integer;
procedure SetName(const AValue: string);
protected
procedure DoInternalWork; virtual;
public
constructor Create(const AName: string);
destructor Destroy; override;
procedure Execute;
property Name: string read FName write SetName;
property Value: Integer read FValue write FValue;
end;
Dokumentation
(*
@abstract(Kurze Beschreibung in einem Satz.)
Ausführliche Beschreibung des Zwecks und der Verwendung.
Kann mehrere Sätze umfassen.
@param(APath Vollständiger Pfad zur Datei)
@param(AOptions Optionale Konfiguration, kann nil sein)
@returns(True wenn erfolgreich, False bei Fehler)
@raises(EWvdSFileNotFound wenn Datei nicht existiert)
@raises(EWvdSAccessDenied wenn keine Leserechte)
Security:
- CWE-22: Pfad wird gegen Path Traversal validiert
@seealso(RelatedFunction)
@seealso(TWvdSRelatedClass)
*)
function ProcessFile(const APath: string; AOptions: TOptions): Boolean;
Inline-Kommentare
// Kurzer Kommentar für einzelne Zeile
Result := CalculateValue;
// Mehrzeiliger Kommentar für komplexere Logik
// Erklärt den Grund, nicht das Was
if (Value > Threshold) and (Mode = mAdvanced) then
begin
// Wir müssen hier den erweiterten Algorithmus verwenden,
// da der einfache bei großen Werten ungenau wird
Result := AdvancedCalculation(Value);
end;
Konstanten statt Magic Numbers
// VERBOTEN
if Length(Name) > 64 then
if Timeout > 30000 then
// KORREKT
const
MAX_PROJECT_NAME_LENGTH = 64;
DEFAULT_TIMEOUT_MS = 30000;
if Length(Name) > MAX_PROJECT_NAME_LENGTH then
if Timeout > DEFAULT_TIMEOUT_MS then
Terminologie
Konsistente Begriffe verwenden:
| Verwende | Vermeide |
| Path | Url, Location, Dir (inkonsistent) |
| Config | Settings, Options, Prefs (inkonsistent) |
| Create | Make, Build (für Objekte) |
| Generate | Create (für Ausgabe) |
| Validate | Check, Verify (für Eingaben) |
| Initialize | Setup, Init (inkonsistent) |
| Execute | Run, Process (inkonsistent) |
Einrückung
2 Spaces für Einrückung (nicht Tabs)
begin auf eigener Zeile bei Blöcken
end auf gleicher Einrückungsebene wie zugehöriges begin
// KORREKT
procedure Example;
begin
if Condition then
begin
DoSomething;
DoMore;
end
else
begin
DoAlternative;
end;
end;
// VERBOTEN
procedure Example; begin
if Condition then begin DoSomething; DoMore; end
else DoAlternative;
end;
Zeilenlänge
// Bei langen Parameterlisten
function VeryLongFunctionName(
const AFirstParameter: string;
const ASecondParameter: Integer;
AThirdParameter: TOptions
): Boolean;
// Bei langen Bedingungen
if (FirstCondition) and
(SecondCondition) and
(ThirdCondition) then
begin
// ...
end;
Verbotene Patterns
Leere Exception-Handler
// VERBOTEN
try
DoSomething;
except
// Nichts tun - Fehler verschlucken!
end;
// KORREKT
try
DoSomething;
except
on E: Exception do
LogError(rsUnexpectedError, [E.ClassName, E.Message]);
end;
TODO/FIXME im Produktionscode
// VERBOTEN in main-Branch
// TODO: Implement this later
// FIXME: This is broken
// ERLAUBT nur in Feature-Branches, muß vor Merge entfernt werden
Hardcodierte Strings
// VERBOTEN
ShowMessage('File not found');
ShowMessage('Datei nicht gefunden');
// KORREKT
ShowMessage(rsFileNotFound); // resourcestring
Globale Variablen in Services
// VERBOTEN
var
GlobalConfig: TConfig; // Schwer testbar!
// KORREKT - Parameter übergeben
function ProcessWithConfig(const AConfig: TConfig): Boolean;
Testbarkeit
Services müssen ohne VSCode/UI testbar sein:
// VERBOTEN - UI in Service
procedure ValidateAndShowError(const AName: string);
begin
if not IsValid(AName) then
ShowMessage('Invalid name'); // UI-Abhängigkeit!
end;
// KORREKT - Rückgabewert
function ValidateName(const AName: string; out AError: string): Boolean;
begin
Result := IsValid(AName);
if not Result then
AError := rsInvalidName;
end;
pas2js Kompatibilität (WICHTIG)
pas2js ist NICHT 100% kompatibel mit FPC! Diese Einschränkungen MÜSSEN beachtet werden.
Nicht unterstützte Features
| Feature | FPC | pas2js | Workaround |
class var | ✓ | ✗ | Unit-Level Variable verwenden |
Inline var | ✓ | ✗ | Im var-Block deklarieren |
Int64 | ✓ | ✗ | Integer verwenden |
| | | |