Tôi có nên viết API giao diện trước khi triển khai không?


14

Gần đây tôi đã đào sâu vào lập trình "có tổ chức" hơn và tôi đã học được rằng tôi nên lập trình lên một giao diện, chứ không phải là một triển khai. Với ý nghĩ đó, sẽ tốt hơn nếu "phác thảo" ra một dự án trong các giao diện trước khi viết triển khai cho nó khi có thể?

Và nếu đây là trường hợp, trong trường hợp sử dụng các thư viện của bên thứ 3 (ví dụ như Lidgren), tôi có nên gói chúng trong các giao diện không và giải quyết chúng thông qua các thùng chứa IOC, hoặc có thể tiếp xúc với các giao diện không?


Theo kinh nghiệm cá nhân của tôi - thật tốt khi thiết kế kiến ​​trúc trước tiên - trách nhiệm của mỗi lớp. Bạn không cần phải viết nó ra, chỉ cần nghĩ về nó hoặc phác thảo nó trên một tờ giấy. Sau đó, đó là về sở thích cá nhân nhưng tôi khuyên bạn nên viết bình luận tài liệu trước cho mọi phương pháp bạn bắt đầu thực hiện. Viết tài liệu thực sự khiến bạn phải suy nghĩ về chức năng trước khi bạn bắt đầu viết mã.
Sulthan

Có, và lập trình cho các giao diện (hoặc các lớp trừu tượng cho vấn đề đó) trước khi bạn triển khai chúng. Nó giúp nhận được luồng thông điệp từ máy khách đến máy chủ và ngược lại "đúng" trước khi bị sa lầy (và đầu tư vào) các triển khai. Trình chiếu rất hay về vấn đề: Cách thiết kế API tốt & Tại sao nó có vấn đề
Marjan Venema 6/12/13

Câu trả lời:


8

Thật không may, bạn sẽ thấy điều này thường sôi theo sở thích cá nhân.

Những gì bạn đã mô tả cho đến nay, mặc dù, có vẻ tốt. Trong thực tế, nếu bạn muốn (và tôi khuyên bạn nên làm như vậy), bạn có thể sử dụng phương pháp sau:

  1. Viết bộ xương ứng dụng của bạn dưới dạng Giao diện, các lớp trừu tượng (còn sơ khai) và các lớp (cũng còn sơ khai)
  2. Viết bài kiểm tra của bạn đối với các giao diện và sơ khai đó (chúng sẽ thất bại ngay bây giờ)
  3. Viết các triển khai của bạn (các bài kiểm tra của bạn sẽ bắt đầu vượt qua khi bạn hoàn thành việc triển khai của mình)

Bạn đang tập trung vào việc cố gắng viết mã "có tổ chức" hơn. Theo dõi TDD sẽ giúp bạn điều này.

Một số điểm bổ sung:

  • IoC container thuận tiện. Sử dụng chúng và DI càng nhiều càng tốt.
  • Đừng bọc thư viện bên thứ 3. Điều này sẽ nới lỏng sự ghép nối giữa mã của bạn (mã bạn kiểm soát) và mã bên thứ 3 (mã bạn không kiểm soát)

1
Đây là những gì tôi đã nghĩ ban đầu nhưng tôi đã nói rằng nó sẽ vi phạm nguyên tắc YAGNI. Vấn đề mà tôi thấy với rất nhiều dự án của mình chưa bao giờ kết thúc là chúng nhanh chóng trở nên không thể duy trì được với số lượng mã blob tôi đã viết, vì tôi không tổ chức đúng kế hoạch hoặc lên kế hoạch tấn công.
Dan Pantry

phần nào sẽ vi phạm YAGNI?
MetaFight

Bao thư viện bên thứ 3.
Dan Pantry

2
Tôi đoán nó sôi sùng sục đến: tỷ lệ cược của thư viện bên thứ 3 thay đổi là gì? Nếu có 0% cơ hội này, thì chắc chắn YAGNI. Nhưng, điều đó hiếm khi xảy ra. Ngoài ra, việc gói các lib của bên thứ 3 có thể giúp cho mã khác của bạn dễ dàng kiểm tra đơn vị hơn (ví dụ: nếu bạn không thể giả lập thư viện của bên thứ 3)
MetaFight

1
@DanPantry: Gói thư viện của bên thứ ba không phải là vi phạm YAGNI, nhưng là sự bảo vệ rất cần thiết đối với "thư viện bên thứ ba xâm nhập mã của chính bạn". Đây không chỉ là việc có thể trao đổi thư viện, mà MetaFight còn nói rằng việc bảo vệ chống lại những thay đổi trong các phiên bản mới hơn của thư viện sẽ yêu cầu thay đổi trong toàn bộ mã của bạn. Bằng cách gói thư viện (và đặc biệt là các loại cụ thể của nó: lớp, enums, structs, v.v.), bạn tự cách ly mã của mình và có một điểm duy nhất để thay đổi khi thư viện thay đổi (vì bất kỳ lý do gì).
Marjan Venema

13

Có, bạn nên viết mã dựa trên các giao diện thay vì các triển khai đã biết và có, bạn nên xây dựng các giao diện trước thay vì chúng xuất hiện từ mã của riêng bạn.

Lý do cho cả hai khuyến nghị phần lớn giống nhau: lập trình máy tính chủ yếu là về các yếu tố con người. Nhiều người thấy điều này đáng ngạc nhiên, nhưng hãy xem xét: có một số lượng gần như vô tận các cách khác nhau để giải quyết cùng một vấn đề điện toán hoạt động tốt như nhau. Gần như tất cả chúng hoàn toàn không thể có ý nghĩa đối với bất kỳ ai không viết chúng (hoặc thực tế cho tác giả một thời gian ngắn sau đó).

Theo sau đó, công nghệ phần mềm tốt phần lớn là về cách đạt được hiệu quả mong muốn (tính toán chính xác với hiệu quả hợp lý) theo cách cho phép mã nguồn được làm việc sau này. Các giao diện và API là một phần quan trọng của môn học đó: chúng cho phép bạn suy nghĩ về một vấn đề ở một cấp độ mô tả tại một thời điểm. Điều này dễ dàng hơn nhiều so với suy nghĩ về các quy tắc nhất quán kinh doanh về việc triển khai danh sách được liên kết cùng một lúc, và do đó áp đặt một mối quan tâm như vậy một cách ép buộc tốt hơn là cho phép lập trình viên khách hàng sử dụng mã của bạn theo bất kỳ cách nào anh ta thích.

Điều này thật khó tin đối với nhiều lập trình viên cao bồi, những người tin rằng họ hiểu mọi thứ họ viết, tốt hơn nhiều so với những người suy nghĩ trung bình và có thể xử lý tất cả sự phức tạp gây rắc rối cho các lập trình viên "ít" hơn. Không nhận thức được giới hạn nhận thức của chính mình là một hiện tượng cực kỳ phổ biến - đây là lý do tại sao các thực tiễn tốt nhất trong tổ chức mã rất quan trọng (và thường bị bỏ qua).

Nhắc lại, các giao diện và rào cản API phần lớn là tốt , ngay cả khi bạn chỉ hợp tác với chính mình. Đối với các thư viện bên ngoài, nếu họ mang theo API chu đáo, tôi sẽ không gặp vấn đề gì khi sử dụng nó miễn là bạn không lường trước việc phải trao đổi thư viện đó cho một thư viện khác. Mặt khác, một lớp bọc hoặc lớp chống tham nhũng có thể là một ý tưởng rất tốt.


Tôi thích quan điểm của bạn về SE phần lớn là đạt được hiệu quả mong muốn theo cách cho phép mã nguồn được làm việc sau này. Tôi ước rằng tôi đã có thể diễn đạt nó tốt trong công việc cuối cùng của tôi, nơi tôi luôn đấu tranh cho mã sạch!
MetaFight

Có một quy ước đặt tên cho các API chỉ là các giao diện mà tôi sẽ sử dụng ở mọi nơi không? Giống như, nếu tôi đang thực hiện một mẫu lệnh, tôi có gọi nó là "lệnh" không?
Rình mò

@StevieV Có nhiều loại, ví dụ như được IBlahthực hiện bởi Blahhoặc được Blahthực hiện bởi BlahImpl. Tôi không thích cả hai và có xu hướng sử dụng được Blahthực hiện bởi OralBlah, WrittenBlahhoặcASLBlah . Nhưng như thường lệ, điều quan trọng là phải tuân thủ cơ sở mã hiện tại và kỳ vọng của bạn hơn bất kỳ tiêu chuẩn chung nào.
Kilian Foth

4

Thay vì chỉ đơn giản là lập trình cho các giao diện, tại sao không xem xét Thiết kế / Phát triển hướng thử nghiệm (TDD)?

Nhiều người nghĩ về TDD như một cách thực hành thử nghiệm, nhưng thực ra đó là cách tiếp cận thiết kế nơi bạn để các thử nghiệm phơi bày cách mã của bạn sẽ được sử dụng thông qua các thử nghiệm (ban đầu thông qua các thử nghiệm đơn vị, nhưng cũng có thể thông qua các thử nghiệm tích hợp).

Lập trình cho các giao diện là một vũ khí quan trọng trong bộ công cụ của bạn, nhưng giống như hầu hết mọi thứ, nó không phải lúc nào cũng là giải pháp / kỹ thuật / thực hành phù hợp, vì không phải lúc nào cũng cần thiết. Bạn nên lập trình đến các giao diện mà bạn cần.

Sử dụng TDD sẽ buộc bạn khám phá nơi các giao diện như vậy là quan trọng và thực sự thì nó không quan trọng. Và vào cuối của nó, bạn sẽ có một bộ kiểm tra đơn vị khá tốt trên cơ sở mã của bạn.

Đối với việc sử dụng các thư viện của bên thứ 3, tôi rất khuyên bạn nên gói chúng trong các bản tóm tắt của riêng bạn khi thích hợp; và không để khách hàng API của bạn "biết" về họ.

Chúc may mắn!

[sửa: đã thấy câu trả lời của megaflight - hoàn toàn đồng ý]


2
TDD hoàn toàn có bạn nghĩ về mặt giao diện chứ không phải là sự kết hợp, mặc dù nó có thể không phải là một tuyên bố "giao diện" chính thức.
DougM

1
Đây là một câu trả lời tuyệt vời. +1 để đề xuất TDD, mà tôi nghĩ là giải pháp cho vấn đề thực sự của OP về việc bắt đầu từ đâu khi làm việc trong một dự án mới và tôi sẽ +1 lại nếu tôi có thể "Sử dụng TDD sẽ buộc bạn khám phá nơi các giao diện như vậy thật là quan trọng và ở đâu, thật lòng mà nói, không thành vấn đề. "
Benjamin Hodgson

2

Tôi nghĩ rằng nó là quá mức cần thiết. Nếu người dùng API của bạn không cần bị buộc phải thực hiện / sử dụng một cái gì đó theo một cách nhất định thì tôi sẽ loại bỏ nó. Giao diện là hợp đồng, nếu tôi không cần thì tại sao lại cho tôi?

Tôi nghĩ mọi người lạm dụng giao diện. Bạn đang thêm một lớp phức tạp không cần thiết trong hầu hết các trường hợp.


Tôi nghĩ rằng, người dưới giao diện -sử dụng. Nếu bạn muốn tạo ra các mảnh có thể tái sử dụng, giao diện không chỉ là một bổ sung "tốt đẹp để có", mà là điều chính cần quan tâm. Bên cạnh việc thực hiện thực tế tất nhiên.
JensG

1

Lập trình chống lại một hợp đồng hầu như luôn luôn là một ý tưởng tốt. Hợp đồng đó không cần phải là một giao diện, nó có thể được thực hiện bởi một lớp thay thế. Theo tôi, các giao diện đã trở nên hơi bị lạm dụng cùng với DI do các mối quan tâm kiểm tra đơn vị và các khung mô phỏng.

Cá nhân tôi thích chỉ mang lại các giao diện khi tôi rất có thể có hoặc có nhiều hơn 1 lần thực hiện hợp đồng. Các giao diện rất tốt cho các kho lưu trữ nơi tôi muốn trừu tượng hóa việc truy cập dữ liệu, nhưng có lẽ ít hơn đối với logic kinh doanh tiêu chuẩn của tôi có khả năng tương đối không linh hoạt.

Bây giờ không có giao diện có thể gây ra vấn đề với thử nghiệm đơn vị, đặc biệt là đối với những người theo chủ nghĩa thuần túy. Nhưng tôi quan tâm đến việc chế nhạo các phụ thuộc bên ngoài của các chương trình của tôi chứ không phải các phụ thuộc bên trong của nó. Tôi muốn các thử nghiệm của mình thực hiện xác nhận mã, không lặp lại cấu trúc mã.

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.