伸进女同桌乳沟里摸爽了,小雪解开乳罩给老杨摸,少妇被按摩师摸高潮了,亲嘴扒胸摸屁股激烈视频,强摸秘书人妻大乳BD,摸BBB揉BBB揉BBB视频

新疆軟件開(kāi)發(fā)

本站首頁(yè) 軟件開(kāi)發(fā) 成功案例 公司新聞 公司簡(jiǎn)介 客服中心 軟件技術(shù) 網(wǎng)站建設(shè)
  您現(xiàn)在的位置: 新疆二域軟件開(kāi)發(fā)公司 >> Java技術(shù) >> 文章正文

如何才能使用Java實(shí)現(xiàn)內(nèi)部領(lǐng)域的特定語(yǔ)言

 
 
 
領(lǐng)域特定語(yǔ)言(DSL)通常被定義為一種特別針對(duì)某類特殊問(wèn)題的計(jì)算機(jī)語(yǔ)言,它不打算解決其領(lǐng)域外的問(wèn)題。對(duì)于DSL的正式研究已經(jīng)持續(xù)很多年,直到最近,在程序員試圖采用最易讀并且簡(jiǎn)煉的方法來(lái)解決他們的問(wèn)題的時(shí)候,內(nèi)部DSL意外地被寫入程序中。近來(lái),隨著關(guān)于Ruby和其他一些動(dòng)態(tài)語(yǔ)言的出現(xiàn),程序員對(duì)DSL的興趣越來(lái)越濃。這些結(jié)構(gòu)松散的語(yǔ)言給DSL提供某種方法,使得DSL允許最少的語(yǔ)法以及對(duì)某種特殊語(yǔ)言最直接的表現(xiàn)。但是,放棄編譯器和使用類似Eclipse這樣最強(qiáng)大的現(xiàn)代集成開(kāi)發(fā)環(huán)境無(wú)疑是該方式的一大缺點(diǎn)。然而,作者終于成功地找到了這兩個(gè)方法的折衷解決方式,并且,他們將證明該折衷方法不但可能,而且對(duì)于使用Java這樣的結(jié)構(gòu)性語(yǔ)言從面向DSL的方式來(lái)設(shè)計(jì)API很有幫助。本文將描述怎樣使用Java語(yǔ)言來(lái)編寫領(lǐng)域特定語(yǔ)言,并將建議一些組建DSL語(yǔ)言時(shí)可采用的模式。
 
Java適合用來(lái)創(chuàng)建內(nèi)部領(lǐng)域特定語(yǔ)言嗎?
 
在我們審視Java語(yǔ)言是否可以作為創(chuàng)建DSL的工具之前,我們首先需要引進(jìn)“內(nèi)部DSL”這個(gè)概念。一個(gè)內(nèi)部DSL在由應(yīng)用軟件的主編程語(yǔ)言創(chuàng)建,對(duì)定制編譯器和解析器的創(chuàng)建(和維護(hù))都沒(méi)有任何要求。Martin Fowler曾編寫過(guò)大量各種類型的DSL,無(wú)論是內(nèi)部的還是外部的,每種類型他都編寫過(guò)一些不錯(cuò)的例子。但使用像Java這樣的語(yǔ)言來(lái)創(chuàng)建DSL,他卻僅僅一筆帶過(guò)。
 
另外還要著重提出的很重要的一點(diǎn)是,在DSL和API兩者間其實(shí)很難區(qū)分。在內(nèi)部DSL的例子中,他們本質(zhì)上幾乎是一樣的。在聯(lián)想到DSL這個(gè)詞匯的時(shí)候,我們其實(shí)是在利用主編程語(yǔ)言在有限的范圍內(nèi)創(chuàng)建易讀的API!皟(nèi)部DSL”幾乎是一個(gè)特定領(lǐng)域內(nèi)針對(duì)特定問(wèn)題而創(chuàng)建的極具可讀性的API的代名詞。
 
任何內(nèi)部DSL都受它基礎(chǔ)語(yǔ)言的文法結(jié)構(gòu)的限制。比如在使用Java的情況下,大括弧,小括弧和分號(hào)的使用是必須的,并且缺少閉包和元編程有可能會(huì)導(dǎo)致DSL比使用動(dòng)態(tài)語(yǔ)言創(chuàng)建來(lái)的更冗長(zhǎng)。
 
但從光明的一面來(lái)看,通過(guò)使用Java,我們同時(shí)能利用強(qiáng)大且成熟的類似于Eclipse和IntelliJ IDEA的集成開(kāi)發(fā)環(huán)境,由于這些集成開(kāi)發(fā)環(huán)境“自動(dòng)完成(auto-complete)”、自動(dòng)重構(gòu)和debug等特性,使得DSL的創(chuàng)建、使用和維護(hù)來(lái)的更加簡(jiǎn)單。另外,Java5中的一些新特性(比如generic、varargs 和static imports)可以幫助我們創(chuàng)建比以往任何版本任何語(yǔ)言都簡(jiǎn)潔的API。
 
一般來(lái)說(shuō),使用Java編寫的DSL不會(huì)造就一門業(yè)務(wù)用戶可以上手的語(yǔ)言,而會(huì)是一種業(yè)務(wù)用戶也會(huì)覺(jué)得易讀的語(yǔ)言,同時(shí),從程序員的角度,它也會(huì)是一種閱讀和編寫都很直接的語(yǔ)言。和外部DSL或由動(dòng)態(tài)語(yǔ)言編寫的DSL相比有優(yōu)勢(shì),那就是編譯器可以增強(qiáng)糾錯(cuò)能力并標(biāo)識(shí)不合適的使用,而Ruby或Pearl會(huì)“愉快接受”荒謬的input并在運(yùn)行時(shí)失敗。這可以大大減少冗長(zhǎng)的測(cè)試,并極大地提高應(yīng)用程序的質(zhì)量。然而,以這樣的方式利用編譯器來(lái)提高質(zhì)量是一門藝術(shù),目前,很多程序員都在為盡力滿足編譯器而非利用它來(lái)創(chuàng)建一種使用語(yǔ)法來(lái)增強(qiáng)語(yǔ)義的語(yǔ)言。
利用Java來(lái)創(chuàng)建DSL有利有弊。最終,你的業(yè)務(wù)需求和你所工作的環(huán)境將決定這個(gè)選擇正確與否。
 
將Java作為內(nèi)部DSL的平臺(tái)
 
動(dòng)態(tài)構(gòu)建SQL是一個(gè)很好的例子,其建造了一個(gè)DSL以適合SQL領(lǐng)域,獲得了引人注意的優(yōu)勢(shì)。
傳統(tǒng)的使用SQL的Java代碼一般類似于:
 
String sql = "select id, name " +
"from customers c, order o " +
"where " +
"c.since >= sysdate - 30 and " +
"sum(o.total) > " + significantTotal + " and " +
"c.id = o.customer_id and " +
"nvl(c.status, 'DROPPED') != 'DROPPED'";  
 
 
從作者最近工作的系統(tǒng)中摘錄的另一個(gè)表達(dá)方式是:
 
Table c = CUSTOMER.alias();
Table o = ORDER.alias();
Clause recent = c.SINCE.laterThan(daysEarlier(30));
Clause hasSignificantOrders = o.TOTAT.sum().isAbove(significantTotal);
Clause ordersMatch = c.ID.matches(o.CUSTOMER_ID);
Clause activeCustomer = c.STATUS.isNotNullOr("DROPPED");
String sql = CUSTOMERS.where(recent.and(hasSignificantOrders)
.and(ordersMatch)
.and(activeCustomer)
.select(c.ID, c.NAME)
.sql();  
 
 
這個(gè)DSL版本有幾項(xiàng)優(yōu)點(diǎn)。后者能夠透明地適應(yīng)轉(zhuǎn)換到使用PreparedStatement的方法——用String拼寫SQL的版本則需要大量的修改才能適應(yīng)轉(zhuǎn)換到使用捆綁變量的方法。如果引用不正確或者一個(gè)integer變量被傳遞到date column作比較的話,后者版本根本無(wú)法通過(guò)編譯。代碼“nvl(foo, 'X') != 'X'”是Oracle SQL中的一種特殊形式,這個(gè)句型對(duì)于非Oracle SQL程序員或不熟悉SQL的人來(lái)說(shuō)很難讀懂。例如在SQL Server方言中,該代碼應(yīng)該這樣表達(dá)“(foo is null or foo != 'X')”。但通過(guò)使用更易理解、更像人類語(yǔ)言的“isNotNullOr(rejectedValue)”來(lái)替代這段代碼的話,顯然會(huì)更具閱讀性,并且系統(tǒng)也能夠受到保護(hù),從而避免將來(lái)為了利用另一個(gè)數(shù)據(jù)庫(kù)供應(yīng)商的設(shè)施而不得不修改最初的代碼實(shí)現(xiàn)。
 
使用Java創(chuàng)建內(nèi)部DSL
 
創(chuàng)建DSL最好的方法是,首先將所需的API原型化,然后在基礎(chǔ)語(yǔ)言的約束下將它實(shí)現(xiàn)。DSL的實(shí)現(xiàn)將會(huì)牽涉到連續(xù)不斷的測(cè)試來(lái)肯定我們的開(kāi)發(fā)確實(shí)瞄準(zhǔn)了正確的方向。該“原型-測(cè)試”方法正是測(cè)試驅(qū)動(dòng)開(kāi)發(fā)模式(TDD-Test-Driven Development)所提倡的。
 
在使用Java來(lái)創(chuàng)建DSL的時(shí)候,我們可能想通過(guò)一個(gè)連貫接口(fluent interface)來(lái)創(chuàng)建DSL。連貫接口可以對(duì)我們所想要建模的領(lǐng)域問(wèn)題提供一個(gè)簡(jiǎn)介但易讀的表示。連貫接口的實(shí)現(xiàn)采用方法鏈接(method chaining)。但有一點(diǎn)很重要,方法鏈接本身不足以創(chuàng)建DSL。一個(gè)很好的例子是Java的StringBuilder,它的方法“append”總是返回一個(gè)同樣的StringBuilder的實(shí)例。這里有一個(gè)例子:
 
StringBuilder b = new StringBuilder();
b.append("Hello. My name is ")
.append(name)
.append(" and my age is ")
.append(age);  
 
 
該范例并不解決任何領(lǐng)域特定問(wèn)題。
 
除了方法鏈接外,靜態(tài)工廠方法(static factory method)和import對(duì)于創(chuàng)建簡(jiǎn)潔易讀的DSL來(lái)說(shuō)是不錯(cuò)的助手。在下面的章節(jié)中,我們將更詳細(xì)地講到這些技術(shù)。
 
1、方法鏈接(Method Chaining)
 
使用方法鏈接來(lái)創(chuàng)建DSL有兩種方式,這兩種方式都涉及到鏈接中方法的返回值。我們的選擇是返回this或者返回一個(gè)中間對(duì)象,這決定于我們?cè)噲D要所達(dá)到的目的。
 
1.1、返回this
 
在可以以下列方式來(lái)調(diào)用鏈接中方法的時(shí)候,我們通常返回this:
 
◆可選擇的。
◆以任何次序調(diào)用。
◆可以調(diào)用任何次數(shù)。
 
我們發(fā)現(xiàn)運(yùn)用這個(gè)方法的兩個(gè)用例:
 
1、相關(guān)對(duì)象行為鏈接。
2、一個(gè)對(duì)象的簡(jiǎn)單構(gòu)造/配置。
 
1.1.1、相關(guān)對(duì)象行為鏈接
 
很多次,我們只在企圖減少代碼中不必要的文本時(shí),才通過(guò)模擬分派“多信息”(或多方法調(diào)用)給同一個(gè)對(duì)象而將對(duì)象的方法進(jìn)行鏈接。下面的代碼段顯示的是一個(gè)用來(lái)測(cè)試Swing GUI的API。測(cè)試所證實(shí)的是,如果一個(gè)用戶試圖不輸入她的密碼而登錄到系統(tǒng)中的話,系統(tǒng)將顯示一條錯(cuò)誤提示信息。
 
DialogFixture dialog = new DialogFixture(new LoginDialog());
dialog.show();
dialog.maximize();
TextComponentFixture usernameTextBox = dialog.textBox("username");
usernameTextBox.clear();
usernameTextBox.enter("leia.organa");
dialog.comboBox("role").select("REBEL");
OptionPaneFixture errorDialog = dialog.optionPane();
errorDialog.requireError();
errorDialog.requireMessage("Enter your password");  
 
 
盡管代碼很容易讀懂,但卻很冗長(zhǎng),需要很多鍵入。
 
下面列出的是在我們范例中所使用的TextComponentFixture的兩個(gè)方法:
 
public void clear() {
target.setText("");
}
public void enterText(String text) {
robot.enterText(target, text);
}  
 
 
我們可以僅僅通過(guò)返回this來(lái)簡(jiǎn)化我們的測(cè)試API,從而激活方法鏈接:
 
public TextComponentFixture clear() {
target.setText("");
return this;
}
public TextComponentFixture enterText(String text) {
robot.enterText(target, text);
return this;
}  
 
 
在激活所有測(cè)試設(shè)施中的方法鏈接之后,我們的測(cè)試代碼現(xiàn)在縮減到:
 
DialogFixture dialog = new DialogFixture(new LoginDialog());
dialog.show().maximize();
dialog.textBox("username").clear().enter("leia.organa");
dialog.comboBox("role").select("REBEL");
dialog.optionPane().requireError().requireMessage("Enter your password"); 
 
 
這個(gè)結(jié)果代碼顯然更加簡(jiǎn)潔易讀。正如先前所提到的,方法鏈接本身并不意味著有了DSL。我們需要將解決領(lǐng)域特定問(wèn)題的對(duì)象的所有相關(guān)行為相對(duì)應(yīng)的方法鏈接起來(lái)。在我們的范例中,這個(gè)領(lǐng)域特定問(wèn)題就是Swing GUI測(cè)試。
 
1.1.2、對(duì)象的簡(jiǎn)單構(gòu)造/配置
 
這個(gè)案例和上文的很相似,不同是,我們不再只將一個(gè)對(duì)象的相關(guān)方法鏈接起來(lái),取而代之的是,我們會(huì)通過(guò)連貫接口創(chuàng)建一個(gè)“builder”來(lái)構(gòu)建和/或配置對(duì)象。
 
下面這個(gè)例子采用了setter來(lái)創(chuàng)建“dream car”:
 
DreamCar car = new DreamCar();
car.setColor(RED);
car.setFuelEfficient(true);
car.setBrand("Tesla");  
 
 
DreamCar類的代碼相當(dāng)簡(jiǎn)單:
 
// package declaration and imports
public class DreamCar {
private Color color;
private String brand;
private boolean leatherSeats;
private boolean fuelEfficient;
private int passengerCount = 2;
// getters and setters for each field
}  
 

 

作者:未知 | 文章來(lái)源:賽迪網(wǎng) | 更新時(shí)間:2008-4-2 13:11:39

  • 上一篇文章:

  • 下一篇文章:

  • 相關(guān)文章:
    JAVA開(kāi)發(fā)的6個(gè)實(shí)踐的例子
    JAVA中的抽象類型的一些概念
    java語(yǔ)言開(kāi)發(fā)程序中的幾個(gè)例子大家看看
    了解java開(kāi)發(fā)語(yǔ)言在軟件開(kāi)發(fā)中的幾個(gè)誤區(qū)
    Java開(kāi)發(fā)學(xué)習(xí)小心使用Date以及Time類
    sun最近修補(bǔ)了一部分java的安全補(bǔ)丁
    Java程序員應(yīng)該了解那些開(kāi)源協(xié)議
    java性能優(yōu)化的一些見(jiàn)解
    解析c#語(yǔ)言和java語(yǔ)言最相似的地方
    GUI JAVA應(yīng)用程序是怎樣做出來(lái)的?
    軟件技術(shù)
    · 開(kāi)發(fā)語(yǔ)言
    · Java技術(shù)
    · .Net技術(shù)
    · 數(shù)據(jù)庫(kù)開(kāi)發(fā)
    最新文章  
    ·j2se 嵌入式腳本抓取引擎
    ·JAVA開(kāi)發(fā)的6個(gè)實(shí)踐的例子
    ·JBuilder7 / Weblogic7開(kāi)發(fā)
    ·JAVA中的抽象類型的一些概
    ·java語(yǔ)言開(kāi)發(fā)程序中的幾個(gè)
    ·了解java開(kāi)發(fā)語(yǔ)言在軟件開(kāi)
    ·如何才能使用Java實(shí)現(xiàn)內(nèi)部
    ·Java開(kāi)發(fā)學(xué)習(xí)小心使用Date
    ·Java程序員應(yīng)該了解那些開(kāi)
    ·java性能優(yōu)化的一些見(jiàn)解
    ·介紹JDK5.0一些collection
    ·基礎(chǔ)學(xué)習(xí):java中使用存儲(chǔ)
    ·解析c#語(yǔ)言和java語(yǔ)言最相
    ·Java語(yǔ)言學(xué)習(xí):jAVA中 的多
    ·Java是不是應(yīng)該增加新特性
    關(guān)于我們 | 軟件開(kāi)發(fā) | 下載試用 | 客服中心 | 聯(lián)系我們 | 友情鏈接 | 網(wǎng)站地圖 | 新疆電子地圖 | RSS訂閱
    版權(quán)所有 © 2016 新疆二域軟件開(kāi)發(fā)網(wǎng) www.zgna.net All Rights Reserved 新ICP備14003571號(hào)
    新疆軟件開(kāi)發(fā)總機(jī):0991-4842803、4811639.
    客服QQ:596589785 ;地址:新疆烏魯木齊北京中路華聯(lián)大廈A-5C 郵編:830000
     
    阿克苏市| 青神县| 德令哈市| 柯坪县| 金沙县| 淄博市| 上犹县| 江陵县| 河北省| 鞍山市| 莫力| 东辽县| 三原县| 南康市| 浑源县| 黑水县| 木里| 抚远县| 新田县| 大城县| 宝应县| 海林市| 德兴市| 施秉县| 邵武市| 花垣县| 清水河县| 阿鲁科尔沁旗| 南召县| 响水县| 女性| 新丰县| 文化| 泸定县| 麦盖提县| 枣阳市| 普宁市| 木兰县| 喜德县| 黔东| 庆阳市|