Freigeben über


Bahnbrechende Änderungen

Für eine .NET-Bibliothek ist es wichtig, ein Gleichgewicht zwischen Stabilität für bestehende Benutzer und Innovationen für die Zukunft zu finden. Bibliotheksautoren neigen dazu, Code umzugestalten und neu zu überdenken, bis es perfekt ist, aber das Unterbrechen ihrer vorhandenen Benutzer hat eine negative Auswirkung, insbesondere für Bibliotheken auf niedriger Ebene.

Projekttypen und Breaking Changes

Wie eine Bibliothek von der .NET-Community verwendet wird, ändert die Auswirkungen von Breaking Changes auf die Endbenutzerentwickler.

  • Bibliotheken auf niedriger und mittlerer Ebene wie serialisierer, HTML-Parser, datenbankobjektrelationaler Mapper oder Webframework sind am meisten betroffen, wenn Änderungen unterbrochen werden.

    Bausteinpakete werden von Endbenutzerentwicklern zum Erstellen von Anwendungen und von anderen Bibliotheken als NuGet-Abhängigkeiten verwendet. Sie erstellen beispielsweise eine Anwendung und verwenden einen Open-Source-Client, um einen Webdienst aufzurufen. Ein fehlerhaftes Update für eine Abhängigkeit, die der Client verwendet, ist nichts, was Sie beheben können. Es ist der Open-Source-Client, der geändert werden muss, und Sie haben keine Kontrolle darüber. Sie müssen kompatible Versionen der Bibliotheken finden oder einen Fix an die Clientbibliothek senden und auf eine neue Version warten. Im schlimmsten Fall sollten Sie zwei Bibliotheken verwenden, die von sich gegenseitig inkompatiblen Versionen einer dritten Bibliothek abhängen.

  • Bibliotheken auf hoher Ebene wie eine Sammlung von Steuerelementen der Benutzeroberfläche sind weniger anfällig für Breaking Changes.

    Allgemeine Bibliotheken werden direkt in einer Endbenutzeranwendung referenziert. Wenn inkompatible Änderungen auftreten, kann der Entwickler auswählen, auf die neueste Version zu aktualisieren oder seine Anwendung so zu ändern, dass sie mit der inkompatiblen Änderung funktioniert.

✔️ Überlegen Sie, wie Ihre Bibliothek verwendet wird. Welche Auswirkungen haben Breaking Changes auf Anwendungen und Bibliotheken, die diese verwenden?

✔️ Minimieren Sie Breaking Changes beim Entwickeln einer .NET-Bibliothek auf niedriger Ebene.

✔️ ERWÄGEN SIE, eine große Neuschreibung einer Bibliothek als neues NuGet-Paket zu veröffentlichen.

Arten von Breaking Changes

Das Aufteilen von Änderungen erfolgt in verschiedene Kategorien und ist nicht gleichermaßen wirkungsvoll.

Breaking Changes in der Quelle

Breaking Changes in der Quelle wirken sich nicht auf die Programmausführung aus, verursachen allerdings Kompilierungsfehler, wenn die Anwendung das nächste Mal erneut kompiliert wird. Beispielsweise kann eine neue Überladung eine Mehrdeutigkeit in zuvor eindeutigen Methodenaufrufen verursachen, oder ein umbenannter Parameter beeinträchtigt Aufrufer, die benannte Parameter verwenden.

public class Task
{
    // Adding a type called Task could conflict with System.Threading.Tasks.Task at compilation
}

Da eine Quellbruchänderung nur schädlich ist, wenn Entwickler ihre Anwendungen neu kompilieren, ist sie die am wenigsten störende Art von Änderung. Entwickler können ihren eigenen fehlerhaften Quellcode problemlos beheben.

Behavior Breaking Changes

Behavior Changes sind die häufigste Art von Breaking Change: Fast jede Verhaltensänderung kann bei einem Consumer einen Logikfehler verursachen. Änderungen an Ihrer Bibliothek, z. B. Methodensignaturen, ausgelöste Ausnahmen oder Eingabe- oder Ausgabedatenformate, können sich negativ auf die Bibliothekskunden auswirken. Sogar eine Fehlerbehebung kann ein Breaking Change sein, wenn sich Benutzer auf das ehemals fehlerhafte Verhalten verlassen haben.

Das Hinzufügen von Features und das Verbessern schlechter Verhaltensweisen ist eine gute Sache, aber ohne Sorgfalt kann es für vorhandene Benutzer sehr schwierig sein, ein Upgrade durchzuführen. Ein Ansatz, um Entwicklern bei der Behandlung von verhaltensverändernden Änderungen zu helfen, besteht darin, sie hinter Einstellungen zu verstecken. Mit den Einstellungen können Entwickler auf die neueste Version Ihrer Bibliothek aktualisieren und gleichzeitig entscheiden, ob sie sich für oder gegen breaking changes entscheiden. Mit dieser Strategie können Entwickler auf dem neuesten Stand bleiben und gleichzeitig ihren nutzenden Code im Laufe der Zeit anpassen.

Beispielsweise hat ASP.NET Core MVC das Konzept einer Kompatibilitätsversion, welche die aktivierten und deaktivierten Funktionen anhand von MvcOptions verändert.

✔️ ERWÄGEN Sie, neue Features standardmäßig deaktiviert zu lassen, wenn sie sich auf vorhandene Benutzer auswirken, und lassen Sie Entwickler sich mit einer Einstellung für das Feature anmelden.

Weitere Informationen zu verhaltensändernden Änderungen in .NET-APIs finden Sie unter Kompatibilität von .NET-Verhaltensänderungen.

Binäre Breaking Changes

Ein binärer Breaking Change tritt auf, wenn Sie die öffentliche API Ihrer Bibliothek ändern, sodass Assemblys, die mit älteren Versionen Ihrer Bibliothek kompiliert wurden, die API nicht mehr aufrufen können. Das Hinzufügen eines neuen Parameters zur Signatur einer Methode führt beispielsweise dazu, dass Assemblys, die gegen die ältere Version der Bibliothek kompiliert wurden, einen Fehler MissingMethodException werfen.

Eine binärer Breaking Change kann auch eine ganze Assembly unterbrechen. Durch das Umbenennen einer Assembly mit AssemblyName wird die Identität der Assembly geändert, genauso wie durch das Hinzufügen, Entfernen oder Ändern des starken Benennungsschlüssels der Assembly. Eine Änderung der Identität einer Assembly unterbricht den gesamten kompilierten Code, der sie verwendet.

❌ Ändern Sie keine Assemblynamen.

❌ FÜGEN SIE NICHT den starken Namensschlüssel hinzu, entfernen oder ändern Sie ihn.

✔️ ERWÄGEN SIE die Verwendung abstrakter Basisklassen anstelle von Schnittstellen.

Das Hinzufügen von Elementen zu einer Schnittstelle führt dazu, dass vorhandene Typen, die sie implementieren, fehlschlagen. Mit einer abstrakten Basisklasse können Sie eine standardmäßige virtuelle Implementierung hinzufügen.

✔️ ERWÄGEN Sie, das ObsoleteAttribute bei Typen und Membern anzuwenden, die Sie entfernen möchten. Das Attribut sollte Anweisungen zum Aktualisieren von Code enthalten, damit die veraltete API nicht mehr verwendet wird.

Code, das Typen und Methoden mit ObsoleteAttribute aufruft, generiert eine Buildwarnung mit der an das Attribut übergebenen Nachricht. Die Warnungen geben Personen, die die veraltete API nutzen, Zeit zur Migration, damit die meisten sie nicht mehr verwenden, wenn die veraltete API entfernt wird.

public class Document
{
    [Obsolete("LoadDocument(string) is obsolete. Use LoadDocument(Uri) instead.")]
    public static Document LoadDocument(string uri)
    {
        return LoadDocument(new Uri(uri));
    }

    public static Document LoadDocument(Uri uri)
    {
        // Load the document
    }
}

✔️ ERWÄGEN SIE, Typen und Methoden mit dem ObsoleteAttribute auf unbestimmte Zeit in Bibliotheken auf niedriger und mittlerer Ebene beizubehalten.

Das Entfernen von APIs ist eine binärer Breaking Change. Sollten Sie darüber nachdenken, veraltete Typen und Methoden beizubehalten, ist deren Wartung kostengünstig und fügt Ihrer Bibliothek keine erheblichen technischen Schulden hinzu. Das Nichtentfernen von Typen und Methoden kann dazu beitragen, die oben genannten Szenarien zu vermeiden.

Weitere Informationen dazu, welche .NET-API-Änderungen die Binäre Kompatibilität unterbrechen, finden Sie unter .NET Public Contract Compatibility.

Siehe auch