Skip to content

Erste eigene Regel

Eine team-spezifische Konvention als CodeCharter-Regel formulieren.

Ein typischer Fall: Ihr Team hat sich darauf geeinigt, dass Repository-Klassen mit Repository enden müssen. Bisher wird das im PR-Review nur angemerkt. Mit CodeCharter wird es vom Build durchgesetzt.

Regelmenge im Repo anlegen

Im Repo-Root:

mkdir -p rules

In dieses Verzeichnis kommen alle .ccr-Dateien. Die CLI findet Regeln im Verzeichnis rules/ im aktuellen Arbeitsverzeichnis automatisch, ohne weitere Konfiguration. Liegen Ihre Regeln woanders, geben Sie das Verzeichnis mit --rules <dir> an.

Die Regel schreiben

rules/repository-naming.ccr:

@name "Repository class must end in 'Repository'"
@severity error
@category "Naming"
@description "Implementations of the Repository pattern must have a 'Repository' suffix for discoverability"
@recommendation "Rename the class to end with 'Repository', e.g. 'UserData' -> 'UserRepository'"

from t in Types
where t.Kind == "Class"
where t.Namespace.FullName.StartsWith("Acme.Infrastructure.Repositories")
where !t.IsAbstract
where !t.Name.EndsWith("Repository")
select t

Anatomie:

  • @name ist der menschenlesbare Titel im Tooling. Der Slug der Regel (der in Findings und Suppressions erscheint) ist der Dateiname ohne Erweiterung, also für diese Regel repository-naming.
  • @severity ist info, warn oder error. Standard ist warn, wenn weggelassen.
  • @category gruppiert die Regel im Output (optional).
  • @description beschreibt, was geprüft wird (optional, aber empfohlen).
  • @recommendation sagt, wie man es behebt (optional, aber empfohlen).
  • Body: eine LINQ-Query gegen das Schema. Hier suchen wir Klassen im Repository-Namespace, die nicht abstrakt sind und deren Name nicht auf "Repository" endet.

Lokal probieren

Prüfen Sie zuerst, ob die Regel parst und typkorrekt ist:

codecharter validate rules/repository-naming.ccr

Dann starten Sie die Analyse. Das Argument von analyze ist der Pfad zu einer .sln-, .slnx- oder .csproj-Datei:

codecharter analyze MySolution.sln

Wenn Ihre Solution eine Klasse namens UserData im Repository-Namespace enthält, erscheint sie jetzt als error.

Hinweis: Läuft die Analyse nur mit einem lokalen rules/-Verzeichnis und ohne Plattform-Profile, erscheint auf stderr ein [DEPRECATION]-Hinweis, der auf Plattform-Profile verweist. Die Analyse läuft trotzdem normal durch.

Ob die Regel wirklich anschlägt, prüfen Sie am besten mit einer Spec aus Hit- und Miss-Fällen: codecharter test rules/repository-naming.ccr --scaffold erzeugt eine repository-naming.spec.md neben der Regel, und codecharter test rules/ führt alle Specs aus.

Was sich noch alles ausdrücken lässt

Die DSL ist eine Untermenge von LINQ. Sie können auf alle Typ-, Methoden-, Property-, Feld-, Event-, Namespace- und Assembly-Eigenschaften zugreifen. Beispiele:

// Methoden ohne CancellationToken finden
from m in Methods
where m.IsAsync
where !m.Parameters.Any(p => p.TypeShortName == "CancellationToken")
where m.AccessModifier == "Public"
select m
// Layer-Verletzung: Domain referenziert Web
from t in Types
where t.Namespace.FullName.StartsWith("Acme.Domain")
where t.UsedTypes.Any(u => u.Namespace.FullName.StartsWith("Acme.Web"))
select t
// Klassen mit zu vielen Methoden
from t in Types
where t.Kind == "Class"
where t.NumberOfMethods > 25
select t

Schema-Übersicht und weitere Details unter Syntax-Übersicht.

Best Practices für eigene Regeln

  • Eine Regel pro .ccr-Datei. Das ist eine Eigenschaft des Formats: jede .ccr-Datei enthält genau eine Query, und der Dateiname wird zur Rule-ID.
  • Sprechende Dateinamen. Sie tauchen im Build-Log auf.
  • @recommendation ehrlich. Wenn die Empfehlung nichts taugt, deaktivieren die Entwickler die Regel, statt sie zu beheben.
  • Klein anfangen. Eine Regel, die zu 50 Findings führt, lässt sich nicht einführen. Stufen Sie sie auf warn ab oder formulieren Sie sie spezifischer.

Mehr unter Best Practices.