Delphi-spec-kit Delphi Clean Code

Pragmatic clean code standards for Delphi — concise, direct, no over-engineering

install
source · Clone the upstream repo
git clone https://github.com/delphicleancode/delphi-spec-kit
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/delphicleancode/delphi-spec-kit "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.gemini/skills/clean-code" ~/.claude/skills/delphicleancode-delphi-spec-kit-delphi-clean-code-e5de7f && rm -rf "$T"
manifest: .gemini/skills/clean-code/SKILL.md
source content

Delphi Clean Code — Skill

CRITICAL SKILL — Be concise, direct and solution-focused.

Fundamental Principles

PrincipleRule
SRPA function/class does ONE thing
DRYDon't repeat code — extract and reuse
KISSSimplest solution that works
YAGNIDon't build what wasn't asked for
Boy ScoutLeave the code better than you found it

Naming Rules (Pascal Guide)

ElementConvention
VariablesReveal intent:
LCustomerCount
not
N
MethodsVerb + noun:
GetCustomerById
not
Customer
BooleansQuestion form:
IsActive
,
HasPermission
,
CanEdit
ConstantsSCREAMING_SNAKE:
MAX_RETRY_COUNT
FieldsPrefix
F
:
FCustomerName
ParametersPrefix
A
:
ACustomerName
Var. locationsPrefix
L
:
LCustomer

Rule: If you need a comment to explain a name, rename it.

Method Rules

RuleDescription
ShortMaximum 20 lines, ideal 5-10
One ThingDo one thing and do it well
One LevelOne level of abstraction per method
Few ArgsMaximum 3 arguments, prefer 0-2
No Side EffectsDon't mute inputs unexpectedly

Code Structure

StandardApplication
Guard ClausesEarly returns for edge cases
Flat > NestedAvoid deep nesting (max 2 levels)
CompositionSmall compound methods
ColocationRelated code together

Guard Clauses in Delphi

// ❌ RUIM — nesting excessivo
procedure ProcessOrder(AOrder: TOrder);
begin
  if Assigned(AOrder) then
  begin
    if AOrder.Items.Count > 0 then
    begin
      if AOrder.IsValid then
      begin
        // logic real aqui
      end;
    end;
  end;
end;

// ✅ BOM — guard clauses
procedure ProcessOrder(AOrder: TOrder);
begin
  if not Assigned(AOrder) then
    raise EArgumentNilException.Create('AOrder cannot be nil');
  if AOrder.Items.Count = 0 then
    raise EBusinessRuleException.Create('Order must have items');
  if not AOrder.IsValid then
    raise EValidationException.Create('Order validation failed');

  // logic real aqui — sem nesting
end;

Anti-Patterns (DO NOT DO)

❌ Pattern✅ Fix
Comment each lineDelete obvious comments
Method > 20 linesShare by responsibility
Magic numbersNamed constants
with
statement
Explicit local variables
Global variablesConstructor injection
Generic CatchSpecific exceptions
Logic in
OnClick
Delegate to Service
God class / God unityOne class = one responsibility
Ignore
Free
try/finally
always

Memory Management

// ✅ Objetos temporários — sempre try/finally
LList := TStringList.Create;
try
  LList.Add('item');
  // usar LList
finally
  LList.Free;
end;

// ✅ Interfaces — reference counting automático
var LService: IMyService;
LService := TMyService.Create; // liberado automaticamente

// ✅ Owner pattern para componentes visuais
LButton := TButton.Create(Self); // Self libera automaticamente

AI Code Style

SituationAction
User requests featureWrite directly
User reports bugCorrect, don't explain
Requirement unclearAsk, don't assume

🔴 Before Editing (THINK FIRST!)

QuestionWhy
Which units use this?They can break
What does this unit matter?Interfaces can change
What tests cover this?Tests may fail
Is it a shared component?Multiple points affected

🔴 Rule: Edit the file + all dependents in the SAME task.

🔴 Self-Check (MANDATORY)

CheckPergunta
Goal achieved?Did I do exactly what was asked?
Edited files?Have I modified everything necessary?
Does the code work?Have I tested/verified?
No errors?Compiles without warnings?
Nothing forgotten?Edge cases treated?
Memory safe?Objects released correctly?

🔴 Rule: If ANY check fails, correct it before finishing.