Sử dụng ngữ pháp ngôn ngữ tự nhiên trong API thông thạo


14

Tôi đang nghiên cứu một bản tóm tắt truy vấn về API cơ sở dữ liệu WebQuery / Phonegap và tôi thấy mình vừa bị thu hút, vừa nghi ngờ về việc xác định một API lưu loát bắt chước việc sử dụng ngữ pháp tiếng Anh tự nhiên.

Có thể dễ dàng nhất để giải thích điều này thông qua các ví dụ. Sau đây là tất cả các truy vấn hợp lệ trong ngữ pháp của tôi và các bình luận giải thích ngữ nghĩa dự định:

//find user where name equals "foo" or email starts with "foo@"
find("user").where("name").equals("foo").and("email").startsWith("foo@")

//find user where name equals "foo" or "bar"
find("user").where("name").equals("foo").or("bar");

//find user where name equals "foo" or ends with "bar"
find("user").where("name").equals("foo").or().endsWith("bar");

//find user where name equals or ends with "foo"
find("user").where("name").equals().or().endsWith("foo");

//find user where name equals "foo" and email is not like "%contoso.com"
find("user").where("name").equals("foo").and("email").is().not().like("%contoso.com");

//where name is not null
find("user").where("name").is().not().null();

//find post where author is "foo" and id is in (1,2,3)
find("post").where("author").is("foo").and("id").is().in(1, 2, 3);

//find post where id is between 1 and 100
find("post").where("id").is().between(1).and(100);

Chỉnh sửa dựa trên phản hồi của Quentin Pradet : Ngoài ra, có vẻ như, API sẽ phải hỗ trợ cả dạng động từ số nhiều và số ít, vì vậy:

//a equals b
find("post").where("foo").equals(1);

//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);

Vì lợi ích của câu hỏi, hãy giả sử rằng tôi đã không sử dụng hết tất cả các cấu trúc có thể có ở đây. Chúng ta cũng giả sử rằng tôi có thể bao quát hầu hết các câu tiếng Anh chính xác - xét cho cùng, chính ngữ pháp bị giới hạn trong các động từ và kết hợp được xác định bởi SQL.


Chỉnh sửa liên quan đến nhóm : Một "câu" là một nhóm và quyền ưu tiên được xác định trong SQL: từ trái sang phải. Nhiều nhóm có thể được thể hiện bằng nhiều wherecâu lệnh:

//the conjunctive "and()" between where statements is optional
find("post")
  .where("foo").and("bar").equal(2).and()
  .where("baz").isLessThan(5);

Như bạn có thể thấy, định nghĩa của mỗi phương thức phụ thuộc vào ngữ cảnh ngữ pháp của nó. Ví dụ: đối số cho "phương thức kết hợp" or()and()có thể bỏ qua hoặc tham chiếu đến tên trường hoặc giá trị mong đợi.

Đối với tôi điều này cảm thấy rất trực quan, nhưng tôi muốn bạn nghe phản hồi của bạn: đây có phải là một API tốt, hữu ích hay tôi nên ủng hộ việc triển khai mạnh mẽ hơn?

Đối với bản ghi: thư viện này cũng sẽ cung cấp API thông thường hơn, không lưu loát dựa trên các đối tượng cấu hình.


1
Chaining cũng là lý do tại sao jQuery rất nổi tiếng. Khá đơn giản, tuần tự, và dễ hiểu.
Joseph

3
Hay đấy! Bạn có lẽ nên hỏi điều này trên các lập trình viên.
Benjamin Gruenbaum

2
Làm thế nào bạn sẽ xử lý nhóm? Tương đương với : ... where foo = 1 or (bar = 2 and qux = 3)?

7
IMO loại API thông thạo này thật kinh khủng. Ví dụ thiếu sự ưu tiên của nhà điều hành là gây phiền nhiễu. Tôi sẽ phân tích where("name").equals("foo").or("bar")như (name=="foo")or bar. Sau đó, không rõ ràng khi một chuỗi đại diện cho một nghĩa đen và khi nó thể hiện một tên cột, ...
CodeInChaos

4
btw. nếu bạn muốn sử dụng DSL để truy vấn cơ sở dữ liệu, bạn có thể sử dụng DSL hiện có tên là SQL.
CodeInChaos

Câu trả lời:


23

Tôi nghĩ nó rất sai. Tôi nghiên cứu langage tự nhiên và nó đầy mơ hồ chỉ có thể được giải quyết với bối cảnh và rất nhiều kiến ​​thức của con người. Thực tế là ngôn ngữ lập trình không mơ hồ là một điều rất tốt! Tôi không nghĩ bạn muốn ý nghĩa của các phương thức thay đổi theo ngữ cảnh:

  • Điều này là thêm nhiều bất ngờ kể từ khi bạn mang lại sự mơ hồ
  • Người dùng của bạn sẽ muốn sử dụng các công trình mà bạn sẽ không được bảo hiểm, ví dụ. find("user").where("name").and("email").equals("foo");
  • Thật khó để báo cáo lỗi: bạn có thể làm gì với find("user").where("name").not().is().null();?

Chúng ta cũng giả sử rằng tôi có thể bao quát hầu hết các câu tiếng Anh chính xác - xét cho cùng, chính ngữ pháp bị giới hạn trong các động từ và kết hợp được xác định bởi SQL.

Không, bạn không thể bao gồm hầu hết các câu tiếng Anh chính xác. Những người khác đã thử trước đây và nó trở nên rất phức tạp rất nhanh. Nó được gọi là hiểu ngôn ngữ tự nhiên nhưng không ai thực sự cố gắng rằng: chúng tôi đang cố gắng giải quyết các vấn đề nhỏ hơn trước. Đối với thư viện của bạn, về cơ bản bạn có hai tùy chọn:

  • hoặc bạn giới hạn bản thân trong một tập hợp tiếng Anh: cung cấp cho bạn SQL,
  • hoặc bạn cố gắng bao quát "tiếng Anh" và bạn phát hiện ra rằng điều đó là không thể do sự mơ hồ, phức tạp và đa dạng của ngôn ngữ.

Cảm ơn vì đầu vào của bạn. Chỉnh sửa câu hỏi của tôi để bao gồm trường hợp đầu tiên bạn liệt kê và thêm một số cảnh báo. Tôi đồng ý với quan điểm của bạn về sự mơ hồ - đó là mấu chốt của câu hỏi của tôi. Có thể chấp nhận cho các ngôn ngữ lập trình trở nên mơ hồ trong bối cảnh được xác định rõ?
fencliff

nếu nó mơ hồ, nó không được xác định rõ. Nếu nó mơ hồ, có nhiều hơn một kết quả tiềm năng, và một cái gì đó phải chọn một trong số chúng. Lựa chọn sẽ được xác định rõ hoặc trình phân tích cú pháp ngôn ngữ sẽ chọn ngẫu nhiên. Vì vậy, sự không rõ ràng trong ngôn ngữ lập trình là ổn nếu bạn muốn một ngôn ngữ ngẫu nhiên (1 + 1 có thể bằng 2, và đôi khi có thể bằng 1 hoặc 3) trái ngược với định thức (1 + 1 luôn bằng 2).
Michael Paulukonis

Bạn đang nói về đề nghị của anh ấy hoặc tiếng Anh? Hầu hết thời gian, sự mơ hồ có thể được giải quyết bằng cách sử dụng bối cảnh và / hoặc kiến ​​thức (một phần trong đó là lẽ thường), một thứ không có sẵn cho máy tính.
Quentin Pradet

+1 Nắm bắt tốt về độ nhạy ngữ cảnh của việc triển khai API thông thạo cụ thể của anh ấy. Tôi thích ý tưởng về API thông thạo của anh ấy ngay từ cái nhìn đầu tiên nhưng không nhìn kỹ để thấy điều này. Chắc chắn vấn đề rất lớn.
Jimmy Hoffa

Nếu anh ta làm cho ngữ pháp rõ ràng và bối cảnh miễn phí thì vấn đề là gì? chắc chắn rằng họ có thể muốn loại bỏ các câu số nhiều dạng động từ và những thứ tương tự, nhưng nó không thay đổi cốt lõi của những gì họ đang cố gắng làm. Bạn sẽ không có is()hoặc equal()chỉ equals(). Không thấy vấn đề của bạn với báo cáo lỗi sau này. null()cũng sẽ trở thành một nghĩa đen để so sánh với, chứ không phải là một hàm cú pháp. find("user").where("name").is().not().null();trở thànhfind("user").where("name").not().equals(null);
whn

3

Tôi có xu hướng phần nào đồng ý với bài viết của người khác rằng đây không phải là một thiết kế tuyệt vời. Tuy nhiên, tôi tin rằng tôi có những lý do khác nhau.

Bạn đang trình bày những gì tôi xem là một cú pháp cụ thể cho các truy vấn SQL. Tôi tin tưởng mạnh mẽ rằng cú pháp cụ thể không bao giờ có thể giúp một ngôn ngữ, chỉ bị tổn thương nếu nó xấu.

Tuy nhiên, cú pháp trừu tượng là một câu chuyện khác nhau. Cú pháp trừu tượng xác định cấu trúc ngôn ngữ của bạn và cách các cụm từ có thể được kết hợp để xây dựng các cụm từ lớn hơn. Tôi cảm thấy rằng sự thành công của một ngôn ngữ phụ thuộc mạnh mẽ vào chất lượng của định nghĩa cú pháp trừu tượng của nó.

Vấn đề của tôi với API thông thạo không phải là nó mơ hồ, không rõ ràng hoặc không biểu cảm - nó che giấu ngôn ngữ thực và cấu trúc của nó, và như vậy, kết thúc khiến mọi thứ trở nên phức tạp hơn nhiều so với chúng ( bằng cách giới thiệu sự mơ hồ, lỗi cú pháp không rõ ràng, v.v.).

Vì bạn đã đề cập rằng bạn cũng sẽ cung cấp "API thông thường hơn", có vẻ như bạn đã biết tất cả điều này. Tôi nói "Tốt!" Nhưng điều đó không có nghĩa là bạn cũng không thể phát triển API thông thạo của mình song song! Một định nghĩa cú pháp trừu tượng duy nhất có thể hỗ trợ nhiều cú pháp cụ thể. Mặc dù bạn nên nhớ rằng cú pháp trừu tượng là vấn đề thực sự, một cú pháp cụ thể cũng có thể rất hữu ích.


2

Ngoài những điểm rất tốt của Quentin Pradet, tôi còn nghi ngờ về những lợi ích bị cáo buộc của ngôn ngữ này.

Có lẽ điểm của một ngữ pháp gần với ngôn ngữ tự nhiên là làm cho nó có thể truy cập được. Nhưng SQL đã khá gần với ngôn ngữ tự nhiên. Là một trong những thực sự gần gũi với tiếng Anh hơn những người khác?

find("user").where("name").equals("foo")

select user from table where name = 'foo'

Tôi thực sự không thấy lợi ích của ngữ pháp của bạn, từ quan điểm trực giác hoặc dễ đọc. Trong thực tế, phiên bản SQL trông dễ đọc hơn (và dễ gõ hơn) vì khoảng trắng của nó.


2

Có một số điều tồi tệ ít hơn các quyết định thiết kế lý tưởng dường như đã được đưa ra khi xem xét API này.

Đầu tiên là câu hỏi về tiện ích - nó phục vụ mục đích gì? Điều này dường như đang tạo ra một cấu trúc dữ liệu sẽ biên dịch thành một phương ngữ của SQL. Ngẫu nhiên, ngữ pháp dường như là một bộ SQL giới hạn. Câu hỏi về "lợi thế này phục vụ gì khi chỉ sử dụng SQL?" trở thành chìa khóa Nếu việc viết bằng giao diện trôi chảy sẽ khó khăn hơn so với việc chỉ viết một chuỗi có nội suy phù hợp trong đó thì người ta sẽ không viết bằng API này.

Tiếng Anh mơ hồ. Cố gắng mô hình một giao diện thông thạo tiếng Anh là một lựa chọn kém (bạn nên sử dụng tiếng Latin tốt hơn ). Khi có nhiều phân tích cú pháp có thể hợp lệ của cùng một chuỗi các cuộc gọi, điều này dẫn đến sự nhầm lẫn và bất ngờ . Cả hai điều này đều không có gì tốt trong API.

Có nhiều phần đối với SQL hơn API này đang phơi bày. Các phép nối (trong bất kỳ dạng nào trong vô số các dạng của chúng) đáng chú ý là dạng không có trong ví dụ được đặt. Truy vấn con ( foo in (select id from bar)), đoàn thể và nhóm bằng một vài trong số những điều thường được sử dụng. Các nhóm logic phức tạp dường như không xuất hiện theo bất kỳ cách trực quan nào.

Nếu một người đã viết bằng API này và sau đó thấy rằng API không có khả năng thể hiện truy vấn mong muốn, thời gian đáng kể sẽ bị mất. Việc sử dụng các kiểu hỗn hợp để thực hiện một truy vấn trong một ứng dụng là một lựa chọn kém (các truy vấn đơn giản trong api này, phức tạp trong sql thô) - và cuối cùng là một kiểu biểu cảm hơn sẽ được sử dụng.

Trong khi lập trình là phổ biến, tiếng Anh lưu loát thì không. Ngay cả với giới hạn của ngôn ngữ đối với "SQL như", vẫn có những sắc thái về cách một người bản ngữ sẽ đọc một cái gì đó và một người có tiếng Anh là ngôn ngữ thứ hai hoặc thứ ba.

Có sự dư thừa không cần thiết trong API vì tiếng Anh. Đặc biệt equal()so vớiequals() làm điều tương tự. Mặc dù tôi không chắc chắn về điều đó, tôi tin rằng đó is()là một bổ sung không vì mục đích tiếng Anh phù hợp gần hơn. Tôi hoan nghênh bất kỳ ai lắng nghe những lời ca tụng của tôi về sự dư thừa của các phương pháp trong ruby ​​trong trò chuyện - đừng phạm sai lầm tương tự.

Hãy ngồi xuống và viết ra một ví dụ toàn diện về các truy vấn bạn muốn có thể sử dụng. Xác định người bạn sẽ xử lý tất cả các ví dụ đó theo cách không mơ hồ, ít rườm rà hơn các truy vấn. Nếu bạn không thể, hãy cân nhắc xem có đáng để đi theo con đường viết API không. SQL là nơi ngày nay (nó không hoàn hảo, nhưng tôi không tìm thấy gì tốt hơn) qua nhiều thập kỷ sàng lọc.

RFC 1925 - Mười hai sự thật về mạng

(12) Trong thiết kế giao thức, sự hoàn hảo đã đạt được không phải khi không còn gì để thêm, mà là khi không còn gì để lấy đi.

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.