Alterações significativas – MRTK2

Os consumidores do MRTK dependem de ter uma superfície de API de versão para lançamento estável, para que possam levar atualizações para o MRTK sem ter grandes alterações significativas a cada vez.

Esta página descreve nossa política atual sobre alterações significativas no MRTK, juntamente com algumas metas de longo prazo sobre como podemos gerenciar melhor a compensação entre manter as alterações significativas baixas e ser capaz de fazer as alterações técnicas de longo prazo certas no código.

O que é uma mudança significativa?

Uma alteração será uma alteração significativa se atender a qualquer uma das condições na Lista A E atender a todas as condições na lista B

ListaR A

  • A adição, remoção ou atualização de qualquer membro ou função de qualquer interface (ou remoção/renomeação de toda a interface).
  • A remoção, a atualização (alterando o tipo/definição, tornando-se privada ou interna) de qualquer membro ou função de classe protegida ou pública. (ou remoção/renomeação de toda a classe).
  • A alteração na ordem dos eventos disparados por uma classe.
  • A renomeação de qualquer SerializedField privado (sem uma marca FormerlySerializedAs correspondente) ou propriedade pública em um ScriptableObject (especialmente alterações nos perfis).
  • Alterando o tipo de um campo em um ScriptableObject (especialmente alterações em perfis).
  • Atualizações para o namespace ou asmdefs de qualquer classe ou interface.
  • Remoção de qualquer pré-fabricado ou remoção de um script no objeto de nível superior de um pré-fabricado.

Lista B

  • O ativo em questão está no pacote de base (ou seja, está em uma das seguintes pastas):

    • MRTK/Core
    • MRTK/Provedores/
    • MRTK/Services/
    • MRTK/SDK/
    • MRTK/Extensões
  • O ativo em questão não pertence ao namespace experimental.

Importante

Qualquer ativo que esteja no pacote de exemplos (ou seja, parte da pasta MRTK/Exemplos/) está sujeito a alterações a qualquer momento, pois os ativos lá são projetados para serem copiados e exibidos pelos consumidores como "implementações de referência", mas não fazem parte do conjunto principal de APIs e ativos. Os ativos no namespace experimental (ou mais geralmente, recursos rotulados como experimentais) são os que são publicados antes de toda a diligência devida ter sido feita (ou seja, testes, iteração de UX, documentação) e são publicados antecipadamente para obter comentários mais cedo. No entanto, como eles não têm testes e documentação, e como provavelmente não acertamos todas as interações e designs, publicamos-os em um estado onde o público deve assumir que eles podem e serão alterados (ou seja, serão modificados, completamente removidos etc.).

Consulte os recursos experimentais para obter mais informações.

Como a área de superfície para alterações significativas é muito grande, é importante observar que ter uma regra absoluta que diz que "nenhuma alteração significativa" seria impossível - pode haver problemas que só podem ser corrigidos de forma sã por ter uma mudança significativa. Para colocar de outra forma, a única maneira de realmente ter "nenhuma mudança significativa" é não ter nenhuma alteração.

Nossa política permanente é evitar fazer alterações significativas, se possível, e só fazê-lo se a alteração acumular um valor significativo de longo prazo do cliente ou da estrutura.

O que fazer sobre alterações significativas

Se for possível realizar algo sem uma alteração significativa e sem comprometer a estrutura de longo prazo e a viabilidade do recurso, não faça a alteração significativa. Se não houver outra maneira, a política atual é avaliar cada alteração de quebra individual, para entender se o benefício de tomar a mudança supera o custo para o consumidor de absorver a alteração. Debate sobre o que vale a pena fazer e o que não é geralmente ocorrerá na pr ou discussão em questão em si.

O que pode acontecer aqui cai em vários buckets:

A alteração significativa adiciona valor, mas pode ser escrita de uma forma que não esteja quebrando

Por exemplo, essa PR adicionou um novo recurso que foi inicialmente escrito de uma forma que estava quebrando - ele modificou uma interface existente - mas depois foi reescrito onde o recurso foi dividido como sua própria interface. Geralmente, esse é o melhor resultado possível. Não tente forçar uma alteração em uma forma sem interrupção se isso comprometer a viabilidade ou a estrutura de longo prazo do recurso.

A alteração significativa adiciona valor suficiente ao cliente que vale a pena fazer

Documente quais são as alterações de falha e forneça a melhor mitigação possível (ou seja, etapas prescritivas sobre como migrar ou melhor ainda ferramentas que migrarão automaticamente para o cliente). Cada versão pode conter uma pequena quantidade de alterações que estão quebrando - elas sempre devem ser documentadas em documentos, como foi feito nesta PR. Se já houver um guia de migração 2.x.x→2.x+1.x+1, adicione instruções ou ferramentas a esse documento. Se ele não existir, crie-o.

A alteração significativa agrega valor, mas a dor do cliente seria muito alta

Nem todos os tipos de alterações significativas são criados iguais - alguns são significativamente mais dolorosos que outros, com base em nossa experiência e com base em experiências do cliente. Por exemplo, as alterações nas interfaces podem ser dolorosas, mas se a alteração significativa for aquela em que é improvável que um cliente tenha sido estendido/implementado no passado (o sistema de visualização de diagnóstico, por exemplo), o custo real provavelmente será baixo para nada. No entanto, se a alteração for o tipo de um campo em um ScriptableObject (por exemplo, em um dos perfis principais do MRTK), isso provavelmente causará uma enorme dor do cliente. Os clientes já clonaram o perfil padrão, mesclar/atualizar perfis pode ser extremamente difícil de fazer manualmente (ou seja, por meio de um editor de texto durante o tempo de mesclagem), e copiar novamente o perfil padrão e reconfigurar tudo manualmente é extremamente provável que leve a regressões difíceis de depurar.

Essas alterações temos que colocar de volta na prateleira até que exista uma ramificação que permita alterações significativamente significativas (juntamente com um valor significativo que dará aos clientes um motivo para atualizar). Esse branch não existe atualmente. Em nossas futuras reuniões de planejamento de iteração, examinaremos o conjunto de alterações/questões que foram "muito significativas" para ver se alcançamos uma massa crítica para tornar razoável buscar um conjunto de mudanças de uma só vez. Observe que é perigoso criar uma ramificação "tudo é permitido" sem a devida diligência sendo feita devido aos recursos de engenharia limitados que temos, e o fato de que teríamos que dividir testes e validação entre esses dois. Precisa haver uma finalidade clara e uma data de início e término bem comunicada de tal branch quando ela existe.

Gerenciamento de longo prazo de alterações significativas

A longo prazo, devemos buscar reduzir o escopo do que é uma alteração significativa aumentando o conjunto de condições na Lista B. Daqui para frente, o conjunto de coisas na Lista A sempre estará tecnicamente quebrado para o conjunto de arquivos e ativos que consideramos estar na "superfície da API pública". A maneira como podemos obter um pouco mais de liberdade para iteração (ou seja, alterar os detalhes da implementação interna, permitindo uma refatoração e compartilhamento mais fácil de código entre várias classes, etc. ) é ser mais explícito sobre quais partes do código são superfície oficial, em vez de detalhes de implementação.

Uma coisa que já fizemos é introduzir o conceito de um recurso "experimental" (ele pertence ao namespace experimental, pode não ter testes/documentação e é proclamado publicamente para existir, mas pode ser removido e atualizado sem aviso). Isso tem liberdade para adicionar novos recursos mais cedo para obter comentários anteriores, mas não ser imediatamente vinculado à sua superfície de API (porque talvez não tenhamos pensado totalmente na superfície da API).

Outros exemplos de coisas que podem ajudar no futuro

  • Uso da palavra-chave interna. Isso nos permitiria ter código compartilhado em nossos próprios assemblies (para reduzir a duplicação de código) sem tornar as coisas públicas para consumidores externos.
  • Criação de um namespace "interno" (ou seja, Microsoft.MixedReality.Toolkit. Internal.Utilities), onde documentamos publicamente que qualquer coisa contida nesse namespace interno está sujeita a alterações a qualquer momento e pode ser removida, etc. Isso é semelhante a como as bibliotecas de cabeçalho C++ usarão namespaces ::internos para ocultar seus detalhes de implementação.