Zmiany powodujące niezgodność — MRTK2

Konsumenci zestawu narzędzi MRTK zależą od stabilnej powierzchni interfejsu API wydania do wydania, dzięki czemu mogą oni podjąć aktualizacje zestawu narzędzi MRTK bez konieczności wprowadzania dużych zmian powodujących niezgodność za każdym razem.

Na tej stronie opisano nasze bieżące zasady dotyczące zmian powodujących niezgodność w zestawie narzędzi MRTK wraz z pewnymi długoterminowymi celami dotyczącymi tego, jak możemy lepiej zarządzać kompromisem między utrzymywaniem niskich zmian powodujących niezgodność i możliwość wprowadzenia odpowiednich długoterminowych zmian technicznych w kodzie.

Co to jest zmiana powodująca niezgodność?

Zmiana jest zmianą powodującą niezgodność, jeśli spełnia którykolwiek z warunków na liście A I spełnia wszystkie warunki na liście B

Lista A

  • Dodanie, usunięcie lub aktualizacja dowolnego elementu członkowskiego lub funkcji dowolnego interfejsu (lub usunięcie/zmiana nazwy całego interfejsu).
  • Usunięcie, aktualizacja (zmiana typu/definicji, tworzenie prywatnego lub wewnętrznego) dowolnej chronionej lub publicznej składowej lub funkcji klasy. (lub usunięcie/zmiana nazwy całej klasy).
  • Zmiana kolejności zdarzeń wyzwalanych przez klasę.
  • Zmiana nazwy dowolnego prywatnego pola serializowanego (bez odpowiedniego tagu DawniejSerializedAs) lub właściwości publicznej w obiekcie ScriptableObject (zwłaszcza zmiany w profilach).
  • Zmiana typu pola w obiekcie ScriptableObject (szczególnie zmiany w profilach).
  • Aktualizacje do przestrzeni nazw lub asmdefs dowolnej klasy lub interfejsu.
  • Usunięcie jakichkolwiek prefab lub usunięcie skryptu na obiekcie najwyższego poziomu prefab.

Lista B

  • Zasób, którego dotyczy problem, znajduje się w pakiecie podstawowym (tj. znajduje się w jednym z następujących folderów):

    • MrTK/Core
    • MRTK/Dostawcy/
    • MRTK/Services/
    • ZESTAW MRTK/ZESTAW SDK/
    • Zestaw narzędzi MRTK/rozszerzenia
  • Omawiany zasób nie należy do eksperymentalnej przestrzeni nazw.

Ważne

Każdy zasób znajdujący się w pakiecie przykładów (tj. część folderu MRTK/Examples/) może ulec zmianie w dowolnym momencie, ponieważ zasoby mają być kopiowane i wyświetlane przez użytkowników jako "implementacje referencyjne", ale nie są częścią podstawowego zestawu interfejsów API i zasobów. Zasoby w eksperymentalnej przestrzeni nazw (lub ogólniej rzecz biorąc, funkcje oznaczone jako eksperymentalne) to te, które są publikowane przed ukończeniem wszystkich testów(tj. testów, iteracji środowiska użytkownika, dokumentacji) i są publikowane na początku, aby uzyskać opinię wcześniej. Jednak ponieważ nie mają testów i dokumentacji, a ponieważ prawdopodobnie nie przybito wszystkich interakcji i projektów, publikujemy je w stanie, w którym opinia publiczna powinna zakładać, że mogą i zmienią się (tj. zostaną zmodyfikowane, całkowicie usunięte itp.).

Aby uzyskać więcej informacji, zobacz Funkcje eksperymentalne .

Ponieważ obszar powierzchni zmian powodujących niezgodność jest bardzo duży, należy pamiętać, że posiadanie bezwzględnej reguły, która mówi, że "żadne zmiany powodujące niezgodność" nie byłyby niemożliwe — mogą wystąpić problemy, które można rozwiązać tylko w rozsądny sposób przez zmianę powodującą niezgodność. Innym sposobem, jedynym sposobem, w jaki moglibyśmy naprawdę "nie wprowadzać zmian powodujących niezgodność", jest brak zmian.

Nasza stała polityka polega na unikaniu wprowadzania zmian powodujących niezgodność, jeśli jest to możliwe, i tylko wtedy, gdy zmiana spowoduje naliczanie znaczącej wartości klienta lub struktury długoterminowej.

Co zrobić z zmianami powodujących niezgodność

Jeśli jest możliwe osiągnięcie czegoś bez zmiany powodującej niezgodność i bez naruszania długoterminowej struktury i rentowności funkcji, nie rób zmiany powodującej niezgodność. Jeśli nie ma innego sposobu, bieżąca polityka polega na ocenienia poszczególnych zmian powodujących niezgodność, aby zrozumieć, czy korzyści wynikające ze zmiany przewyższają koszty dla konsumenta w celu wchłonięcia zmiany. Debata na temat tego, co warto zrobić i co nie będzie na ogół odbywać się w sprawie żądania ściągnięcia lub dyskusji na temat kwestii.

To, co może się zdarzyć tutaj, wchodzi w kilka zasobników:

Zmiana powodująca niezgodność dodaje wartość, ale może zostać zapisana w sposób, który nie powoduje przerwania

Na przykład to żądanie ściągnięcia dodało nową funkcję, która początkowo została napisana w sposób powodujący niezgodność — zmodyfikowała istniejący interfejs — ale następnie została przepisana, gdzie funkcja została podzielona jako własny interfejs. Jest to zazwyczaj najlepszy możliwy wynik. Nie należy próbować wymusić zmiany w formularzu niezwiązanym z naruszeniem długoterminowej rentowności lub struktury funkcji.

Zmiana powodująca niezgodność dodaje klientowi wystarczającą wartość, którą warto wykonać

Udokumentowanie zmian powodujących niezgodność i zapewnienie najlepszego możliwego ograniczenia ryzyka (tj. kroków preskrypcyjnych dotyczących sposobu migracji lub lepszego jeszcze narzędzi, które będą automatycznie migrowane dla klienta). Każda wersja może zawierać niewielką ilość zmian powodujących niezgodność — należy je zawsze udokumentować w dokumentacji, tak jak to miało miejsce w tym żądaniu ściągnięcia. Jeśli istnieje już przewodnik migracji 2.x.x→2.x+1.x+1, dodaj instrukcje lub narzędzia do tego dokumentu. Jeśli nie istnieje, utwórz go.

Zmiana powodująca niezgodność dodaje wartość, ale ból klienta byłby zbyt wysoki

Nie wszystkie typy zmian powodujących niezgodność są jednakowe — niektóre są znacznie bardziej bolesne, że inne, w oparciu o nasze doświadczenie i na podstawie doświadczeń klientów. Na przykład zmiany interfejsów mogą być bolesne, ale jeśli zmiana powodująca niezgodność jest jedną z nich, w której klient prawdopodobnie nie przedłużył/zaimplementował w przeszłości (na przykład system wizualizacji diagnostycznych), rzeczywisty koszt jest prawdopodobnie niski do niczego. Jeśli jednak zmiana jest typem pola w obiekcie ScriptableObject (na przykład w jednym z podstawowych profilów zestawu narzędzi MRTK), może to spowodować ogromny ból klienta. Klienci sklonowali już profil domyślny, scalanie/aktualizowanie profilów może być bardzo trudne do wykonania ręcznie (tj. za pośrednictwem edytora tekstów w czasie scalania), a ponowne skopiowanie domyślnego profilu i ponowne skonfigurowanie wszystkich elementów ręcznie może prowadzić do trudnego do debugowania regresji.

Te zmiany musimy umieścić z powrotem na półce, dopóki nie istnieje gałąź, która umożliwi znaczne zmiany powodujące niezgodność (wraz ze znaczącą wartością, która da klientom powód do uaktualnienia). Taka gałąź nie istnieje obecnie. W naszych przyszłych spotkaniach dotyczących planowania iteracji dokonamy przeglądu zestawu zmian/problemów, które były "zbyt łamiące", aby sprawdzić, czy osiągnęliśmy masę krytyczną, aby umożliwić realizację zestawu zmian jednocześnie. Należy pamiętać, że niebezpieczne jest uruchomienie gałęzi "wszystko jest dozwolone" bez należytej staranności wykonywanej z powodu ograniczonych zasobów inżynieryjnych, które mamy, i fakt, że musielibyśmy podzielić testowanie i walidację między tymi dwoma. Musi istnieć jasny cel i dobrze skomunikowana data rozpoczęcia i zakończenia takiej gałęzi, gdy istnieje.

Długoterminowe zarządzanie zmianami powodujących niezgodność

W dłuższej perspektywie powinniśmy dążyć do zmniejszenia zakresu zmian powodujących niezgodność, zwiększając zestaw warunków na liście B. W przyszłości zestaw rzeczy na liście A zawsze będzie technicznie przerywany dla zestawu plików i zasobów, które uznajemy za znajdujący się w "publicznej powierzchni interfejsu API". Sposób, w jaki możemy uzyskać nieco większą swobodę iteracji (tj. zmianę wewnętrznych szczegółów implementacji, co pozwala na łatwiejsze refaktoryzowanie i udostępnianie kodu między wieloma klasami itp.), jest bardziej jawne określenie, które fragmenty kodu są oficjalną powierzchnią, a nie szczegółami implementacji.

Jedną z rzeczy, które już zrobiliśmy, jest wprowadzenie koncepcji "eksperymentalnej" funkcji (należy ona do eksperymentalnej przestrzeni nazw, może nie mieć testów/dokumentacji i jest publicznie ogłoszona, że istnieje, ale może zostać usunięta i zaktualizowana bez ostrzeżenia). Daje to swobodę dodawania nowych funkcji wcześniej, aby uzyskać wcześniejsze opinie, ale nie być natychmiast powiązane z jej powierzchnią interfejsu API (ponieważ możemy nie w pełni przemyśleć powierzchnię interfejsu API).

Inne przykłady rzeczy, które mogą pomóc w przyszłości

  • Użycie wewnętrznego słowa kluczowego. Pozwoliłoby to na udostępnienie kodu we własnych zestawach (w celu zmniejszenia duplikacji kodu) bez udostępniania elementów użytkownikom zewnętrznym.
  • Utworzenie "wewnętrznej" przestrzeni nazw (tj. Microsoft.MixedReality.Toolkit.Internal.Utilities), w której publicznie dokumentujemy, że wszystkie elementy zawarte w tej wewnętrznej przestrzeni nazw mogą ulec zmianie w dowolnym momencie i można je usunąć itp. Jest to podobne do tego, w jaki sposób biblioteki nagłówków języka C++ będą używać przestrzeni nazw ::internal w celu ukrycia szczegółów implementacji.