Breaking changes — MRTK2

Benutzer von MRTK sind auf eine stabile Release-to-Release-API-Oberfläche angewiesen, sodass sie Updates für MRTK übernehmen können, ohne jedes Mal große Breaking-Änderungen vorzunehmen.

Auf dieser Seite wird unsere aktuelle Richtlinie in Bezug auf Breaking Changes im MRTK beschrieben, zusammen mit einigen längerfristigen Zielen, wie wir den Kompromiss zwischen dem Niedrighalten von Breaking Changes und der Möglichkeit, die richtigen langfristigen technischen Änderungen am Code vorzunehmen, besser verwalten können.

Was ist eine breaking change?

Eine Änderung ist eine Breaking Change, wenn sie eine der Bedingungen in der Liste A erfüllt UND alle Bedingungen in Liste B erfüllt.

Auflisten von A

  • Das Hinzufügen, Entfernen oder Aktualisieren eines Elements oder einer Funktion einer beliebigen Schnittstelle (oder das Entfernen/Umbenennen der gesamten Schnittstelle).
  • Das Entfernen, Aktualisieren (Ändern des Typs/der Definition, Privates oder Internes) eines geschützten oder öffentlichen Elements oder einer Funktion der Klasse. (oder entfernen/umbenennen der gesamten Klasse).
  • Die Änderung in der Reihenfolge der Ereignisse, die von einer -Klasse ausgelöst werden.
  • Die Umbenennung einer privaten SerializedField-Eigenschaft (ohne ein entsprechendes FormerlySerializedAs-Tag) oder einer öffentlichen Eigenschaft für ein ScriptableObject (insbesondere Änderungen an Profilen).
  • Ändern des Typs eines Felds für ein ScriptableObject (insbesondere Änderungen an Profilen).
  • Updates an den Namespace oder die Asmdefs einer beliebigen Klasse oder Schnittstelle.
  • Entfernen eines Prefabs oder Entfernen eines Skripts auf dem Objekt der obersten Ebene eines Prefabs.

Liste B

  • Das betreffende Objekt befindet sich im Foundation-Paket (d. h. es befindet sich in einem der folgenden Ordner):

    • MRTK/Kern
    • MRTK/Anbieter/
    • MRTK/Services/
    • MRTK/SDK/
    • MRTK/Erweiterungen
  • Das betreffende Objekt gehört nicht zum experimentellen Namespace.

Wichtig

Alle Ressourcen, die sich im Beispielpaket befinden (d. h. teil des MRTK/Examples/Ordners), können sich jederzeit ändern, da die Dort gespeicherten Ressourcen als "Referenzimplementierungen" kopiert und von Consumern als "Referenzimplementierungen" angezeigt werden, aber nicht Teil des Kernsatzes von APIs und Ressourcen sind. Ressourcen im experimentellen Namespace (oder allgemein als "experimentell" bezeichnete Features) werden veröffentlicht, bevor alle Due Diligence-Prüfungen durchgeführt wurden (d. h. Tests, UX-Iteration, Dokumentation) und frühzeitig veröffentlicht werden, um früher Feedback zu erhalten. Da sie jedoch keine Tests und Dokumentationen haben und wir wahrscheinlich noch nicht alle Interaktionen und Designs festgefahren haben, veröffentlichen wir sie in einem Zustand, in dem die Öffentlichkeit davon ausgehen sollte, dass sie sich ändern können und werden (d. h. geändert, vollständig entfernt usw.).

Weitere Informationen finden Sie unter Experimentelle Features .

Da die Oberfläche für Breaking Changes sehr groß ist, ist es wichtig zu beachten, dass es unmöglich ist, eine absolute Regel zu haben, die besagt, dass "keine Breaking Changes" vorhanden ist . Es kann Probleme geben, die nur auf vernünftige Weise durch eine Breaking Change behoben werden können. Anders ausgedrückt: Der einzige Weg, wie wir wirklich "keine Breaking Changes" haben könnten, besteht darin, überhaupt keine Änderungen zu haben.

Unsere ständige Richtlinie besteht darin, nach Möglichkeit breaking changes zu vermeiden und dies nur dann zu tun, wenn die Änderung einen erheblichen langfristigen Kunden- oder Frameworkwert erzielen würde.

Vorgehensweise bei Breaking Changes

Wenn es möglich ist, etwas zu erreichen, ohne eine breaking Change zu erreichen und ohne die langfristige Struktur und Die Rentabilität des Features zu beeinträchtigen, sollten Sie die Breaking Change nicht durchführen. Wenn es keine andere Möglichkeit gibt, besteht die aktuelle Richtlinie darin, jede einzelne Breaking Change zu bewerten, um zu verstehen, ob der Nutzen der Änderung die Kosten für den Verbraucher überwiegt, um die Änderung zu absorbieren. Die Debatte darüber, was es wert ist, zu tun und was nicht, wird in der Regel in der PR- oder Themendebatte selbst stattfinden.

Was hier passieren kann, fällt in mehrere Buckets:

Die breaking change führt zu einem Mehrwert, kann aber so geschrieben werden, dass es sich nicht um einen Breaking handelt.

Dieser PR hat z. B. ein neues Feature hinzugefügt, das zunächst so geschrieben wurde, dass es sich um eine vorhandene Schnittstelle handelte, aber dann neu geschrieben wurde, wo das Feature als eigene Schnittstelle ausgebrochen wurde. Dies ist in der Regel das bestmögliche Ergebnis. Versuchen Sie nicht, eine Änderung in eine unterbrechungsfreie Form zu erzwingen, wenn dies die langfristige Tragfähigkeit oder Struktur des Features beeinträchtigen würde.

Die breaking change fügt dem Kunden einen ausreichenden Mehrwert hinzu, den es sich lohnt

Dokumentieren Sie die breaking changes und bieten Sie die bestmögliche Entschärfung (d. h. vorgeschriebene Schritte zur Migration oder besser noch Tools, die automatisch für den Kunden migriert werden). Jede Version kann eine kleine Menge an Änderungen enthalten, die breaking sind. Diese sollten immer in der Dokumentation dokumentiert werden, wie in diesem PR geschehen. Wenn bereits ein Migrationshandbuch 2.x.x→2.x+1.x+1 vorhanden ist, fügen Sie diesem Dokument Anweisungen oder Tools hinzu. Wenn sie nicht vorhanden ist, erstellen Sie sie.

Die breaking change führt zu einem Mehrwert, aber der Kundenschmerz wäre zu hoch.

Nicht alle Arten von Breaking Changes sind gleich - einige sind deutlich schmerzhafter als andere, basierend auf unserer Erfahrung und auf Kundenerfahrungen. Beispielsweise können Änderungen an Schnittstellen schmerzhaft sein, aber wenn es sich bei der breaking change um eine Änderung handelt, bei der ein Kunde in der Vergangenheit wahrscheinlich nicht erweitert/implementiert hat (z. B. das Diagnosevisualisierungssystem), dann sind die tatsächlichen Kosten wahrscheinlich niedrig bis nichts. Wenn die Änderung jedoch der Typ eines Felds in einem ScriptableObject ist (z. B. auf einem der Kernprofile des MRTK), wird dies wahrscheinlich zu massiven Kundenschmerzen führen. Kunden haben das Standardprofil bereits geklont, das Zusammenführen/Aktualisieren von Profilen kann sehr schwer manuell (d. h. über einen Text-Editor während der Mergezeit) erfolgen, und das erneute Kopieren des Standardprofils und die manuelle Neukonfiguration aller Elemente führen sehr wahrscheinlich zu schwer zu debuggenden Regressionen.

Diese Änderungen müssen wir wieder ins Regal legen, bis ein Branch vorhanden ist, der erhebliche Änderungen ermöglicht (zusammen mit einem erheblichen Wert, der Kunden einen Grund für ein Upgrade bietet). Ein solcher Branch ist derzeit nicht vorhanden. In unseren zukünftigen Iterationsplanungssitzungen werden wir die Reihe von Änderungen/Problemen überprüfen, die "zu breaking" waren, um festzustellen, ob wir eine kritische Masse erreicht haben, um es vernünftig zu machen, eine Reihe von Änderungen auf einmal zu verfolgen. Beachten Sie, dass es aufgrund der begrenzten technischen Ressourcen und der Tatsache, dass wir Tests und Validierungen auf diese beiden Bereiche verteilen müssten, gefährlich ist, einen Branch "Alles ist zulässig" ohne Sorgfalt zu starten. Es muss einen klaren Zweck und ein gut kommuniziertes Start- und Enddatum eines solchen Branchs geben, wenn er vorhanden ist.

Langfristiges Management von Breaking Changes

Langfristig sollten wir versuchen, den Umfang einer breaking change zu verringern, indem wir die Bedingungen in Der Liste B erhöhen. In Zukunft wird der Satz von Dingen in Liste A immer für die Gruppe von Dateien und Ressourcen, die wir als auf der "öffentlichen API-Oberfläche" eramen, technisch immer ein Bruch sein. Die Art und Weise, wie wir ein wenig mehr Freiheit für Iterationen erhalten können (d. h. die Änderung der internen Implementierungsdetails, die einfachere Umgestaltung und freigabe von Code zwischen mehreren Klassen usw.) ist expliziter, welche Teile des Codes offizielle Oberfläche sind, anstatt Implementierungsdetails.

Eine Sache, die wir bereits getan haben, ist die Einführung des Konzepts eines "experimentellen" Features (es gehört in den experimentellen Namespace, es verfügt möglicherweise nicht über Tests/Dokumentationen und wird öffentlich als vorhanden erklärt, kann aber ohne Warnung entfernt und aktualisiert werden). Dies hat die Freiheit gegeben, neue Features früher hinzuzufügen, um früheres Feedback zu erhalten, aber nicht sofort an die API-Oberfläche gebunden (da wir die API-Oberfläche möglicherweise nicht vollständig durchdacht haben).

Weitere Beispiele für Dinge, die in Zukunft helfen könnten

  • Verwendung der internen Schlüsselwort (keyword). Dies würde es uns ermöglichen, code in unseren eigenen Assemblys freigegeben zu haben (zur Verringerung der Codeduplizierung), ohne die Dinge für externe Verbraucher öffentlich zu machen.
  • Erstellen eines "internen" Namespace (d. h. Microsoft.MixedReality.Toolkit.Internal.Utilities), in dem wir öffentlich dokumentieren, dass sich alles, was in diesem internen Namespace enthalten ist, jederzeit ändern kann und entfernt werden kann usw. Dies ähnelt der Verwendung von ::internen Namespaces in C++-Headerbibliotheken, um ihre Implementierungsdetails auszublenden.