jQuery is DSL (Part 1 - DSL)
2009-08-10 23:47 Cat Chen 閱讀(6928) 評論(30) 收藏 舉報(bào)jQuery剛剛出來的時(shí)候,我沒有太多關(guān)注它,覺得這不過是Yet Another JavaScript Library。早期的jQuery專注于DOM節(jié)點(diǎn)的篩選與操作,不提供眾多的基礎(chǔ)類擴(kuò)展,更不提供UI組件,因此體積能夠做到很小。然而,我實(shí)在看不出它和我熟悉的Prototype比有什么明顯的優(yōu)勢——jQuery能做的各項(xiàng)獨(dú)立的操作,Prototype都能做。
后來用jQuery的人越來越多,并且大家都愛用它的鏈?zhǔn)椒椒ㄕ{(diào)用,甚至還把這種寫法推廣到其它語言中去。例如ASP.NET MVP Omar AL Zabir就把他的服務(wù)器端C#組件設(shè)計(jì)為支持鏈?zhǔn)椒椒ㄕ{(diào)用的。這時(shí)候我才開始關(guān)注jQuery,并且逐漸喜歡上了鏈?zhǔn)椒椒ㄕ{(diào)用的寫法,也在我自己的JavaScript組件中實(shí)現(xiàn)類似的API(參考Async和Overload)。最后,我突然明白到,這其實(shí)就是一種Internal DSL嘛!
在這篇文章里,我準(zhǔn)備先討論Internal DSL,在下一篇文章里面再解釋為什么jQuery是Internal DSL。現(xiàn)在我們就從最根本的問題開始吧——
什么是Internal DSL?
DSL是指Domain Specific Language,也就是用于描述和解決特定領(lǐng)域問題的語言。例如說,我們有專門描述字符串特征的正則表達(dá)式,有專門描述數(shù)據(jù)庫查詢的SQL,有專門描述XML結(jié)構(gòu)的DTD和XSD,甚至有專門描述XML變換的XSLT,這些都是DSL。
當(dāng)然,并非我們關(guān)注的領(lǐng)域都有現(xiàn)成的DSL,這時(shí)候我們有三個(gè)選擇:
- 使用通用語言描述該領(lǐng)域的問題(non-DSL)
- 發(fā)明一門全新的語言描述該領(lǐng)域的問題(External DSL)
- 在一門現(xiàn)成語言內(nèi)實(shí)現(xiàn)針對領(lǐng)域問題的描述(Internal DSL)
I.DepositTo(new USD(200), CitiBank); /* C# */I deposit 200USD to CitiBank /* E-DSL */I.deposit(200.USD()).to(CitiBank); /* I-DSL */
deposit [something] to [somewhere]?)。
第2種做法的成本最高,你需要寫一個(gè)全新的解釋器,至少是寫一組全新的規(guī)則,然后讓YACC這類工具幫你生成一個(gè)解釋器,但這樣出來的語法最貼近人類思維方式,甚至就如同自然語言一樣流暢。
第3種做法術(shù)語上述兩者的折中方案,如果語法不太復(fù)雜可以使用Builder模式實(shí)現(xiàn)語法分析,寫出來的語法相當(dāng)貼近自然語言,但還是有學(xué)習(xí)門檻。由于腳本語言有相當(dāng)?shù)撵`活性,所以現(xiàn)在很多人傾向于選擇在腳本語言內(nèi)實(shí)現(xiàn)Internal DSL。
如何構(gòu)造Internal DSL?
常見的兩種Internal DSL實(shí)現(xiàn)方法是Method Chaining和Function Sequence。如果我們需要描述一臺(tái)機(jī)器的硬件組成,兩種實(shí)現(xiàn)方式的代碼分別如下:
/* Method Chaining */
computer()
.processor()
.cores(2)
.i386()
.disk()
.size(150)
.disk()
.size(75)
.speed(7200)
.sata()
.end();
/* Function Sequence */
computer();
processor();
cores(2);
processorType(i386);
disk();
diskSize(150);
disk();
diskSize(75);
diskSpeed(7200);
diskInterface(SATA);
無論是哪一種寫法,中間都必須寫一個(gè)分析器層。就如同語法分析器需要使用狀態(tài)機(jī)一樣,Internal DSL的實(shí)現(xiàn)也必須內(nèi)置一個(gè)狀態(tài)機(jī),以記錄當(dāng)前執(zhí)行到什么狀態(tài)了,并且接下來可以轉(zhuǎn)移到哪些有效狀態(tài)。
由于這不是一篇專門講語法分析器和狀態(tài)機(jī)實(shí)現(xiàn)的文章,所以我們把關(guān)注點(diǎn)保持在API層面就可以了,不深入討論其實(shí)現(xiàn)細(xì)節(jié)和成本。我們知道鏈?zhǔn)椒椒ㄕ{(diào)用能夠?qū)崿F(xiàn)Internal DSL就夠了,至于jQuery是如何利用好這一點(diǎn)的,我們在下一篇文章里再作討論。
小結(jié)
在這篇文章里,我們了解了Internal DSL與External DSL之間的區(qū)別,同時(shí)還了解到實(shí)現(xiàn)Internal DSL的具體方式,這為我們接下來討論jQuery的Internal DSL式接口做好了鋪墊。在下一篇文章里,我們將深入地來看看為什么jQuery的接口要如此設(shè)計(jì),它能為用戶帶來了怎樣的便利,同時(shí)它自身的實(shí)現(xiàn)上又有什么優(yōu)勢。
如果你不希望錯(cuò)過下一篇文章,你可以考慮訂閱我的博客:
浙公網(wǎng)安備 33010602011771號