Sto armeggiando con un'astrazione di query sull'API del database WebSQL / Phonegap e mi trovo sia attratto, sia dubbioso, a definire un'API fluente che imita l'uso della grammatica della lingua inglese naturale.
Potrebbe essere più semplice spiegarlo tramite esempi. Di seguito sono tutte le query valide nella mia grammatica e i commenti spiegano la semantica prevista:
//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);
Modifica in base al feedback di Quentin Pradet : inoltre, l'API dovrebbe supportare forme verbali sia plurali che singolari, quindi:
//a equals b
find("post").where("foo").equals(1);
//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);
Per motivi di ipotesi, supponiamo che non abbia esaurito tutti i possibili costrutti qui. Supponiamo anche che io possa coprire la maggior parte delle frasi inglesi corrette - dopo tutto, la grammatica stessa è limitata ai verbi e alle congiunzioni definite da SQL.
Modifica per quanto riguarda il raggruppamento : una "frase" è un gruppo e la precedenza è come definita in SQL: da sinistra a destra. Più gruppi potrebbero essere espressi con più whereistruzioni:
//the conjunctive "and()" between where statements is optional
find("post")
.where("foo").and("bar").equal(2).and()
.where("baz").isLessThan(5);
Come puoi vedere, la definizione di ciascun metodo dipende dal contesto grammaticale in cui si trova. Ad esempio l'argomento "metodi di congiunzione" or()e and()può essere lasciato fuori, oppure fare riferimento al nome di un campo o al valore previsto.
Per me questo sembra molto intuitivo, ma vorrei che tu ascoltassi il tuo feedback: è una buona e utile API o dovrei tornare indietro a un'implementazione più diretta?
Per la cronaca: questa libreria fornirà anche un'API più convenzionale, non fluente, basata su oggetti di configurazione.
... where foo = 1 or (bar = 2 and qux = 3):?
where("name").equals("foo").or("bar")come (name=="foo")or bar. Quindi non è chiaro quando una stringa rappresenta un valore letterale e quando presenta un nome di colonna, ...