Làm thế nào để bạn phát triển và phiên bản một giao diện?


22

Giả sử bạn có giao diện IFoo:

public interface IFoo {
    void Bar(string s);
    int Quux(object o);
}

Trong phiên bản 2 của API, bạn cần thêm một phương thức Glargvào giao diện này. Làm thế nào để bạn làm như vậy mà không phá vỡ người dùng API hiện tại của bạn và duy trì khả năng tương thích ngược? Điều này chủ yếu nhằm vào .NET, nhưng cũng có thể áp dụng cho các khung & ngôn ngữ khác.


Bạn có thể thêm mà không có vấn đề. Các vấn đề xảy ra khi bạn thay đổi / loại bỏ một cái gì đó đã có sẵn.
Giàn

1
@Rig: Ít nhất là trong C #, bạn sẽ gặp lỗi biên dịch nếu bạn thêm một phương thức vào một giao diện và không thêm nó vào các lớp thực hiện giao diện đó.
Malice

Vâng, đó là sự thật. Tôi đã suy nghĩ nhiều hơn từ kịch bản lớp người dùng có thể hỗn loạn tối thiểu so với việc thay đổi chữ ký phương thức hoặc xóa một chữ ký phương thức. Vì vậy, tôi cho rằng nó có thể dẫn đến một số công việc nếu bạn cần thêm vào giao diện của mình.
Giàn

Câu trả lời:


9

Trong phiên bản 2 của API, bạn cần thêm một phương thức Glargvào giao diện này.

Tại sao?

Các giao diện được xác định để sử dụng với API có hai vai trò hoàn toàn khác nhau:

  1. Nghịch đảo phụ thuộc - các giao diện như vậy được sử dụng bởi API của bạn. Chúng cho phép mã máy khách tạo plugin, v.v.
  2. Trừu tượng hóa - các giao diện như vậy được API của bạn trả về và ẩn chi tiết triển khai của các đối tượng được trả về.

Bây giờ đối với một phiên bản API nhất định, cùng một giao diện có thể hoạt động như cả hai. Tuy nhiên, trong các phiên bản trong tương lai, điều này có thể được tách rời.

  1. Bạn muốn trích xuất thêm thông tin từ giao diện bạn tiêu thụ. Để tăng cường hiệu suất, hoặc thêm linh hoạt hoặc bất cứ điều gì. Xác định một giao diện mới, có thể bắt nguồn từ giao diện cũ và xây dựng một phương thức riêng tiêu thụ nó. AFAIK hầu hết các ngôn ngữ .NET cho phép nạp chồng phương thức, vì vậy điều này có thể xảy ra mà không cần thêm nhiều lộn xộn.
  2. Bạn muốn "trả lại nhiều hơn", tức là sự trừu tượng hóa của một đối tượng "giàu hơn" từ API của bạn. Ở đây bạn có hai lựa chọn:

    • Bạn có thể giả định một cách hợp lý rằng mã khách hàng sẽ không có người triển khai giao diện riêng. Theo giả định này, việc thêm các tiện ích mở rộng của bạn vào giao diện hiện tại là an toàn.
    • Xác định một giao diện mới, nếu có thể xuất phát từ giao diện trước đó. Nếu việc tạo dẫn xuất như vậy là không thể, hãy tạo các phương thức riêng để truy vấn các phiên bản của giao diện mới hoặc sử dụng thành phần:

      interface MyNewInterface extends MyOldInterface { 
           FancyNewInterface getFancyShit();
      }
      

15

DirectX thêm số phiên bản vào giao diện của nó. Trong trường hợp của bạn, giải pháp sẽ là một cái gì đó như

public interface IFoo2 : IFoo
{
    void Glarg();
}

API vẫn sẽ đề cập đến IFoo và chỉ đến IFoo2 trong các phương thức, v.v ... nơi yêu cầu chức năng IFoo2.

Việc triển khai API nên kiểm tra các phương thức (= phiên bản 1) hiện có xem một đối tượng tham số IFoo có thực sự triển khai IFoo2 hay không, nếu ngữ nghĩa của phương thức khác với IFoo2.


3

Việc thêm một phương thức (hoặc phương thức) mới vào API của bạn nên được thực hiện theo cách mà nó không có bất kỳ tác dụng phụ nào đối với API hiện có. Quan trọng nhất, ai đó tiếp tục sử dụng API cũ như thể API mới không tồn tại, sẽ không bị ảnh hưởng bởi nó. Sử dụng API cũ cũng không có tác dụng phụ không mong muốn đối với API mới.

Nếu bất kỳ phương thức hiện có nào trong API được thay thế bởi các phương thức mới, đừng loại bỏ chúng ngay lập tức. Đánh dấu chúng là không dùng nữa và đưa ra lời giải thích về những gì nên được sử dụng thay thế. Điều đó mang lại cho người dùng cảnh báo mã của bạn rằng các phiên bản trong tương lai có thể không còn hỗ trợ nó thay vì phá vỡ mã của họ mà không có cảnh báo.

Nếu các API mới và cũ không tương thích và không thể tồn tại cùng nhau mà không có tác dụng phụ không mong muốn, hãy tách chúng ra và ghi lại rằng nếu API mới được thông qua, API cũ phải được loại bỏ hoàn toàn. Điều này ít được mong muốn hơn vì sẽ luôn có ai đó cố gắng sử dụng cả hai và cảm thấy thất vọng khi nó không hoạt động.

Vì bạn đã hỏi về .NET một cách cụ thể, bạn có thể muốn đọc bài viết này về sự phản đối trong .NET, liên kết đến ObsoleteAttribute(được sử dụng trong ví dụ sau):

using System;

public sealed class App {
   static void Main() {      
      // The line below causes the compiler to issue a warning:
      // 'App.SomeDeprecatedMethod()' is obsolete: 'Do not call this method.'
      SomeDeprecatedMethod();
   }

   // The method below is marked with the ObsoleteAttribute. 
   // Any code that attempts to call this method will get a warning.
   [Obsolete("Do not call this method.")]
   private static void SomeDeprecatedMethod() { }
}

2

Thay đổi giao diện công cộng liên quan đến phá vỡ. Chiến lược chung là chỉ thực hiện những điều này trên các phiên bản chính và sau một thời gian đóng băng (vì vậy nó không xảy ra bất chợt). Bạn có thể thoát khỏi mà không phá vỡ khách hàng của mình nếu bạn thêm bạn vào một giao diện mới (và việc triển khai của bạn có thể cung cấp cả hai trên cùng một lớp). Điều đó không lý tưởng, và nếu bạn tiếp tục làm điều đó, bạn sẽ có một mớ hỗn độn.

Với các loại sửa đổi khác mặc dù (loại bỏ phương thức, thay đổi chữ ký), bạn bị mắc kẹt.


2
Bạn có thể đặt trước một tiền tố cho các tên phương thức trong tương lai và cảnh báo tất cả người dùng rằng họ không nên sử dụng không gian tên đó, nhưng ngay cả điều đó tạo ra một API không phù hợp. Nói chung, cha mẹ hoàn toàn đúng: loại bỏ (và thường là bổ sung) các phương thức sẽ phá vỡ người dùng hiện tại và bạn không thể làm gì về điều đó ngoại trừ lên kế hoạch một cách khôn ngoan.
Kilian Foth

1

Giao diện là một hợp đồng, do đó nó không nên có phiên bản. Điều gì xảy ra nếu một cầu thủ bóng đá có được hợp đồng mới? Là cái cũ vẫn còn hiệu lực? Không. Nếu một người thay đổi giao diện, hợp đồng sẽ thay đổi và hợp đồng (giao diện) trước đó không còn hiệu lực.

Mặc dù bạn có thể sử dụng chiến lược IFoo2, cuối cùng điều đó sẽ trở nên lộn xộn khi bạn có:

  • IFoo2
  • IFoo3
  • IFoo4
  • v.v.

Kinh quá.

Một API là khác nhau. Tôi cung cấp cho thư viện mã để sử dụng. Tháng tới tôi cung cấp cho bạn một thư viện cập nhật. Như một poster khác đã nói, đừng phá vỡ những gì tôi đang sử dụng, chỉ cần thêm chức năng / phương thức mới.

Nếu bạn muốn phiên bản một cái gì đó, hãy sử dụng một lớp rút gọn thay vì một giao diện.

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.