버전 관리 API


9

API 기반에서 지원하는 대규모 프로젝트가 있다고 가정하십시오. 이 프로젝트는 또한 최종 사용자가 사용할 수있는 공개 API를 제공합니다.

때때로 프로젝트를 지원하는 API 기반을 변경해야합니다. 예를 들어, API 변경, 새로운 방법이 필요하거나 객체 중 하나를 변경하거나 API로 (부터) 전달 된 객체 중 하나의 형식을 변경해야하는 기능을 추가해야합니다.

공개 API에서도 이러한 객체를 사용한다고 가정하면 공개 객체도이 작업을 수행 할 때마다 변경되므로 클라이언트가 구문 분석 코드가 작동하도록 API 객체가 동일하게 유지되므로 바람직하지 않습니다. (기침 C ++ WSDL 클라이언트 ...)

따라서 가능한 한 가지 해결책은 API를 버전 화하는 것입니다. 그러나 API를 "버전"이라고 말하면 API 객체의 버전을 변경하고 변경된 각 메소드 서명에 대해 중복 된 메소드 호출을 제공해야 함을 의미합니다. 그래서 나는 각 버전의 api에 대해 오래된 오래된 clr 객체를 갖게 될 것입니다. 그리고이 작업을 수행하더라도 엄청난 양의 중복 코드로 끝나기 때문에 각 객체를 처음부터 작성하지는 않을 것입니다. 오히려 API는 기본 API에 사용하는 개인 객체를 확장 할 가능성이 있지만 공개 API에서 추가 속성을 사용할 수 없기 때문에 동일한 속성을 사용할 수 있습니다.

그렇다면이 상황에 일반적으로 적용되는 정신은 무엇입니까? Windows 용 Git과 같은 많은 공용 서비스는 버전이 지정된 API를 유지 관리하지만 다양한 버전의 메서드 및 입력 / 출력 개체를 다루는 방대한 양의 중복 코드없이이를 지원하는 아키텍처를 상상하는 데 어려움을 겪고 있습니다.

시맨틱 버전 관리와 같은 프로세스는 퍼블릭 API 중단이 발생할 약간의 정신을 가지려고 시도한다는 것을 알고 있습니다. 문제는 더 많거나 대부분의 변경 사항이 객체가 더 분리되지 않은 경우 공개 API를 중단 해야하는 것처럼 보이지만 코드를 복제하지 않고는 그렇게하는 좋은 방법을 보지 못합니다.


1
I don't see a good way to do that without duplicating code-새로운 API는 항상 기존 API에서 메소드를 호출하거나 그 반대로 호출 할 수 있습니다.
Robert Harvey

2
불행히도 예-각 계약의 고유 버전이 필요합니다. 계약에서 참조하는 모든 객체가 해당 계약의 일부임을 잊지 마십시오. 결과적으로 실제 구현에는 고유 한 단일 버전의 모델이 있어야하며 단일 버전을 다양한 계약 버전으로 변환해야합니다. AutoMapper를 사용하면 계약 모델보다 내부 모델을 더 똑똑하게 만들 수 있습니다. AutoMapper가없는 경우 확장 방법을 사용하여 내부 모델과 계약 모델간에 간단한 변환을 만들었습니다.
Jimmy Hoffa

이에 대한 특정 플랫폼 / 컨텍스트가 있습니까? (즉, DLL, REST API 등)
GrandmasterB

.NET, MVC 및 Webforms ui, dll 클래스 우리는 휴식과 비누 API를 가지고 있습니다.
Case

답변:


6

타사에서 사용하는 API를 유지 관리 할 때는 반드시 변경해야합니다. 복잡성의 수준은 발생하는 변경 유형에 따라 다릅니다. 주요 시나리오는 다음과 같습니다.

  1. 기존 API에 추가 된 새로운 기능
  2. API에서 더 이상 사용되지 않는 이전 기능
  3. 어떤 방식 으로든 API의 기존 기능 변경

기존 API에 추가 된 새로운 기능

이것은 지원하기 가장 쉬운 시나리오입니다. API에 새 메소드를 추가하면 기존 클라이언트를 변경할 필요가 없습니다. 기존 클라이언트에 대한 업데이트가 없으므로 새로운 기능이 필요한 클라이언트에 배포하는 것이 안전합니다.

API에서 더 이상 사용되지 않는 이전 기능

이 시나리오에서는 기능이 장기적으로 지원되지 않는다는 기존 API 소비자와 통신해야합니다. 이전 기능에 대한 지원을 중단하거나 모든 클라이언트가 새 기능으로 업그레이드 될 때까지 이전 및 새 API 기능을 동시에 유지해야합니다. 그것이 제공되는 라이브러리라면 대부분의 언어는 오래된 메소드를 더 이상 사용되지 않거나 더 이상 사용하지 않는 것으로 표시 할 수 있습니다. 어떤 종류의 타사 서비스 인 경우 일반적으로 이전 / 새로운 기능에 대해 서로 다른 엔드 포인트를 갖는 것이 가장 좋습니다.

어떤 방식 으로든 API의 기존 기능 변경

이 시나리오는 변경 유형에 따라 다릅니다. 입력 매개 변수를 더 이상 사용할 필요가없는 경우 서비스 / 라이브러리를 업데이트하여 추가 데이터를 무시할 수 있습니다. 라이브러리에서는 오버로드 된 메소드가 내부적으로 더 적은 매개 변수를 필요로하는 새 메소드를 호출해야합니다. 호스팅 된 서비스에서 엔드 포인트는 추가 데이터를 무시하고 두 가지 유형의 클라이언트 모두에 서비스를 제공하고 동일한 논리를 실행할 수 있습니다.

기존 기능에 새로운 필수 요소를 추가해야하는 경우 서비스 / 라이브러리에 대해 두 개의 엔드 포인트 / 방법이 있어야합니다. 클라이언트가 업데이트 될 때까지 두 버전을 모두 지원해야합니다.

다른 생각들

Rather, the API is likely to extend the private objects we are using for our base API, but then we run into the same problem because added properties would also be available in the public API when they are not supposed to be.

라이브러리 / 서비스를 통해 내부 개인 개체를 노출시키지 마십시오. 고유 한 유형을 작성하고 내부 구현을 맵핑하십시오. 이를 통해 내부 변경을 수행하고 외부 클라이언트가 업데이트해야하는 양을 최소화 할 수 있습니다.

The problem is more that it seems like many or most changes require breaking the public API if the objects aren't more separated, but I don't see a good way to do that without duplicating code.

서비스인지 라이브러리인지 API는 클라이언트와의 통합 지점에서 안정적이어야합니다. 입력 및 출력이 무엇인지 식별하고 별도의 엔티티로 유지하는 데 더 많은 시간이 걸리면 많은 골칫거리를 줄일 수 있습니다. API 계약을 별도의 엔티티로 만들고 실제 작업을 제공하는 클래스에 맵핑하십시오. 내부 구현이 변경 될 때 절약되는 시간은 추가 인터페이스를 정의하는 데 걸리는 추가 시간을 상쇄해야합니다.

이 단계를 "중복 코드"로 보지 마십시오. 비슷하지만 그것들은 만들 가치가있는 별도의 엔티티입니다. 외부 API 변경은 거의 항상 내부 구현에 해당하는 변경이 필요하지만 내부 구현 변경이 항상 외부 API를 변경해서는 안됩니다.

지불 처리 솔루션을 제공한다고 가정하십시오. PaymentProviderA를 사용하여 신용 카드 거래를 수행하고 있습니다. 나중에 PaymentProviderB의 결제 프로세서를 통해 더 나은 요금을 얻을 수 있습니다. API가 PaymentProviderA의 표시 대신 유형의 신용 카드 / 청구서 주소 필드를 노출 한 경우 인터페이스가 동일하게 유지되므로 API 변경은 0입니다 (어쨌든 PaymentProviderB가 PaymentProviderA에 필요하지 않은 데이터를 요구하는 경우, 다음 중 하나를 선택해야합니다) PaymentProviderA로 둘 다 지원하거나 더 나쁜 비율을 유지하십시오).


이 매우 자세한 답변에 감사드립니다. 기존 프로젝트에서이 작업을 수행 한 방법을 배우기 위해 숙달 할 수있는 오픈 소스 프로젝트의 예를 알고 있습니까? 공유 메소드를 호출하면 분할해야하기 때문에 다양한 POCO 생성 코드를 다양한 버전 객체에 복사하지 않고이를 수행 할 수있는 코드를 구성하는 방법에 대한 구체적인 예를보고 싶습니다. 버전이 지정된 객체의 해당 객체를 편집 할 수있는 공유 메서드
Case

1
나는 "나의 머리 꼭대기에서 좋은 예를 알지 못한다. 이번 주말에 시간이 있으면 GitHub에 던질 테스트 앱을 만들어 이러한 것들 중 일부가 어떻게 구현 될 수 있는지 보여줄 수있다"
Phil Patterson

1
까다로운 부분은 높은 수준에서 클라이언트와 서버 사이의 연결을 최소화하려는 다양한 방법이 있다는 것입니다. WCF에는 IExtensibleDataObject라는 인터페이스가 있습니다.이 인터페이스를 사용하면 계약서에없는 데이터를 클라이언트에서 전달하여 유선을 통해 서버로 보낼 수 있습니다. Google은 시스템 간 통신을 위해 Protobuf를 만들었습니다 (.NET, Java 등을위한 오픈 소스 구현이 있음). 또한 작동 할 수있는 많은 메시지 기반 시스템이 있습니다 (프로세스를 비동기 적으로 수행 할 수 있다고 가정).
Phil Patterson

새로운 스택 오버플로 질문으로 제거하려는 코드 중복의 특정 예를 보여주고 커뮤니티에서 어떤 솔루션을 제안하는지 나쁜 생각이 아닐 수도 있습니다. 일반적인 용어로 질문에 대답하기는 어렵습니다. 특정 시나리오가 더 좋습니다.
Phil Patterson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.