詳解半靜態(tài)語(yǔ)言原理及價(jià)值
51CTO編者按:我們?cè)?jīng)在《基于JVM的語(yǔ)言正在開(kāi)始流行》一文中介紹過(guò)全新的基于JVM的腳本語(yǔ)言是Groovy和Scala。這兩門(mén)語(yǔ)言現(xiàn)在都越來(lái)越流行,不同的是,Groovy是動(dòng)態(tài)腳本語(yǔ)言,而是Scala是靜態(tài)語(yǔ)言,那什么是半靜態(tài)語(yǔ)言呢?本文將由阿里巴巴技術(shù)部中文站架構(gòu)師何坤(Raymond He)系統(tǒng)地向大家介紹這篇《詳解半靜態(tài)語(yǔ)言原理及價(jià)值》。
引言
動(dòng)態(tài)類(lèi)型語(yǔ)言在企業(yè)開(kāi)發(fā)和互聯(lián)網(wǎng)領(lǐng)域應(yīng)用廣泛,如Ruby ,Velocity, Python等。 動(dòng)態(tài)類(lèi)型語(yǔ)言在運(yùn)行時(shí)進(jìn)行類(lèi)型推斷,以解釋方式執(zhí)行,修改即生效,開(kāi)發(fā)靈活性高;而靜態(tài)類(lèi)型語(yǔ)言(如:Java,C/C+/C++) 在執(zhí)行前做類(lèi)型檢查,需要編譯運(yùn)行,對(duì)于互聯(lián)網(wǎng)前端開(kāi)發(fā)不夠靈活。
因此,許多大型互聯(lián)網(wǎng)站選擇 Freemarker, Velocity這樣的動(dòng)態(tài)模板語(yǔ)言作為頁(yè)面開(kāi)發(fā)語(yǔ)言,在一定程度上滿足了前端敏捷開(kāi)發(fā)的需求。
然而,對(duì)于大型電子商務(wù)網(wǎng)站,不僅具有一般互聯(lián)網(wǎng)需求頻繁變更的特點(diǎn),更顯著特點(diǎn)則是業(yè)務(wù)繁多,業(yè)務(wù)模型和業(yè)務(wù)關(guān)系復(fù)雜。 因此,在此類(lèi)應(yīng)用開(kāi)發(fā)中,Velocity 的開(kāi)發(fā)也遇到了一些的問(wèn)題。
前端模板開(kāi)發(fā)問(wèn)題
1、降低軟件質(zhì)量
Velocity是弱類(lèi)型動(dòng)態(tài)語(yǔ)言,運(yùn)行時(shí)才能檢查出類(lèi)型錯(cuò)誤。由于動(dòng)態(tài)類(lèi)型等特點(diǎn),有的錯(cuò)誤在遇到特定參數(shù)時(shí),才能激發(fā)執(zhí)行路徑,軟件質(zhì)量不能很好的保證。
2、測(cè)試成本高
由于無(wú)法像靜態(tài)語(yǔ)言一樣,在運(yùn)行前進(jìn)行類(lèi)型檢查,因此軟件的測(cè)試周期長(zhǎng),測(cè)試成本高。
3、開(kāi)發(fā)不敏捷
缺乏一些敏捷開(kāi)發(fā)功能如IDE內(nèi)實(shí)時(shí)驗(yàn)證、代碼提示、代碼重構(gòu)等。雖然能修改即生效,但對(duì)于企業(yè)級(jí)開(kāi)發(fā),效率較低。
4、維護(hù)性差
對(duì)于一個(gè)大型系統(tǒng),在重構(gòu)業(yè)務(wù)模型(Java Model)或代碼時(shí), 無(wú)法知道哪些Velocity模板會(huì)受到影響;常常需要花費(fèi)大量時(shí)間搜索相關(guān)模板,然后修改、測(cè)試。例如:筆者所在公司的一個(gè)基礎(chǔ)產(chǎn)品升級(jí),由于受影響模板眾多,重構(gòu)復(fù)雜,項(xiàng)目評(píng)估達(dá)上千人日。
這些動(dòng)態(tài)語(yǔ)言天生的缺點(diǎn)在企業(yè)級(jí)和大型網(wǎng)站應(yīng)用中非常突出,嚴(yán)重的影響了開(kāi)發(fā)質(zhì)量和開(kāi)發(fā)效率。因此,在技術(shù)上亟待一種新的高質(zhì)量、高效率的開(kāi)發(fā)技術(shù)。
靜態(tài)語(yǔ)言的優(yōu)勢(shì)
綜合考慮后,我們發(fā)現(xiàn)動(dòng)態(tài)類(lèi)型語(yǔ)言(Dynamic Language)“解釋執(zhí)行方式和修改即生效”的最大優(yōu)點(diǎn)仍是不能舍棄的。必須從問(wèn)題出發(fā),找到一條平滑的線路來(lái)解決問(wèn)題。
遇到上述問(wèn)題時(shí),我們不由自主的會(huì)贊美Java的優(yōu)點(diǎn):
1、靜態(tài)語(yǔ)法和靜態(tài)類(lèi)型實(shí)時(shí)檢查。
如果賦值類(lèi)型不匹配,方法不存在,參數(shù)類(lèi)型錯(cuò)誤等信息能馬上在IDE中顯示;
2、代碼提示:
調(diào)用屬性,方法時(shí)能代碼提示,開(kāi)發(fā)非常高效;
3、代碼熱鏈接:
通過(guò)變量和類(lèi)名熱鏈接到對(duì)應(yīng)的Java類(lèi);
4、代碼重構(gòu):
修改一個(gè)Java類(lèi)時(shí),受影響的Java代碼會(huì)被實(shí)時(shí)重新驗(yàn)證,馬上會(huì)顯示紅色的錯(cuò)誤; 更強(qiáng)大的是重構(gòu),對(duì)Java類(lèi),方法敏性重命名,會(huì)自動(dòng)修改所有相關(guān)代碼中對(duì)它的引用。
Java等靜態(tài)類(lèi)型語(yǔ)言的這些優(yōu)勢(shì)就是解決問(wèn)題的方向。那為什么動(dòng)態(tài)語(yǔ)言不能做到這些呢? 原因在于動(dòng)態(tài)語(yǔ)言的根本特點(diǎn)是變量無(wú)類(lèi)型(即弱類(lèi)型特點(diǎn)),類(lèi)型在運(yùn)行時(shí)推斷,這使得它無(wú)法在開(kāi)發(fā)階段進(jìn)行類(lèi)型檢查。
那如何將動(dòng)態(tài)語(yǔ)言和靜態(tài)語(yǔ)言的優(yōu)點(diǎn)結(jié)合呢?答案就是半靜態(tài)語(yǔ)言。
Phone Club——51CTO移動(dòng)開(kāi)發(fā)線下技術(shù)沙龍
本期主題:Android應(yīng)用開(kāi)發(fā)技術(shù)進(jìn)階
地點(diǎn):創(chuàng)新工場(chǎng) 北京市海淀區(qū)北四環(huán)西路66號(hào)第三極大廈B座18層
演講講師:王明禮(創(chuàng)新工場(chǎng)) 范懷宇(網(wǎng)易)
#p#
半靜態(tài)語(yǔ)言(Semi-Static Language)
1 定義
半靜態(tài)語(yǔ)言,嚴(yán)格說(shuō)應(yīng)該是靜態(tài)化類(lèi)型的動(dòng)態(tài)語(yǔ)言(Statically Typed Dynamic Language)。它是這樣一種語(yǔ)言:以靜態(tài)方式開(kāi)發(fā),以解釋方式執(zhí)行;通過(guò)變量顯式聲明或隱式聲明,運(yùn)行前可對(duì)變量類(lèi)型進(jìn)行推斷和驗(yàn)證。
靜態(tài)語(yǔ)言,動(dòng)態(tài)語(yǔ)言和半靜態(tài)語(yǔ)言的特點(diǎn)對(duì)比分析如下:
語(yǔ)言類(lèi)型 優(yōu)點(diǎn) 缺點(diǎn) 舉例 適用場(chǎng)景 Static Language 強(qiáng)類(lèi)型,運(yùn)行前類(lèi)型檢查,程序健壯 對(duì)Java等支持反射的語(yǔ)言,可實(shí)現(xiàn)代碼提示,重構(gòu)等敏捷開(kāi)發(fā)特性 需編譯運(yùn)行,發(fā)布慢 無(wú)法快速響應(yīng)需求變化 Java C/C++ 企業(yè)級(jí)后端開(kāi)發(fā) 大型互聯(lián)網(wǎng)后端開(kāi)發(fā) Dynamic Language 靈活性高,修改即生效 快速響應(yīng)需求變化 弱類(lèi)型,運(yùn)行時(shí)類(lèi)型檢查,程序不健壯,測(cè)試成本高 PHP Ruby Velocity 業(yè)務(wù)簡(jiǎn)單的小型互聯(lián)網(wǎng)前端開(kāi)發(fā) Semi-Static Laguange 開(kāi)發(fā)時(shí)(Devtime)強(qiáng)類(lèi)型,程序健壯 運(yùn)行時(shí)(Runtime)弱類(lèi)型,修改即生效,快速響應(yīng)需求變化 業(yè)務(wù)復(fù)雜的企業(yè)級(jí)開(kāi)發(fā)和大型互聯(lián)網(wǎng)前端開(kāi)發(fā)
半靜態(tài)語(yǔ)言集合了靜態(tài)語(yǔ)言和動(dòng)態(tài)語(yǔ)言的優(yōu)點(diǎn),更適合企業(yè)級(jí)和大型互聯(lián)網(wǎng)開(kāi)發(fā),例如:電子商務(wù),ERP,金融,保險(xiǎn)等。
2 技術(shù)原理
2.1 范例
為了實(shí)現(xiàn)目標(biāo),需要在動(dòng)態(tài)類(lèi)型語(yǔ)言基礎(chǔ)上,引入變量聲明技術(shù)。因此本質(zhì)上,半靜態(tài)語(yǔ)言也是一種聲明式語(yǔ)言(Declarative Language), 這一點(diǎn)與靜態(tài)類(lèi)型語(yǔ)言一樣。
以Velocity模板語(yǔ)言為例:
當(dāng)前Velocity Template編程代碼范例如下:
- [Code 1] showBuyProducts.vm
- <HTML>>
- Hello $customer.Name
- <table>>
- #foreach( $product in $buyingProducts )
- Buy: $product.Name, Price: $product.Price,
- #end
- table>>
該模板執(zhí)行后,HTML頁(yè)面上將用 $customer.Name 顯示“客戶名稱”,循環(huán)顯示該客戶購(gòu)買(mǎi)的每個(gè)產(chǎn)品的名稱和價(jià)格。在Velocity中,運(yùn)行時(shí)通過(guò)Velocity Context傳遞變量$customer和 $buyingProducts,而開(kāi)發(fā)時(shí)這兩個(gè)變量是未定型的(Untyped,或者說(shuō)都是Object類(lèi)型)。
為了實(shí)現(xiàn)靜態(tài)化開(kāi)發(fā),引入變量聲明,在模板頂部對(duì)變量$customer,$buyingProducts進(jìn)行顯式類(lèi)型聲明。變量聲明指令為“##$”。
格式為:
- ##$ <Type> <var1[,var2[,[…]]]>
帶有變量聲明的半靜態(tài)模板代碼為:
- [Code 2] showBuyProducts_static.vm
- ##$ com.abc.crm.Customer customer
- ##$ com.abc.saling.Product product
- ##$ List<Product> buyingProducts
- <HTML>
- Hello $customer.Name
- <table>
- #foreach( $product in $buyingProducts )
- Buy: $product.Name, Price: $product.Price,
- #end
- table>
上述代碼中,指定了變量customer的類(lèi)型為 com.abc.crm.Customer,變量buyingProducts 的類(lèi)型為Product泛型集合。由于 "##"是Velocity的注釋指令,因此 "##$" 在Velocity Engine解析(Parse)和渲染(Render)時(shí)不會(huì)與現(xiàn)有語(yǔ)法沖突,Velocity引擎能正常執(zhí)行,從而保證了兼容性。
Phone Club——51CTO移動(dòng)開(kāi)發(fā)線下技術(shù)沙龍
本期主題:Android應(yīng)用開(kāi)發(fā)技術(shù)進(jìn)階
地點(diǎn):創(chuàng)新工場(chǎng) 北京市海淀區(qū)北四環(huán)西路66號(hào)第三極大廈B座18層
演講講師:王明禮(創(chuàng)新工場(chǎng)) 范懷宇(網(wǎng)易)
#p#
2.2 動(dòng)態(tài)語(yǔ)言一階段模型
在動(dòng)態(tài)類(lèi)型語(yǔ)言中,只有一個(gè)運(yùn)行時(shí)(Run Time)階段,運(yùn)行階段由解釋器(Intepreter)來(lái)對(duì)源代碼進(jìn)行解析(Parsing)、執(zhí)行(Evaluation)產(chǎn)生執(zhí)行結(jié)果。過(guò)程如下:
由于動(dòng)態(tài)語(yǔ)言無(wú)類(lèi)型的特點(diǎn),在解析步驟中產(chǎn)生的抽象語(yǔ)法樹(shù)(Abstract Syntax Tree,AST)所有變量被存儲(chǔ)為統(tǒng)一的類(lèi)型,例如JavaScript,Velocity中變量都作為 Object 類(lèi)型。在執(zhí)行步驟,一般由類(lèi)型推斷系統(tǒng)(Type Inference System)負(fù)責(zé)根據(jù)變量的實(shí)際值動(dòng)態(tài)判斷變量的類(lèi)型,并判斷函數(shù)、方法或?qū)傩哉{(diào)用是否正確,由解釋器進(jìn)行執(zhí)行或計(jì)算,從而產(chǎn)生結(jié)果。
2.3 半靜態(tài)語(yǔ)言兩階段模型
而半靜態(tài)語(yǔ)言,分開(kāi)發(fā)時(shí)(Develop Time)和運(yùn)行時(shí)(Run Time)兩個(gè)階段,兩個(gè)階段互不干擾。
1、開(kāi)發(fā)時(shí)階段。
開(kāi)發(fā)時(shí)進(jìn)行類(lèi)型檢查。一個(gè)“編譯器”,更嚴(yán)格說(shuō)是類(lèi)型化解析器(Typing Parser)負(fù)責(zé)對(duì)源代碼進(jìn)行解析和類(lèi)型檢查,然后輸出檢查結(jié)果。“變量聲明”是類(lèi)型檢查的必要條件。檢查結(jié)果包含類(lèi)型檢查失敗的錯(cuò)誤信息和警告信息,類(lèi)似于 Java編譯時(shí)的錯(cuò)誤信息。
與靜態(tài)類(lèi)型語(yǔ)言不同,此編譯器不輸出機(jī)器代碼或字節(jié)碼,只輸出類(lèi)型檢查錯(cuò)誤信息。
2、運(yùn)行時(shí)階段。
此階段中,源代碼仍由解釋器以解釋方式執(zhí)行,同動(dòng)態(tài)語(yǔ)言的解釋執(zhí)行過(guò)程。
半靜態(tài)語(yǔ)言的兩階段模型如下圖所示:
需要指出的是,運(yùn)行時(shí)階段仍采用無(wú)類(lèi)型解析器(Untyping Parser), 是一個(gè)類(lèi)型推斷系統(tǒng)。而開(kāi)發(fā)時(shí)采用的是一個(gè)新的類(lèi)型化解析器(Typing Parser), 是一個(gè)類(lèi)型檢查系統(tǒng)(Type Checking System)。
2.4 開(kāi)發(fā)流程
半靜態(tài)語(yǔ)言的開(kāi)發(fā)流程涉及5個(gè)步驟:
1、編碼
2、編譯(類(lèi)型檢查).
半靜態(tài)語(yǔ)言的編譯與靜態(tài)類(lèi)型語(yǔ)言很不相同,它的編譯只進(jìn)行類(lèi)型檢查,不產(chǎn)生機(jī)器碼或字節(jié)碼。因此,半靜態(tài)語(yǔ)言的編譯可以稱為“檢查”(Checking).
在這個(gè)步驟中,如果代碼存在類(lèi)型錯(cuò)誤(Error),編譯失敗,那么你必須退回到步驟1)修改代碼bug,直到代碼編譯正確。
編譯過(guò)程還可以產(chǎn)生警告(Warning),程序員可以有選擇的忽略。
3、測(cè)試
QA 執(zhí)行功能測(cè)試,集成測(cè)試和系統(tǒng)測(cè)試。
如果測(cè)試失敗,必須退回到步驟 1)。
4、發(fā)布
將代碼發(fā)布到生產(chǎn)環(huán)境
5、執(zhí)行
最終用戶訪問(wèn)用半靜態(tài)語(yǔ)言開(kāi)發(fā)的應(yīng)用功能。
從上面的開(kāi)發(fā)流程可見(jiàn), 開(kāi)發(fā)時(shí)階段覆蓋了步驟 1)、2), 運(yùn)行時(shí)階段覆蓋了步驟 3)、4)、5).
為了保證只有編譯合法的半靜態(tài)語(yǔ)言程序在生產(chǎn)環(huán)境運(yùn)行,需要有以下兩條約束規(guī)則來(lái)保證:
1、代碼編譯合法后,才能提交到測(cè)試階段;
2、測(cè)試正確的代碼才能發(fā)布上線。
由于半靜態(tài)語(yǔ)言仍用解析器運(yùn)行,理論上代碼仍具有修改即生效的特點(diǎn)。但從軟件質(zhì)量保證角度,這個(gè)缺點(diǎn)應(yīng)該規(guī)避。因此上線后的代碼不允許未經(jīng)編譯、測(cè)試的隨意修改。
Phone Club——51CTO移動(dòng)開(kāi)發(fā)線下技術(shù)沙龍
本期主題:Android應(yīng)用開(kāi)發(fā)技術(shù)進(jìn)階
地點(diǎn):創(chuàng)新工場(chǎng) 北京市海淀區(qū)北四環(huán)西路66號(hào)第三極大廈B座18層
演講講師:王明禮(創(chuàng)新工場(chǎng)) 范懷宇(網(wǎng)易)
#p#
2.5 類(lèi)型檢查系統(tǒng)和原理
半靜態(tài)語(yǔ)言的類(lèi)型檢查系統(tǒng)中的核心組件編譯器Compiler(或稱為Checker),它本質(zhì)上是一個(gè)類(lèi)型化解析器。編譯時(shí),該系統(tǒng)采用類(lèi)型檢查算法(Type Checking Algorithm);而在運(yùn)行時(shí)階段,仍由解釋器執(zhí)行代碼,采用類(lèi)型推斷算法(Type Inference Algorithm)。
半靜態(tài)語(yǔ)言的類(lèi)型檢查基本原理是,根據(jù)變量聲明對(duì)源碼進(jìn)行解析、類(lèi)型檢查和語(yǔ)義檢查,輸出檢查結(jié)果。這個(gè)系統(tǒng)中類(lèi)型檢查系統(tǒng)的基本原理如下圖所示:
我們使用一個(gè)命令行工具 vmcheck 來(lái)編譯半靜態(tài)語(yǔ)言代碼。格式為:
- Format: vmcheck templateFile
以前面的聲明式Velocity源碼為例,類(lèi)型檢查系統(tǒng)包含以下幾個(gè)基本規(guī)則和檢查點(diǎn):
1、變量是否聲明;
如果變量 $customer 未聲明,編譯錯(cuò)誤如下:
- Error: line:2,column:7,variable $customer not declared !
2、JavaBean的屬性和方法是否存在
如果com.alibaba.saling.Customer類(lèi)沒(méi)有屬性 'Name' , 編譯錯(cuò)誤如下:
- Error: line:2, column:7, property 'Name' not found for $customer.
如果com.alibaba.utils.CurrencyUtil 類(lèi)沒(méi)有方法 'convert' , 編譯錯(cuò)誤如下:
- Error: line:6, column:22, method 'convert' not found for $currencyUtil.
3、方法調(diào)用的參數(shù)匹配;
3.1) 如果這樣調(diào)用 'convert' 方法:
- $currencyUtil.convert()
則產(chǎn)生如下編譯錯(cuò)誤信息:
- Error: line:6, column:22, insufficient parameters for method call 'convert' .
3.2) 如果這樣調(diào)用 'convert' 方法
- $currencyUtil.convert( $customer , "##.##" )
則產(chǎn)生編譯錯(cuò)誤信息:
- Error: line:6, column:22, parameter type mismatched of $customer for method call 'convert' , Double is required.
4、特定語(yǔ)句的類(lèi)型匹配,如條件,循環(huán)語(yǔ)句:
如果有下面的復(fù)制語(yǔ)句調(diào)用
- #set( $customer.Name = $product.Price)
則產(chǎn)生編譯錯(cuò)誤信息:
- Error: line:11, column:5, type mismatched of assignment statement.
'if', 'foreach' 等語(yǔ)句使用的類(lèi)型匹配規(guī)則類(lèi)似。這與Java等強(qiáng)類(lèi)型語(yǔ)言一樣。
集合泛型的類(lèi)型匹配
對(duì)于Java語(yǔ)言,JDK5+支持泛型特性。因此,類(lèi)型檢查也需支持泛型。對(duì)于以下代碼
- ##$ List buyingProducts
- $buyingProducts.add( $customer)
編譯錯(cuò)誤如下:
- Error: line:12, column:5, parameter type mismatched of $buyingProducts for method call 'add' , 'com.alibaba.saling.Product' is required.
- As for the previous Velocity code snippet [Code 1], after executing 'vcheck' command on console,
Phone Club——51CTO移動(dòng)開(kāi)發(fā)線下技術(shù)沙龍
本期主題:Android應(yīng)用開(kāi)發(fā)技術(shù)進(jìn)階
地點(diǎn):創(chuàng)新工場(chǎng) 北京市海淀區(qū)北四環(huán)西路66號(hào)第三極大廈B座18層
演講講師:王明禮(創(chuàng)新工場(chǎng)) 范懷宇(網(wǎng)易)
#p#
3 變量聲明
變量聲明就是對(duì)變量的類(lèi)型進(jìn)行聲明。變量聲明根據(jù)放置的地點(diǎn)分為兩種,顯示聲明(Explicit Declaration)和隱式聲明(Implicit Declaration)。
1、顯式聲明
顯式聲明采用特殊指令(Directive)或語(yǔ)句(Statement),在源碼中對(duì)變量進(jìn)行類(lèi)型聲明。
顯式聲明通常的格式為:
為了保持與運(yùn)行時(shí)解釋器的兼容性,我們引入一種“基于注釋的擴(kuò)展聲明指令”技術(shù)。以Velocity模板語(yǔ)言(VTL)為例, 在Velocity注釋指令“##”上擴(kuò)展“##$”指令用于變量聲明。如下例所示:
- [Code 3] showBuyProducts_static.vm
- ##$ com.abc.crm.Customer customer
- ##$ List buyingProducts
- ##$ String flag, sss, abc
對(duì)于其他動(dòng)態(tài)類(lèi)型語(yǔ)言,同樣使用“基于注釋的擴(kuò)展聲明指令”來(lái)實(shí)現(xiàn)兼容性的半靜態(tài)語(yǔ)言。
Language |
Comment Instruction |
S2L Declaration Instruction |
Velocity |
## |
##$ |
Javascript |
// |
//$ |
Ruby |
# |
#$ |
Python |
# |
#$ |
2、隱式聲明
隱式聲明不用在源碼中編寫(xiě)聲明語(yǔ)句,而從配置文件或其他地方分析變量聲明。例如,使用Velocity進(jìn)行Web App開(kāi)發(fā)時(shí),如果需要直接頻繁操作request,response,session等Servlet容器對(duì)象,編譯器可以將它們作為內(nèi)置變量,使用隱式聲明。如下表所示:
Built-in variable |
Type |
request |
HttpServletRequest |
response |
HttpServletResponse |
session |
HttpSession |
application |
ServletContext |
以下代碼使用隱式聲明變量 request, session,
- Hello, $request.getParameter("username") !
- Your logged in at $session.getAttribute("loginTime") last time.
- body>
這段代碼看起來(lái),對(duì)現(xiàn)有Velocity語(yǔ)法沒(méi)有任何擴(kuò)展. 但實(shí)際上,在編譯時(shí),編譯器使用內(nèi)置變量對(duì)源碼進(jìn)行類(lèi)型檢查。
如果編寫(xiě)了一段錯(cuò)誤的調(diào)用,例如:
- $session.getParameter("loginTime")
則編譯器輸出一條“方法不存在的”錯(cuò)誤信息:
- Error: line:12, column:5, method 'getParameter' not found for $session!.
Phone Club——51CTO移動(dòng)開(kāi)發(fā)線下技術(shù)沙龍
本期主題:Android應(yīng)用開(kāi)發(fā)技術(shù)進(jìn)階
地點(diǎn):創(chuàng)新工場(chǎng) 北京市海淀區(qū)北四環(huán)西路66號(hào)第三極大廈B座18層
演講講師:王明禮(創(chuàng)新工場(chǎng)) 范懷宇(網(wǎng)易)
#p#
4 語(yǔ)法約束
半靜態(tài)語(yǔ)言基于某種動(dòng)態(tài)類(lèi)型語(yǔ)言進(jìn)行實(shí)現(xiàn),但它在語(yǔ)法語(yǔ)義上更接近與靜態(tài)類(lèi)型語(yǔ)言。在這兩個(gè)端點(diǎn),存在一些矛盾的地方,比如:變量動(dòng)態(tài)定型,ducking type等。因此,半靜態(tài)語(yǔ)言需要有語(yǔ)法約束:
1、變量先聲明,后使用
2、變量在作用域scope內(nèi)置能聲明為一個(gè)類(lèi)型;
3、禁止Ducking type 也就是多, 動(dòng)態(tài)語(yǔ)言的無(wú)繼承多態(tài)特性不允許使用,因?yàn)檫@與靜態(tài)類(lèi)型系統(tǒng)是沖突的。
如果違反這幾個(gè)規(guī)則,編譯器會(huì)產(chǎn)生相應(yīng)的編譯錯(cuò)誤。以ducking type 為例(Ruby支持,而Velocity等Java系列腳本不支持), 如果嘗試訪問(wèn)一個(gè)不存在的方法,則會(huì)產(chǎn)生下面的錯(cuò)誤。
- Error: line:12, column:5, method 'quack' not found for $dog.
而在Ruby中,只要 dog 存在 quack 方法,代碼運(yùn)行是正確的。
5 半靜態(tài)語(yǔ)言組成模型和實(shí)現(xiàn)方式
半靜態(tài)語(yǔ)言本質(zhì)上是動(dòng)態(tài)語(yǔ)言思想和靜態(tài)語(yǔ)言思想的結(jié)合的產(chǎn)物。一種基本的半靜態(tài)語(yǔ)言實(shí)現(xiàn),核心功能是在運(yùn)行前進(jìn)行類(lèi)型檢查和語(yǔ)義檢查。其組件集合 SS包括:
1、一種靜態(tài)類(lèi)型語(yǔ)言S,S以編譯方式運(yùn)行;
2、一種以S語(yǔ)言為基礎(chǔ)的動(dòng)態(tài)類(lèi)型語(yǔ)言 D。D以解釋方式由P執(zhí)行,解釋器 P 由S 編寫(xiě);
3、在語(yǔ)言D的語(yǔ)法集合上擴(kuò)展變量聲明語(yǔ)法,新語(yǔ)法集合名為 SD ;
4、用語(yǔ)言S對(duì)解釋器P進(jìn)行擴(kuò)展,實(shí)現(xiàn) SD 的類(lèi)型編譯器C;
5、開(kāi)發(fā)時(shí),遵循SD語(yǔ)法集合的代碼由 C 進(jìn)行類(lèi)型檢查;
6、運(yùn)行時(shí),遵循SD語(yǔ)法集合的代碼由 P 進(jìn)行解釋執(zhí)行。
因此,新的半靜態(tài)語(yǔ)言SS是基本組成是:新語(yǔ)法集合SD和類(lèi)型編譯器C.
SS = SD + C
舉例:
Java 是一種靜態(tài)類(lèi)型語(yǔ)言,運(yùn)行前進(jìn)行編譯和類(lèi)型檢查;
Velocity是一種基于Java的動(dòng)態(tài)模板語(yǔ)言,通過(guò) Velocity Engine以解釋方式運(yùn)行;
基于Velocity實(shí)現(xiàn)半靜態(tài)語(yǔ)言的方式為:為Velocity基本語(yǔ)法增加變量聲明指令(語(yǔ)句),基于Velocity 解釋器 實(shí)現(xiàn)類(lèi)型編譯器 ,負(fù)責(zé)在開(kāi)發(fā)時(shí)對(duì)模板進(jìn)行類(lèi)型檢查。
實(shí)踐中,Java體系的動(dòng)態(tài)類(lèi)型語(yǔ)言一般與Java語(yǔ)言天生的結(jié)合使用,應(yīng)用廣泛。以它們?yōu)榛A(chǔ),很容易通過(guò)擴(kuò)展方式實(shí)現(xiàn)類(lèi)型編譯器,進(jìn)而實(shí)現(xiàn)半靜態(tài)語(yǔ)言。 例如Freemarker,Groovy,JRuby,Bean Shell等。其他動(dòng)態(tài)類(lèi)型語(yǔ)言也可以基于此原理設(shè)計(jì)半靜態(tài)語(yǔ)言,如:Python,Ruby。
Phone Club——51CTO移動(dòng)開(kāi)發(fā)線下技術(shù)沙龍
本期主題:Android應(yīng)用開(kāi)發(fā)技術(shù)進(jìn)階
地點(diǎn):創(chuàng)新工場(chǎng) 北京市海淀區(qū)北四環(huán)西路66號(hào)第三極大廈B座18層
演講講師:王明禮(創(chuàng)新工場(chǎng)) 范懷宇(網(wǎng)易)
#p#
IDE敏捷開(kāi)發(fā)(Agile Development in IDE)
對(duì)于Velocity,F(xiàn)reemarker這類(lèi)動(dòng)態(tài)類(lèi)型語(yǔ)言,它們基于Java等強(qiáng)類(lèi)型語(yǔ)言,在模板內(nèi)能直接操作傳入的Java對(duì)象。由于Java等語(yǔ)言有反射(Reflection)機(jī)制。因而,除了靜態(tài)類(lèi)型檢查的基本功能,可以在類(lèi)型檢查和反射技術(shù)基礎(chǔ)上,實(shí)現(xiàn)一系列IDE敏捷開(kāi)發(fā)功能。包括:
1、代碼提示:編輯器內(nèi)的Java對(duì)象的屬性,方法代碼提示;
2、參數(shù)提示:編輯器內(nèi)的Java對(duì)象的方法參數(shù)提示;
3、全量構(gòu)建和增量構(gòu)建:Java類(lèi)修改對(duì)相關(guān)Velocity模板的增量檢查;
4、代碼重構(gòu):修改Java屬性或方法名稱,自動(dòng)批量修改相關(guān)模板中所有對(duì)應(yīng)類(lèi)型的JavaBean屬性或方法名稱。
其中3),4) 功能對(duì)于大型系統(tǒng)的維護(hù)和重構(gòu)價(jià)值尤為明顯。以上這些敏捷開(kāi)發(fā)功能可獨(dú)立實(shí)現(xiàn)或結(jié)合集成開(kāi)發(fā)環(huán)境(IDE)如Eclipse插件來(lái)實(shí)現(xiàn)。
結(jié)論
通過(guò)以上分析可見(jiàn),半靜態(tài)化語(yǔ)言結(jié)合了靜態(tài)語(yǔ)言和動(dòng)態(tài)語(yǔ)言的優(yōu)點(diǎn),能很好的解決動(dòng)態(tài)語(yǔ)言編程的開(kāi)發(fā)質(zhì)量和開(kāi)發(fā)效率問(wèn)題。半靜態(tài)化語(yǔ)言保留了動(dòng)態(tài)語(yǔ)言的靈活性優(yōu)點(diǎn),同時(shí)達(dá)到了靜態(tài)語(yǔ)言在開(kāi)發(fā)時(shí)強(qiáng)類(lèi)型檢查優(yōu)勢(shì),能有效提升程序健壯性,減低測(cè)試復(fù)雜性和測(cè)試成本。通過(guò)與IDE結(jié)合,實(shí)現(xiàn)代碼提示,代碼重構(gòu)等敏捷開(kāi)發(fā)功能,有效提升動(dòng)態(tài)語(yǔ)言的開(kāi)發(fā)效率。在企業(yè)級(jí)應(yīng)用和互聯(lián)網(wǎng)應(yīng)用開(kāi)發(fā)中有著良好的應(yīng)用價(jià)值。
Phone Club——51CTO移動(dòng)開(kāi)發(fā)線下技術(shù)沙龍
本期主題:Android應(yīng)用開(kāi)發(fā)技術(shù)進(jìn)階
地點(diǎn):創(chuàng)新工場(chǎng) 北京市海淀區(qū)北四環(huán)西路66號(hào)第三極大廈B座18層
演講講師:王明禮(創(chuàng)新工場(chǎng)) 范懷宇(網(wǎng)易)
【編輯推薦】