Skip to content

Erstes Finding fixen

Wie man ein konkretes Finding versteht, fixt oder bewusst ignoriert.

CodeCharter liefert ein Finding. Was jetzt? Drei Reaktionen sind möglich: fixen, bewusst unterdrücken oder die Regel deaktivieren wenn sie nicht zum Team passt.

Ein Finding lesen

Beispiel-Ausgabe:

  --- Warning (1) ---

  WARN   [Testability] Direct DateTime/DateTimeOffset usage instead of TimeProvider
        PricingEngine.Calculate
        Acme.Domain/Calculations/PricingEngine.cs:42
        ↳ Inject TimeProvider via constructor and call GetUtcNow() or GetLocalNow(). For testing, use Microsoft.Extensions.Time.Testing.FakeTimeProvider

Darin steckt:

  • Severity: Findings werden nach Severity gruppiert (--- Warning (1) ---), jedes Finding beginnt mit einem Kürzel wie WARN
  • Kategorie und Regelname: [Testability] gefolgt vom Anzeigenamen der Regel. Der Slug der Regel ist datetime-direct-usage (der Dateiname der Regel); er wird für Suppressions und Konfiguration gebraucht und ist im Wiki suchbar.
  • Betroffener Code: die Code-Stelle (PricingEngine.Calculate) sowie Datei und Zeile darunter
  • Empfehlung: die Zeile mit . Die vollständige Regelbeschreibung ist in der json-Ausgabe enthalten.

Variante A: fixen

Vor:

public class PricingEngine
{
    public decimal Calculate(decimal basePrice)
    {
        var now = DateTime.UtcNow;
        if (now.DayOfWeek == DayOfWeek.Sunday) return basePrice * 1.5m;
        return basePrice;
    }
}

Nach:

public class PricingEngine
{
    private readonly TimeProvider _time;
    public PricingEngine(TimeProvider time) => _time = time;

    public decimal Calculate(decimal basePrice)
    {
        var now = _time.GetUtcNow();
        if (now.DayOfWeek == DayOfWeek.Sunday) return basePrice * 1.5m;
        return basePrice;
    }
}

Test:

[Fact]
public void Sunday_Price_Is_Surcharged()
{
    var clock = new FakeTimeProvider();
    clock.SetUtcNow(new DateTimeOffset(2024, 1, 7, 12, 0, 0, TimeSpan.Zero)); // Sunday
    var engine = new PricingEngine(clock);
    engine.Calculate(100m).Should().Be(150m);
}

Beim nächsten codecharter analyze ist das Finding weg.

Variante B: bewusst unterdrücken

Manchmal gibt es einen guten Grund, die Regel an einer bestimmten Stelle nicht zu befolgen, z.B. in einer Migrations-Klasse, die historisch gewachsen ist und nicht angefasst wird.

Inline-Suppression direkt im Code, auf derselben Zeile:

var migrationTimestamp = DateTime.UtcNow; // codecharter-disable datetime-direct-usage

Oder auf der Zeile über der betroffenen Stelle:

// codecharter-disable datetime-direct-usage
var migrationTimestamp = DateTime.UtcNow;

Oder mit codecharter-disable-next-line, wenn explizit nur die folgende Zeile gemeint ist:

// codecharter-disable-next-line datetime-direct-usage
var migrationTimestamp = DateTime.UtcNow;

Mehrere Regel-Slugs werden durch Leerzeichen getrennt, der Slug muss exakt übereinstimmen (kleingeschrieben). Ein // codecharter-disable ohne Slug ist keine zeilenweise Suppression: Auf einer eigenen Zeile unterdrückt es alle Findings in der gesamten Datei. Mehr Details unter Suppressions.

Variante C: Regel deaktivieren

Wenn Sie eine Regel im gesamten Repo nicht haben möchten, schalten Sie sie zentral ab, statt sie an jeder Stelle einzeln zu unterdrücken.

Um eine Regel im gesamten Repository abzuschalten, fügen Sie einen ignore-Eintrag in Ihre .codecharter/config.yml ein:

version: 1
ignore:
  - rule: datetime-direct-usage

Mit in: oder match: grenzen Sie die Suppression auf einen Namespace oder passende Entity-Namen ein. Als Mittelweg können Sie die Regel behalten und nur ihre Severity senken, mit einem overrides-Eintrag (severity: error, warning oder info). Siehe Konfigurationsdatei für alle verfügbaren Abschnitte.

Ein dateiweites // codecharter-disable gibt es ebenfalls, es unterdrückt aber alle Regeln in dieser Datei, nicht nur eine. Weitere Optionen unter Suppressions.

Nutzen Sie diese Option nur, wenn die Regel wirklich nicht zum Team passt, nicht um eine einzelne Stelle zu vermeiden. Für eine konkrete Stelle ist die Inline-Suppression die richtige Wahl.

Reihenfolge der Reaktion

Faustregel:

  1. Erst überlegen ob das Finding richtig ist. Steht es im Konflikt mit einer expliziten Architektur-Entscheidung, ist die Regel falsch für das Projekt. Dann Variante C.
  2. Wenn die Regel richtig ist, aber die Stelle eine echte Ausnahme: Variante B mit Begründung im Kommentar.
  3. Sonst: Variante A. Wenn ein Finding zum Schweigen gebracht wird, ohne dass dahinter eine echte Entscheidung steckt, wird das Tooling sehr schnell wertlos.

Bestehende Findings: Baseline nutzen

Wenn Sie CodeCharter in eine bestehende Codebasis einführen, müssen Sie nicht jedes vorhandene Finding sofort fixen oder unterdrücken. Halten Sie den Ist-Zustand in einer Baseline fest:

codecharter analyze MySolution.sln --write-baseline codecharter-baseline.json

Spätere Läufe mit --baseline codecharter-baseline.json melden nur noch Findings, die nicht in der Baseline stehen.

Findings als Datei

codecharter analyze MySolution.sln --output json --output-file findings.json

analyze erwartet den Pfad zur .sln-, .slnx- oder .csproj-Datei. Damit lassen sich Findings im PR-System weiterverarbeiten, in Tickets mappen oder als Trend tracken. Format-Details unter Output-Formate.