CodeGuard

Erste eigene Regel

Eine team-spezifische Konvention als CodeGuard-Regel formulieren.

Erste eigene Regel

Ein typischer Fall: euer Team hat sich darauf geeinigt dass Repository-Klassen mit Repository enden müssen. Bisher wird das im PR-Review gechallenged. Mit CodeGuard wird es vom Build durchgesetzt.

Regelmenge im Repo anlegen

Im Repo-Root:

mkdir -p .codeguard/rules

In dieses Verzeichnis kommen alle .cgr-Dateien.

Die Regel schreiben

.codeguard/rules/repository-naming.cgr:

@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.StartsWith("Acme.Infrastructure.Repositories")
where !t.IsAbstract
where !t.Name.EndsWith("Repository")
select t

Anatomie:

  • @name ist der menschenlesbare Titel im Tooling.
  • @severity ist info, warn oder error.
  • @category gruppiert die Regel im Output.
  • @description beschreibt was geprüft wird.
  • @recommendation sagt wie man es fixt.
  • 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

codeguard analyze .

Wenn ihr eine Klasse namens UserData im Repository-Namespace habt, sollte sie jetzt als error rausfallen.

Was du noch alles ausdrücken kannst

Die DSL ist eine Untermenge von LINQ. Du kannst 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.StartsWith("Acme.Domain")
where t.UsedTypes.Any(u => u.Namespace.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 .cgr pro Regel. Das macht Versionierung und Suchen leichter.
  • Sprechende Dateinamen. Sie tauchen im Build-Log auf.
  • @recommendation ehrlich. Wenn die Empfehlung Müll ist, deaktivieren die Devs die Regel statt zu fixen.
  • Klein anfangen. Eine Regel die in 50 Findings resultiert ist nicht einführbar. Stuft sie auf warn ab oder schreibt sie spezifischer.

Mehr unter Best Practices.