Критические изменения — MRTK2

Потребители MRTK зависят от стабильной поверхности API выпуска до выпуска, чтобы они могли получать обновления MRTK без значительных критических изменений каждый раз.

На этой странице описывается текущая политика в отношении критических изменений в MRTK, а также некоторые долгосрочные цели по поводу того, как мы можем лучше управлять компромиссом между сохранением критических изменений низким и возможностью внесения правильных долгосрочных технических изменений в код.

Что такое критическое изменение?

Изменение является критическим изменением, если оно удовлетворяет любым из условий в списке A И удовлетворяет всем условиям в списке B

Список A

  • Добавление, удаление или обновление любого элемента или функции любого интерфейса (или удаление или переименование всего интерфейса).
  • Удаление, обновление (изменение типа или определения, создание частного или внутреннего) любого защищенного или общедоступного члена или функции класса. (или удаление или переименование всего класса).
  • Изменение порядка событий, вызванных классом.
  • Переименование любого частного SerializedField (без соответствующего тега FormerlySerializedAs) или открытого свойства в ScriptableObject (особенно изменения в профилях).
  • Изменение типа поля в ScriptableObject (особенно изменения профилей).
  • Актуальные данные в пространство имен или asmdefs любого класса или интерфейса.
  • Удаление всех префаб или удаление скрипта на объекте верхнего уровня префаба.

Список B

  • Указанный ресурс находится в базовом пакете (т. е. в одной из следующих папок):

    • MRTK/Core
    • MRTK/Providers/
    • MRTK/Services/
    • MRTK/SDK/
    • MRTK/Extensions
  • Указанный ресурс не принадлежит экспериментальному пространству имен.

Важно!

Любой ресурс, который находится в пакете примеров (т. е. часть папки MRTK/Examples/), может быть изменен в любое время, так как ресурсы предназначены для копирования и просмотра потребителями как "эталонных реализаций", но не являются частью основного набора API и ресурсов. Ресурсы в экспериментальном пространстве имен (или, как правило, функции, помеченные как экспериментальные) — это те, которые публикуются до того, как все должной осмотрительности было выполнено (т. е. тесты, итерация пользовательского интерфейса, документация) и публикуются рано, чтобы получить отзывы раньше. Тем не менее, поскольку у них нет тестов и документации, и, вероятно, мы не прибили все взаимодействия и проекты, мы публикуем их в состоянии, где общественность должна предполагать, что они могут и будут изменяться (т. е. быть изменены, полностью удалены и т. д.).

Дополнительные сведения см. в разделе "Экспериментальные функции ".

Поскольку поверхность для критических изменений очень велика, важно отметить, что наличие абсолютного правила, которое говорит, что "критические изменения" не будут невозможными - могут возникнуть проблемы, которые могут быть исправлены только в здравом порядке, имея критическое изменение. Чтобы поставить еще один способ, единственный способ, который мы могли бы действительно иметь "никаких критических изменений" заключается в том, чтобы не иметь никаких изменений вообще.

Наша постоянная политика заключается в том, чтобы избежать внесения критических изменений, если это возможно, и делать это только в том случае, если изменение будет начислять значительное значение клиента или платформы в долгосрочной перспективе.

Что делать с критическими изменениями

Если можно выполнить что-то без критического изменения и без ущерба для долгосрочной структуры и жизнеспособности функции, не выполняйте критические изменения. Если нет другого способа, текущая политика заключается в оценке каждого отдельного критического изменения, чтобы понять, если выгода от принятия изменений перевешивает затраты на потребителя поглощения изменений. Дебаты о том, что стоит делать, и то, что, как правило, не будет происходить на PR или вопрос обсуждения самого.

Что может произойти здесь, попадает в несколько контейнеров:

Критическое изменение добавляет значение, но может быть записано таким образом, который не нарушается

Например, этот запрос на вытягивание добавил новую функцию, которая изначально была написана таким образом, который был нарушен - он изменил существующий интерфейс, но затем был перезаписан, когда эта функция была разбита в качестве собственного интерфейса. Как правило, это лучший результат. Не пытайтесь заставить изменение в некримируемую форму, если это приведет к нарушению долгосрочной жизнеспособности или структуры функции.

Критическое изменение добавляет достаточное значение клиенту, что стоит сделать

Задокументируйте критические изменения и предоставьте наилучшие возможные меры (т. е. инструкции по миграции или улучшению инструментов, которые будут автоматически переноситься для клиента). Каждый выпуск может содержать небольшое количество критических изменений. Они всегда должны быть задокументированы в документах, как это было сделано в этом запросе на вытягивание. Если уже существует руководство по миграции 2.x.x→2.x+1.x+1, добавьте инструкции или инструменты в этот документ. Если он не существует, создайте его.

Критическое изменение добавляет ценность, но боль клиента будет слишком высокой

Не все типы критических изменений создаются равными - некоторые из них значительно более болезненны, что другие, основываясь на нашем опыте и на основе взаимодействия с клиентами. Например, изменения в интерфейсах могут быть болезненными, но если критическое изменение является одним из них, в котором клиент вряд ли расширит или реализовал в прошлом (например, система визуализации диагностики), то фактические затраты, вероятно, не ниже. Однако если изменение является типом поля в ScriptableObject (например, в одном из основных профилей MRTK), это, вероятно, приведет к массовой боли клиента. Клиенты уже клонировали профиль по умолчанию, слияние и обновление профилей может быть очень трудно сделать вручную (т. е. через текстовый редактор во время слияния), а повторное копирование профиля по умолчанию и перенастройка всего вручную, скорее всего, приведет к сложной отладке регрессии.

Эти изменения необходимо вернуть на полку до тех пор, пока ветвь не будет существовать, которая позволит значительно нарушить изменения (наряду со значительным значением, которое даст клиентам причину для обновления). Такая ветвь в настоящее время не существует. В наших будущих собраниях по планированию итерации мы рассмотрим набор изменений или проблем, которые были "слишком критическими", чтобы увидеть, достигли ли мы критической массы, чтобы сделать его разумным для проведения набора изменений все сразу. Обратите внимание, что это опасно развернуть "все разрешено" ветвь без должной осмотрительности делается из-за ограниченных инженерных ресурсов, которые у нас есть, и тот факт, что нам придется разделить тестирование и проверку между этими двумя. Там должна быть четкая цель и хорошо сообщаемая дата начала и окончания такой ветви, когда она существует.

Долгосрочное управление критическими изменениями

В долгосрочной перспективе мы должны стремиться уменьшить масштаб того, что является критическим изменением, увеличив набор условий в списке Б. Идти вперед набор вещей в списке A всегда будет ломать для набора файлов и ресурсов, которые мы считаем, в "общедоступной области API". То, как мы можем получить немного больше свободы для итерации (т. е. изменение внутренних сведений о реализации, что позволяет упростить рефакторинг и совместное использование кода между несколькими классами и т. д.) заключается в том, чтобы быть более явным о том, какие части кода являются официальной поверхностью, а не подробной реализацией.

Одна вещь, которую мы уже сделали, заключается в концепции "экспериментальной" функции (она относится к экспериментальному пространству имен, она может не иметь тестов и документации, и публично объявлена, но может быть удалена и обновлена без предупреждения). Это дало свободу добавлять новые функции раньше, чтобы получить более ранние отзывы, но не сразу привязывать к своей поверхности API (так как мы, возможно, не полностью думали о поверхности API).

Другие примеры вещей, которые могут помочь в будущем

  • Использование внутреннего ключевого слова. Это позволит нам иметь общий код в собственных сборках (для уменьшения дублирования кода), не делая вещи общедоступными для внешних потребителей.
  • Создание "внутреннего" пространства имен (например, Microsoft.MixedReality.Toolkit.Internal.Utilities), в котором мы публикуем документ о том, что все, что содержится в этом внутреннем пространстве имен, может быть изменено в любое время и может быть удалено и т. д. Это похоже на то, как библиотеки заголовков C++ будут использовать пространства имен ::internal для скрытия сведений о реализации.