2009-10-26 28 views
47

Làm cách nào để tạo một API thông thạo bản chất?tạo API thông thạo

Điều này có sử dụng phương pháp mở rộng chủ yếu không?

+0

bản sao có thể có của [Mẹo để viết giao diện thông thạo trong C# 3] (http://stackoverflow.com/questions/224730/tips-for-writing-fluent-interfaces-in-c-sharp-3) – nawfal

Trả lời

43

This article giải thích nó tốt hơn nhiều so với trước đây.

EDIT, không thể ép này trong một bình luận ...

có hai bên để giao diện, thực hiện và cách sử dụng. Có nhiều việc phải làm ở phía sáng tạo, tôi đồng ý với điều đó, tuy nhiên, những lợi ích chính có thể được tìm thấy ở khía cạnh sử dụng của mọi thứ. Thật vậy, đối với tôi, lợi thế chính của giao diện thông thạo là tự nhiên hơn, dễ nhớ và dễ sử dụng hơn và tại sao không, API làm hài lòng hơn về mặt thẩm mỹ. Và có lẽ, nỗ lực của việc phải bóp một API dưới dạng thông thạo có thể dẫn đến suy nghĩ tốt hơn về API?

Như Martin Fowler nói trong the original article about fluent interfaces:

Có lẽ điều quan trọng nhất để thông báo về phong cách này là các Mục đích là để làm một cái gì đó dọc theo dòng của một nội DomainSpecificLanguage. Thực tế đây là lý do tại sao chúng tôi chọn cụm từ 'thông thạo' thành mô tả nó theo nhiều cách mà hai cụm từ là từ đồng nghĩa. API là được thiết kế chủ yếu để có thể đọc được và để truyền. Giá của sự lưu loát này là nhiều nỗ lực hơn, cả trong suy nghĩ và trong chính bản thân xây dựng API. API đơn giản của hàm tạo, setter và các phương thức bổ sung dễ dàng hơn nhiều để viết . Sắp ra mắt với một API thông minh thông thạo rất cần một chút suy nghĩ.

Như trong hầu hết các trường hợp, API được tạo một lần và được sử dụng lặp đi lặp lại, nỗ lực bổ sung có thể đáng giá.

Và tiết lộ? Tôi là tất cả cho verbosity nếu nó phục vụ khả năng đọc của một chương trình.

+0

Tôi không 't thực sự hiểu làm thế nào điều này làm cho một API thông thạo, và thực sự nghĩ rằng mô hình thiết kế này là rất tiết. – badbod99

+0

ok ... vì vậy nó phù hợp với định nghĩa wikipedia http://en.wikipedia.org/wiki/Fluent_interface Tôi vẫn nghĩ rằng đó là khủng khiếp để thực hiện. – badbod99

+0

Lỗi không cung cấp khả năng đọc của chương trình trong trường hợp này, nó phục vụ khả năng đọc của ứng dụng khách. API của bạn vẫn cần được cải thiện và duy trì. – badbod99

0

Không và có. Những điều cơ bản là một giao diện hay giao diện tốt cho các loại mà bạn muốn cư xử lưu loát. Các thư viện với các phương thức mở rộng có thể mở rộng hành vi này và trả về giao diện. Các phương thức mở rộng cung cấp cho người khác khả năng mở rộng API thông thạo của bạn với nhiều phương thức hơn.

Thiết kế thông thạo tốt có thể khó và mất một khoảng thời gian dùng thử và thời gian khá dài để hoàn toàn hoàn thành các khối xây dựng cơ bản. Chỉ cần một API thông thạo để cấu hình hoặc thiết lập không phải là khó.

Học xây dựng một API thông thạo làm một bằng cách xem các API hiện có. So sánh FluentNHibernate với các API .NET thông thạo hoặc các giao diện thông thạo ICriteria. Nhiều API cấu hình cũng được thiết kế "lưu loát".

6

KISS: Hãy giữ nó thật ngu ngốc.

Thiết kế thông thạo là một nguyên tắc thiết kế thẩm mỹ được sử dụng trong suốt API. Phương pháp bạn sử dụng trong API của mình có thể thay đổi một chút, nhưng nói chung là tốt hơn để duy trì tính nhất quán.

Mặc dù bạn có thể nghĩ rằng 'mọi người đều có thể sử dụng API này, vì nó sử dụng tất cả các loại phương pháp khác nhau'.Sự thật là người dùng sẽ bắt đầu cảm thấy bị mất vì bạn luôn thay đổi cấu trúc/cấu trúc dữ liệu của API thành nguyên tắc thiết kế mới hoặc quy ước đặt tên.

Nếu bạn muốn thay đổi nửa chừng sang nguyên tắc thiết kế khác, ví dụ: Chuyển đổi từ mã lỗi sang xử lý ngoại lệ vì một số quyền chỉ huy cao hơn. Nó sẽ là điên rồ và bình thường trong rất nhiều đau đớn. Tốt hơn là nên duy trì khóa học và thêm chức năng mà khách hàng của bạn có thể sử dụng và bán để làm cho họ viết lại và khám phá lại tất cả các vấn đề của họ một lần nữa.

Theo dõi từ trên, bạn có thể thấy rằng có nhiều công việc viết API thông thạo hơn so với mắt của bạn. Có những lựa chọn tâm lý, và thẩm mỹ để thực hiện trước khi bắt đầu viết một và thậm chí sau đó cảm giác, nhu cầu, và mong muốn phù hợp với nhu cầu của khách hàng và nhất quán là khó nhất của tất cả.

6

một API thông thạo là gì

Wikipedia định nghĩa chúng ở đây http://en.wikipedia.org/wiki/Fluent_interface

Why Not sử dụng một giao diện thông thạo

tôi sẽ đề nghị không thực hiện một giao diện thông thạo truyền thống, vì nó làm tăng số lượng mã bạn cần để viết, làm phức tạp mã của bạn và chỉ thêm bản mẫu không cần thiết.

Một tùy chọn khác, không phải làm gì cả!

Không thực hiện bất kỳ điều gì. Không cung cấp các hàm tạo "dễ" cho việc thiết lập các thuộc tính và không cung cấp một giao diện thông minh để giúp khách hàng của bạn. Cho phép ứng dụng khách đặt các thuộc tính theo cách thông thường. Trong .Net C# hoặc VB, điều này có thể đơn giản như sử dụng object initializers.

Car myCar = new Car { Name = "Chevrolet Corvette", Color = Color.Yellow }; 

Vì vậy, bạn không cần tạo bất kỳ giao diện thông minh nào trong mã của mình và điều này rất dễ đọc.

Nếu bạn có rất phức tạp Đặt thuộc tính phải được đặt hoặc đặt theo thứ tự nhất định, sau đó sử dụng đối tượng cấu hình riêng và chuyển cho lớp qua một thuộc tính riêng.

CarConfig conf = new CarConfig { Color = Color.Yellow, Fabric = Fabric.Leather }; 
Car myCar = new Car { Config = conf }; 
+11

Các upsides của một API thông thạo (khả năng đọc tốt hơn và một cách trực quan hơn để làm việc với API của bạn) quan trọng hơn nhiều so với việc có một mã phức tạp hơn một chút. NẾU bạn tạo một API, thì đó là tất cả về người dùng sẽ truy cập vào API của bạn. Nếu bạn có thể làm hài lòng anh ta với một phong cách thông thạo, tôi sẽ nỗ lực hết mình để làm việc với API dễ dàng nhất có thể, ngay cả khi điều đó có nghĩa là đặt nhiều công việc hơn vào API. –

+3

Nó tạo ra một giao diện khác với giao diện của người khác. Điều đó không giúp bất cứ ai hiểu API của bạn hoặc sử dụng nó dễ dàng. Mô hình khởi tạo hoặc đối tượng thuộc tính là tiêu chuẩn hơn nhiều, và tự mô tả trong OO bình thường. – badbod99

+0

Trình khởi tạo đối tượng không cho phép tạo đối tượng bất biến hữu ích cho một số thứ nhất định. – mmmdreg

28

MrBlah,

Mặc dù bạn có thể viết phương pháp khuyến nông để viết một giao diện thông thạo, một cách tiếp cận tốt hơn là sử dụng các mô hình xây dựng. Tôi đang ở trong cùng một chiếc thuyền như bạn và tôi đang cố gắng tìm ra một vài tính năng nâng cao của giao diện thông thạo.

Dưới đây bạn sẽ thấy một số mẫu mã mà tôi tạo ra trong another thread

public class Coffee 
{ 
    private bool _cream; 
    private int _ounces; 

    public static Coffee Make { get { return new Coffee(); } } 

    public Coffee WithCream() 
    { 
     _cream = true; 
     return this; 
    } 
    public Coffee WithOuncesToServe(int ounces) 
    { 
     _ounces = ounces; 
     return this; 
    } 
} 

var myMorningCoffee = Coffee.Make.WithCream().WithOuncesToServe(16); 
+2

Giống như nó, ví dụ rất rõ ràng mặc dù đâu là định nghĩa giao diện? :) – Hace

+0

Sử dụng cú pháp khởi tạo đối tượng C# thay vì ví dụ của bạn sẽ gọn gàng hơn (và tránh cần phải viết phương thức 'WithFoo') và làm rõ rằng chỉ các thuộc tính đang được thiết lập. Tôi nghĩ rằng phong cách "thông thạo" chỉ nên được sử dụng nếu bạn cần các tác dụng phụ. – Dai

1

Viết họ một API thông thạo nó phức tạp, đó là lý do tại sao tôi đã viết Diezel là trình tạo API thông thạo cho Java.Nó tạo ra các API với giao diện (hoặc khóa học) tới:

  1. kiểm soát sự kêu gọi chảy
  2. bắt kiểu generic (như Guice một)

Nó cũng tạo ra hiện thực.

Đó là plugin maven.

15

Trong khi nhiều người đã trích dẫn Martin Fowler như là một số mũ nổi bật trong thảo luận API thông thạo, tuyên bố thiết kế ban đầu của ông thực sự phát triển xung quanh một fluent builder pattern hoặc method chaining. API thông thạo có thể được phát triển thêm vào thực tế internal domain-specific languages. Một bài viết mà giải thích làm thế nào một ký hiệu BNF của một ngữ pháp có thể được tự biến thành một "API thông thạo" có thể được nhìn thấy ở đây:

http://blog.jooq.org/2012/01/05/the-java-fluent-api-designer-crash-course/

Nó biến đổi ngữ pháp này:

enter image description here

Into Java API này:

// Initial interface, entry point of the DSL 
interface Start { 
    End singleWord(); 
    End parameterisedWord(String parameter); 
    Intermediate1 word1(); 
    Intermediate2 word2(); 
    Intermediate3 word3(); 
} 

// Terminating interface, might also contain methods like execute(); 
interface End { 
    void end(); 
} 

// Intermediate DSL "step" extending the interface that is returned 
// by optionalWord(), to make that method "optional" 
interface Intermediate1 extends End { 
    End optionalWord(); 
} 

// Intermediate DSL "step" providing several choices (similar to Start) 
interface Intermediate2 { 
    End wordChoiceA(); 
    End wordChoiceB(); 
} 

// Intermediate interface returning itself on word3(), in order to allow 
// for repetitions. Repetitions can be ended any time because this 
// interface extends End 
interface Intermediate3 extends End { 
    Intermediate3 word3(); 
} 

Java và C# hơi tương tự, ví dụ này chắc chắn dịch sang trường hợp sử dụng của bạn là tốt. Kỹ thuật trên đã được sử dụng rất nhiều trong jOOQ, một API thông thạo/ngôn ngữ cụ thể tên miền nội bộ mô hình hóa ngôn ngữ SQL trong Java

7

Đây là câu hỏi rất cũ, và câu trả lời này có thể là một nhận xét chứ không phải là câu trả lời, nhưng Tôi nghĩ rằng đó là một chủ đề đáng để tiếp tục nói về, và phản hồi này quá dài để có thể nhận xét.

Suy nghĩ ban đầu liên quan đến "lưu loát" dường như về cơ bản là tăng thêm sức mạnh và tính linh hoạt (phương pháp chuỗi, vv) cho các đối tượng trong khi làm cho mã tự giải thích hơn một chút.

Ví dụ

Company a = new Company("Calamaz Holding Corp"); 
Person p = new Person("Clapper", 113, 24, "Frank"); 
Company c = new Company(a, 'Floridex', p, 1973); 

ít "thông thạo" hơn

Company c = new Company().Set 
    .Name("Floridex"); 
    .Manager(
     new Person().Set.FirstName("Frank").LastName("Clapper").Awards(24) 
    ) 
    .YearFounded(1973) 
    .ParentCompany(
     new Company().Set.Name("Calamaz Holding Corp") 
    ) 
; 

Nhưng với tôi, sau này không phải là thực sự bất cứ mạnh hơn hoặc linh hoạt hoặc tự giải thích hơn

Company c = new Company(){ 
    Name = "Floridex", 
    Manager = new Person(){ FirstName="Frank", LastName="Clapper", Awards=24 }, 
    YearFounded = 1973, 
    ParentCompany = new Company(){ Name="Calamaz Holding Corp." } 
}; 

..trong thực tế, tôi sẽ gọi phiên bản cuối cùng này dễ dàng hơn để tạo, đọc và duy trì hơn phiên bản trước và tôi sẽ nói rằng nó đòi hỏi hành lý ít hơn đáng kể đằng sau hậu trường, là tốt. Điều quan trọng đối với tôi, vì (ít nhất) hai lý do:

1 - Chi phí liên quan đến việc tạo và duy trì các lớp đối tượng (bất kể ai làm) cũng giống như thực tế, có liên quan và quan trọng như chi phí liên quan tạo và duy trì mã tiêu thụ chúng.

2 - Mã bloat được nhúng trong các lớp đối tượng sẽ tạo ra nhiều lỗi (nếu không nhiều) như mã bloat trong mã tiêu thụ các đối tượng đó.

Sử dụng phiên bản cuối cùng có nghĩa là bạn có thể thêm thuộc tính (có khả năng hữu ích) vào lớp Công ty chỉ bằng cách thêm một dòng mã rất đơn giản.

Đó không phải là để nói rằng tôi cảm thấy không có chỗ cho phương pháp chuỗi. Tôi thực sự thích việc có thể làm những việc như (trong JavaScript)

var _this = this; 
Ajax.Call({ 
    url: '/service/getproduct', 
    parameters: {productId: productId}, 
) 
.Done(
    function(product){ 
     _this.showProduct(product); 
    } 
) 
.Fail(
    function(error){ 
     _this.presentError(error); 
    } 
); 

..where (trong trường hợp giả thuyết tôi đang tưởng tượng) Done và Fail đã bổ sung vào đối tượng Ajax gốc, và có thể được bổ sung mà không thay đổi bất kỳ mã đối tượng Ajax gốc nào hoặc bất kỳ mã hiện có nào đã sử dụng đối tượng Ajax ban đầu và không tạo ra các thứ một lần ngoại lệ cho tổ chức chung của mã.

Vì vậy, tôi chắc chắn đã tìm thấy giá trị trong việc tạo một tập hợp con các hàm của đối tượng trả về đối tượng 'this'. Trong thực tế bất cứ khi nào tôi có một chức năng mà nếu không sẽ trở lại void, tôi xem xét việc có nó trở lại này.

Nhưng tôi chưa thực sự tìm thấy giá trị đáng kể trong việc thêm "giao diện thông thạo" (.eg "Set") vào một đối tượng, mặc dù về mặt lý thuyết có vẻ như có thể là một tổ chức mã giống như không gian tên. ra khỏi thực hành làm điều đó, có thể đáng giá. ("Set" có thể không có giá trị đặc biệt, nhưng "Command", "Query" và "Transfer" có thể, nếu nó giúp tổ chức mọi thứ và tạo điều kiện và giảm thiểu tác động của việc bổ sung và thay đổi.) Một trong những lợi ích tiềm năng của việc thực hành đó , tùy thuộc vào cách nó đã được thực hiện, có thể được cải thiện trong mức độ điển hình của một người chăm sóc và sự chú ý đến mức độ bảo vệ - sự thiếu hụt trong đó chắc chắn đã gây ra khối lượng lớn đau buồn.

Các vấn đề liên quan