Einleitung: Warum SOLID die Grundlage für qualitativ hochwertigen C#-Code ist
Die Entwicklung mit C# im .NET-Ökosystem erfordert nicht nur Kenntnisse der Syntax, sondern auch die Fähigkeit, flexible, wartbare und testbare Anwendungen zu entwerfen. SOLID ist ein Akronym für fünf grundlegende Prinzipien des objektorientierten Designs, formuliert von Robert Martin. Sie helfen Entwicklern, "harte" Abhängigkeiten, Code-Duplizierung und Probleme bei der Skalierung zu vermeiden.
In diesem Artikel werden wir jedes der fünf SOLID-Prinzipien in Bezug auf C# analysieren: von der Theorie bis zu realen Codebeispielen. Sie erfahren, wie Refactoring unter Berücksichtigung von SOLID Ihren Code sauberer und die Projektwartung einfacher macht.
1. Single Responsibility Principle (SRP) — Prinzip der einzigen Verantwortung
Theorie
Eine Klasse sollte nur einen Grund für eine Änderung haben. Mit anderen Worten, jede Klasse ist für genau eine Funktionalität oder Geschäftslogik verantwortlich. Wenn eine Klasse zu viel tut, wird es schwierig, sie zu testen, zu ändern und wiederzuverwenden.
Praxis: Verletzung des SRP
public class OrderProcessor{ public void ProcessOrder(Order order) { // 1. Validierung der Bestellung if (order.Total <= 0) throw new Exception("Invalid order"); // 2. Speichern in der Datenbank using var db = new AppDbContext(); db.Orders.Add(order); db.SaveChanges(); // 3. Senden einer E-Mail-Benachrichtigung SmtpClient client = new SmtpClient(); client.Send("admin@shop.com", order.CustomerEmail, "Order confirmed", "Thank you!"); }}Hier verletzt OrderProcessor das SRP: Er ist verantwortlich für die Validierung, die Datenbankarbeit und das Senden von E-Mails. Eine Änderung der Logik zum Senden von Benachrichtigungen würde eine Änderung derselben Klasse erfordern.
Refactoring mit SRP
public class OrderValidator{ public bool Validate(Order order) => order.Total > 0;}
public class OrderRepository{ public void Save(Order order) { using var db = new AppDbContext(); db.Orders.Add(order); db.SaveChanges(); }}
public class EmailService{ public void SendConfirmation(string email) { SmtpClient client = new SmtpClient(); client.Send("admin@shop.com", email, "Order confirmed", "Thank you!"); }}
public class OrderProcessor{ private readonly OrderValidator _validator; private readonly OrderRepository _repository; private readonly EmailService _emailService;
public OrderProcessor(OrderValidator validator, OrderRepository repository, EmailService emailService) { _validator = validator; _repository = repository; _emailService = emailService; }
public void ProcessOrder(Order order) { if (!_validator.Validate(order)) throw new Exception("Invalid order"); _repository.Save(order); _emailService.SendConfirmation(order.CustomerEmail); }}Jetzt hat jede Klasse einen Verantwortungsbereich. Dies vereinfacht das Testen und die Modifikation.
2. Open/Closed Principle (OCP) — Prinzip der Offenheit/Geschlossenheit
Theorie
Softwareentitäten (Klassen, Module, Funktionen) sollten für Erweiterungen offen, aber für Modifikationen geschlossen sein. Das heißt, Sie sollten in der Lage sein, neue Funktionalität hinzuzufügen, ohne vorhandenen Code zu ändern.
Praxis: Verletzung des OCP
public class ShapeDrawer{ public void DrawShape(object shape) { if (shape is Circle circle) Console.WriteLine($"Drawing circle with radius {circle.Radius}"); else if (shape is Rectangle rect) Console.WriteLine($"Drawing rectangle {rect.Width}x{rect.Height}"); // Beim Hinzufügen eines neuen Formtyps muss diese Methode geändert werden! }}Refactoring mit OCP durch Abstraktion
public abstract c