Refactoring von Legacy-Code in C#: von A bis Z

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Legacy-Code ein Refactoring benötigt?

\n\n

Jeder Entwickler, der mit der .NET-Plattform arbeitet, stößt früher oder später auf Legacy-Code. Das sind Programme, die in älteren Versionen von C# (z. B. .NET Framework 4.x) geschrieben wurden, veraltete Muster wie DataTable in ASP.NET Web Forms oder monolithische Klassen mit tausenden von Zeilen verwenden. Solcher Code ist eine Quelle technischer Schulden: Er ist schwer zu warten, enthält versteckte Fehler und bremst die Einführung neuer Funktionen.

\n\n

Refactoring ist der Prozess der Änderung der internen Struktur von Code, ohne sein externes Verhalten zu verändern. In diesem Artikel werden wir einen schrittweisen Plan für das Refactoring von Legacy-Code in C# durchgehen, von der Diagnose bis zur Einführung moderner Praktiken. Sie erfahren, wie Sie ein altes Projekt mit .NET-Tools und bewährten Techniken sicher verbessern können.

\n\n

1. Diagnose und Vorbereitung: Wo anfangen?

\n\n

Bevor Sie den Code ändern, müssen Sie seinen aktuellen Zustand verstehen. Ohne Analyse riskieren Sie, die Funktionalität zu beschädigen.

\n\n

1.1. Bewertung der technischen Schulden

\n

Verwenden Sie Code-Analysatoren, die in Visual Studio integriert oder über NuGet verfügbar sind:

\n
    \n
  • Roslyn-Analysatoren — finden potenzielle Fehler und veraltete Konstrukte.
  • \n
  • SonarQube (oder SonarCloud) — bewertet Codequalität, Duplikate und Komplexität.
  • \n
  • NDepend — visualisiert Abhängigkeiten zwischen Klassen und Modulen.
  • \n
\n\n

1.2. Schreiben von Tests als Sicherheitsnetz

\n

Refactoring ohne Tests ist russisches Roulette. Bei Legacy-Code gibt es oft keine Unit-Tests. Beginnen Sie mit dem Schreiben von Charakterisierungstests (characterization tests), die das aktuelle Verhalten festhalten:

\n\n
// Beispieltest für eine alte Methode\n[Test]\npublic void CalculateDiscount_ShouldReturn10Percent_WhenOrderTotalIsGreaterThan100()\n{\n    // Arrange\n    var legacyClass = new OrderProcessor();\n    var order = new Order { Total = 150 };\n    \n    // Act\n    var result = legacyClass.CalculateDiscount(order);\n    \n    // Assert\n    Assert.AreEqual(15, result); // 10% von 150\n}
\n\n

Erstellen Sie Tests für kritische Pfade. So können Sie sicher refactoren, da Sie wissen, dass sich das Verhalten nicht ändert.

\n\n

1.3. Strategiewahl: "Die Gartenstrategie"

\n

Versuchen Sie nicht, das gesamte Projekt auf einmal zu refactoren. Wählen Sie ein Modul oder eine Klasse aus, die die meisten Probleme verursacht (hohe Komplexität, häufige Fehler). Arbeiten Sie iterativ: kleine Schritte, häufige Commits.

\n\n

2. Wichtige Refactoring-Techniken für Legacy-Code in C#

\n\n

Betrachten wir die wichtigsten Methoden, um "Spaghetti-Code" in eine saubere Architektur zu verwandeln.

\n\n

2.1. Beseitigung von God-Objekten (große Klassen)

\n

Legacy-Code enthält oft Klassen, die alles machen: mit der Datenbank arbeiten, Daten validieren, E-Mails senden. Verwenden Sie das Single-Responsibility-Prinzip (SRP).

\n\n

Vor dem Refactoring:

\n
public class UserService\n{\n    public void RegisterUser(string name, string email)\n    {\n        // Validierung\n        if (string.IsNullOrEmpty(name)) throw new Exception();\n        \n        // Datenbankarbeit\n        using (var conn = new SqlConnection("..."))\n        {\n            conn.Execute("INSERT INTO Users ...");\n        }\n        \n        // E-Mail-Versand\n        SmtpClient client = new SmtpClient();\n        client.Send(new MailMessage(...));\n    }\n}
\n\n

Nach dem Refactoring:

\n
public class UserService\n{\n    private readonly IUserRepository _userRepository;\n    private readonly IEmailService _emailService;\n    private readonly IValidator<UserRegistration> _validator;\n\n    public UserService(IUserRepository repo, IEmailService email, IValidator<UserRegistration> validator)\n    {\n        _userRepository = repo;\n        _emailService = email;\n        _validator = validator;\n    }\n\n    public void RegisterUse                

Blogs

Buchempfehlungen