Majstruję przy abstrakcji zapytań dotyczących interfejsu API bazy danych WebSQL / Phonegap, i jestem przekonany, że mam wątpliwości co do zdefiniowania płynnego interfejsu API, który naśladuje użycie naturalnej gramatyki języka angielskiego.
Najłatwiej to wyjaśnić za pomocą przykładów. Poniżej znajdują się wszystkie poprawne zapytania w mojej gramatyce, a komentarze wyjaśniają zamierzony semantyczny:
//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);
Edycja na podstawie opinii Quentin Pradet : Ponadto wydaje się, że interfejs API musiałby obsługiwać zarówno formy liczby mnogiej, jak i liczby pojedynczej, więc:
//a equals b
find("post").where("foo").equals(1);
//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);
Dla celów pytania załóżmy, że nie wyczerpałem tutaj wszystkich możliwych konstrukcji. Załóżmy również, że potrafię objąć najbardziej poprawne zdania angielskie - w końcu sama gramatyka jest ograniczona do czasowników i koniugatów zdefiniowanych przez SQL.
Edycja dotycząca grupowania : jedno „zdanie” to jedna grupa, a pierwszeństwo jest zdefiniowane w SQL: od lewej do prawej. Wiele grupowań można wyrazić za pomocą wielu where
instrukcji:
//the conjunctive "and()" between where statements is optional
find("post")
.where("foo").and("bar").equal(2).and()
.where("baz").isLessThan(5);
Jak widać, definicja każdej metody zależy od kontekstu gramatycznego, w którym się znajduje. Na przykład argument „metody koniunkcji” or()
i and()
można go pominąć lub odwołać się do nazwy pola lub oczekiwanej wartości.
Moim zdaniem wydaje się to bardzo intuicyjne, ale chciałbym usłyszeć Twoją opinię: czy jest to dobry, przydatny interfejs API, czy powinienem cofnąć się do prostszej implementacji?
Dla przypomnienia: ta biblioteka zapewni również bardziej konwencjonalny, nie płynny interfejs API oparty na obiektach konfiguracyjnych.
where("name").equals("foo").or("bar")
jak (name=="foo")or bar
. Wtedy nie jest jasne, kiedy ciąg reprezentuje literał, a kiedy przedstawia nazwę kolumny, ...