Wird geladen...

Clean Code Prinzipien mit C#

Lernen Sie Clean Code Prinzipien mit C#, um lesbaren, wartbaren und skalierbaren Code zu schreiben.

Clean Code (Sauberer Code) ist eine Philosophie, bei der Code nicht nur funktionieren, sondern auch lesbar, wartbar und erweiterbar sein soll. Nach dem Prinzip „Code wird einmal geschrieben, aber tausendmal gelesen.“ zielt Clean Code nicht nur darauf ab, ein fehlerfreies Programm zu erstellen, sondern auch darauf, dass zukünftige Leser (einschließlich uns selbst) den Code leicht verstehen können. In diesem Artikel werden die grundlegenden Prinzipien und praktischen Beispiele für sauberen Code in C# erläutert.


1. Aussagekräftige Benennungen (Meaningful Naming)

Die Namen von Variablen, Methoden und Klassen beeinflussen die Lesbarkeit des Codes direkt. Verwenden Sie kurze, aber aussagekräftige und zweckorientierte Namen anstelle von kryptischen Abkürzungen.


// Schlechtes Beispiel
int x = 5;
var lst = new List<string>();
void DoIt() { ... }

// Gutes Beispiel
int retryCount = 5;
List<string> customerNames = new();
void ProcessOrder() { ... }

2. Single Responsibility Principle (Prinzip der einzigen Verantwortung)

Jede Klasse oder Methode sollte nur eine Verantwortung haben. Wenn eine Methode sowohl in die Datenbank schreibt als auch eine E-Mail sendet, erfüllt sie wahrscheinlich zwei verschiedene Aufgaben.


// Schlechtes Beispiel: Mehrere Verantwortlichkeiten
public class OrderService
{
    public void CompleteOrder(Order order)
    {
        SaveToDatabase(order);
        SendEmail(order);
    }
}

// Gutes Beispiel: Getrennte Verantwortlichkeiten
public class OrderRepository
{
    public void Save(Order order) { ... }
}

public class EmailService
{
    public void SendOrderConfirmation(Order order) { ... }
}

Jede Klasse sollte nur aus einem Grund geändert werden. Das verbessert die Wartbarkeit und erleichtert das Testen.


3. Kurze und fokussierte Methoden

Lange Methoden erhöhen die Komplexität und die Fehlerwahrscheinlichkeit. Jede Methode sollte eine kleine, in sich geschlossene Einheit sein, die nur eine Aufgabe erfüllt.


// Schlechtes Beispiel
public void Process()
{
    // Über 100 Zeilen Logik ...
}

// Gutes Beispiel
public void Process()
{
    Validate();
    CalculateTotal();
    SaveChanges();
    NotifyCustomer();
}

Kleine, beschreibende Methoden sind einfacher zu testen, wiederzuverwenden und zu debuggen.


4. Wiederholungen vermeiden (DRY – Don’t Repeat Yourself)

Wiederholter Code erschwert die Wartung und erhöht das Risiko von Fehlern. Verschieben Sie gemeinsame Logik in Hilfsmethoden, Utility-Klassen oder Erweiterungen.


// Schlechtes Beispiel
if (age >= 18) Console.WriteLine("Volljährig");
if (age >= 18) SendMail();

// Gutes Beispiel
bool IsAdult(int age) => age >= 18;
if (IsAdult(age)) { Console.WriteLine("Volljährig"); SendMail(); }

Wenn Sie Wiederholungen reduzieren, verringert sich die Auswirkung von Änderungen und das Fehlerrisiko sinkt.


5. Weniger Kommentare – Der Code sollte für sich selbst sprechen

Zu viele Kommentare verlieren schnell ihre Aktualität. Der Code sollte idealerweise selbsterklärend sein.


// Schlechtes Beispiel
// Druckt den Namen des Benutzers
Console.WriteLine(user.Name);

// Gutes Beispiel
Console.WriteLine(user.FullName);

Kommentare sollten erklären warum etwas getan wird, nicht was getan wird.


6. Konstanten statt Magic Numbers verwenden

Das direkte Verwenden von Zahlen oder Zeichenketten („Magic Numbers“) verringert die Lesbarkeit. Definieren Sie sie als Konstanten oder benannte Variablen.


// Schlechtes Beispiel
if (speed > 120) Console.WriteLine("Zu schnell!");

// Gutes Beispiel
const int MaxSpeed = 120;
if (speed > MaxSpeed) Console.WriteLine("Zu schnell!");

7. Guard Clauses (Schutzbedingungen) verwenden

Anstatt verschachtelter if-Blöcke sollten Sie frühzeitig zurückkehren, um die Lesbarkeit zu verbessern.


// Schlechtes Beispiel
if (user != null)
{
    if (user.IsActive)
    {
        Process(user);
    }
}

// Gutes Beispiel
if (user is null) return;
if (!user.IsActive) return;
Process(user);

Guard Clauses vereinfachen den Kontrollfluss durch die Verwendung des „Early Return“-Musters.


8. Abhängigkeiten Injizieren (Dependency Injection)

Vermeide es, Objekte direkt im Code zu erstellen. Stattdessen sollten Abhängigkeiten von außen übergeben werden – das erhöht die Testbarkeit und Flexibilität.


// Schlechtes Beispiel
public class NotificationService
{
    private EmailSender sender = new EmailSender();
    public void Notify() => sender.Send();
}

// Gutes Beispiel
public class NotificationService
{
    private readonly IEmailSender _sender;
    public NotificationService(IEmailSender sender) => _sender = sender;
    public void Notify() => _sender.Send();
}

Dieser Ansatz ist die Grundlage der Prinzipien Inversion of Control (IoC) und Dependency Injection (DI).


9. Ausnahmebehandlung (Exception Management)

Fange Ausnahmen nur ab, wenn es notwendig ist – und behandle sie dann sinnvoll.


// Schlechtes Beispiel
try
{
    Save();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

// Gutes Beispiel
try
{
    Save();
}
catch (SqlException ex)
{
    _logger.LogError(ex, "Datenbankfehler aufgetreten.");
    throw; // an die höhere Ebene weitergeben
}

Breite catch (Exception)-Blöcke erschweren die Fehlerbehandlung und verbergen häufig Probleme.


10. Befolge die SOLID-Prinzipien

Sauberer Code steht im Einklang mit den SOLID-Prinzipien:

Diese Prinzipien bilden das Fundament für sauberen, wartbaren Code.


11. Vermeide unnötige Komplexität (KISS & YAGNI)


// Schlechtes Beispiel
public interface IAnimal { void Bark(); void Fly(); void Swim(); }

// Gutes Beispiel
public interface IDog { void Bark(); }
public interface IFish { void Swim(); }

Code sollte einfach, zielgerichtet und nicht übermäßig generalisiert sein.


12. Formatierung und Konsistenz


// Beispiel .editorconfig
[*.cs]
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true

Beispiel: Bereinigung eines Bestellservices

Im folgenden Beispiel wird ein komplexer und schwer wartbarer Code mithilfe von Clean-Code-Prinzipien überarbeitet.


// Schlechtes Beispiel
public class OrderManager
{
    public void Process(Order order)
    {
        if (order.Total <= 0) throw new Exception("Ungültiger Betrag");
        Console.WriteLine("Bestellung verarbeitet: " + order.Id);
        File.AppendAllText("log.txt", DateTime.Now + " - " + order.Id);
    }
}

// Gutes Beispiel
public interface ILogger { void Log(string msg); }
public class FileLogger : ILogger
{
    public void Log(string msg) => File.AppendAllText("log.txt", $"{DateTime.Now} - {msg}\n");
}

public class OrderValidator
{
    public void Validate(Order order)
    {
        if (order.Total <= 0) throw new ArgumentException("Betrag muss größer als 0 sein");
    }
}

public class OrderService
{
    private readonly ILogger _logger;
    private readonly OrderValidator _validator;

    public OrderService(ILogger logger, OrderValidator validator)
    {
        _logger = logger;
        _validator = validator;
    }

    public void Process(Order order)
    {
        _validator.Validate(order);
        Console.WriteLine($"Bestellung verarbeitet: {order.Id}");
        _logger.Log($"Bestellung {order.Id} verarbeitet.");
    }
}

Jetzt hat jede Klasse eine klare Verantwortung – der Code ist testbar, lesbar und wartbar.


TL;DR

  • Clean Code bedeutet Lesbarkeit und Wartbarkeit.
  • Aussagekräftige Namen, kurze Methoden, Single Responsibility und kein Code-Duplikat sind entscheidend.
  • Bevorzuge gute Namensgebung, Guard Clauses und Dependency Injection statt übermäßiger Kommentare.
  • Reduziere Komplexität (KISS, YAGNI) und halte dich an die SOLID-Prinzipien.
  • Schreibe Code sowohl für Menschen als auch für Maschinen.

Ähnliche Artikel