Umstieg auf .NET Core, Teil 1: Migrieren oder nicht migrieren?

Seite 2: Sollte man auf .NET Core migrieren?

Inhaltsverzeichnis

Wer bei .NET Framework verbleibt, begibt sich allerdings auf ein Abstellgleis. Microsoft wird nur noch .NET Core (beziehungsweise .NET 5, .NET 6, .NET 7 usw.) aktiv weiterentwickeln. Hin und wieder wird vielleicht ein Nuget-Paket veröffentlicht, das auch auf dem klassischen .NET Framework läuft – wie im Fall der neuen JSON-Bibliothek. Aber es wird auch immer mehr Bibliotheken geben, die nur noch auf .NET Core laufen, wie etwa ASP.NET Core und Entity Framework Core, die bisher nicht nur in .NET Core, sondern auch auf dem klassischen .NET Framework liefen. In der Version 3.0 erfordern sie aber den .NET Standard 2.1, den es nicht auf dem klassischen .NET Framework gibt – das bleibt bei .NET Standard 2.0 in .NET Framework 4.8 stehen. Auch einige Sprachfeatures in C# 8.0, darunter Ranges, Indexe und asynchrone Streams, erfordern Klassen, die es in .NET Standard 2.0 nicht gibt und die somit in .NET Framework 4.8 nicht verfügbar sind.

Für Entity Framework Core 3.1 hat Microsoft das zwar inzwischen revidiert: die Preview-2-Version von Entity Framework Core 3.1 basiert wieder auf .NET Standard 2.0. Das soll aber der letzte derartige Kompromiss gewesen sein.

Mit dem Umstieg auf .NET Core lässt sich nicht nur Stillstand vermeiden, es gibt auch noch weitere positive Anreize für die Migration:

  1. NET Core ist plattfomunabhängig und nicht wie .NET Framework auf Windows beschränkt. Allerdings gilt diese Aussage nur eingeschränkt. Wenn man die UI-Frameworks Windows Forms und Windows Presentation Foundation (WPF) in .NET Core verwendet (das ist seit Version 3.0 möglich), klebt man auch mit .NET Core auf Windows fest.
  2. .NET Core bietet in vielen Klassen eine höhere Ausführungsgeschwindigkeit. Microsoft hat laut eigener Aussage viel Arbeit in die Leistungsoptimierung der Common Language Runtime (CLR) und der Basisklassen in .NET Core investiert. Basis dafür sind die in .NET Core 2.x/C# 7.x eingeführten neuen Sprachfeatures und Speicherverwaltungsklassen Span<T> und Memory<T>. Auch die modulare Architektur von .NET Core hilft, die Ressourcen des ausführenden Systems zu schonen.
  3. Neben einem vereinfachten Projektformat bietet .NET Core auch zahlreiche Kommandozeilenwerkzeuge, die den Einsatz außerhalb von Visual Studio sowie die Integration in automatisierte DevOps-Prozesse vereinfachen.
  4. Die Verbreitung .NET-Core-basierter Anwendungen ist einfacher, weil Entwickler nicht mehr wie bisher zunächst ein .NET-Framework-Setup ausführen müssen, sondern die komplette .NET-Core-Laufzeitumgebung mit der eigenen Anwendung ausliefern können (Self Contained Deployment). Dadurch lassen sich beliebig viele Versionen der .NET-Core-Laufzeitumgebung auf einem Rechner parallel betreiben. Somit entfällt auch das erneute Testen aller anderen Anwendungen, weil für eine Anwendung nur ein Laufzeitumgebungs-Update erforderlich ist.
  5. Zu guter Letzt finden sich in den .NET-Core-basierten Anwendungsframeworks auch interessante neue Softwarearchitekturen und Konzepte, darunter Razor Pages, Razor Class Librarys, Tag Helper sowie die Entwicklung von Single-Page-Web-Apps mit Blazor.

Wer schon mit .NET Core arbeitet, der weiß, dass .NET Core auch einige Nachteile mit sich bringt. Festzuhalten ist zunächst, dass nicht alle Funktionen aus dem klassischen .NET Framework in .NET Core verfügbar sind. Wie in Abbildung 1 zu erkennen ist, gibt es immer noch rund 50.000 APIs (Microsoft zählt hier nicht Klassen, sondern einzelne Properties und Methoden), die das klassische .NET Framework dem .NET Core voraus hat. Microsoft hat in diesem Zusammenhang angekündigt, dass die Übertragung von APIs aus dem klassischen .NET Framework zu .NET Core abgeschlossen sei. Damit steht fest, dass es nach .NET Core 3.0 keine weitere Übernahme von Funktionen aus .NET Framework zu .NET Core mehr geben wird. Was jetzt nicht drin ist, das bleibt zusammen mit dem klassischen .NET Framework auf dem Abstellgleis zurück (siehe Abbildung 2).

Techniken, die es nicht aus dem klassischen .NET Framework zu .NET Core schaffen, und mögliche Alternativen (Abb. 2).

Fehlende Programmierschnittstellen bedingen auch, dass nicht alle Bibliotheken von Drittanbietern wie einige der grafischen Bibliotheken auf .NET Core laufen können. Das macht eine Umstellung auf .NET Core für betroffene Kunden unmöglich.

Weitere Nachteile in .NET Core sind:

  • .NET Core folgt dem Konzept des Semantic Versioning, das Breaking Changes in Hauptversionen erlaubt. Microsoft hat davon beim Wechsel von .NET Core 1.1 zu 2.0 sowie von 2.2 zu 3.0 jeweils umfassend Gebrauch gemacht, wie die lange Liste der Breaking Changes in Entity Framework Core 3.0 anschaulich zeigt. Anders als beim klassischen .NET Framework kann man sich also in .NET Core nicht darauf verlassen, dass eine einige Jahre alte Anwendung auch noch auf einer aktuellen Version der Runtime lauffähig ist. Versionsumstellungen sind daher mit viel Arbeit verbunden.
  • Erschwerend kommt die radikal verkürzte Support-Dauer hinzu. Beim klassischen .NET Framework gab es in der Regel zehn Jahre Support – Ausnahmen davon betrafen jedoch 4.0, 4.5 und 4.5.1. Bei .NET Core gibt es für ein Long-Term-Support-Release (LTS) drei Jahre Support, für ein Current Release nur drei Monate nach dem Erscheinen des nächsten. Microsoft hat somit den Support für .NET Core 1.0, 1.1 und 2.0 bereits eingestellt. Die Version 2.2 flog am 23.12.2019 aus dem Support. Lediglich die LTS-Version 2.1 wird noch bis Mitte 2021 unterstützt (siehe Abbildung 3). Nicht wenige Nutzer des klassischen .NET Framework haben konservativ agiert und viele Jahre auf die gleiche Version vertraut. Mit .NET Core werden sie zu einer Agilität gezwungen, die sie zumindest bisher nicht wollten.

Support-Dauer der im Umlauf befindlichen .NET Core-Versionen (Abb. 3).

(Bild: Microsoft )

  • Die Dokumentation aller Core-Produkte hat nicht mehr den Umfang, die Tiefe und die Aktualität, die das klassische .NET Framework bot. So finden sich in der Klassendokumentation nur noch kurze Texte und keine Beispiele mehr.
  • Das Nuget-Paketsystem hat trotz aller Verbesserungen der letzten Jahre immer noch technische Probleme (siehe Abbildung 4): Pakete lassen sich nicht installieren oder deinstallieren, oder sich widersprechende Paketversionsanforderungen führen in die "Pakethölle". Für die Paketverwaltung einschließlich der ständigen Nachverfolgung, ob Pakete beispielsweise wegen Sicherheitslücken zu aktualisieren sind, müssen Anwender überdurchschnittlich viel Arbeitszeit einplanen.

Nuget-Bug: Ein Paket ist installiert, wird aber dennoch vom Compiler nicht gefunden (Abb. 4).

Ein Kunde kommentierte diese Mischung aus Agilität und verkürztem Support neulich so: ".NET Core ist nichts für die deutsche Industrie! Wir werden alternative Techniken prüfen müssen". Das beschreibt eindrücklich die Erwartung an Konstanz, die zumindest diese Branche hat. Da aber auch andere Frameworks zur Softwareentwicklung sich inzwischen dem agilen Ansatz verschrieben haben, wird sich auch die deutsche Industrie künftig bewegen müssen – im Zweifelsfall durch mehr Personaleinsatz in der Softwareentwicklung.

Der API-Browser von .NET bietet zu jeder Klasse und jedem Klassenmitglied die Informationen, auf welchen .NET-Varianten die APIs verfügbar sind. Die Migrierbarkeit des eigenen Programmcodes anhand dieser Daten zu ermitteln, erweist sich jedoch als unnötig mühsamer Weg.

Stattdessen empfiehlt sich der Einsatz des Werkzeugs .NET Portability-Analyzer, das zu einem bestehenden .NET Framework-Projekt eine Excel-Datei der in .NET Core nicht unterstützten Klassen und Klassenmitglieder liefert. Zu beachten ist aber, dass das Werkzeug die API-Nutzung aus dem eigenen Quellcode an einen Microsoft-Webservice überträgt und erst dort die Ergebnisse generiert. Anhand eines Windows-Forms-Projekt zeigen die Abbildungen 5 und 6 die Zusammenfassung sowie einen Ausschnitt aus den Detailergebnissen.

Zusammenfassung des .NET Portability-Analyzer für ein Windows Forms-Projekt (Abb. 5).

Die Detailliste zeigt, welche Klassen und Klassenmitglieder in .NET Core 3.0 fehlen (Abb. 6).

Als "Platform Extensions" bezeichnet Microsoft Zusatzklassen für .NET Core, die nicht zum Standardlieferumfang der .NET Core gehören. Dazu zählen insbesondere die .NET Core Windows Desktop Runtime, die Windows Forms und WPF enthält sowie das Windows Compatibility Pack für .NET Core, ein Metapaket, das viele nichtvisuelle Klassen wie den Zugriff auf Registry, Zugriffsrechtelisten, Ereignisprotokoll, Performance-Counter, Systeminformationen, ODBC-Datenbanken, LDAP-Server und Grafikfunktionen sowie das alte Code Document Object Model (CodeDOM) zur Laufzeitcodeauswertung und -generierung umfasst.