Karl Gorman
24
Februar
2015
Tags: .NET Core.NET FrameworkEntwicklung
.NET 2015

Einführung in .NET Core

Lassen Sie uns zunächst zurückblicken, um zu verstehen, wie die .NET-Plattform in der Vergangenheit verpackt wurde. Dies hilft dabei, einige der Entscheidungen und Ideen zu motivieren, die zur Erstellung von .NET Core geführt haben.

.NET – eine Reihe von Vertikalen

Als wir das .NET Framework im Jahr 2002 ursprünglich auslieferten, gab es nur ein einziges Framework. Kurz darauf veröffentlichten wir das .NET Compact Framework, das eine Teilmenge des .NET Frameworks darstellte, die in den Footprint kleinerer Geräte, insbesondere Windows Mobile, passte. Das Compact Framework war eine vom .NET Framework getrennte Codebasis. Es enthielt die gesamte Vertikale: eine Laufzeit, ein Framework und ein Anwendungsmodell darüber.

Seitdem haben wir diese Unterteilungsübung viele Male wiederholt: Silverlight, Windows Phone und zuletzt für den Windows Store. Dies führt zu einer Fragmentierung, da die .NET-Plattform nicht eine einzige Einheit ist, sondern eine Reihe von Plattformen, die verschiedenen Teams gehören und unabhängig voneinander gepflegt werden.

Natürlich ist es nicht falsch, spezialisierte Funktionen anzubieten, um einen bestimmten Bedarf zu decken. Aber es wird zum Problem, wenn es keinen systematischen Ansatz gibt und die Spezialisierung auf jeder Ebene stattfindet, ohne Rücksicht auf die entsprechenden Ebenen in anderen Branchen. Das Ergebnis ist eine Reihe von Plattformen, die nur aufgrund der Tatsache, dass sie von einer gemeinsamen Codebasis ausgehen, gemeinsame APIs nutzen. Mit der Zeit führt dies zu mehr Divergenz, es sei denn, es werden explizite (und teure) Maßnahmen zur Konvergenz der APIs ergriffen.

Was ist das Problem mit der Fragmentierung? Wenn Sie nur ein einziges vertikales Ziel haben, gibt es eigentlich kein Problem. Ihnen wird ein API-Set zur Verfügung gestellt, das für Ihre Vertikale optimiert ist. Das Problem entsteht, sobald Sie auf die Horizontale, also mehrere Vertikale, abzielen wollen. Jetzt müssen Sie sich Gedanken über die Verfügbarkeit von APIs machen und einen Weg finden, Assets zu produzieren, die in allen Vertikalen funktionieren, auf die Sie abzielen wollen.

Heutzutage ist es äußerst üblich, Anwendungen zu haben, die sich über mehrere Geräte erstrecken: Es gibt praktisch immer ein Backend, das auf dem Webserver läuft, es gibt oft ein administratives Frontend, das den Windows-Desktop verwendet, und eine Reihe von mobilen Anwendungen, die für den Verbraucher bestimmt sind und für mehrere Geräte verfügbar sind. Daher ist es wichtig, Entwickler bei der Erstellung von Komponenten zu unterstützen, die alle .NET-Vertikale überspannen können.

promo image3
Auf der Suche nach einer neuen Herausforderung?

Interessante Projekte

Zuverlässige Arbeitgeber

Faire Vergütung

Geburt der portablen Klassenbibliotheken

Ursprünglich gab es kein Konzept für die gemeinsame Nutzung von Code über vertikale Grenzen hinweg. Keine portablen Klassenbibliotheken, keine gemeinsamen Projekte. Sie waren im Wesentlichen darauf angewiesen, mehrere Projekte, verknüpfte Dateien und #if zu erstellen. Dies machte die Ausrichtung auf mehrere Branchen zu einer entmutigenden Aufgabe. Im Zeitrahmen von Windows 8 haben wir einen Plan entwickelt, um dieses Problem zu lösen. Als wir das Windows Store-Profil entwarfen, führten wir ein neues Konzept ein, um das Subsetting auf eine bessere Art und Weise zu modellieren: Verträge.

Ursprünglich wurde das .NET Framework unter der Annahme entwickelt, dass es immer als eine einzige Einheit bereitgestellt wird, so dass die Faktorisierung kein Problem darstellte. Die eigentliche Kern-Assembly, von der alles andere abhängt, ist die mscorlib. Die vom .NET Framework bereitgestellte mscorlib enthält viele Funktionen, die nicht überall unterstützt werden können (z. B. Remoting und AppDomains). Dies zwingt jede Vertikale dazu, selbst den Kern der Plattform zu subseten. Dies machte es sehr kompliziert, eine Klassenbibliothek so zu gestalten, dass man mehrere Vertikale ansprechen kann.

Die Idee von Verträgen ist es, eine gut durchdachte API-Fläche bereitzustellen. Verträge sind einfach Assemblies, gegen die Sie kompilieren. Im Gegensatz zu regulären Assemblies sind Contracts-Assemblies auf eine gute Faktorisierung ausgelegt. Wir achten sehr auf die Abhängigkeiten zwischen Verträgen und darauf, dass sie nur eine einzige Verantwortung haben, anstatt eine Wundertüte von APIs zu sein. Verträge werden unabhängig voneinander versioniert und folgen korrekten Versionierungsregeln, z. B. führt das Hinzufügen von APIs zu einer neueren Version der Baugruppe.

Wir verwenden Verträge, um API-Sets für alle Branchen zu modellieren. Die Vertikalen können dann einfach auswählen, welche Verträge sie unterstützen wollen. Der wichtige Aspekt ist, dass vertikale Organisationen einen Vertrag entweder vollständig oder gar nicht unterstützen müssen. Mit anderen Worten, sie können den Inhalt eines Vertrags nicht unterteilen. Dies ermöglicht eine Argumentation über die API-Unterschiede zwischen den Vertikalen auf der Baugruppenebene, im Gegensatz zur individuellen API-Ebene, die wir vorher hatten. Dieser Aspekt ermöglichte es uns, eine Klassenbibliothek bereitzustellen, die auf mehrere Vertikalen ausgerichtet werden kann, auch bekannt als portable Klassenbibliotheken.

Einheitliche API-Form versus einheitliche Implementierung

Sie können sich portable Klassenbibliotheken als eine Erfahrung vorstellen, die die verschiedenen .NET-Vertikalen basierend auf ihrer API-Form vereinheitlicht. Damit wurde das dringendste Bedürfnis angesprochen, nämlich die Möglichkeit, Bibliotheken zu erstellen, die auf verschiedenen .NET-Vertikalen laufen. Es diente auch als Design-Tool, um die Konvergenz zwischen den Vertikalen voranzutreiben, zum Beispiel zwischen Windows 8.1 und Windows Phone 8.1.

Es gibt jedoch immer noch verschiedene Implementierungen – oder Forks – der .NET-Plattform. Diese Implementierungen gehören verschiedenen Teams, sind unabhängig voneinander versioniert und haben unterschiedliche Transportmittel. Dies macht die Vereinheitlichung der API-Form zu einer ständigen Herausforderung: APIs sind nur portabel, wenn die Implementierung über alle Vertikalen hinweg vorangetrieben wird, aber da die Codebasen unterschiedlich sind, ist das ziemlich teuer und unterliegt daher immer einer (Neu-)Priorisierung. Und selbst wenn wir einen perfekten Job mit der Konvergenz der APIs machen könnten: Die Tatsache, dass alle Vertikalen unterschiedliche Versandvehikel haben, bedeutet, dass ein Teil des Ökosystems immer hinterherhinken wird.

Ein viel besserer Ansatz ist die Vereinheitlichung der Implementierungen: Anstatt nur eine gut faktorisierte Ansicht bereitzustellen, sollten wir eine gut faktorisierte Implementierung bereitstellen. Dies würde es den Vertikalen ermöglichen, einfach die gleiche Implementierung zu verwenden. Konvergenz wäre nicht mehr etwas Zusätzliches; sie wird durch die Konstruktion erreicht. Natürlich gibt es immer noch Fälle, in denen wir mehrere Implementierungen benötigen. Ein gutes Beispiel ist die Datei-I/O, die je nach Umgebung den Einsatz unterschiedlicher Technologien erfordert. Es ist jedoch viel einfacher, jedes Team, das eine bestimmte Komponente besitzt, zu bitten, sich Gedanken darüber zu machen, wie ihre APIs über alle Bereiche hinweg funktionieren, als zu versuchen, nachträglich einen konsistenten API-Stack auf die Beine zu stellen. Das liegt daran, dass Portabilität nicht etwas ist, das man nachträglich bereitstellen kann. Unsere Datei-APIs enthalten zum Beispiel Unterstützung für Windows Access Control Lists (ACL), die nicht in allen Umgebungen unterstützt werden können. Das Design der APIs muss dies berücksichtigen und z. B. diese Funktionalität in einer separaten Assembly bereitstellen, die auf Plattformen, die ACLs nicht unterstützen, weggelassen werden kann.

Maschinenweite Frameworks versus anwendungslokale Frameworks

Eine weitere interessante Herausforderung hat damit zu tun, wie das .NET Framework eingesetzt wird. Das .NET Framework ist ein maschinenübergreifendes Framework. Alle Änderungen, die daran vorgenommen werden, wirken sich auf alle Anwendungen aus, die von diesem Framework abhängig sind. Ein maschinenweites Framework war eine bewusste Entscheidung, weil es diese Probleme löst:

1. Es ermöglicht eine zentrale Wartung
2. Es reduziert den Speicherplatz
3. Ermöglicht die gemeinsame Nutzung nativer Bilder durch Anwendungen

Aber es hat auch seinen Preis.

Zum einen ist es für Anwendungsentwickler kompliziert, eine Abhängigkeit von einem kürzlich veröffentlichten Framework zu nehmen. Sie müssen entweder eine Abhängigkeit vom neuesten Betriebssystem annehmen oder ein Anwendungsinstallationsprogramm bereitstellen, das in der Lage ist, das .NET Framework zu installieren, wenn die Anwendung installiert wird. Wenn Sie ein Webentwickler sind, haben Sie möglicherweise nicht einmal diese Möglichkeit, da die IT-Abteilung Ihnen vorschreibt, welche Version Sie verwenden dürfen. Und wenn Sie ein mobiler Entwickler sind, haben Sie wirklich keine andere Wahl als das Betriebssystem, auf das Sie abzielen.

Aber selbst wenn Sie bereit sind, sich die Mühe zu machen, ein Installationsprogramm bereitzustellen, um das .NET Framework-Setup einzuketten, können Sie feststellen, dass die Aktualisierung des .NET Frameworks andere Anwendungen kaputt machen kann.

Moment mal – sagen wir nicht, dass unsere Upgrades hochkompatibel sind? Sind wir. Und wir nehmen Kompatibilität extrem ernst. Wir haben strenge Prüfungen für alle Änderungen, die am .NET Framework vorgenommen werden. Und für alles, was eine bahnbrechende Änderung sein könnte, haben wir spezielle Prüfungen, um die Auswirkungen zu untersuchen. Wir betreiben ein Kompatibilitätslabor, in dem wir viele beliebte .NET-Anwendungen testen, um sicherzustellen, dass wir sie nicht zurückstufen. Wir haben auch die Möglichkeit, festzustellen, gegen welches .NET Framework die Anwendung kompiliert wurde. Dadurch können wir die Kompatibilität mit bestehenden Anwendungen aufrechterhalten und gleichzeitig ein besseres Verhalten für Anwendungen bieten, die sich für eine spätere Version des .NET Frameworks entschieden haben.

Leider haben wir auch gelernt, dass selbst kompatible Änderungen Anwendungen kaputt machen können. Lassen Sie mich ein paar Beispiele nennen:

  • Das Hinzufügen einer Schnittstelle zu einem vorhandenen Typ kann Anwendungen unterbrechen, da es die Serialisierung des Typs beeinträchtigen kann.
  • Das Hinzufügen einer Überladung zu einer Methode, die vorher keine Überladungen hatte, kann Reflection-Consumer kaputt machen, die nie das Finden von mehr als einer Methode behandelt haben.
  •  Das Umbenennen eines internen Typs kann Anwendungen unterbrechen, wenn der Typname über eine ToString()-Methode aufgetaucht ist.

Das sind alles seltene Fälle, aber wenn Sie einen Kundenstamm von 1,8 Milliarden Rechnern haben, kann eine 99,9%ige Kompatibilität immer noch bedeuten, dass 1,8 Millionen Rechner betroffen sind. Interessanterweise ist es in vielen Fällen ziemlich trivial, betroffene Anwendungen zu reparieren. Das Problem ist jedoch, dass der Anwendungsentwickler nicht unbedingt involviert ist, wenn der Bruch auftritt. Lassen Sie uns ein konkretes Beispiel betrachten.

Sie haben Ihre Anwendung mit .NET Framework 4 getestet, und das haben Sie auch mit Ihrer App installiert. Aber eines Tages hat einer Ihrer Kunden eine andere Anwendung installiert, die den Rechner auf .NET Framework 4.5 aktualisiert hat. Sie wissen nicht, dass Ihre Anwendung defekt ist, bis dieser Kunde Ihren Support anruft. An diesem Punkt ist die Behebung des Kompatibilitätsproblems in Ihrer Anwendung ziemlich kostspielig, da Sie die entsprechenden Quellen beschaffen, eine Repro-Maschine einrichten, die Anwendung debuggen, die notwendigen Änderungen vornehmen, sie in den Release-Zweig integrieren, eine neue Version Ihrer Software produzieren, sie testen und schließlich ein Update für Ihre Kunden freigeben müssen.

Vergleichen Sie dies mit dem Fall, in dem Sie sich entscheiden, die Vorteile einer Funktion zu nutzen, die in einer späteren Version des .NET Frameworks veröffentlicht wird. An diesem Punkt im Entwicklungsprozess sind Sie bereits darauf vorbereitet, Änderungen an Ihrer Anwendung vorzunehmen. Wenn es eine kleine Kompatibilitätsstörung gibt, können Sie diese einfach als Teil der Feature-Arbeit behandeln. Aufgrund dieser Probleme dauert es eine Weile, bis eine neue Version des .NET Frameworks veröffentlicht wird. Und je drastischer die Änderung ist, desto mehr Zeit brauchen wir, um sie zu backen. Das führt zu der paradoxen Situation, dass unsere Betas bereits ziemlich abgeschlossen sind und wir so gut wie keine Design-Änderungswünsche annehmen können.

Vor zwei Jahren haben wir begonnen, Bibliotheken über NuGet auszuliefern. Da wir diese Bibliotheken nicht in das .NET Framework aufgenommen haben, bezeichnen wir sie als „Out-of-Band“. Out-of-Band-Bibliotheken leiden nicht unter dem Problem, das wir gerade besprochen haben, weil sie anwendungslokal sind. Mit anderen Worten: Die Bibliotheken werden so bereitgestellt, als wären sie Teil Ihrer Anwendung. Damit sind so ziemlich alle Probleme gelöst, die Sie daran hindern, auf eine neuere Version zu aktualisieren. Ihre Fähigkeit, eine neuere Version zu nehmen, wird nur durch Ihre Fähigkeit begrenzt, eine neuere Version Ihrer Anwendung zu veröffentlichen. Es bedeutet auch, dass Sie die Kontrolle darüber haben, welche Version der Bibliothek von einer bestimmten Anwendung verwendet wird. Upgrades werden im Kontext einer einzelnen Anwendung durchgeführt, ohne Auswirkungen auf andere Anwendungen, die auf demselben Rechner laufen.

Dies ermöglicht es uns, Updates auf eine viel agilere Weise zu veröffentlichen. NuGet bietet auch das Konzept der Vorschauversionen, die es uns ermöglichen, Bits zu veröffentlichen, ohne sich auf eine bestimmte API oder ein bestimmtes Verhalten festzulegen. Dies unterstützt einen Arbeitsablauf, bei dem wir Ihnen unser neuestes Design zur Verfügung stellen können und – wenn es Ihnen nicht gefällt – es einfach ändern können. Ein gutes Beispiel dafür sind unveränderliche Sammlungen. Es gab eine Beta-Phase von etwa neun Monaten. Wir haben viel Zeit damit verbracht, das Design richtig hinzubekommen, bevor wir die allererste Version ausgeliefert haben. Unnötig zu sagen, dass das endgültige Design – dank des umfangreichen Feedbacks, das Sie uns gegeben haben – viel besser ist als die erste Version.

.NET Core eingeben

All diese Aspekte haben uns dazu veranlasst, den Ansatz der Modellierung der .NET-Plattform zu überdenken und zu ändern. Dies resultierte in der Schaffung von .NET Core:

.NET Core ist eine modulare Implementierung, die in einer Vielzahl von Branchen eingesetzt werden kann, vom Rechenzentrum bis zu Touch-basierten Geräten skaliert, als Open Source verfügbar ist und von Microsoft auf Windows, Linux und Mac OSX unterstützt wird.

Lassen Sie mich ein wenig mehr ins Detail gehen, wie .NET Core aussieht und wie es die zuvor besprochenen Probleme angeht.

Einheitliche Implementierung für .NET Native und ASP.NET

Als wir .NET Native entwickelt haben, war klar, dass wir das .NET Framework nicht als Grundlage für die Framework-Klassenbibliotheken verwenden können. Das liegt daran, dass .NET Native im Wesentlichen das Framework mit der Anwendung verschmilzt und dann die Teile entfernt, die von der Anwendung nicht benötigt werden, bevor es den nativen Code generiert (ich vereinfache diesen Prozess hier grob. Für weitere Details werfen Sie einen Blick auf diesen Deep Dive). Wie ich bereits erklärt habe, ist die .NET Framework-Implementierung nicht faktorisiert, was es für einen Linker ziemlich schwierig macht, den Anteil des Frameworks, der in die Anwendung kompiliert wird, zu reduzieren – der Abhängigkeitsabschluss ist einfach zu groß.

ASP.NET 5 stand vor ähnlichen Herausforderungen. Obwohl es kein .NET Native verwendet, war eines der Ziele des neuen ASP.NET 5 Web-Stacks, einen implementierbaren Stack bereitzustellen, damit Web-Entwickler sich nicht mit ihrer IT-Abteilung abstimmen müssen, um Abhängigkeiten von späteren Versionen zu übernehmen. In diesem Szenario ist es auch wichtig, die Größe des Frameworks zu minimieren, da es zusammen mit der Anwendung bereitgestellt werden muss.

.NET Core ist im Wesentlichen ein Fork des NET Frameworks, dessen Implementierung ebenfalls um Factoring Concerns herum optimiert ist. Auch wenn die Szenarien von .NET Native (Touch-basierte Geräte) und ASP.NET 5 (serverseitige Webentwicklung) recht unterschiedlich sind, konnten wir eine einheitliche Base Class Library (BCL) bereitstellen.

Die API-Fläche für die .NET Core BCL ist sowohl für .NET Native als auch für ASP.NET 5 identisch. An der Unterseite der BCL haben wir eine sehr dünne Schicht, die spezifisch für die .NET-Laufzeit ist. Wir haben derzeit zwei Implementierungen: eine, die spezifisch für die .NET Native-Laufzeit ist, und eine, die spezifisch für die CoreCLR ist, die von ASP.NET 5 verwendet wird. Diese Schicht ändert sich jedoch nicht sehr oft. Sie enthält Typen wie String und Int32. Der Großteil der BCL sind reine MSIL-Assemblies, die unverändert weitergegeben werden können. Mit anderen Worten, die APIs sehen nicht nur gleich aus – sie haben auch die gleiche Implementierung. Zum Beispiel gibt es keinen Grund, unterschiedliche Implementierungen für Sammlungen zu haben.

Zusätzlich zur BCL gibt es app-modellspezifische APIs. Beispielsweise bietet die .NET Native-Seite APIs, die spezifisch für die Windows-Client-Entwicklung sind, wie z. B. WinRT-Interop. ASP.NET 5 fügt APIs wie MVC hinzu, die spezifisch für die serverseitige Webentwicklung sind.

Wir denken, dass .NET Core weder für .NET Native noch für ASP.NET 5 spezifisch ist – die BCL und die Laufzeiten sind universell und modular aufgebaut. Als solches bildet es die Grundlage für alle zukünftigen .NET-Verticals.

NuGet als erstklassiges Liefervehikel

Im Gegensatz zum .NET Framework wird die .NET Core-Plattform als eine Reihe von NuGet-Paketen ausgeliefert. Wir haben uns für NuGet entschieden, weil sich dort bereits der Großteil des Bibliotheks-Ökosystems befindet. Um unser Bestreben, modular und gut durchdacht zu sein, fortzusetzen, stellen wir nicht einfach die gesamte .NET Core-Plattform als ein einziges NuGet-Paket bereit. Stattdessen handelt es sich um eine Reihe von feinkörnigen NuGet-Paketen:

Für die BCL-Schicht werden wir eine 1:1-Beziehung zwischen Assemblies und NuGet-Paketen haben. In Zukunft wird das NuGet-Paket denselben Namen wie die Assembly haben. Beispielsweise werden unveränderliche Sammlungen nicht mehr in einem NuGet-Paket namens Microsoft.Bcl.Immutable bereitgestellt, sondern in einem Paket namens System.Collections.Immutable.

Darüber hinaus haben wir uns für die Verwendung der semantischen Versionierung für unsere Assembly-Versionierung entschieden. Die Versionsnummer des NuGet-Pakets wird mit der Assembly-Version übereinstimmen. Die Angleichung der Benennung und Versionierung zwischen Assemblys und Paketen hilft enorm bei der Erkennung. Es ist nicht länger ein Rätsel, welches NuGet-Paket System.Foo, Version=1.2.3.0 enthält – es wird vom System.Foo-Paket in Version 1.2.3 bereitgestellt.

NuGet ermöglicht es uns, .NET Core auf agile Weise bereitzustellen. Wenn wir also ein Upgrade für eines der NuGet-Pakete bereitstellen, können Sie einfach die entsprechende NuGet-Referenz aktualisieren. Durch die Bereitstellung des Frameworks selbst über NuGet wird auch der Unterschied zwischen dem Ausdruck von 1st-Party-.NET-Abhängigkeiten und 3rd-Party-Abhängigkeiten aufgehoben – sie sind alle NuGet-Abhängigkeiten. So kann ein 3rd-Party-Paket z. B. ausdrücken, dass es eine höhere Version der System.Collections-Bibliothek benötigt. Die Installation dieses 3rd-Party-Pakets kann Sie nun auffordern, Ihre Referenz auf System.Collections zu aktualisieren. Sie müssen den Abhängigkeitsgraphen nicht verstehen – Sie müssen nur zustimmen, dass

Änderungen an ihm vorgenommen werden.

Die NuGet-basierte Bereitstellung macht die .NET Core-Plattform außerdem zu einem app-lokalen Framework. Der modulare Aufbau von .NET Core sorgt dafür, dass jede Anwendung nur das bereitstellen muss, was sie benötigt. Wir arbeiten auch daran, Smart Sharing zu ermöglichen, wenn mehrere Anwendungen die gleichen Framework-Bits verwenden. Das Ziel ist jedoch, sicherzustellen, dass jede Anwendung logischerweise ihr eigenes Framework hat, so dass ein Upgrade andere Anwendungen, die auf demselben Rechner laufen, nicht beeinträchtigt. Unsere Entscheidung, NuGet als Bereitstellungsmechanismus zu verwenden, ändert nichts an unserer Verpflichtung zur Kompatibilität. Wir nehmen die Kompatibilität weiterhin sehr ernst und werden keine API- oder verhaltensverändernden Änderungen vornehmen, sobald ein Paket als stabil markiert ist. Die app-lokale Bereitstellung stellt jedoch sicher, dass der seltene Fall, dass eine Änderung, die als additiv angesehen wird, eine Anwendung bricht, nur auf die Entwicklungszeit beschränkt ist. Mit anderen Worten, für .NET Core können diese Brüche nur auftreten, nachdem Sie eine Paketreferenz aktualisiert haben. In diesem Moment haben Sie zwei Möglichkeiten: den Kompatibilitätsfehler in Ihrer Anwendung zu beheben oder auf die vorherige Version des NuGet-Pakets zurückzusetzen. Aber im Gegensatz zum .NET Framework treten diese Brüche nicht auf, nachdem Sie die Anwendung bei einem Kunden oder auf dem Produktionsserver bereitgestellt haben.

Unternehmenstauglich

Das NuGet-Bereitstellungsmodell ermöglicht agile Releases und schnellere Upgrades. Wir möchten jedoch nicht die One-Stop-Shop-Erfahrung gefährden, die das .NET Framework heute bietet. Eine der großartigen Eigenschaften des .NET Frameworks ist, dass es als ganzheitliche Einheit ausgeliefert wird, was bedeutet, dass Microsoft alle Komponenten als eine Einheit getestet und unterstützt hat. Für .NET Core werden wir die gleiche Erfahrung bieten. Wir werden den Begriff einer .NET Core-Distribution schaffen. Dies ist im Wesentlichen nur ein Schnappschuss aller Pakete in der spezifischen Version, die wir getestet haben.

Die Idee ist, dass unsere Teams im Allgemeinen individuelle Pakete besitzen. Die Auslieferung einer neuen Version des Pakets des Teams erfordert nur, dass das Team seine Komponente testet, und zwar im Zusammenhang mit den Komponenten, von denen sie abhängen. Da Sie in der Lage sein werden, NuGet-Pakete zu mischen und anzupassen, kann es natürlich Fälle geben, in denen bestimmte Kombinationen von Komponenten nicht gut zusammenspielen. Distributionen werden dieses Problem nicht haben, da alle Komponenten in Kombination getestet werden. Wir erwarten, dass Distributionen in einer geringeren Kadenz ausgeliefert werden als einzelne Pakete. Wir denken derzeit an bis zu vier Mal pro Jahr. Das berücksichtigt die Zeit, die wir brauchen, um die notwendigen Tests, Korrekturen und Abnahmen durchzuführen.

Obwohl .NET Core als eine Reihe von NuGet-Paketen ausgeliefert wird, bedeutet dies nicht, dass Sie jedes Mal Pakete herunterladen müssen, wenn Sie ein Projekt erstellen möchten. Wir werden einen Offline-Installer für die Distributionen bereitstellen und diese auch in Visual Studio einbinden, sodass das Erstellen neuer Projekte so schnell wie heute sein wird und keine Internetverbindung im Entwicklungsprozess benötigt wird. Während das app-lokale Deployment großartig ist, um die Auswirkungen der Übernahme von Abhängigkeiten auf neuere Features zu isolieren, ist es nicht für alle Fälle geeignet. Kritische Sicherheitsfixes müssen schnell und ganzheitlich bereitgestellt werden, um effektiv zu sein. Wir setzen uns voll und ganz für die Bereitstellung von Sicherheitsfixes ein, wie wir es schon immer für .NET getan haben.

Um die Kompatibilitätsprobleme zu vermeiden, die wir in der Vergangenheit mit zentralisierten Updates für das .NET Framework gesehen haben, ist es wichtig, dass diese nur auf die Sicherheitslücken abzielen. Natürlich gibt es immer noch eine kleine Chance, dass diese bestehende Anwendungen zerstören. Deshalb machen wir dies nur bei wirklich kritischen Problemen, bei denen es akzeptabel ist, dass eine sehr kleine Anzahl von Anwendungen nicht mehr funktioniert, anstatt alle Anwendungen mit der Sicherheitslücke laufen zu lassen.

Stiftung für Open Source und Cross-Plattform

Um .NET nachhaltig plattformübergreifend zu machen, haben wir uns für Open Source .NET Core entschieden. Aus Erfahrung wissen wir, dass der Erfolg von Open Source von der Community abhängt. Ein wichtiger Aspekt dabei ist ein offener und transparenter Entwicklungsprozess, der es der Community ermöglicht, an Code-Reviews teilzunehmen, Design-Dokumente zu lesen und Änderungen am Produkt beizutragen.

Open Source ermöglicht es uns, die Vereinheitlichung von .NET auf die plattformübergreifende Entwicklung auszuweiten. Es schadet dem Ökosystem aktiv, wenn grundlegende Komponenten wie Collections mehrfach implementiert werden müssen. Das Ziel von .NET Core ist es, eine einzige Codebasis zu haben, die für die Entwicklung und Unterstützung aller Plattformen verwendet werden kann, einschließlich Windows, Linux und Mac OSX. Natürlich erfordern bestimmte Komponenten, wie z. B. das Dateisystem, unterschiedliche Implementierungen. Das NuGet-Bereitstellungsmodell ermöglicht es uns, diese Unterschiede zu abstrahieren. Wir können ein einziges NuGet-Paket haben, das mehrere Implementierungen bereitstellt, eine für jede Umgebung. Das Wichtigste ist jedoch, dass es sich um ein Implementierungsdetail dieser Komponente handelt. Alle Verbraucher sehen eine einheitliche API, die zufällig über alle Plattformen hinweg funktioniert.

Eine andere Sichtweise ist, dass Open Source eine Fortsetzung unseres Wunsches ist, .NET-Komponenten in einer agilen Art und Weise zu veröffentlichen:

  • Open Source bietet quasi Echtzeit-Kommunikation für die Umsetzung und Gesamtausrichtung
  •  Die Freigabe von Paketen auf NuGet.org bietet Agilität auf Komponentenebene
  •  Distributionen bieten Agilität auf der Plattform-Ebene

Mit allen drei Elementen können wir ein breites Spektrum an Agilität und Reife bieten.

Beziehung von .NET Core zu bestehenden Plattformen

Obwohl wir .NET Core so konzipiert haben, dass es die Grundlage für alle zukünftigen Stacks wird, sind wir uns des Dilemmas sehr bewusst, den „einen universellen Stack“ zu schaffen, den jeder verwenden kann:

Wir glauben, dass wir ein gutes Gleichgewicht zwischen der Schaffung der Grundlage für die Zukunft und der Beibehaltung einer großen Interoperabilität mit den bestehenden Stacks gefunden haben. Ich werde mehr ins Detail gehen, indem ich mir einige dieser Plattformen anschaue.

.NET Framework 4.6

Das .NET Framework ist immer noch die Plattform der Wahl für die Erstellung von Rich-Desktop-Anwendungen und .NET Core ändert daran nichts. Für Visual Studio 2015 ist es unser Ziel, sicherzustellen, dass .NET Core eine reine Teilmenge des .NET Entwickler ist. Mit anderen Worten: Es würde keine Funktionslücken geben. Nach der Veröffentlichung von Visual Studio 2015 ist unsere Erwartung, dass .NET Core schneller versioniert wird als das .NET Framework. Das bedeutet, dass es Zeitpunkte geben wird, an denen ein Feature nur auf den .NET Core-basierten Plattformen verfügbar sein wird.

Wir werden weiterhin Updates für .NET Framework veröffentlichen. Derzeit gehen wir davon aus, dass die Veröffentlichungshäufigkeit in etwa die gleiche sein wird wie heute, d. h. etwa einmal pro Jahr. In diesen Updates werden wir die Innovationen, die wir in .NET Core entwickelt haben, in das .NET Framework einbringen. Wir werden jedoch nicht einfach blind alle Funktionen portieren – dies wird auf einer Kosten-Nutzen-Analyse basieren. Wie ich bereits erwähnt habe, können selbst additive Änderungen am .NET Framework Probleme für bestehende Anwendungen verursachen. Unser Ziel ist es, API- und Verhaltensunterschiede zu minimieren und gleichzeitig die Kompatibilität mit bestehenden .NET Framework-Anwendungen nicht zu unterbrechen. Es gibt auch Investitionen, die ausschließlich für das .NET Framework getätigt werden, wie die Arbeiten, die wir in der WPF-Roadmap angekündigt haben.

Mono

Viele von Ihnen haben gefragt, was die .NET Core Cross-Plattform-Geschichte für Mono bedeutet. Das Mono-Projekt ist im Wesentlichen eine Open-Source-Re-Implementierung des .NET Frameworks. Als solches teilt es den Reichtum der APIs mit dem .NET Framework, aber es teilt auch einige seiner Probleme, insbesondere rund um die Implementierung Factoring. Mono ist lebendig und hat ein großes Ökosystem an der Spitze. Deshalb haben wir, unabhängig von .NET Core, auch Teile des .NET Framework Reference Source unter einer Open-Source-freundlichen Lizenz auf GitHub veröffentlicht. Dies geschah, um der Mono-Community zu ermöglichen, die Lücken zwischen dem .NET Framework und Mono zu schließen, indem sie denselben Code verwenden. Aufgrund der Komplexität des .NET Frameworks sind wir jedoch nicht in der Lage, es als Open-Source-Projekt auf GitHub zu betreiben. Insbesondere sind wir nicht in der Lage, Pull-Requests dafür zu akzeptieren.

Eine andere Art, es zu betrachten: Das .NET Framework hat im Wesentlichen zwei Abzweigungen. Ein Fork wird von Microsoft bereitgestellt und ist nur für Windows geeignet. Der andere Fork ist Mono, den man auf Linux und Mac verwenden kann. Mit .NET Core sind wir in der Lage, einen kompletten .NET-Stack als vollständiges Open-Source-Projekt zu entwickeln. Damit entfällt die Notwendigkeit, separate Forks zu pflegen: Gemeinsam mit der Mono-Community werden wir .NET Core für Windows, Linux und Mac OSX fit machen. Dies ermöglicht es der Mono-Community auch, auf dem schlankeren .NET Core-Stack Innovationen zu entwickeln und ihn auch in Umgebungen zu bringen, an denen Microsoft nicht interessiert ist.

Windows Store & Windows Phone

Sowohl die Windows Store 8.1 als auch die Windows Phone 8.1 Plattform sind viel kleinere Untermengen des .NET Frameworks. Sie sind jedoch auch eine Untermenge von .NET Core. Dies ermöglicht es uns, .NET Core als zugrundeliegende Implementierung für diese beiden Plattformen zu verwenden. Wenn Sie also für diese Plattformen entwickeln, sind Sie in der Lage, alle Innovationen direkt zu nutzen, ohne auf ein aktualisiertes Framework warten zu müssen.

Es bedeutet auch, dass die Anzahl der BCL-APIs, die auf beiden Plattformen verfügbar sind, identisch mit denjenigen sein wird, die Sie heute in ASP.NET 5 sehen können. Dazu gehören zum Beispiel nicht-generische Sammlungen. Dadurch wird es für Sie viel einfacher, bestehenden Code, der auf dem .NET Framework läuft, in die Touch-basierte Anwendungserfahrung zu bringen. Ein weiterer offensichtlicher Nebeneffekt ist, dass die BCL-APIs in Windows Store und Windows Phone vollständig konvergiert sind und konvergiert bleiben werden, da die zugrunde liegende .NET-

Plattform nun beide von .NET Core angetrieben wird.

Gemeinsame Nutzung von Code zwischen .NET Core und anderen .NET-Plattformen
Eine andere Sichtweise ist, dass Open Source eine Fortsetzung unseres Wunsches ist, .NET-Komponenten in einer agilen Art und Weise zu veröffentlichen:

  •   Portable Klassenbibliotheken sind großartig, wenn Ihr gemeinsamer Code plattformunabhängig ist, aber auch für wiederverwendbare Bibliotheken, bei denen der plattformspezifische Code ausgeklammert werden kann.
  •   Gemeinsame Projekte sind großartig, wenn Ihr gemeinsamer Code ein paar Bits plattformspezifischen Code hat, da Sie ihn mit #if anpassen können.

In Zukunft werden portable Klassenbibliotheken auch die Ausrichtung auf .NET Core-basierte Plattformen unterstützen. Der einzige Unterschied ist, dass Sie, wenn Sie nur auf .NET Core-basierte Plattformen abzielen, keinen festen API-Satz erhalten. Stattdessen basiert es auf NuGet-Paketen, die Sie nach Belieben aktualisieren können. Wenn Sie auch auf mindestens eine Plattform abzielen, die nicht auf .NET Core basiert, sind Sie durch die APIs eingeschränkt, die mit dieser Plattform gemeinsam genutzt werden können. In diesem Modus können Sie immer noch NuGet-Pakete aktualisieren, aber Sie werden möglicherweise aufgefordert, höhere Plattformversionen auszuwählen oder die Unterstützung für diese komplett einzustellen. Dieser Ansatz ermöglicht es Ihnen, in beiden Welten zu koexistieren und dennoch die Vorteile von .NET Core zu nutzen.

Zusammenfassung

Die .NET Core-Plattform ist ein neuer .NET-Stack, der für Open-Source-Entwicklung und agile Bereitstellung über NuGet optimiert ist. Wir arbeiten mit der Mono-Community zusammen, um es auf Windows, Linux und Mac großartig zu machen, und Microsoft wird es auf allen drei Plattformen unterstützen. Wir behalten die Werte bei, die das .NET Framework für die Entwicklung in Unternehmen mit sich bringt. Wir werden .NET Core-Distributionen anbieten, die einen Satz von NuGet-Paketen darstellen, die wir gemeinsam getestet und unterstützt haben. Visual Studio bleibt Ihr One-Stop-Shop für die Entwicklung. Für das Aufrufen von NuGet-Paketen, die Teil einer Distribution sind, ist keine Internetverbindung erforderlich.

Wir bekennen uns zu unserer Verantwortung und unterstützen weiterhin die Auslieferung von kritischen Sicherheitskorrekturen, ohne dass der Anwendungsentwickler etwas dafür tun muss, auch wenn die betroffene Komponente ausschließlich als NuGet-Paket vertrieben wird.

Source: msdn