Saya mengutak-atik abstraksi kueri tentang WebSQL / Phonegap Database API, dan saya merasa tertarik, dan ragu-ragu, mendefinisikan API yang lancar yang meniru penggunaan tata bahasa Inggris alami.
Mungkin paling mudah untuk menjelaskan ini melalui contoh. Berikut ini adalah semua kueri yang valid dalam tata bahasa saya, dan komentar menjelaskan semantik yang dimaksud:
//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);
Sunting berdasarkan umpan balik Quentin Pradet : Selain itu, API harus mendukung bentuk kata kerja jamak dan tunggal, jadi:
//a equals b
find("post").where("foo").equals(1);
//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);
Demi pertanyaan, mari kita anggap bahwa saya belum kehabisan semua kemungkinan konstruksi di sini. Mari kita juga berasumsi bahwa saya dapat mencakup sebagian besar kalimat bahasa Inggris yang benar - setelah semua, tata bahasa itu sendiri terbatas pada kata kerja dan kata kerja yang didefinisikan oleh SQL.
Edit mengenai pengelompokan : Satu "kalimat" adalah satu kelompok, dan prioritasnya adalah seperti yang didefinisikan dalam SQL: kiri ke kanan. Pengelompokan berganda dapat diungkapkan dengan banyak where
pernyataan:
//the conjunctive "and()" between where statements is optional
find("post")
.where("foo").and("bar").equal(2).and()
.where("baz").isLessThan(5);
Seperti yang Anda lihat, definisi masing-masing metode bergantung pada konteks tata bahasa tempatnya. Misalnya argumen untuk "metode konjungsi" or()
dan and()
dapat ditinggalkan, atau merujuk ke nama bidang atau nilai yang diharapkan.
Bagi saya ini terasa sangat intuitif, tetapi saya ingin Anda mendengar tanggapan Anda: apakah ini API yang baik dan bermanfaat, atau haruskah saya mundur ke implementasi yang lebih lurus?
Sebagai catatan: pustaka ini juga akan menyediakan API non-fasih yang lebih konvensional berdasarkan objek konfigurasi.
sumber
... where foo = 1 or (bar = 2 and qux = 3)
?where("name").equals("foo").or("bar")
sebagai(name=="foo")or bar
. Maka tidak jelas kapan string mewakili literal, dan ketika string menyajikan nama kolom, ...Jawaban:
Saya pikir itu sangat salah. Saya belajar bahasa alami dan penuh dengan ambiguitas yang hanya bisa diselesaikan dengan konteks dan banyak pengetahuan manusia. Fakta bahwa bahasa pemrograman tidak ambigu adalah hal yang sangat bagus! Saya tidak berpikir Anda ingin makna metode berubah sesuai konteks:
find("user").where("name").and("email").equals("foo");
find("user").where("name").not().is().null();
?Tidak, Anda tidak dapat membahas kalimat bahasa Inggris yang paling tepat. Yang lain telah mencoba sebelumnya, dan itu menjadi sangat rumit dengan sangat cepat. Ini disebut Pemahaman bahasa alami tetapi tidak ada yang benar-benar mencobanya: kami mencoba memecahkan masalah yang lebih kecil terlebih dahulu. Untuk perpustakaan Anda, Anda pada dasarnya memiliki dua opsi:
sumber
is()
atauequal()
hanyaequals()
. Jangan melihat masalah Anda dengan pelaporan kesalahan setelah ini.null()
juga akan menjadi literal untuk dibandingkan, bukan fungsi sintaks.find("user").where("name").is().not().null();
menjadifind("user").where("name").not().equals(null);
Saya cenderung setuju dengan posting orang lain bahwa ini bukan desain yang bagus. Namun, saya yakin saya punya alasan berbeda.
Anda menyajikan apa yang saya lihat sebagai sintaks konkret untuk kueri SQL. Saya sangat percaya sintaksis yang konkret tidak pernah bisa membantu bahasa, hanya menyakitkan jika itu buruk.
Namun, sintaksis abstrak adalah cerita yang berbeda. Sintaksis abstrak mendefinisikan struktur bahasa Anda dan bagaimana frasa dapat digabungkan untuk membangun frasa yang lebih besar. Saya merasa bahwa keberhasilan suatu bahasa sangat tergantung pada kualitas definisi sintaksis abstraknya.
Masalah saya dengan API yang lancar bukan karena ambigu, atau tidak jelas, atau tidak ekspresif - itu karena ia menyembunyikan bahasa asli dan strukturnya, dan dengan demikian, akhirnya membuat hal-hal jauh lebih rumit daripada yang seharusnya ( dengan memperkenalkan ambiguitas, kesalahan sintaksis yang tidak jelas, dll.).
Karena Anda menyebutkan bahwa Anda juga akan memberikan "API yang lebih konvensional", sepertinya Anda sudah mengetahui semua ini. Untuk itu saya katakan "Bagus!" Tetapi itu tidak berarti bahwa Anda tidak dapat juga mengembangkan API lancar Anda secara paralel! Definisi sintaksis tunggal abstrak dapat mendukung banyak sintaksis konkret. Meskipun Anda harus ingat bahwa sintaksis abstrak adalah yang sebenarnya, sintaksis konkret juga bisa sangat membantu.
sumber
Selain poin-poin Quentin Pradet yang sangat bagus, saya ragu dengan manfaat bahasa ini.
Agaknya titik tata bahasa yang dekat dengan bahasa alami adalah untuk membuatnya dapat diakses. Tapi SQL sudah cukup dekat dengan bahasa alami. Apakah salah satunya benar-benar lebih dekat ke bahasa Inggris daripada yang lain?
Saya tidak benar-benar melihat manfaat dari tata bahasa Anda, dari sudut pandang intuitif atau keterbacaan. Bahkan, versi SQL terlihat lebih mudah dibaca (dan lebih mudah untuk mengetik) karena spasinya.
sumber
Ada beberapa yang
burukkurang dari keputusan desain yang ideal yang tampaknya telah dibuat dalam mempertimbangkan API ini.Yang pertama adalah masalah utilitas - apa tujuannya? Ini tampaknya membuat struktur data yang akan dikompilasi menjadi dialek SQL. Kebetulan, tata bahasa tampaknya menjadi kumpulan SQL yang terbatas. Pertanyaan tentang "apa manfaatnya hanya menggunakan SQL?" menjadi kunci. Jika lebih sulit untuk menulis menggunakan antarmuka yang lancar daripada hanya menulis string dengan interpolasi yang sesuai di dalamnya maka orang tidak akan menulis menggunakan API ini.
Bahasa Inggris ambigu. Mencoba memodelkan antarmuka yang fasih berbahasa Inggris adalah pilihan yang buruk (Anda lebih baik menggunakan bahasa Latin ). Ketika ada beberapa parsing yang mungkin valid dari rangkaian panggilan yang sama, ini menyebabkan kebingungan dan kejutan . Tidak satu pun dari hal-hal ini baik untuk dimiliki dalam API.
Ada lebih banyak bagian untuk SQL daripada yang diungkapkan oleh API ini. Gabungan (dalam salah satu dari banyak bentuk mereka) terutama tidak ada dalam contoh yang ditetapkan. Subqueries (
foo in (select id from bar)
), unions, dan group by adalah beberapa hal yang sering digunakan. Pengelompokan logika yang rumit tampaknya tidak hadir dengan cara intuitif apa pun.Jika seseorang menulis menggunakan API ini dan kemudian menemukan bahwa API tidak mampu mengekspresikan permintaan yang diinginkan, waktu yang signifikan akan hilang. Ini adalah pilihan yang buruk untuk menggunakan gaya campuran untuk melakukan permintaan dalam aplikasi (pertanyaan sederhana dalam api ini, kompleks dalam sql mentah) - dan akhirnya yang lebih ekspresif akan digunakan.
Sementara pemrograman tersebar luas, kelancaran berbahasa Inggris tidak. Bahkan dengan keterbatasan bahasa untuk "SQL like" ada nuansa bagaimana penutur asli akan membaca sesuatu dan seseorang yang memiliki bahasa Inggris sebagai bahasa kedua atau ketiga.
Tidak ada redundansi yang tidak perlu di API demi bahasa Inggris. Khususnya
equal()
vsequals()
melakukan hal yang sama. Meskipun saya tidak yakin akan hal itu, saya percaya ituis()
adalah no-op yang ditambahkan demi bahasa Inggris yang lebih cocok. Saya menyambut siapa pun untuk mendengarkan ocehan saya tentang redundansi metode ruby dalam obrolan - jangan membuat kesalahan yang sama.Duduk dan tulis satu set contoh pertanyaan yang komprehensif yang ingin Anda dapat gunakan. Tentukan siapa yang akan Anda tangani semua contoh itu dengan cara yang tidak ambigu yang kurang rumit daripada kueri itu sendiri. Jika Anda tidak bisa, pertimbangkan apakah bermanfaat untuk menempuh jalur penulisan API. SQL adalah tempatnya sekarang (tidak sempurna, tapi saya belum menemukan yang lebih baik) selama beberapa dekade perbaikan.
RFC 1925 - Dua Belas Jejaring Kebenaran
sumber