Menggunakan tata bahasa alami dalam API yang lancar


14

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 wherepernyataan:

//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.


1
Chaining juga mengapa jQuery sangat terkenal. Cukup mudah, berurutan, dan dapat dimengerti.
Joseph

3
Ini menarik! Anda mungkin harus menanyakan ini pada programmer.
Benjamin Gruenbaum

2
Bagaimana Anda menangani pengelompokan? Setara dengan: ... where foo = 1 or (bar = 2 and qux = 3)?

7
IMO jenis API lancar ini mengerikan. Misalnya kurangnya prioritas operator mengganggu. Saya akan menguraikan where("name").equals("foo").or("bar")sebagai (name=="foo")or bar. Maka tidak jelas kapan string mewakili literal, dan ketika string menyajikan nama kolom, ...
CodesInChaos

4
btw. jika Anda ingin menggunakan DSL untuk menanyakan database, Anda bisa menggunakan DSL yang sudah ada yang disebut SQL.
CodesInChaos

Jawaban:


23

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:

  • Ini menambah lebih banyak kejutan karena Anda membawa ambiguitas
  • Pengguna Anda ingin menggunakan konstruksi yang tidak akan Anda bahas, mis. find("user").where("name").and("email").equals("foo");
  • Sulit melaporkan kesalahan: apa yang dapat Anda lakukan find("user").where("name").not().is().null();?

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.

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:

  • baik Anda membatasi diri Anda ke subset dari bahasa Inggris: yang memberi Anda SQL,
  • atau Anda mencoba untuk menutupi "Bahasa Inggris" dan Anda menemukan bahwa itu tidak mungkin karena ambiguitas, kompleksitas dan keragaman bahasa.

Terima kasih atas masukan Anda. Mengedit pertanyaan saya untuk membahas kasus pertama yang Anda daftarkan dan menambahkan beberapa peringatan. Saya setuju dengan posisi Anda tentang ambiguitas - itulah inti dari pertanyaan saya. Apakah dapat diterima bahwa bahasa pemrograman bersifat ambient dalam konteks yang terdefinisi dengan baik?
fencliff

jika ambigu, itu tidak didefinisikan dengan baik. Jika ambigu, ada lebih dari satu hasil potensial, dan sesuatu harus memilih salah satunya. Pilihannya akan didefinisikan dengan baik, atau parser bahasa akan memilih secara acak. Jadi, ambiguitas dalam bahasa pemrograman tidak apa-apa jika Anda menginginkan bahasa stokastik (1 +1 mungkin sama dengan 2, dan kadang-kadang mungkin sama dengan 1 atau 3) sebagai kebalikan dari deterministik (1 +1 selalu sama dengan 2).
Michael Paulukonis

Apakah Anda berbicara tentang proposal atau bahasa Inggrisnya? Sebagian besar waktu, ambiguitas dapat diatasi dengan menggunakan konteks dan / atau pengetahuan (bagian dari hal tersebut adalah akal sehat), sesuatu yang tidak tersedia untuk komputer.
Quentin Pradet

+1 Tangkapan yang baik pada sensitivitas konteks penerapan khusus dari API yang lancar. Saya menyukai gagasan tentang APInya yang fasih pada pandangan pertama tetapi tidak melihat terlalu dekat untuk melihat ini. Masalah yang sangat besar.
Jimmy Hoffa

jika ia membuat tata bahasa tidak ambigu dan bebas konteks lalu apa masalahnya? tentu saja mereka ingin menghapus bentuk jamak dari bentuk jamak tunggal kata kerja dan hal-hal seperti itu, tetapi itu tidak mengubah inti dari apa yang mereka coba lakukan. Anda tidak akan memiliki is()atau equal()hanya equals(). 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);
whn

3

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.


2

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?

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

select user from table where name = 'foo'

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.


2

Ada beberapa yang buruk kurang 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()vs equals()melakukan hal yang sama. Meskipun saya tidak yakin akan hal itu, saya percaya itu is()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

(12) Dalam desain protokol, kesempurnaan telah dicapai bukan ketika tidak ada yang tersisa untuk ditambahkan, tetapi ketika tidak ada yang tersisa untuk diambil.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.