Belangrijke wijzigingen — MRTK2

Gebruikers van MRTK zijn afhankelijk van een stabiel API-oppervlak voor release-naar-release, zodat ze updates voor MRTK kunnen uitvoeren zonder dat ze elke keer grote wijzigingen moeten uitvoeren die fouten veroorzaken.

Op deze pagina wordt ons huidige beleid beschreven met betrekking tot wijzigingen die fouten veroorzaken in de MRTK, samen met enkele doelstellingen op langere termijn over hoe we 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 beter kunnen beheren.

Wat is een wijziging die fouten veroorzaakt?

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

Lijst A

  • Het toevoegen, 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 beschermd of openbaar lid of functie van klasse. (of het verwijderen/hernoemen van de hele klasse).
  • De wijziging in de volgorde van gebeurtenissen die door een klasse worden geactiveerd.
  • De naam van een private 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 naar de naamruimte of asmdefs van een klasse of interface.
  • Verwijdering van prefab of verwijdering van een script op het hoogste niveau-object van een prefab.

Lijst B

  • De betreffende asset bevindt zich in het basispakket (dat wil doen in een van de volgende mappen):

    • MRTK/Core
    • MRTK/Providers/
    • MRTK/Services/
    • MRTK/SDK/
    • MRTK/extensies
  • De betreffende asset behoort niet tot de experimentele naamruimte.

Belangrijk

Elke asset die zich in het voorbeeldenpakket bevindt (dat wil gezegd een deel van de map MRTK/Examples/) kan op elk gewenst moment worden gewijzigd, omdat de assets daar zijn ontworpen om door consumenten te worden gekopieerd en bekeken als 'referentie-implementaties', maar geen deel uitmaken van de kernset api's en assets. Assets in de experimentele naamruimte (of meer in het algemeen functies die als experimenteel worden aangeduid) zijn assets die worden gepubliceerd voordat alle due diligence is uitgevoerd (d.w.w. tests, UX-iteratie, documentatie) en die vroeg 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 vastgelegd, publiceren we ze in een staat waarin het publiek ervan uit moet gaan dat ze kunnen en zullen veranderen (bijvoorbeeld worden gewijzigd, volledig verwijderd, enzovoort).

Zie Experimentele functies voor meer informatie.

Omdat de oppervlakte voor wijzigingen die fouten veroorzaken erg groot is, is het belangrijk om te weten dat een absolute regel met de tekst 'geen wijzigingen die fouten veroorzaken' onmogelijk is. Er kunnen problemen zijn die alleen op een verstandige manier kunnen worden opgelost door een wijziging die fouten 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 zo mogelijk wijzigingen worden aangebracht die fouten veroorzaken en dit alleen doen als de wijziging aanzienlijke waarde voor de klant of het kader op de lange termijn zou opleveren.

Wat u moet doen bij wijzigingen die fouten veroorzaken

Als het mogelijk is om iets te bereiken zonder een belangrijke wijziging en zonder de structuur en levensvatbaarheid van de functie op lange termijn in gevaar te brengen, moet u de wijziging die fouten veroorzaakt niet uitvoeren. Als er geen andere manier is, is het huidige beleid om elke afzonderlijke wijziging te evalueren die fouten veroorzaakt, om te begrijpen of het voordeel van het nemen van de wijziging opweegt tegen de kosten voor de consument van het absorberen van de wijziging. Het debat over wat de moeite waard is en wat niet, vindt doorgaans plaats in de pr- of kwestiediscussie zelf.

Wat hier kan gebeuren, valt in verschillende buckets:

De wijziging die fouten veroorzaakt, voegt waarde toe, maar kan worden geschreven op een manier die niet verbreekt

Met deze pull-aanvraag is bijvoorbeeld een nieuwe functie toegevoegd die in eerste instantie op een niet-werkende manier is geschreven: het heeft een bestaande interface gewijzigd, maar is vervolgens herschreven waarbij de functie is opgesplitst als een eigen interface. Dit is over het algemeen het best mogelijke resultaat. Probeer niet een wijziging af te dwingen in een niet-brekende vorm als dit de levensvatbaarheid of structuur van de functie op de lange termijn in gevaar zou brengen.

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

Documenteer wat de wijzigingen zijn die fouten veroorzaken en bied de best mogelijke beperking (d.w.w. prescriptieve stappen voor migreren, of nog beter, hulpprogramma's die automatisch worden gemigreerd voor de klant). Elke release kan een kleine hoeveelheid wijzigingen bevatten die fouten veroorzaken. Deze moeten altijd worden gedocumenteerd in documenten zoals in deze pull-aanvraag is gedaan. Als er al een 2.x.x→2.x+1.x+1-migratiehandleiding is, voegt u instructies of hulpprogramma's toe aan dat document. Als deze niet bestaat, maakt u deze.

De belangrijke wijziging voegt waarde toe, maar de pijn van de klant zou te hoog zijn

Niet alle typen wijzigingen die fouten veroorzaken, zijn gelijk- sommige zijn aanzienlijk pijnlijker dan andere, op basis van onze ervaring en op basis van klantervaringen. Wijzigingen in interfaces kunnen bijvoorbeeld pijnlijk zijn, maar als de wijziging die fouten veroorzaakt een klant waarschijnlijk niet heeft uitgebreid of geïmplementeerd in het verleden (bijvoorbeeld het diagnostische visualisatiesysteem), zijn de werkelijke kosten waarschijnlijk laag tot niets. Als de wijziging echter het type veld op een ScriptableObject is (bijvoorbeeld op een van de kernprofielen van de MRTK), veroorzaakt dit waarschijnlijk enorme problemen voor de klant. Klanten hebben het standaardprofiel al gekloond. Het samenvoegen/bijwerken van profielen kan zeer moeilijk zijn om handmatig uit te voeren (dat wil zeggen via een teksteditor tijdens het samenvoegen). Het opnieuw kopiëren van het standaardprofiel en het handmatig opnieuw configureren van alles leidt zeer waarschijnlijk tot moeilijk om fouten in regressies op te sporen.

Deze wijzigingen moeten we terugzetten op de plank totdat er een vertakking bestaat die belangrijke wijzigingen mogelijk maakt (samen met een aanzienlijke waarde die klanten een reden geeft om te upgraden). Een dergelijke vertakking bestaat momenteel niet. In onze toekomstige iteratieplanningsvergaderingen bekijken we de set wijzigingen/problemen die 'te breken' waren om te zien of we een kritieke massa hebben bereikt om het redelijk te maken om een reeks wijzigingen in één keer door te voeren. Houd er rekening mee dat het gevaarlijk is om een vertakking 'alles is toegestaan' op te zetten zonder dat er due diligence wordt uitgevoerd vanwege de beperkte technische resources die we hebben en het feit dat we tests en validatie over deze twee moeten verdelen. Er moet een duidelijk doel en goed gecommuniceerde begin- en einddatum van een dergelijke vertakking zijn wanneer deze bestaat.

Langetermijnbeheer van wijzigingen die fouten veroorzaken

Op de lange termijn moeten we proberen het bereik van een wijziging die fouten veroorzaakt te beperken door de set voorwaarden in lijst B te vergroten. In de toekomst zal de set zaken in lijst A technisch gezien altijd fouten veroorzaken voor de set bestanden en assets die zich in het 'openbare API-gebied' bevinden. De manier waarop we een beetje meer vrijheid kunnen krijgen voor iteratie (d.w.w. het wijzigen van de interne implementatiedetails, waardoor het eenvoudiger is om code te herstructureren en delen tussen meerdere klassen, enzovoort) is om explicieter te zijn over welke gedeelten van de code officieel zijn, in plaats van implementatiedetails.

Een ding dat we al hebben gedaan, is het concept van een 'experimentele' functie introduceren (deze hoort in de experimentele naamruimte, heeft mogelijk geen tests/documentatie en wordt openbaar verklaard te bestaan, maar kan zonder waarschuwing worden verwijderd en bijgewerkt). Dit heeft de vrijheid gekregen om eerder nieuwe functies toe te voegen om eerdere feedback te krijgen, maar is niet onmiddellijk gekoppeld aan het API-oppervlak (omdat we mogelijk niet volledig hebben nagedacht over het API-oppervlak).

Andere voorbeelden van dingen die in de toekomst kunnen helpen

  • Gebruik van het interne trefwoord. Hierdoor kunnen we code delen binnen onze eigen assembly's (om dubbele code te verminderen) zonder dat dingen openbaar worden gemaakt voor externe consumenten.
  • Het maken van een 'interne' naamruimte (d.w.e. Microsoft.MixedReality.Toolkit.Internal.Utilities), waarin openbaar wordt vastgelegd dat alles in die interne naamruimte op elk gewenst moment kan worden gewijzigd en kan worden verwijderd, enzovoort. Dit is vergelijkbaar met hoe C++-headerbibliotheken gebruikmaken van ::interne naamruimten om de implementatiedetails te verbergen.