Akıcı API'da doğal dil gramerini kullanma


14

WebSQL / Phonegap Veritabanı API üzerinde bir sorgu soyutlama ile uğraşıyorum ve kendimi hem doğal hem de dilbilgisi kullanımını taklit eden akıcı bir API tanımlamak için çizilmiş ve şüpheli buluyorum.

Bunu örneklerle açıklamak en kolay yol olabilir. Aşağıdakiler dilbilgimdeki geçerli tüm sorgulardır ve yorumlar amaçlanan semantiği açıklar:

//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);

Quentin Pradet'in geri bildirimlerine dayanarak düzenleme : Ek olarak, API'nin hem çoğul hem de tekil fiil formlarını desteklemesi gerekecek gibi görünüyor:

//a equals b
find("post").where("foo").equals(1);

//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);

Soru uğruna, burada olası tüm yapıları tüketmediğimi varsayalım. Ayrıca, en doğru İngilizce cümleleri de kapsayabileceğimi varsayalım - sonuçta, dilbilgisinin kendisi SQL tarafından tanımlanan fiiller ve konjonktürlerle sınırlıdır.


Gruplamaya ilişkin düzenleme : Bir "cümle" bir gruptur ve öncelik SQL'de tanımlandığı gibidir: soldan sağa. Birden çok gruplama, birden çok whereifadeyle ifade edilebilir :

//the conjunctive "and()" between where statements is optional
find("post")
  .where("foo").and("bar").equal(2).and()
  .where("baz").isLessThan(5);

Görüldüğü gibi, her bir yöntemin tanımı bağımsız değişken "birlikte yöntemleri" örneğin., İçinde bulunduğu gramer bağlamda bağlıdır or()ve and()her iki dışında kalan, olabilir veya bir alan adı bakınız veya beklenen değer.

Bana göre bu çok sezgisel hissettiriyor, ancak geri bildiriminizi duymanızı istiyorum: Bu iyi, kullanışlı bir API mı, yoksa daha doğrudan uygulamaya geri dönmeli miyim?

Kayıt için: Bu kütüphane ayrıca yapılandırma nesnelerine dayalı daha geleneksel, akıcı olmayan bir API sağlayacaktır.


1
Zincirleme de jQuery'nin çok ünlü olmasının nedenidir. Oldukça basit, sıralı ve anlaşılır.
Joseph

3
Bu ilginç! Muhtemelen bunu programcılara sormalısınız.
Benjamin Gruenbaum

2
Gruplamayı nasıl ele alırsınız? Eşdeğer: ... where foo = 1 or (bar = 2 and qux = 3)?

7
IMO bu tür akıcı API korkunç. Örneğin, operatör önceliğinin olmaması can sıkıcıdır. where("name").equals("foo").or("bar")Olarak ayrıştırırdım (name=="foo")or bar. Bir dize değişmezi temsil ettiğinde ve bir sütun adı gösterdiğinde, o zaman net değildir ...
CodesInChaos 15 Mart'ta

4
Btw. bir veritabanını sorgulamak için bir DSL kullanmak istiyorsanız, SQL adlı mevcut DSL'yi kullanabilirsiniz.
CodesInChaos

Yanıtlar:


23

Bence bu çok yanlış. Doğal dili inceliyorum ve sadece bağlam ve çok sayıda insan bilgisi ile çözülebilecek belirsizlik dolu. Programlama dillerinin belirsiz olmaması çok iyi bir şey! Yöntemlerin anlamının bağlama göre değişmesini istediğinizi düşünmüyorum:

  • Bu, belirsizlik getirdiğiniz için daha fazla sürpriz ekler
  • Kullanıcılarınız, örneğin kapsamına girmeyeceğiniz yapıları kullanmak isteyecektir. find("user").where("name").and("email").equals("foo");
  • Hataları rapor etmek zor: ne yapabilirsiniz find("user").where("name").not().is().null();?

Ayrıca, en doğru İngilizce cümleleri de kapsayabileceğimi varsayalım - sonuçta, dilbilgisinin kendisi SQL tarafından tanımlanan fiiller ve konjonktürlerle sınırlıdır.

Hayır, en doğru İngilizce cümleleri kapsayamazsınız. Diğerleri daha önce denedi ve çok hızlı bir şekilde karmaşıklaşıyor. Buna Doğal dil anlama denir, ancak kimse bunu gerçekten denemez: önce daha küçük sorunları çözmeye çalışıyoruz. Kütüphaneniz için temel olarak iki seçeneğiniz vardır:

  • ya kendinizi İngilizce'nin bir alt kümesiyle sınırlandırırsınız: bu size SQL verir,
  • ya da "İngilizce" yi kapsamaya çalışırsınız ve dilin belirsizliği, karmaşıklığı ve çeşitliliği nedeniyle bunun mümkün olmadığını öğrenirsiniz.

Giriş için teşekkürler. Sorumu, listelediğiniz ilk davayı kapsayacak şekilde düzenledi ve bazı uyarılar ekledi. Belirsizlik konusundaki tavrınıza katılıyorum - bu sorumun temelini oluşturuyor. Programlama dilleri için iyi tanımlanmış bağlamlarda kararsız olmak kabul edilebilir mi?
fencliff

belirsiz ise iyi tanımlanmamıştır. Belirsizse, birden fazla potansiyel sonuç vardır ve bir şey bunlardan birini seçmek zorundadır. Seçim iyi tanımlanmış veya dil ayrıştırıcı rasgele seçilecektir. Bu nedenle, stokastik bir dil istiyorsanız (1 + 1 2'ye eşit olabilir ve bazen 1 veya 3'e eşit olabilir) bir programlama dilindeki belirsizlik iyidir (1 + 1 her zaman 2'ye eşittir).
Michael Paulukonis

Onun teklifinden mi yoksa İngilizce'den mi bahsediyorsun? Çoğu zaman, belirsizlik, bir bilgisayar için mevcut olmayan bir şey olan bağlam ve / veya bilgi (bir kısmı sağduyu) kullanılarak çözülebilir.
Quentin Pradet

+1 Akıcı bir API'yı uygulamadaki bağlam duyarlılığını iyi yakalar. Akıcı API fikrini ilk bakışta beğendim, ancak bunu görmek için çok yakından bakmadım. Kesinlikle büyük bir sorun.
Jimmy Hoffa

dilbilgisini açık ve bağlamsız yaparsa sorun nedir? elbette çoğul ayetlerin tekil fiil biçimlerini ve bunun gibi şeyleri kaldırmak isteyebilirler, ancak yapmaya çalıştıkları şeyin çekirdeğini değiştirmezler. Sahip olmazdın is()ya da equal()sadece equals(). Bundan sonra raporlama hatalarıyla ilgili sorununuzu görmeyin. null()aynı zamanda bir sözdizimi işlevinden ziyade, karşılaştırılacak bir gerçek haline gelir. find("user").where("name").is().not().null();olurfind("user").where("name").not().equals(null);
whn

3

Bunun harika bir tasarım olmadığını başkalarının yayınlarına biraz katılıyorum. Ancak, farklı nedenlerim olduğuna inanıyorum.

SQL sorguları için somut bir sözdizimi olarak gördüğümü sunuyorsunuz. Somut sözdiziminin bir dile asla yardımcı olamayacağına inanıyorum , sadece kötü ise acıyor.

Ancak, soyut sözdizimi farklı bir hikaye. Özet sözdizimi, dilinizin yapısını ve daha büyük ifadeler oluşturmak için ifadelerin nasıl birleştirilebileceğini tanımlar. Bir dilin başarısının büyük ölçüde soyut sözdizimi tanımının kalitesine bağlı olduğunu hissediyorum.

Akıcı API ile ilgili sorunum, belirsiz veya belirsiz veya ifade edici olmaması değil - gerçek dili ve yapısını gizliyor ve bu şekilde işleri olması gerekenden çok daha karmaşık hale getiriyor ( belirsizlikler, açık olmayan sözdizimi hataları vb. tanıtarak).

Ayrıca "daha geleneksel bir API" sağlayacağınızdan bahsettiğinizden, zaten tüm bunları bildiğiniz gibi görünüyor. Buna "Güzel!" Diyorum. Ancak bu, akıcı API'nizi paralel olarak geliştiremeyeceğiniz anlamına gelmez! Tek bir soyut sözdizimi tanımı birden çok somut sözdizimini destekleyebilir. Soyut sözdiziminin gerçek anlaşma olduğunu unutmamalısınız, ancak somut bir sözdizimi de çok yardımcı olabilir.


2

Quentin Pradet'in çok iyi noktalarına ek olarak, bu dilin iddia edilen faydalarından şüpheliyim.

Muhtemelen doğal dile yakın bir dilbilgisinin amacı onu erişilebilir kılmaktır. Ancak SQL zaten doğal dile oldukça yakın. Bunlardan biri İngilizceye gerçekten diğerinden daha yakın mı?

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

select user from table where name = 'foo'

Ben sezgisellik veya okunabilirlik açısından dilbilginizin faydasını gerçekten görmüyorum. Aslında, SQL sürümü boşluk nedeniyle daha okunabilir görünüyor (ve yazılması daha kolay).


2

Bu API dikkate alındığında alınan ideal tasarım kararlarından çok daha az kötü vardır .

Birincisi fayda sorunu - hangi amaca hizmet ediyor? Bu, bir SQL lehçesine derlenecek bir veri yapısı oluşturuyor gibi görünmektedir. Bu arada, gramer sınırlı bir SQL kümesi gibi görünmektedir. "Bu sadece SQL kullanımında ne gibi bir avantaj sağlıyor?" anahtar olur. Eğer akıcı arayüzü kullanarak yazmak sadece içinde uygun enterpolasyona sahip bir dize yazmaktan daha zahmetli ise, bu API kullanılarak yazılmaz.

İngilizce belirsizdir. İngilizce akıcı bir arayüz modelleme girişimi kötü bir seçimdir ( Latince kullanmak daha iyidir ). Aynı çağrı zincirinin birden fazla geçerli ayrışması olduğunda, bu karışıklığa ve sürprizlere yol açar . Bunların hiçbiri bir API'de olması iyi şeyler değildir.

SQL'de bu API'nın gösterdiklerinden daha fazla bölüm var. Birleştirmeler (sayısız formunun herhangi birinde), örnek kümede özellikle yoktur. Alt sorgular ( foo in (select id from bar)), birlikler ve gruplama, sık kullanılan şeylerden bazılarıdır. Karmaşık mantık gruplamaları sezgisel bir şekilde mevcut görünmemektedir.

Biri bu API'yı kullanarak yazıyor ve ardından API'nın istenen sorguyu ifade edemediğini tespit ederse, önemli zaman kaybedilecektir. Bir uygulamada sorgular yapmak için karışık stiller kullanmak kötü bir seçimdir (bu API'de basit sorgular, ham sql'de karmaşık) - ve sonuçta daha etkileyici olanı kullanılacaktır.

Programlama yaygın olsa da, İngilizce akıcı değildir. Dilin "SQL benzeri" ile sınırlandırılmasına rağmen, anadili İngilizce olan bir kişinin bir şeyi nasıl okuyacağı ve ikinci veya üçüncü dil olarak İngilizce olan birinin nüansları vardır.

İngilizce uğruna API'da gereksiz fazlalık vardır. Özellikle aynı şeyi yapmak equal()vs. equals()Bundan emin is()olmasam da, bunun İngilizceye daha yakın olması için eklenen bir op olduğuna inanıyorum . Sohbette yakut yöntemlerin fazlalığı hakkındaki sıralamamı dinlemek için hoş geldiniz - aynı hatayı yapmayın.

Oturup kullanmak istediğiniz sorguların kapsamlı bir örnek setini yazın. Tüm bu örnekleri, sorguların kendilerinden daha az külfetli olan belirsiz olmayan bir şekilde ele alacağınızı belirleyin. Yapamıyorsanız, API yazma yolunda ilerlemeye değip değmeyeceğini düşünün. SQL, bugünlerde olduğu yerdir (mükemmel değildir, ancak daha iyi bir şey bulamadım), onlarca yıldır yapılan incelik.

RFC 1925 - On İki Ağ Gerçekleri

(12) Protokol tasarımında, eklenecek hiçbir şey kalmadığında değil, alınacak hiçbir şey kalmadığında mükemmellik elde edildi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.