Wijzigingen die fouten veroorzaken

Consumenten van de MRTK zijn afhankelijk van een stabiele release-naar-release-API, zodat ze updates voor de MRTK kunnen aanbrengen zonder dat er steeds grote wijzigingen worden doorgevoerd.

Op deze pagina wordt ons huidige beleid beschreven met betrekking tot belangrijke wijzigingen in de MRTK, samen met enkele doelstellingen voor de langere termijn met betrekking tot het beter beheren van de balans tussen het laag houden van belangrijke wijzigingen en het kunnen aanbrengen van de juiste technische wijzigingen op de lange termijn in de code.

Wat is een wijziging die een wijziging in de weg staat?

Een wijziging is een wijziging die een wijziging onderbreekt als deze voldoet aan een van de voorwaarden in lijst A EN voldoet aan alle voorwaarden in lijst B

Lijst A

  • Het optelling, verwijderen of bijwerken van een lid of functie van een interface (of het verwijderen/hernoemen van de hele interface).
  • Het verwijderen, bijwerken (wijzigen van type/definitie, privé of intern maken) van een beveiligd of openbaar lid of functie van klasse. (of verwijder/wijzig de naam van de hele klasse).
  • De wijziging in de volgorde van gebeurtenissen die door een klasse worden afgelost.
  • De naam van een persoonlijke SerializedField (zonder een bijbehorende tag FormerlySerializedAs) of openbare eigenschap op een ScriptableObject (met name wijzigingen in profielen).
  • Het type van een veld op een ScriptableObject wijzigen (met name wijzigingen in profielen).
  • Updates voor de naamruimte of asmdefs van een klasse of interface.
  • Verwijderen van een prefab of verwijderen van een script op het hoogste niveau object van een prefab.

Lijst B

  • De activum in kwestie maakt deel uit van het basispakket (dat wil zeggen dat deze zich in een van de volgende mappen staat):

    • MRTK/Core
    • MRTK/Providers/
    • MRTK/Services/
    • MRTK/SDK/
    • MRTK/extensies
  • De activum in kwestie behoort niet tot de experimentele naamruimte.

Belangrijk

Elke asset die zich in het voorbeeldpakket bevindt (dat wil zeggen een onderdeel van de map MRTK/Examples/) kan op elk moment worden gewijzigd, omdat er assets zijn ontworpen om te worden gekopieerd en bekeken door consumenten als 'referentie-implementaties', maar die geen deel uitmaken van de kernset van API's en assets. Assets in de experimentele naamruimte (of meer in het algemeen functies die zijn gelabeld als experimenteel) zijn assets die worden gepubliceerd voordat alle zorgvuldigheid is uitgevoerd (dat wil zeggen tests, UX-iteratie, documentatie) en die eerder worden gepubliceerd om eerder feedback te krijgen. Omdat ze echter geen tests en documentatie hebben en omdat we waarschijnlijk niet alle interacties en ontwerpen hebben platgepijt, publiceren we ze in een toestand waarin het publiek ervan uit moet gaan dat ze kunnen en zullen veranderen (dat wil zeggen worden gewijzigd, volledig verwijderd, enzovoort).

Zie Experimentele functies voor meer informatie.

Omdat de surface area voor belangrijke wijzigingen erg groot is, is het belangrijk om te weten dat het onmogelijk is om een absolute regel te hebben met de naam 'geen wijzigingen die wijzigingen veroorzaken'. Er kunnen problemen zijn die alleen op een goede manier kunnen worden opgelost door een wijziging die een wijziging veroorzaakt. Anders gezegd, de enige manier waarop we echt 'geen belangrijke wijzigingen' kunnen hebben, is door helemaal geen wijzigingen te hebben.

Ons permanente beleid is om te voorkomen dat er, indien mogelijk, belangrijke wijzigingen worden aangebracht. Dit doet u alleen als de wijziging aanzienlijke waarde voor de klant of het framework op de lange termijn met zich mee zou brengen.

Wat te doen met wijzigingen die wijzigingen verbreken

Als het mogelijk is om iets te bereiken zonder dat er een wijziging die iets in de weg staat en zonder dat dit ten koste gaat van de structuur op de lange termijn en de bruikbaarheid van de functie, moet u de belangrijke wijziging niet uitvoeren. Als er geen andere manier is, is het huidige beleid om elke afzonderlijke wijziging die een wijziging doorbreekt te evalueren, om te begrijpen of het voordeel van het nemen van de wijziging opweegt tegen de kosten voor de consument van het opnemen van de wijziging. Tijdens de discussie over wat de moeite waard is en wat niet is, wordt over het algemeen gediscussie over de pr of het onderwerp zelf.

Wat hier kan gebeuren, valt in verschillende buckets:

De wijziging die de wijziging doorbreekt, voegt waarde toe, maar kan worden geschreven op een manier die niet doorbreekt

Met deze pr is bijvoorbeeld een nieuwe functie toegevoegd die in eerste instantie werd geschreven op een manier die werd verbroken - het heeft een bestaande interface gewijzigd - maar vervolgens herschreven waar de functie is opgesplitst als een eigen interface. Dit is doorgaans het best mogelijke resultaat. Probeer geen wijziging af te dwingen in een niet-brekende vorm als dit de haalbaarheid of structuur van de functie op de lange termijn in gevaar zou brengen.

De wijziging die de wijziging doorbreekt, voegt voldoende waarde toe aan de klant die het de moeite waard is om te doen

Documenteren wat de belangrijke wijzigingen zijn en bieden de best mogelijke oplossing (dat wil zeggen prescriptieve stappen voor het migreren of nog beter nog hulpprogramma's die automatisch worden gemigreerd voor de klant). Elke release kan een kleine hoeveelheid wijzigingen bevatten die worden doorgevoerd. Deze moeten altijd worden gedocumenteerd in documenten zoals is gedaan in deze pr. Als er al een migratiehandleiding 2.x.x→2.x+1.x+1 bestaat, voegt u instructies of hulpprogramma's toe aan dat document. Als deze niet bestaat, maakt u deze.

De wijziging die de wijziging veroorzaakt, voegt waarde toe, maar de klant zou te veel moeite hebben

Niet alle typen belangrijke wijzigingen worden gelijk gemaakt. Sommige zijn aanzienlijk moeilijker dan andere, op basis van onze ervaring en op basis van klantervaringen. Wijzigingen in interfaces kunnen bijvoorbeeld erg groot zijn, maar als de wijziging die de wijzigingen doorbreekt er een is waarin het onwaarschijnlijk is dat een klant in het verleden is uitgebreid/geïmplementeerd (bijvoorbeeld het diagnostische visualisatiesysteem), zijn de werkelijke kosten waarschijnlijk laag tot niets. Als de wijziging echter het type van een veld op een ScriptableObject is (bijvoorbeeld op een van de belangrijkste profielen van de MRTK), is dit waarschijnlijk zeer lastig voor de klant. Klanten hebben het standaardprofiel al gekloond, het samenvoegen/bijwerken van profielen kan zeer moeilijk handmatig worden gedaan (dat wil zeggen via een teksteditor tijdens de samenvoegingstijd), en het opnieuw kopiëren van het standaardprofiel en het handmatig opnieuw configureren van profielen leidt waarschijnlijk zeer waarschijnlijk tot het opsporen van fouten in regressies.

Deze wijzigingen moeten we weer op het rek zetten totdat er een vertakking bestaat die belangrijke wijzigingen mogelijk maakt (samen met een aanzienlijke waarde die klanten een reden geeft om een upgrade uit te voeren). Een dergelijke vertakking bestaat momenteel niet. In onze toekomstige iteratieplanningsvergaderingen bekijken we de set wijzigingen/problemen die 'te ernstig' waren om te zien of er een kritieke massa is bereikt om het redelijk te maken om in één keer een set wijzigingen na te streven. Houd er rekening mee dat het gevaarlijk is om een vertakking 'alles is toegestaan' te maken zonder dat er zorgvuldig te werk gaat vanwege de beperkte technische resources die we hebben en het feit dat we tests en validatie over deze twee moeten splitsen. Er moet een duidelijk doel en een goed gecommuniceerd begin- en einddatum van een dergelijke vertakking zijn wanneer deze bestaat.

Langetermijnbeheer van belangrijke wijzigingen

Op de lange termijn moeten we proberen het bereik te beperken van wat een wijziging die een wijziging veroorzaakt door de set voorwaarden in lijst B te verhogen. De set dingen in lijst A zal in technisch opzicht altijd breken voor de set bestanden en assets die we in het 'openbare API-oppervlak' achten. De manier waarop we iets meer vrijheid voor iteratie kunnen krijgen (dat wil zeggen het wijzigen van de interne implementatiedetails, waardoor eenvoudiger code kan worden gefactored en gedeeld tussen meerdere klassen, enzovoort), is om explicieter te zijn over welke delen van de code officiële ruimte zijn, in plaats van implementatiedetails.

Eén ding dat we al hebben gedaan, is het concept van een 'experimentele' functie introduceren (deze behoort tot de experimentele naamruimte, heeft mogelijk geen tests/documentatie en is openbaar beproefd, maar kan zonder waarschuwing worden verwijderd en bijgewerkt). Dit heeft de vrijheid gegeven om eerder nieuwe functies toe te voegen om eerder feedback te krijgen, maar niet onmiddellijk te worden gekoppeld aan het API-oppervlak (omdat we het API-oppervlak mogelijk nog niet volledig hebben gezien).

Andere voorbeelden van dingen die in de toekomst kunnen helpen

  • Gebruik van het interne trefwoord. Hierdoor kunnen we code in onze eigen assemblies hebben gedeeld (voor het verminderen van codeduplicatie) zonder dat dit openbaar wordt gemaakt voor externe consumenten.
  • Het maken van een 'interne' naamruimte (dat wil zeggen Microsoft.MixedReality.Toolkit. Internal.Utilities), waarbij we openbaar documenteren dat alles in die interne naamruimte op elk gewenst moment kan worden gewijzigd en kan worden verwijderd, enzovoort. Dit is vergelijkbaar met de manier waarop C++-headerbibliotheken gebruikmaken van ::interne naamruimten om de implementatiedetails te verbergen.