다음을 통해 공유


호환성이 손상되는 변경 — MRTK2

MRTK의 소비자는 매번 큰 호환성이 손상되는 변경 없이 MRTK를 업데이트할 수 있도록 안정적인 릴리스-릴리스 API 표면을 사용하는 데 의존합니다.

이 페이지에서는 MRTK의 호환성이 손상되는 변경에 대한 현재 정책과 호환성이 손상되는 변경 내용을 낮게 유지하고 코드에 대한 적절한 장기 기술 변경을 수행할 수 있는 방법 간의 절충을 더 잘 관리할 수 있는 방법에 대한 몇 가지 장기적인 목표를 설명합니다.

호환성이 손상되는 변경이란?

목록 A의 조건을 충족하고 목록 B의 모든 조건을 충족하는 경우 변경 내용이 호환성이 손상되는 변경입니다.

목록 A

  • 인터페이스의 멤버 또는 함수를 추가, 제거 또는 업데이트합니다(또는 전체 인터페이스의 제거/이름 바꾸기).
  • 클래스의 보호된 멤버 또는 공용 멤버 또는 함수의 제거, 업데이트(형식/정의 변경, 비공개 또는 내부 만들기)입니다. (또는 전체 클래스의 제거/이름 바꾸기).
  • 클래스에서 발생한 이벤트의 순서 변경입니다.
  • ScriptableObject(특히 프로필 변경)에서 프라이빗 SerializedField(해당 FormerlySerializedAs 태그 없음) 또는 공용 속성의 이름 바꾸기입니다.
  • ScriptableObject에서 필드 형식 변경(특히 프로필 변경).
  • 모든 클래스 또는 인터페이스의 네임스페이스 또는 asmdefs에 업데이트.
  • 프리팹의 최상위 개체에서 스크립트를 제거하거나 프리팹을 제거합니다.

목록 B

  • 해당 자산은 기본 패키지에 있습니다(즉, 다음 폴더 중 하나에 있음).

    • MRTK/Core
    • MRTK/공급자/
    • MRTK/Services/
    • MRTK/SDK/
    • MRTK/확장
  • 해당 자산이 실험적 네임스페이스에 속하지 않습니다.

중요

예제 패키지에 있는 모든 자산(예: MRTK/Examples/폴더의 일부)은 언제든지 변경될 수 있습니다. 자산은 소비자가 '참조 구현'으로 복사하고 볼 수 있도록 설계되었지만 API 및 자산의 핵심 집합에 포함되지 않기 때문에 언제든지 변경될 수 있습니다. 실험적 네임스페이스의 자산(또는 일반적으로 실험으로 레이블이 지정된 기능)은 모든 실사가 완료되기 전에 게시되는 자산(예: 테스트, UX 반복, 설명서)이며 피드백을 더 빨리 받기 위해 일찍 게시됩니다. 그러나 테스트 및 설명서가 없기 때문에 모든 상호 작용 및 디자인을 못 박지 않았기 때문에 대중이 변경할 수 있고 변경될 것이라고 가정해야 하는 상태(즉, 수정, 완전히 제거 등)에 게시합니다.

자세한 내용은 실험적 기능을 참조하세요.

호환성이 손상되는 변경에 대한 노출 영역이 매우 크기 때문에 "호환성이 손상되는 변경 없음"이라는 절대 규칙을 갖는 것은 불가능할 수 있습니다. 호환성이 손상되는 변경을 통해서만 제정신으로 해결할 수 있는 문제가 있을 수 있습니다. 다른 방법으로 말하자면, 우리가 정말로 "주요 변경 내용 없음"을 가질 수있는 유일한 방법은 전혀 변경하지 않는 것입니다.

우리의 서있는 정책은 가능한 경우 호환성이 손상되는 변경을 방지하고, 변경이 상당한 고객 또는 프레임 워크 장기 가치를 발생시킬 경우에만 그렇게하는 것입니다.

호환성이 손상되는 변경에 대해 수행할 사항

호환성이 손상되는 변경 없이 기능의 장기적인 구조와 실행 가능성을 손상시키지 않고 수행할 수 있는 경우 호환성이 손상되는 변경을 수행하지 마세요. 다른 방법이 없는 경우, 현재 정책은 각 개별 호환성이 손상되는 변경을 평가하고, 변경을 통해 얻는 이점이 변화를 흡수하는 소비자에게 드는 비용보다 더 큰지 이해하는 것입니다. 무엇을 할 가치가 있는지에 대한 토론과 일반적으로 PR 또는 문제 토론 자체에서 열리지 않을 것입니다.

여기서 발생할 수 있는 작업은 여러 버킷에 속합니다.

호환성이 손상되는 변경은 가치를 더하지만 호환되지 않는 방식으로 작성될 수 있습니다.

예를 들어 이 PR 은 처음에 기존 인터페이스를 수정하는 방식으로 작성된 새 기능을 추가했지만, 해당 기능이 자체 인터페이스로 분리된 곳에서 다시 작성되었습니다. 이것은 일반적으로 최상의 결과입니다. 이렇게 하면 기능의 장기적인 생존 가능성 또는 구조가 손상되는 경우 변경을 강제 적용하지 마세요.

호환성이 손상되는 변경은 고객에게 가치가 있는 충분한 가치를 더합니다.

호환성이 손상되는 변경 내용을 문서화하고 최상의 완화(예: 마이그레이션 방법에 대한 규범적 단계 또는 고객을 위해 자동으로 마이그레이션되는 더 나은 도구)를 제공합니다. 각 릴리스에는 호환성이 손상되는 약간의 변경 내용이 포함될 수 있습니다. 이러한 변경 내용은 항상 이 PR에서 수행한 대로 문서에 문서화되어야 합니다. 2.x.x→2.x+1.x+1 마이그레이션 가이드가 이미 있는 경우 해당 문서에 지침 또는 도구를 추가합니다. 존재하지 않는 경우 만듭니다.

호환성이 손상되는 변경으로 가치를 더하지만 고객의 고통이 너무 높아질 수 있습니다.

모든 유형의 호환성이 손상되는 변경이 동일하게 만들어지는 것은 아닙니다 - 일부는 우리의 경험과 고객 경험을 기반으로 다른 사람들이 훨씬 더 고통스럽습니다. 예를 들어 인터페이스에 대한 변경은 고통스러울 수 있지만 호환성이 손상되는 변경이 고객이 과거에 확장/구현할 가능성이 거의 없는 경우(예: 진단 시각화 시스템) 실제 비용은 낮을 수 있습니다. 그러나 변경 내용이 ScriptableObject의 필드 유형인 경우(예: MRTK의 핵심 프로필 중 하나) 이로 인해 고객에게 큰 고통이 발생할 수 있습니다. 고객은 이미 기본 프로필을 복제했으며, 프로필 병합/업데이트는 수동으로(예: 병합 시간 동안 텍스트 편집기를 통해) 매우 어려울 수 있으며, 기본 프로필을 다시 복사하고 모든 항목을 직접 다시 구성하면 디버그 회귀가 어려울 가능성이 큽니다.

이러한 변경 내용은 고객에게 업그레이드 이유를 제공하는 중요한 가치와 함께 크게 호환되는 변경을 허용하는 분기가 존재할 때까지 선반에 다시 배치해야 합니다. 이러한 분기는 현재 존재하지 않습니다. 향후 반복 계획 회의에서는 '너무 깨뜨린' 변경/문제 집합을 검토하여 한 번에 일련의 변경 내용을 추구하는 것이 합리적일 수 있도록 중요한 질량에 도달했는지 확인합니다. 우리가 가지고있는 제한된 엔지니어링 리소스로 인해 실사가 수행되지 않고 "모든 것이 허용됩니다"분기를 스핀 업하는 것은 위험하며, 이러한 두 가지에 걸쳐 테스트 및 유효성 검사를 분할해야 한다는 사실에 유의하십시오. 이러한 분기가 있는 경우 명확한 목적과 잘 전달된 시작 및 종료 날짜가 있어야 합니다.

호환성이 손상되는 변경의 장기 관리

장기적으로는 목록 B에서 조건 집합을 늘려 호환성이 손상되는 변경에 대한 scope 줄이려고 노력해야 합니다. 앞으로 목록 A의 항목 집합은 "공용 API 표면"에 있는 것으로 간주되는 파일 및 자산 집합에 대해 항상 기술적으로 중단됩니다. 반복에 좀 더 많은 자유를 얻을 수 있는 방법(즉, 내부 구현 세부 정보를 변경하여 여러 클래스 간에 코드를 더 쉽게 리팩터링하고 공유할 수 있도록 허용)은 구현 세부 정보보다는 코드의 어느 부분이 공식적인 표면인지에 대해 더 명시적이어야 합니다.

이미 수행한 한 가지는 "실험적" 기능의 개념을 도입하는 것입니다(실험적 네임스페이스에 속하고, 테스트/설명서가 없을 수 있으며, 공개적으로 존재한다고 선언되지만 경고 없이 제거 및 업데이트될 수 있음). 이렇게 하면 이전 피드백을 얻기 위해 새 기능을 더 빨리 추가할 수 있지만 API 표면에 즉시 연결되지는 않습니다(API 표면을 완전히 생각하지 않았을 수 있기 때문).

미래에 도움이 될 수 있는 다른 예

  • 내부 키워드(keyword) 사용. 이렇게 하면 외부 소비자에게 공개하지 않고도 자체 어셈블리 내에서(코드 중복을 줄이기 위해) 공유 코드를 사용할 수 있습니다.
  • "내부" 네임스페이스(예: Microsoft.MixedReality.Toolkit.Internal.Utilities)를 만듭니다. 여기서 내부 네임스페이스에 포함된 모든 항목은 언제든지 변경될 수 있으며 제거될 수 있음을 공개적으로 문서화합니다. 이는 C++ 헤더 라이브러리가 ::internal 네임스페이스를 사용하여 구현 세부 정보를 숨기는 방법과 유사합니다.