Verhältnis zu anderen Seiten: dieses Tutorial führt euch Schritt für Schritt durch das Schreiben eurer ersten Regel. Syntax-Übersicht ist die kompakte Alltagsreferenz; DSL-Grammatik ist der formale Anhang.
Die einfachste sinnvolle CodeCharter-Regel hat neun Zeilen. Hier ist sie:
@name "Class must not be named Manager"
@severity warn
@category "Naming"
@description "Classes called *Manager are vague, name them after what they actually do"
@recommendation "Pick a verb-based name: OrderProcessor, EmailDispatcher, PriceCalculator"
from t in Types
where t.Kind == "Class"
where t.Name.EndsWith("Manager")
select t
Speichert das als rules/no-manager-suffix.ccr in eurem Repo. Wenn ihr
nicht bei null anfangen möchtet: codecharter init legt das rules/-Verzeichnis
mit zwei Beispielregeln für euch an und deklariert es unter rules: in
.codecharter/config.yml. Habt ihr das Verzeichnis selbst angelegt, deklariert
es einmal mit codecharter config add rules rules. Startet die Analyse dann aus dem
Repo-Root. analyze erwartet den Pfad zu einer .sln-, .slnx- oder
.csproj-Datei:
codecharter analyze MySolution.sln
Der Lauf liest das deklarierte rules/-Verzeichnis, die Rules:-Zeile auf
stderr bestätigt es. Wenn ihr eine Klasse mit Manager-Suffix habt, taucht sie
als Finding auf.
Was passiert hier
Fünf Zeilen Metadaten und vier Zeilen Query. Gehen wir das durch.
Metadaten
Alle Direktiven sind optional und haben sinnvolle Defaults. Der Regel-Slug
kommt aus dem Dateinamen (no-manager-suffix), nicht aus @name. @name ist
der menschenlesbare Titel, der im CI-Log und den Output-Formaten erscheint;
wenn er fehlt, wird der Dateiname verwendet. @severity hat den Default
warn. Auch unbekannte @severity-Werte fallen auf warn zurück; achtet
also auf Tippfehler.
@name "Class must not be named Manager"
@severity warn
@category "Naming"
@description "..."
@recommendation "..."
| Direktive | Pflicht | Default | Beschreibung |
|---|---|---|---|
@name |
nein | Dateiname | Menschenlesbarer Titel |
@severity |
nein | warn |
info, warn oder error |
@category |
nein | General |
Frei wählbar, gruppiert verwandte Regeln |
@description |
nein | -- | Was die Regel prüft |
@recommendation |
nein | -- | Wie man es fixt |
Alle sind optional, aber @name, @description und @recommendation auszufüllen macht Findings deutlich hilfreicher.
Query
Der Body ist eine LINQ-Query gegen das Code-Modell:
from t in Types // alle Typen
where t.Kind == "Class" // nur Klassen
where t.Name.EndsWith("Manager") // mit Manager-Suffix
select t // gibt alle Treffer als Findings zurück
Kommentare in .ccr-Dateien nutzen //. select t ist der Pflicht-Abschluss.
Was ihr selektiert, wird zum Finding. t ist ein TypeModel, also zeigt das
Finding auf die Datei und Zeile, wo t deklariert ist.
Variante: Mehrere Suffixe verbieten
@name "No vague class suffixes"
@severity warn
from t in Types
where t.Kind == "Class"
where t.Name.EndsWith("Manager")
|| t.Name.EndsWith("Helper")
|| t.Name.EndsWith("Util")
select t
Bedingungen lassen sich mit && und || kombinieren. Die Query-Sprache
unterstützt eine feste Auswahl an LINQ-artigen Methoden wie Where, Any,
OrderBy und Count; die Syntax-Übersicht listet, was
verfügbar ist.
Variante: Mehrere Bedingungen kombinieren
Eine Regel, die nur Klassen findet, die zu groß sind und zu viele Felder haben:
@name "Large class with many fields, split candidate"
@severity warn
@category "Design"
from t in Types
where t.Kind == "Class"
where t.LinesOfCode > 400
where t.Fields.Count > 15
select t
Die Regel testen
codecharter test rules/no-manager-suffix.ccr --scaffold legt eine
Starter-Spec-Datei rules/no-manager-suffix.spec.md neben der Regel an. Tragt
dort Code-Schnipsel ein, die die Regel treffen bzw. nicht treffen soll, und
prüft die Regel anschließend mit codecharter test rules/ dagegen.
Weitere Beispiele
Die Seite Regel-Beispiele enthält eine Galerie fertiger Regeln nach Kategorie, darunter das vollständige Manager-Suffix- und Async/CancellationToken-Beispiel. Dort weiterlesen, sobald die Grundlagen sitzen.
Wo geht's weiter
- Datei-Struktur, wie das
rules/-Verzeichnis aufgebaut ist - Syntax-Übersicht, Collections-Übersicht und Query-Formen
- Prädikat-Katalog, vollständige Property-Liste aller Modell-Typen
- Best Practices, was gute von schlechten Regeln unterscheidet