API phiên bản


9

Giả sử rằng bạn có một dự án lớn được hỗ trợ bởi cơ sở API. Dự án cũng gửi một API công khai mà người dùng cuối (ish) có thể sử dụng.

Đôi khi bạn cần thay đổi cơ sở API hỗ trợ dự án của bạn. Ví dụ: bạn cần thêm một tính năng cần thay đổi API, phương thức mới hoặc yêu cầu thay đổi một trong các đối tượng hoặc định dạng của một trong các đối tượng đó, được chuyển đến hoặc từ API.

Giả sử rằng bạn cũng đang sử dụng các đối tượng này trong API công khai của mình, các đối tượng công khai cũng sẽ thay đổi bất cứ khi nào bạn thực hiện việc này, điều không mong muốn vì khách hàng của bạn có thể dựa vào các đối tượng API giống hệt nhau để mã phân tích cú pháp của họ hoạt động. (ho khách hàng C ++ WSDL ...)

Vì vậy, một giải pháp tiềm năng là phiên bản API. Nhưng khi chúng ta nói "phiên bản" API, có vẻ như điều này cũng có nghĩa là phải phiên bản các đối tượng API cũng như cung cấp các lệnh gọi phương thức trùng lặp cho mỗi chữ ký phương thức đã thay đổi. Vì vậy, sau đó tôi sẽ có một đối tượng clr cũ đơn giản cho mỗi phiên bản api của tôi, một lần nữa dường như không mong muốn. Và ngay cả khi tôi làm điều này, tôi chắc chắn sẽ không xây dựng từng đối tượng từ đầu vì điều đó sẽ kết thúc với số lượng lớn mã trùng lặp. Thay vào đó, API có khả năng mở rộng các đối tượng riêng mà chúng tôi đang sử dụng cho API cơ sở của chúng tôi, nhưng sau đó chúng tôi gặp vấn đề tương tự vì các thuộc tính được thêm vào cũng sẽ có sẵn trong API công khai khi chúng không được phép.

Vì vậy, một số sự tỉnh táo thường được áp dụng cho tình huống này là gì? Tôi biết nhiều dịch vụ công cộng như Git cho Windows duy trì API được phiên bản, nhưng tôi gặp khó khăn khi tưởng tượng một kiến ​​trúc hỗ trợ điều này mà không có số lượng lớn mã trùng lặp bao gồm các phương thức được nhập và các đối tượng đầu vào / phiên bản khác nhau.

Tôi biết rằng các quy trình như phiên bản ngữ nghĩa cố gắng đặt sự tỉnh táo khi xảy ra sự cố vỡ API công khai. Vấn đề là nhiều hơn có vẻ như nhiều hoặc hầu hết các thay đổi đều yêu cầu phá vỡ API công khai nếu các đối tượng không tách biệt hơn, nhưng tôi không thấy cách nào tốt để làm điều đó mà không cần sao chép mã.


1
I don't see a good way to do that without duplicating code- API mới của bạn luôn có thể gọi các phương thức trong API cũ hoặc ngược lại.
Robert Harvey

2
Thật không may, AutoMapper để giải cứu, thật không may - bạn cần các phiên bản riêng biệt của mỗi hợp đồng, đừng quên tất cả các đối tượng được tham chiếu bởi hợp đồng của bạn là một phần của hợp đồng đó. Kết quả là việc triển khai thực tế của bạn sẽ có phiên bản mô hình duy nhất của riêng nó và bạn cần chuyển đổi phiên bản đơn thành các phiên bản hợp đồng khác nhau. AutoMapper có thể giúp bạn ở đây cũng như làm cho các mô hình nội bộ thông minh hơn các mô hình hợp đồng. Khi không có AutoMapper, tôi đã sử dụng các phương thức mở rộng để tạo các bản dịch đơn giản giữa các mô hình nội bộ và mô hình hợp đồng.
Jimmy Hoffa

Có một nền tảng / bối cảnh cụ thể cho việc này? (ví dụ: DLL, API REST, v.v.)
GrandmasterB

.NET, với các lớp MVC và Webforms ui, dll. Chúng tôi có cả API nghỉ ngơi và xà phòng.
Trường hợp

Câu trả lời:


6

Khi duy trì API được sử dụng bởi các bên thứ ba, bạn không cần phải thay đổi. Mức độ phức tạp sẽ phụ thuộc vào loại thay đổi đang xảy ra. Đây là những kịch bản chính xuất hiện:

  1. Chức năng mới được thêm vào API hiện có
  2. Chức năng cũ không dùng nữa từ API
  3. Chức năng hiện có trong API thay đổi theo một cách nào đó

Chức năng mới Thêm vào API hiện có

Đây là kịch bản dễ nhất để hỗ trợ. Việc thêm các phương thức mới vào API sẽ không yêu cầu bất kỳ thay đổi nào đối với các máy khách hiện tại. Điều này là an toàn để triển khai cho các khách hàng cần chức năng mới vì nó không có bản cập nhật cho bất kỳ khách hàng hiện tại nào.

Chức năng cũ không dùng nữa từ API

Trong trường hợp này, bạn phải liên lạc với người tiêu dùng hiện tại về API của mình rằng chức năng sẽ không được hỗ trợ lâu dài. Cho đến khi bạn bỏ hỗ trợ cho chức năng cũ (hoặc cho đến khi tất cả khách hàng đã nâng cấp lên chức năng mới), bạn phải giữ chức năng API cũ và mới cùng một lúc. Nếu đó là một thư viện được cung cấp, hầu hết các ngôn ngữ đều có cách đánh dấu các phương thức cũ là lỗi thời / không dùng nữa. Nếu đó là dịch vụ của bên thứ ba thuộc loại nào đó, tốt nhất là thường có các điểm cuối khác nhau cho chức năng cũ / mới.

Chức năng hiện có trong API thay đổi theo một cách nào đó

Kịch bản này sẽ phụ thuộc vào loại thay đổi. Nếu các tham số đầu vào không còn cần phải được sử dụng thì bạn chỉ cần cập nhật dịch vụ / thư viện để bỏ qua dữ liệu bổ sung. Trong một thư viện, sẽ có phương thức quá tải bên trong gọi phương thức mới yêu cầu ít tham số hơn. Trong một dịch vụ lưu trữ, bạn có điểm cuối bỏ qua dữ liệu bổ sung và nó có thể phục vụ cả hai loại máy khách và chạy cùng một logic.

Nếu chức năng hiện có cần thêm các yếu tố cần thiết mới thì bạn phải có hai điểm cuối / phương thức cho dịch vụ / thư viện của mình. Cho đến khi khách hàng cập nhật, bạn cần hỗ trợ cả hai phiên bản.

Những suy nghĩ khác

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.

Không để lộ các đối tượng riêng tư nội bộ thông qua thư viện / dịch vụ của bạn. Tạo các loại của riêng bạn và lập bản đồ thực hiện nội bộ. Điều này sẽ cho phép bạn thực hiện các thay đổi nội bộ và giảm thiểu số lượng cập nhật mà khách hàng bên ngoài cần thực hiện.

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 cho dù đó là dịch vụ hay thư viện cần ổn định tại điểm tích hợp với máy khách. Bạn càng mất nhiều thời gian để xác định đầu vào và đầu ra nên là gì và giữ chúng như những thực thể riêng biệt sẽ giúp bạn tiết kiệm rất nhiều vấn đề đau đầu. Tạo API hợp đồng thực thể riêng của nó và ánh xạ tới các lớp cung cấp công việc thực sự. Thời gian được lưu khi triển khai nội bộ thay đổi sẽ bù đắp thêm thời gian cần thiết để xác định giao diện bổ sung.

Đừng xem bước này là "mã trùng lặp". Mặc dù tương tự, chúng là các thực thể riêng biệt đáng để tạo ra. Mặc dù các thay đổi API bên ngoài hầu như luôn yêu cầu thay đổi tương ứng với triển khai nội bộ, các thay đổi triển khai nội bộ không nên luôn thay đổi API bên ngoài.

Thí dụ

Giả sử bạn đang cung cấp một giải pháp xử lý thanh toán. Bạn đang sử dụng PaymentProviderA để thực hiện các giao dịch thẻ tín dụng. Sau này, bạn nhận được mức giá tốt hơn thông qua bộ xử lý thanh toán của PaymentProviderB. Nếu API của bạn tiếp xúc với các trường Thẻ tín dụng / Địa chỉ hóa đơn thuộc loại của bạn thay vì đại diện của PaymentProviderA thì thay đổi API là 0 vì giao diện vẫn như cũ (dù sao, nếu PaymentProviderB yêu cầu dữ liệu không được PaymentProviderA yêu cầu thì bạn cần phải chọn hỗ trợ cả hai hoặc giữ tỷ lệ tồi tệ hơn với PaymentProviderA).


Cảm ơn câu trả lời rất chi tiết này. Bạn có biết bất kỳ ví dụ nào về các dự án nguồn mở mà tôi có thể xem qua để tìm hiểu cách các dự án hiện tại đã thực hiện việc này không? Tôi muốn xem một số ví dụ cụ thể về cách họ đã tổ chức mã cho phép họ làm điều này mà không cần sao chép mã xây dựng POCO khác nhau của họ vào các đối tượng phiên bản khác nhau, vì nếu bạn gọi các phương thức được chia sẻ, bạn sẽ phải tách nó ra của phương thức được chia sẻ để có thể chỉnh sửa đối tượng đó cho đối tượng được phiên bản.
Trường hợp

1
Tôi không nhận ra bất kỳ ví dụ hay nào ngoài đỉnh đầu. Nếu tôi có thời gian vào cuối tuần này, tôi có thể tạo một ứng dụng thử nghiệm để ném vào GitHub để cho thấy một số điều này có thể được thực hiện như thế nào.
Phil Patterson

1
Phần khó khăn là từ cấp cao, có rất nhiều cách khác nhau để cố gắng giảm thiểu khớp nối giữa máy khách và máy chủ. WCF có một giao diện gọi là IExtensibleDataObject cho phép bạn truyền dữ liệu không có trong hợp đồng từ máy khách và gửi nó qua dây đến máy chủ. Google đã tạo Protobuf để liên lạc giữa các hệ thống (có các triển khai nguồn mở cho .NET, Java, v.v.). Ngoài ra, có nhiều hệ thống dựa trên thông báo cũng có thể hoạt động (giả sử rằng quy trình của bạn có thể được thực hiện không đồng bộ).
Phil Patterson

Có thể không phải là một ý tưởng tồi để hiển thị một ví dụ cụ thể về sao chép mã mà bạn đang cố xóa (như một câu hỏi tràn ngăn xếp mới) và xem cộng đồng đưa ra giải pháp nào. Thật khó để trả lời câu hỏi nói chung; vì vậy một kịch bản cụ thể có thể tốt hơn.
Phil Patterson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.