Convenzioni del codice
Standard di codifica vincolanti per la suite WvdS FPC RAD.
Convenzioni di naming
Tipi
| Categoria | Prefisso | Esempio |
| Classe | TWvdS* | TWvdSBuildConfig, TWvdSProjectManager |
| Interface | IWvdS* | IWvdSLogger, IWvdSParser |
| Record | TWvdS* | TWvdSBuildResult, TWvdSToolPath |
| Enum | TWvdS* | TWvdSProjectType, TWvdSBuildStatus |
| Exception | EWvdS* | EWvdSFileNotFound, EWvdSParseError |
| Callback | TWvdS* | TWvdSBuildCallback, TWvdSProgressHandler |
I tipi
API esterni (VSCode, Node.js) mantengono i loro nomi originali.
Nomi delle unit
Namespace stile Microsoft con prefisso WvdS:
WvdS.{Domain}.{Layer}.pas
Esempi:
WvdS.Build.Models.pas
WvdS.Build.Service.pas
WvdS.Projects.SettingsDialog.pas
WvdS.VSCode.Commands.pas
Suffissi layer
| Suffisso | Contenuto | Esempio |
| .Models | Record, enum, tipi | WvdS.Build.Models |
| .Service | Logica di business | WvdS.Build.Service |
| .Dialog | Dialoghi WebView | WvdS.Projects.SettingsDialog |
| .Provider | Wrapper API VSCode | WvdS.Designer.EditorProvider |
Variabili e parametri
| Categoria | Prefisso | Esempio |
| Campi privati | F | FProjectPath, FConfig |
| Parametri | A | APath, AOptions, ACallback |
| Variabili locali | Nessuno | Result, I, Config |
Resourcestrings
Prefisso per feature:
| Prefisso | Feature |
| rsCore* | Estensione Core |
| rsBuild* | Estensione Build |
| rsProject* | Estensione Projects |
| rsDesigner* | UI Designer |
| rsPreview* | UI Preview |
| rsMeta* | UI Meta |
| rsPackaging* | Packaging |
| rsTool* | Toolchain |
Struttura del codice
Struttura unit
unit WvdS.{Feature}.{Layer};
{$mode objfpc}{$H+}
interface
uses
// 1. Unit di sistema
SysUtils, Classes,
// 2. WvdS Common
WvdS.System, WvdS.Collections,
// 3. Specifiche della feature
WvdS.{Feature}.Models;
type
// Definizioni di tipo
function PublicFunction(const AParam: string): Boolean;
procedure PublicProcedure(AValue: Integer);
implementation
uses
// Uses privati (unit necessarie solo qui)
WvdS.VSCode.Strings;
// Tipi e variabili private
type
TInternalHelper = class
end;
var
InternalState: TObject;
// Implementazioni
function PublicFunction(const AParam: string): Boolean;
begin
// ...
end;
procedure PublicProcedure(AValue: Integer);
begin
// ...
end;
initialization
// Inizializzazione
finalization
// Pulizia
end.
Struttura classe
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;
Documentazione
(*
@abstract(Breve descrizione in una frase.)
Descrizione dettagliata dello scopo e dell'utilizzo.
Puo comprendere piu frasi.
@param(APath Percorso completo del file)
@param(AOptions Configurazione opzionale, puo essere nil)
@returns(True se successo, False in caso di errore)
@raises(EWvdSFileNotFound se il file non esiste)
@raises(EWvdSAccessDenied se non ci sono permessi di lettura)
Security:
- CWE-22: Il percorso viene validato contro Path Traversal
@seealso(RelatedFunction)
@seealso(TWvdSRelatedClass)
*)
function ProcessFile(const APath: string; AOptions: TOptions): Boolean;
// Commento breve per singola riga
Result := CalculateValue;
// Commento multiriga per logica piu complessa
// Spiega il perche, non il cosa
if (Value > Threshold) and (Mode = mAdvanced) then
begin
// Dobbiamo usare l'algoritmo avanzato qui,
// perche quello semplice diventa impreciso con valori grandi
Result := AdvancedCalculation(Value);
end;
Costanti invece di magic number
// VIETATO
if Length(Name) > 64 then
if Timeout > 30000 then
// CORRETTO
const
MAX_PROJECT_NAME_LENGTH = 64;
DEFAULT_TIMEOUT_MS = 30000;
if Length(Name) > MAX_PROJECT_NAME_LENGTH then
if Timeout > DEFAULT_TIMEOUT_MS then
Terminologia
Usare termini consistenti:
| Usa | Evita |
| Path | Url, Location, Dir (inconsistente) |
| Config | Settings, Options, Prefs (inconsistente) |
| Create | Make, Build (per oggetti) |
| Generate | Create (per output) |
| Validate | Check, Verify (per input) |
| Initialize | Setup, Init (inconsistente) |
| Execute | Run, Process (inconsistente) |
Indentazione
2 spazi per indentazione (non tab)
begin su riga propria per i blocchi
end stesso livello di indentazione del begin corrispondente
// CORRETTO
procedure Example;
begin
if Condition then
begin
DoSomething;
DoMore;
end
else
begin
DoAlternative;
end;
end;
// VIETATO
procedure Example; begin
if Condition then begin DoSomething; DoMore; end
else DoAlternative;
end;
Lunghezza riga
// Per liste parametri lunghe
function VeryLongFunctionName(
const AFirstParameter: string;
const ASecondParameter: Integer;
AThirdParameter: TOptions
): Boolean;
// Per condizioni lunghe
if (FirstCondition) and
(SecondCondition) and
(ThirdCondition) then
begin
// ...
end;
Pattern vietati
Handler eccezioni vuoti
// VIETATO
try
DoSomething;
except
// Non fare nulla - ingoiare l'errore!
end;
// CORRETTO
try
DoSomething;
except
on E: Exception do
LogError(rsUnexpectedError, [E.ClassName, E.Message]);
end;
TODO/FIXME nel codice di produzione
// VIETATO nel branch main
// TODO: Implement this later
// FIXME: This is broken
// CONSENTITO solo in branch feature, deve essere rimosso prima del merge
Stringhe hardcoded
// VIETATO
ShowMessage('File not found');
ShowMessage('File non trovato');
// CORRETTO
ShowMessage(rsFileNotFound); // resourcestring
Variabili globali nei service
// VIETATO
var
GlobalConfig: TConfig; // Difficile da testare!
// CORRETTO - passare parametri
function ProcessWithConfig(const AConfig: TConfig): Boolean;
Testabilita
I service devono essere testabili senza VSCode/UI:
// VIETATO - UI nel service
procedure ValidateAndShowError(const AName: string);
begin
if not IsValid(AName) then
ShowMessage('Invalid name'); // Dipendenza UI!
end;
// CORRETTO - valore di ritorno
function ValidateName(const AName: string; out AError: string): Boolean;
begin
Result := IsValid(AName);
if not Result then
AError := rsInvalidName;
end;
Compatibilita pas2js (IMPORTANTE)
pas2js NON e 100% compatibile con FPC! Queste limitazioni DEVONO essere rispettate.
Feature non supportate
| Feature | FPC | pas2js | Workaround |
class var | OK | No | Usare variabile a livello unit |
var inline | OK | No | Dichiarare nel blocco var |
Int64 | OK | No | Usare Integer |
| | | |