"Mach es einfach schnell lauffähig, wir refactorn das später!" – Ein Satz, den wohl jeder Softwareentwickler schon einmal gehört hat. In der Realität kommt dieses "Später" allerdings fast nie. In diesem Artikel betrachte ich aus der Praxis, warum sich der Mehraufwand für saubere Architektur fast immer auszahlt.
Die Illusion der Geschwindigkeit
Zu Beginn eines Projekts mag das "Hacken" ohne Rücksicht auf Design-Patterns schneller erscheinen. Features fliegen nur so in die Codebase. Das Problem beginnt, wenn das Projekt wächst. Ohne Konzepte wie DRY (Don't Repeat Yourself) oder das Single Responsibility Principle (SRP) fängt der Code an zu "verrotten" (Code Rot).
SOLID ist kein Buzzword
Die SOLID-Prinzipien (von Robert C. Martin) sind nicht einfach nur akademische Theorie, sondern das Fundament wartbarer Software in objektorientierten Sprachen wie C#.
- S - Single Responsibility: Eine Klasse sollte genau eine Aufgabe haben. Ein
CustomerService, der E-Mails verschickt, PDF-Rechnungen generiert und in die Datenbank schreibt, ist ein Albtraum beim Testen. - O - Open/Closed: Der Code sollte offen für Erweiterungen, aber geschlossen für Modifikationen sein. Anstatt bei jeder neuen Zahlungsmethode eine riesige
switch-Anweisung zu erweitern, nutzen wir Interfaces (IPaymentProcessor) und Dependency Injection. - D - Dependency Inversion: Wir hängen von Abstraktionen ab, nicht von konkreten Implementierungen. Genau deshalb nutzen wir in ASP.NET Core exzessiv die
IServiceCollection.
Interfaces und Dependency Injection in C#
Nehmen wir ein praktisches Beispiel. Anstatt einen Logger hart zu instanziieren, fordern wir ihn im Konstruktor an:
public class OrderService
{
private readonly ILogger<OrderService> _logger;
private readonly IOrderRepository _repository;
public OrderService(ILogger<OrderService> logger, IOrderRepository repository)
{
_logger = logger;
_repository = repository;
}
public async Task ProcessOrder(Order order)
{
_logger.LogInformation($"Processing order {order.Id}");
await _repository.SaveAsync(order);
}
}
Dieser Code ist nun zu 100% testbar. Im Unit-Test (z.B. mit xUnit und Moq) können wir das IOrderRepository einfach mocken, ohne dass wirklich etwas in eine echte Datenbank geschrieben wird.
Fazit: Wann lohnt sich "Quick & Dirty"?
Für Einweg-Skripte, kleine Proof of Concepts oder Wegwerf-Prototypen ist "Quick & Dirty" absolut legitim. Aber für produktiven Code, der über Monate oder Jahre gewartet, im Team bearbeitet und skaliert werden muss, ist fehlende Architektur die größte Kostenfalle der modernen Softwareentwicklung. Wir lesen Code zehnmal häufiger, als wir ihn schreiben. Er sollte sich wie ein gut geschriebenes Buch lesen.