Uso de la gramática del lenguaje natural en API fluida

14

Estoy jugando con una abstracción de consultas a través de la API de base de datos WebSQL / Phonegap, y me siento atraído y dudoso de definir una API fluida que imite el uso de la gramática del idioma inglés natural.

Podría ser más fácil de 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);

Por el bien de la pregunta, supongamos que no he agotado todas las posibles construcciones 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í está limitada a los verbos y las conjunciones definidas por SQL.

Editar con respecto a la agrupación : una "oración" es un grupo, y la prioridad es la definida en SQL: de izquierda a derecha. Se pueden expresar múltiples agrupaciones con varias declaraciones where :

//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 encuentra. Por ejemplo, el argumento de "métodos de conjunción" or() y and() se puede omitir, o se refiere a un nombre de campo o valor esperado.

Para mí, esto es muy intuitivo, pero me gustaría que escuchara sus comentarios: ¿es esta una API buena y útil, o debería retroceder a una implementación más directa?

Para el registro: esta biblioteca también proporcionará una API más convencional y no fluida basada en objetos de configuración.

    
pregunta fencliff 01.03.2013 - 15:52

4 respuestas

23

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 de acuerdo con el contexto:

  • Esto agrega más sorpresas ya que traes ambigüedad
  • Sus usuarios querrán usar construcciones que usted no habrá cubierto, por ejemplo. %código%
  • Es difícil informar errores: ¿qué puedes hacer con find("user").where("name").and("email").equals("foo"); ?
  

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í está limitada a los verbos y las conjunciones.   definido por SQL.

No, no puedes cubrir la mayoría de las oraciones correctas en inglés. Otros lo han intentado antes, y se complica muy rápidamente. Se llama Comprensión del lenguaje natural , pero nadie lo intenta realmente: primero intentamos resolver problemas más pequeños. Para tu biblioteca, básicamente tienes dos opciones:

  • o bien te restringes a un subconjunto de inglés: eso te da SQL,
  • o intenta cubrir "inglés" y descubre que no es posible debido a la ambigüedad, complejidad y diversidad del idioma.
respondido por el Quentin Pradet 01.03.2013 - 16:00
3

Tiendo a coincidir un poco con las publicaciones de otros en que este no es un gran diseño. Sin embargo, creo que tengo diferentes razones.

Estás presentando lo que veo como una sintaxis concreta para las consultas SQL. Creo firmemente que la sintaxis concreta nunca puede ayudar a un idioma, solo duele si es mala.

Sin embargo, sintaxis abstracta es una historia diferente. La sintaxis abstracta define la estructura de su lenguaje y cómo se pueden combinar las frases para construir frases más grandes. Creo 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, hace que las cosas sean mucho más complicadas de lo que son. 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 digo "¡Bien!" ¡Pero eso no significa que no puedas desarrollar tu API fluida en paralelo! Una única definición de sintaxis abstracta puede soportar 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.

    
respondido por el user39685 01.03.2013 - 18:59
2

Además de los buenos puntos de Quentin Pradet, dudo de los supuestos beneficios de este lenguaje.

Presumiblemente, el punto de una gramática cercana al lenguaje natural es hacerlo accesible. Pero el SQL ya está bastante cerca del lenguaje natural. ¿Es uno de estos realmente más cercano al inglés que el otro?

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

select user from table where name = 'foo'

Realmente no veo el beneficio de su gramática, desde el punto de vista de la intuición o la 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.

    
respondido por el user82096 01.03.2013 - 17:12
2

Hay una cantidad de bad menos que las decisiones de diseño 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 "¿qué ventaja tiene esto sobre el uso de SQL?" se convierte en clave. Si es más engorroso escribir con la interfaz fluida que solo escribir una cadena con la interpolación adecuada, entonces no se escribirá con esta API.

El inglés es ambiguo. Intentar modelar una interfaz fluida en inglés es una mala elección (es mejor usar Latin ). Cuando hay varios análisis posiblemente válidos del mismo conjunto de cadenas de llamadas, esto genera confusión y sorpresa . Ninguno de estos es bueno tener en una API.

Hay más partes en SQL de lo que esta API está exponiendo. Las combinaciones (en cualquiera de sus múltiples formas) están notablemente ausentes en el conjunto de ejemplos. Subconsultas ( foo in (select id from bar) ), uniones y agrupaciones son algunas de las cosas que se usan a menudo. Las agrupaciones complejas de lógica no parecen estar presentes de manera intuitiva.

Si uno estaba escribiendo usando esta API y luego encontró que la API no es capaz de expresar la consulta deseada, se perderá un tiempo significativo. Es una mala elección usar estilos mixtos para realizar consultas en una aplicación (consultas simples en esta api, complejas en sql sin formato), y en última instancia se usará la que sea más expresiva.

Si bien la programación está muy extendida, la fluidez en inglés no lo está. Incluso con una limitación del idioma a "SQL like", hay matices de cómo un hablante nativo leería algo y alguien que tiene el inglés como segundo o tercer idioma.

Hay redundancia innecesaria en la API por el bien del inglés. En particular, equal() vs equals() haciendo lo mismo. Si bien no estoy seguro de eso, creo que is() es un no-op agregado por el bien de un cerrador de inglés que coincida. Doy la bienvenida a cualquiera que escuche mis comentarios sobre la redundancia de métodos en el chat de ruby, no cometas el mismo error.

Siéntese y escriba un conjunto completo de ejemplos de las consultas que desea poder usar. Determine quién manejará todos esos ejemplos de una manera no ambigua que sea menos incómoda que las consultas en sí 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 conexión en red

  

(12) En el diseño de protocolos, se ha alcanzado la perfección no cuando hay   no queda nada por agregar, pero cuando no queda nada por quitar.

    
respondido por el user40980 01.03.2013 - 17:15

Lea otras preguntas en las etiquetas