Estoy jugando con una abstracción de consulta sobre la API de base de datos WebSQL / Phonegap, y me siento atraído y dudoso por definir una API fluida que imite el uso de la gramática del idioma inglés natural.
Puede ser más fácil explicar esto a través de ejemplos. Las siguientes son todas las consultas válidas en mi gramática, y los comentarios explican la semántica 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);
Edición basada en los comentarios de Quentin Pradet : Además, parece que la API debería admitir formas verbales tanto en plural como en singular, por lo que:
//a equals b
find("post").where("foo").equals(1);
//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);
En aras de la pregunta, supongamos que no he agotado todas las construcciones posibles aquí. Supongamos también que puedo cubrir la mayoría de las oraciones correctas en inglés; después de todo, la gramática en sí misma se limita a los verbos y conjunciones definidos por SQL.
Editar con respecto a la agrupación : una "oración" es un grupo, y la precedencia es como se define en SQL: de izquierda a derecha. Se pueden expresar múltiples agrupaciones con múltiples where
declaraciones:
//the conjunctive "and()" between where statements is optional
find("post")
.where("foo").and("bar").equal(2).and()
.where("baz").isLessThan(5);
Como puede ver, la definición de cada método depende del contexto gramatical en el que se encuentre. Por ejemplo, el argumento de "métodos de conjunción" or()
y and()
puede omitirse o referirse a un nombre de campo o valor esperado.
Para mí, esto se siente muy intuitivo, pero me gustaría que escuche sus comentarios: ¿es esta una API buena y útil, o debería retroceder para una implementación más sencilla?
Para el registro: esta biblioteca también proporcionará una API más convencional y no fluida basada en objetos de configuración.
fuente
... where foo = 1 or (bar = 2 and qux = 3)
:?where("name").equals("foo").or("bar")
como(name=="foo")or bar
. Entonces no está claro cuándo una cadena representa un literal, y cuando presenta un nombre de columna, ...Respuestas:
Creo que está muy mal. Estudio el lenguaje natural y está lleno de ambigüedad que solo se puede resolver con contexto y mucho conocimiento humano. ¡El hecho de que los lenguajes de programación no sean ambiguos es algo muy bueno! No creo que quieras que el significado de los métodos cambie según el contexto:
find("user").where("name").and("email").equals("foo");
find("user").where("name").not().is().null();
?No, no puedes cubrir la mayoría de las oraciones correctas en inglés. Otros lo han intentado antes, y se vuelve muy complicado muy rápidamente. Se llama comprensión del lenguaje natural, pero en realidad nadie lo intenta: primero intentamos resolver problemas más pequeños. Para su biblioteca, básicamente tiene dos opciones:
fuente
is()
oequal()
soloequals()
. No vea su problema con los errores de informe después de esto.null()
también se convertiría en un literal para comparar, en lugar de una función de sintaxis.find("user").where("name").is().not().null();
se conviertefind("user").where("name").not().equals(null);
Tiendo a estar de acuerdo con las publicaciones de otros de que este no es un gran diseño. Sin embargo, creo que tengo diferentes razones.
Estás presentando lo que yo veo como una sintaxis concreta para consultas SQL. Creo firmemente que la sintaxis concreta nunca puede ayudar a un idioma, solo duele si es malo.
Sin embargo, la sintaxis abstracta es una historia diferente. La sintaxis abstracta define la estructura de su idioma y cómo se pueden combinar las frases para construir frases más grandes. Siento que el éxito de un lenguaje depende en gran medida de la calidad de su definición de sintaxis abstracta.
Mi problema con la API fluida no es que sea ambiguo, poco claro o no expresivo, es que oculta el lenguaje real y su estructura, y al hacerlo, termina haciendo las cosas mucho más complicadas de lo que deben ser ( introduciendo ambigüedades, errores de sintaxis no obvios, etc.).
Como mencionó que también proporcionará una "API más convencional", parece que ya sabe todo esto. A eso le digo "¡Bien!" ¡Pero eso no significa que no puedas desarrollar tu API fluida en paralelo! Una sola definición de sintaxis abstracta puede admitir múltiples sintaxis concretas. Si bien debe tener en cuenta que la sintaxis abstracta es la verdadera, una sintaxis concreta también puede ser muy útil.
fuente
Además de los muy buenos puntos de Quentin Pradet, dudo de los supuestos beneficios de este lenguaje.
Presumiblemente, el objetivo de una gramática cercana al lenguaje natural es hacerlo accesible. Pero SQL ya está bastante cerca del lenguaje natural. ¿Uno de estos está más cerca del inglés que el otro?
Realmente no veo el beneficio de su gramática, desde un punto de vista de intuición o legibilidad. De hecho, la versión SQL parece más legible (y es más fácil de escribir) debido a su espacio en blanco.
fuente
Hay una serie de
malasdecisiones de diseño menos que ideales que parecen haberse tomado al considerar esta API.La primera es la cuestión de la utilidad: ¿para qué sirve? Esto parece estar creando una estructura de datos que se compilará en un dialecto de SQL. Por cierto, la gramática parece ser un conjunto limitado de SQL. La pregunta de "¿para qué sirve esto con solo usar SQL?" se convierte en clave Si es más engorroso escribir usando la interfaz fluida que simplemente escribir una cadena con la interpolación apropiada, entonces uno no escribirá usando esta API.
El inglés es ambiguo. Intentar modelar una interfaz fluida en inglés es una mala elección (es mejor usar el latín ). Cuando hay múltiples análisis posiblemente válidos del mismo conjunto de cadenas de llamadas, esto genera confusión y sorpresa . Ninguno de estos son cosas buenas para tener en una API.
Hay más partes de SQL que esta API está exponiendo. Las uniones (en cualquiera de sus innumerables formas) están notablemente ausentes del conjunto de ejemplos. Las subconsultas (
foo in (select id from bar)
), los sindicatos y el grupo por son algunas de las cosas que se usan con frecuencia. Las agrupaciones complejas de lógica no parecen estar presentes de manera intuitiva.Si uno estaba escribiendo usando esta API y luego descubrió que la API no es capaz de expresar la consulta deseada, se perderá un tiempo considerable. Es una mala elección utilizar estilos mixtos para realizar consultas en una aplicación (consultas simples en esta API, complejas en sql sin formato) y, en última instancia, se utilizará la que sea más expresiva.
Si bien la programación es generalizada, la fluidez en inglés no lo es. Incluso con una limitación del lenguaje a "SQL like", hay matices de cómo un hablante nativo leería algo y alguien que tiene inglés como segundo o tercer idioma.
Hay redundancia innecesaria en la API por el bien del inglés. En particular
equal()
vsequals()
hacer lo mismo. Si bien no estoy seguro de eso, creo queis()
es un no-op agregado en aras de un inglés más cercano. Doy la bienvenida a cualquiera que escuche mis quejas sobre la redundancia de métodos en ruby en el chat; no cometa el mismo error.Siéntese y escriba un conjunto completo de ejemplos de las consultas que desea poder utilizar. Determine quién manejará todos esos ejemplos de una manera no ambigua que sea menos engorrosa que las consultas mismas. Si no puede, considere si vale la pena seguir el camino de escribir la API. SQL está donde está hoy (no es perfecto, pero no he encontrado nada mejor) durante décadas de refinamiento.
RFC 1925 - Las doce verdades de redes
fuente