Я возился с абстракцией запросов через API баз данных WebSQL / Phonegap, и я чувствую себя неуверенно и не в силах определить свободный API, который имитирует использование естественной грамматики английского языка.
Это может быть проще объяснить с помощью примеров. Следующее - все допустимые запросы в моей грамматике, и комментарии объясняют предполагаемую семантику:
//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);
Редактирование на основе отзывов Квентина Праде : Кроме того, похоже, что API должен был бы поддерживать как формы множественного числа, так и формы единственного числа, поэтому:
//a equals b
find("post").where("foo").equals(1);
//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);
Ради вопроса, давайте предположим, что я не исчерпал все возможные конструкции здесь. Давайте также предположим, что я могу охватить большинство правильных английских предложений - в конце концов, сама грамматика ограничена глаголами и конъюнкциями, определенными в SQL.
Редактировать в отношении группировки : одно «предложение» - это одна группа, и приоритет такой, как определено в SQL: слева направо. Несколько группировок могут быть выражены несколькими where
операторами:
//the conjunctive "and()" between where statements is optional
find("post")
.where("foo").and("bar").equal(2).and()
.where("baz").isLessThan(5);
Как вы можете видеть, определение каждого метода зависит от грамматического контекста он находится. Например, аргумент «метода сопряжения» or()
и and()
может быть либо опущено, либо ссылаться на имя поля или ожидаемое значение.
Для меня это кажется очень интуитивным, но я хотел бы, чтобы вы услышали ваши отзывы: это хороший, полезный API, или я должен вернуться к более простой реализации?
Для справки: эта библиотека также предоставит более обычный, не беглый API на основе объектов конфигурации.
источник
... where foo = 1 or (bar = 2 and qux = 3)
?where("name").equals("foo").or("bar")
как(name=="foo")or bar
. Тогда неясно, когда строка представляет литерал, а когда она представляет имя столбца, ...Ответы:
Я думаю, что это очень неправильно. Я изучаю естественный язык, и он полон неоднозначности, которая может быть решена только с учетом контекста и большого количества человеческих знаний. Тот факт, что языки программирования не являются неоднозначными, это очень хорошая вещь! Я не думаю, что вы хотите, чтобы значение методов менялось в зависимости от контекста:
find("user").where("name").and("email").equals("foo");
find("user").where("name").not().is().null();
?Нет, вы не можете охватить большинство правильных английских предложений. Другие пробовали раньше, и это очень сложно очень быстро. Это называется пониманием естественного языка, но на самом деле этого никто не пытается: сначала мы пытаемся решить более мелкие проблемы. Для вашей библиотеки у вас есть два варианта:
источник
is()
илиequal()
толькоequals()
. После этого не вижу проблем с сообщениями об ошибках.null()
также станет литералом для сравнения, а не синтаксической функцией.find("user").where("name").is().not().null();
становитсяfind("user").where("name").not().equals(null);
Я склонен несколько согласиться с постами других, что это не очень хороший дизайн. Однако я считаю, что у меня есть другие причины.
Вы представляете то, что я рассматриваю как конкретный синтаксис для запросов SQL. Я твердо верю, что конкретный синтаксис никогда не поможет языку, а только повредит, если он плохой.
Однако абстрактный синтаксис - это отдельная история. Абстрактный синтаксис определяет структуру вашего языка и то, как фразы могут быть объединены для создания больших фраз. Я чувствую, что успех языка сильно зависит от качества определения абстрактного синтаксиса.
Моя проблема с беглым API не в том, что он двусмысленный, неясный или не выразительный, а в том, что он скрывает реальный язык и его структуру, и, в результате, делает вещи намного сложнее, чем они должны быть ( путем введения неоднозначностей, неочевидных синтаксических ошибок и т. д.).
Поскольку вы упомянули, что вы также предоставите «более традиционный API», похоже, вы уже все это знаете. На что я говорю "Хорошо!" Но это не значит, что вы не можете разрабатывать свой свободный API параллельно! Одно определение абстрактного синтаксиса может поддерживать несколько конкретных синтаксисов. Хотя вы должны помнить, что абстрактный синтаксис - это реальная сделка, конкретный синтаксис также может быть очень полезным.
источник
В дополнение к очень хорошим моментам Квентина Праде, я сомневаюсь в предполагаемых преимуществах этого языка.
Предположительно, смысл грамматики, близкой к естественному языку, состоит в том, чтобы сделать ее доступной. Но SQL уже довольно близок к естественному языку. Один из них действительно ближе к английскому, чем другой?
Я не вижу пользы от вашей грамматики с точки зрения интуитивности или читабельности. На самом деле, версия SQL выглядит более читабельной (и ее легче набирать) из-за пробелов.
источник
Существует множество
плохих, ноне идеальных, дизайнерских решений, которые были приняты при рассмотрении этого API.Во-первых, вопрос полезности - какой цели он служит? Похоже, это создает структуру данных, которая скомпилируется в диалект SQL. Между прочим, грамматика представляется ограниченным набором SQL. Вопрос о том, "какое преимущество это дает по сравнению только с использованием SQL?" становится ключом. Если писать с использованием беглого интерфейса более громоздко, чем просто писать строку с соответствующей интерполяцией, то с помощью этого API нельзя писать.
Английский неоднозначен. Попытка смоделировать свободный интерфейс на английском языке - плохой выбор (лучше использовать латынь ). Когда существует несколько возможных действительных разборов одного и того же набора цепочек вызовов, это приводит к замешательству и удивлению . Ни одна из этих вещей не является хорошей вещью в API.
В SQL больше частей, чем этот API. Соединения (в любой их бесчисленной форме) заметно отсутствуют в наборе примеров. Подзапросы (
foo in (select id from bar)
), объединения и группировка - вот некоторые из вещей, которые часто используются. Сложные логические группы, кажется, не присутствуют каким-либо интуитивным образом.Если кто-то писал с использованием этого API, а затем обнаружил, что API не способен выразить желаемый запрос, значительное время будет потеряно. Неправильно использовать смешанные стили для выполнения запросов в приложении (простые запросы в этом API, сложные в raw sql) - и в конечном итоге будет использоваться более выразительный.
В то время как программирование широко распространено, беглость английского языка - нет. Даже с ограничением языка «SQL как» есть нюансы того, как носитель языка будет читать что-то и кто-то, у кого английский является вторым или третьим языком.
Излишняя избыточность в API ради английского языка. В частности ,
equal()
противequals()
делать то же самое. Хотя я не уверен в этом, я полагаю, чтоis()
этот вариант не добавлен ради соответствия английского ближе. Я приветствую всех, кто послушает мои разговоры о избыточности методов в ruby в чате - не делайте ту же ошибку.Сядьте и напишите исчерпывающий набор примеров запросов, которые вы хотите использовать. Определите, с кем вы будете обращаться со всеми этими примерами не однозначным образом, который будет менее громоздким, чем сами запросы. Если вы не можете, подумайте, стоит ли идти по пути написания API. SQL находится там, где он есть сегодня (он не идеален, но я не нашел ничего лучшего) за десятилетия совершенствования.
RFC 1925 - Двенадцать сетевых истин
источник