Enterprise C#: Wie man Code schreibt, den man bei Code-Reviews zeigen kann

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

Enterprise C#: Warum Code für eine Bank und Code für ein Pet-Projekt zwei verschiedene Welten sind

\n\n

Wenn Sie jemals von einem kleinen Webstudio in einen großen Konzern oder Fintech gewechselt sind, kennen Sie dieses Gefühl des leichten Kulturschocks. Gestern konnten Sie noch einen „heißen Fix“ ohne Tests und mit einem einzigen Kommentar //TODO: refactor committen, und heute erhalten Sie ein Review mit 20 Anmerkungen, bei dem jede öffentliche Methode eine XML-Dokumentation erfordert und jede Abhängigkeit im DI-Container registriert werden muss.

\n\n

Entwicklung mit C# im Enterprise-Umfeld geht nicht um „schnell machen“, sondern darum, „es so zu machen, dass es in drei Jahren nicht kaputt geht, wenn der Autor des Codes bereits entlassen wurde“. Es geht um Vorhersagbarkeit, Skalierung und endlose Code-Reviews. Lassen Sie uns anschauen, woraus die Enterprise-Entwicklung mit C# tatsächlich besteht und wie Sie nicht schon in der ersten Woche durchfallen.

\n\n

1. Architektur: SOLID ist kein Modewort, sondern ein Gesetz

\n\n

In einem Startup können Sie sich einen Monolithen mit „magischen“ Strings und riesigen Klassen mit 2000 Zeilen leisten. Im Enterprise nicht. Hier ist jedes SOLID-Prinzip keine Abstraktion, sondern eine Handlungsanleitung.

\n\n

Single Responsibility Principle (SRP)

\n

Ihre Klasse sollte nicht wissen, wie man gleichzeitig E-Mails sendet, in die Datenbank speichert und XML parst. Wenn Sie in einer Klasse drei oder mehr „Verantwortlichkeiten“ sehen – das ist ein Alarmzeichen. Im Enterprise wird solcher Code im Code-Review mit der Begründung „SRP-Verletzung, neu schreiben“ abgewiesen. Beispiel für schlechten Code:

\n\n
public class OrderService\n{\n    public void ProcessOrder(Order order)\n    {\n        // 1. Validierung\n        // 2. Speichern in DB\n        // 3. E-Mail senden\n        // 4. Logging\n    }\n}
\n\n

Der richtige Ansatz ist die Aufteilung in separate Dienste und die Verwendung des Mediator- oder Pipeline-Musters:

\n\n
public class ProcessOrderCommandHandler : IRequestHandler<ProcessOrderCommand, bool>\n{\n    private readonly IOrderRepository _repo;\n    private readonly IEmailService _email;\n    private readonly ILogger<ProcessOrderCommandHandler> _logger;\n\n    public ProcessOrderCommandHandler(IOrderRepository repo, IEmailService email, ILogger<ProcessOrderCommandHandler> logger)\n    {\n        _repo = repo;\n        _email = email;\n        _logger = logger;\n    }\n\n    public async Task<bool> Handle(ProcessOrderCommand request, CancellationToken cancellationToken)\n    {\n        var order = await _repo.GetByIdAsync(request.OrderId);\n        // Logik\n        await _email.SendAsync(order.CustomerEmail, "Order processed");\n        _logger.LogInformation("Order {Id} processed", order.Id);\n        return true;\n    }\n}
\n\n

Beachten Sie: Jeder Dienst macht genau eine Sache. Solchen Code zu testen ist um ein Vielfaches einfacher.

\n\n

2. Dependency Injection – Ihr bester Freund

\n\n

In Enterprise-Projekten mit C# werden Sie fast nie new MyService() innerhalb einer Klasse sehen. Stattdessen kommt ein DI-Container zum Einsatz (normalerweise Autofac oder der integrierte Microsoft.Extensions.DependencyInjection).

\n\n

Die Regel ist einfach: Wenn eine Klasse ihre Abhängigkeiten selbst erstellt, verstößt sie gegen das Dependency Inversion Principle. Im Enterprise wird dies als Architekturfehler betrachtet. Beispiel:

\n\n
// ❌ Schlecht: feste Kopplung\npublic class ReportGenerator\n{\n    private readonly PdfExporter _exporter = new PdfExporter();\n    public byte[] Generate() => _exporter.Export();\n}\n\n// ✅ Gut: Abhängigkeitsinversion\npublic class ReportGenerator\n{\n    private readonly IExporter _exporter;\n    public ReportGenerator(IExporter exporter) => _exporter = exporter;\n    public byte[] Generate() => _exporter.Export();\n}
\n\n

Registrierung im Startup:

\n
services.AddScoped<IExporter, PdfExporter>();\nservices.AddScoped<ReportGenerator>();
\n\n

Wozu das Ganze? Erstens für Tests: Sie können IExporter mocken und müssen nicht

Blogs

Buchempfehlungen