<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 5, comments - 16, trackbacks - 0, articles - 0

    2006年9月8日

    收藏一篇DLEE老大的文章,里面的話句句說(shuō)到了我的心坎里。

    為什么我說(shuō)Struts/WebWork會(huì)受到Ajax的威脅呢?有的人可能覺得大家相安無(wú)事不是很好,你是不是有神經(jīng)病故意挑起人民內(nèi)部矛盾?問題是他們之間確實(shí)存在著一些深層的內(nèi)在矛盾和沖突,這些矛盾才是目前Struts和 WebWork都只能在非常有限的程度上支持Ajax的原因。所以,問題是架構(gòu)性的,并不是小型的修補(bǔ)或者更好的編程技巧可以徹底解決的。

    傳統(tǒng)的服務(wù)器端MVC架構(gòu)設(shè)計(jì)(也就是Model2),存在著一個(gè)基本的假設(shè)就是Web應(yīng)用的工作流是由一系列的頁(yè)面切換構(gòu)成的。這種架構(gòu)中的一個(gè)View,從語(yǔ)義上來(lái)講只能代表一個(gè)完整的HTML頁(yè)面。整個(gè)Web應(yīng)用的表現(xiàn)層,被劃分成為非常多的頁(yè)面的組合。

    而Ajax開發(fā)者眼里,Web應(yīng)用的工作流并不是這樣構(gòu)成的。Ajax開發(fā)者看待Web應(yīng)用的角度與傳統(tǒng)開發(fā)者相比差別非常大。在一個(gè)Ajax應(yīng)用中,只有相對(duì)很少的頁(yè)面。每個(gè)頁(yè)面,包括頁(yè)面引用CSS樣式、JS腳本,都是一個(gè)更小型的Ajax應(yīng)用。甚至一些功能簡(jiǎn)單的Ajax應(yīng)用,本身僅僅由一個(gè)單一的頁(yè)面構(gòu)成。例如一個(gè)簡(jiǎn)單的RSS閱讀器,還有IBM筆記本上那個(gè)獲得天氣預(yù)報(bào)的桌面。
    按照Ajax in Action,Ajax應(yīng)用可以分成3種類型:

    1. 以內(nèi)容為中心的應(yīng)用,服務(wù)器返回的是一段HTML內(nèi)容。
    2. 以腳本為中心的應(yīng)用,服務(wù)器返回的是一段JS腳本。
    3. 以數(shù)據(jù)為中心的應(yīng)用,服務(wù)器返回的是一段數(shù)據(jù),可以是XML格式、JSON格式或者其他文本格式。
    服務(wù)器返回給Ajax應(yīng)用的3種類型的網(wǎng)絡(luò)流量(不稱為數(shù)據(jù)是與上面第3種Ajax應(yīng)用相區(qū)別),任何一種都不能被簡(jiǎn)單地視作傳統(tǒng)MVC架構(gòu)中的View,因?yàn)樗麄兏髯运淼恼Z(yǔ)義與傳統(tǒng)MVC架構(gòu)中的View的語(yǔ)義是完全不同的。所以可以看出,除了初次交付給瀏覽器一個(gè)完整的Ajax應(yīng)用之外,傳統(tǒng)的MVC架構(gòu)對(duì)于Ajax應(yīng)用的支持是非常有限的。其實(shí)為了給客戶端提供上面3類網(wǎng)絡(luò)流量,一個(gè)Servlet已經(jīng)足夠了。DWR、JSON-RPC、Buffalo在服務(wù)器端也就是由Servlet實(shí)現(xiàn)的,不要求服務(wù)器端一定要安裝某種MVC框架。
    上面3類應(yīng)用,前面的兩類,客戶端JS代碼比較簡(jiǎn)單,表現(xiàn)邏輯僅有一部分位于客戶端,大部分仍然位于服務(wù)器端,因此傳統(tǒng)的服務(wù)器端MVC架構(gòu)仍然是非常有價(jià)值的。但是大家注意第3類Ajax應(yīng)用,實(shí)際上它已經(jīng)將絕大部分甚至可以將全部的表現(xiàn)邏輯都轉(zhuǎn)移到客戶端來(lái)執(zhí)行,這個(gè)時(shí)候服務(wù)器端傳統(tǒng)的Web表現(xiàn)層實(shí)際上被架空了(皮之不存,毛將焉附?)。而對(duì)于Ajax應(yīng)用來(lái)說(shuō),雖然近期可能還是以第1類Ajax應(yīng)用為主(例如,所謂的AHAH技術(shù)),但是最有生命力和發(fā)展前景的還是第3類Ajax應(yīng)用。

    自從1999年M$推出IE5.0支持XMLHTTP,可以不刷新頁(yè)面以異步方式從服務(wù)器獲取數(shù)據(jù)之后,Web開發(fā)的領(lǐng)域就埋下了一顆定時(shí)炸彈(6年以后,一個(gè)新詞Ajax的出現(xiàn)引爆了這顆炸彈)。Model2最初的設(shè)計(jì)應(yīng)該發(fā)生在這件大事(現(xiàn)在應(yīng)該承認(rèn),M$做了一件天大的好事)發(fā)生之前,其設(shè)計(jì)師不可能想到異步請(qǐng)求的價(jià)值。按照Model2的設(shè)計(jì)思想直接產(chǎn)生了Struts。但是后來(lái)的WebWork在最初設(shè)計(jì)階段仍然與這個(gè)技術(shù)失之交臂,這是相當(dāng)可惜的一件事情。WebWork其實(shí)最初設(shè)計(jì)的時(shí)候就可以走的更遠(yuǎn),但是他們只想超越Struts,做一個(gè)更好的Model2 MVC開發(fā)框架?,F(xiàn)在他們?cè)傧脍s上這班列車已經(jīng)有點(diǎn)晚了。如果基礎(chǔ)的服務(wù)器端MVC架構(gòu)的價(jià)值是可疑的,那么其他圍繞這個(gè)架構(gòu)所開發(fā)的基礎(chǔ)架構(gòu)的價(jià)值也同樣是可疑的。

    所以在現(xiàn)在這個(gè)時(shí)刻,重新正本清源地思考Model2最初的設(shè)計(jì),它帶來(lái)的Web開發(fā)的巨大進(jìn)步,以及它所存在的不足,是一個(gè)非常現(xiàn)實(shí)的問題。

    posted @ 2006-09-08 22:16 BennyBao 閱讀(282) | 評(píng)論 (0)編輯 收藏

         摘要: 在網(wǎng)上看到了有些同志提到了為Ajax的XMLHttpRequest提供一個(gè)對(duì)象池,也讀了他們給出的實(shí)現(xiàn)代碼。感覺不是特別理想,于是模仿apache的commons中的ObjectPool的思路寫了一個(gè)簡(jiǎn)單的JavaScript版。望指教: function ...  閱讀全文

    posted @ 2006-09-08 17:47 BennyBao 閱讀(2489) | 評(píng)論 (3)編輯 收藏

    2006年9月5日

    在JavaScript可以使用try...catch來(lái)進(jìn)行異常處理。例如:
    try ? {
    ????foo.bar();
    }
    ? catch ?(e)?
    {
    ????alert(e.name?
    + ? " :? " ? +
    ?e.message);
    }

    目前我們可能得到的系統(tǒng)異常主要包含以下6種:
    • EvalError:?raised when an error occurs executing code in eval()
    • RangeError:?raised when a numeric variable or parameter is outside of its valid range
    • ReferenceError: raised when de-referencing an invalid reference
    • SyntaxError: raised when a syntax error occurs while parsing code in eval()
    • TypeError: raised when a variable or parameter is not a valid type
    • URIError: raised when encodeURI() or decodeURI() are passed invalid parameters

    上面的六種異常對(duì)象都繼承自Error對(duì)象。他們都支持以下兩種構(gòu)造方法:

    new ?Error();
    new ?Error( " 異常信息 " );

    手工拋出異常的方法如下:

    try ? {
    ????
    throw ? new ?Error( " Whoops! "
    );
    }
    ? catch ?(e)? {
    ????alert(e.name?
    + ? " :? " ? +
    ?e.message);
    }

    如要判斷異常信息的類型,可在catch中進(jìn)行判斷:

    try ? {
    ????foo.bar();
    }
    ? catch ?(e)?
    {
    ????
    if ?(e? instanceof ?EvalError)?
    {
    ????????alert(e.name?
    + ? " :? " ? +
    ?e.message);
    ????}
    ? else ? if ?(e? instanceof ?RangeError)? {
    ????????alert(e.name?
    + ? " :? " ? +
    ?e.message);
    ????}

    ????
    // ??etc
    }

    Error具有下面一些主要屬性:

    • description: 錯(cuò)誤描述 (僅IE可用).
    • fileName: 出錯(cuò)的文件名 (僅Mozilla可用).
    • lineNumber: 出錯(cuò)的行數(shù) (僅Mozilla可用).
    • message: 錯(cuò)誤信息 (在IE下同description)
    • name: 錯(cuò)誤類型.
    • number: 錯(cuò)誤代碼 (僅IE可用).
    • stack: 像Java中的Stack Trace一樣的錯(cuò)誤堆棧信息 (僅Mozilla可用).
    因此為了更好的了解錯(cuò)誤信息我們可以將catch部分改為如下形式:

    try ? {
    ????foo.bar();
    }
    ? catch ?(e)?
    {
    ????
    if ?(browserType? != ?BROWSER_IE)?
    {????????????????????????????
    ????????alert(
    ????????????
    " name:? " ? + ?e.name? +

    ????????????
    " \nmessage:? " ? + ?e.message? +
    ????????????
    " \nlineNumber:? " ? + ?e.lineNumber? +
    ????????????
    " \nfileName:? " ? + ?e.fileName? +
    ????????????
    " \nstack:? " ? + ?e.stack);????????
    ????}

    ????
    else ? {????????????????????
    ????????alert(
    ????????????
    " name:? " ? + ?e.name? +
    ????
    ????????????
    " \nerrorNumber:? " ? + ?(e.number? & ? 0xFFFF )? +

    ????????????
    " \nmessage:? " ? + ?e.message " );????????
    ????}

    }

    JavaScript中的throw命令事實(shí)上可以拋出任何對(duì)象,并且我們可以在catch接受到此對(duì)象。例如:

    try ? {
    ????
    throw ? new ?Date();???? // ?拋出當(dāng)前時(shí)間對(duì)象

    }
    ? catch ?(e)? {
    ????alert(e.toLocaleString());????
    // ?使用本地格式顯示當(dāng)前時(shí)間

    }

    posted @ 2006-09-05 17:56 BennyBao 閱讀(2001) | 評(píng)論 (1)編輯 收藏

    2006年9月3日

    本文著重討論的是具有RIA特征的Web應(yīng)用。例如目前比較流行的的Ajax類Web應(yīng)用。傳統(tǒng)的基于純HTML的Web應(yīng)用不在本文討論之列。

    隨著Ajax的升溫,開發(fā)人員逐漸對(duì)Web應(yīng)用中的各種UI控件和開發(fā)框架開始有了越來(lái)越濃厚的興趣。目前所知的這方面的控件集或開發(fā)框架可以說(shuō)是并不鮮見。筆者將這些產(chǎn)品大致分為兩個(gè)大類:離散控件集型和數(shù)據(jù)模型驅(qū)動(dòng)型。這兩個(gè)詞大家應(yīng)該很陌生,因?yàn)樗麄兌际潜扇俗栽斓摹?br />
    離散控件集型 - 此類產(chǎn)品以提供一系列相對(duì)獨(dú)立的界面控件為主要目的??丶念愋捅容^全面,例如搭建Web應(yīng)用常見的各種Grid、Tree、Menu、ToolBar、Window等。不過此類產(chǎn)品一般不會(huì)過多的考慮界面中的數(shù)據(jù)和操作邏輯的封裝,至多只會(huì)提供相對(duì)簡(jiǎn)單的靜態(tài)數(shù)據(jù)綁定*。我認(rèn)為此類產(chǎn)品的主要出發(fā)點(diǎn)是改善Web應(yīng)用的界面表現(xiàn)能力,同時(shí)借助自帶的SDK提供一種更加規(guī)范的開發(fā)模式。
    目前我所知的大部分產(chǎn)品似乎都屬于這一類別。例如: backbase、qooxdoo、NetAdventage、bindows等。
    Backbase實(shí)例中心:
    http://www.backbase.com/demos/explorer

    數(shù)據(jù)模型驅(qū)動(dòng)型 - 此類產(chǎn)品除了要提供一組比較好用的UI控件集之外,更會(huì)提供對(duì)界面中數(shù)據(jù)模型的管理功能。其UI控件以數(shù)據(jù)敏感控件為主。數(shù)據(jù)敏感控件可以通過于數(shù)據(jù)模型的綁定來(lái)實(shí)現(xiàn)對(duì)表現(xiàn)層中數(shù)據(jù)的展示和控制。這種數(shù)據(jù)綁定可成為動(dòng)態(tài)數(shù)據(jù)綁定*。可以說(shuō)這一類產(chǎn)品的主要出發(fā)點(diǎn)除改善Web應(yīng)用的界面表現(xiàn)能力外,也非常注重提供一種快速開發(fā)的模式。
    好的數(shù)據(jù)模型驅(qū)動(dòng)型的開發(fā)框架應(yīng)該首先包含離散控件集中的各種功能,它事實(shí)上是一種相對(duì)于單純的UI控件集而言更高層次的抽象。
    o_binding.png
    這種模式其實(shí)在以前CS下非常常見,例如VB、Delphi等RAD開發(fā)工具提交數(shù)據(jù)庫(kù)應(yīng)用開發(fā)模式都屬于這種類型。不過到了BS下人們似乎都忘記這種開發(fā)模式??赡苁且?yàn)椴粔蛞姸嘧R(shí)廣,目前筆者所知的此類產(chǎn)品只有dorado。
    dorado的示例中心:
    http://sample.bstek.com

    對(duì)于上面提到的兩種數(shù)據(jù)綁定方式的解釋如下:

    靜態(tài)數(shù)據(jù)綁定 – 是指在控件可以根據(jù)指派給他的數(shù)據(jù)源(往往是XML數(shù)據(jù)源或簡(jiǎn)單的數(shù)組)自動(dòng)的提取并展示其中的數(shù)據(jù)。這種提取過程是主動(dòng)完成的,當(dāng)提取過程結(jié)束后控件無(wú)法繼續(xù)感知數(shù)據(jù)源中數(shù)據(jù)的變化。這事實(shí)上是從控件到數(shù)據(jù)源的拉模式(Pull Mode)。

    動(dòng)態(tài)數(shù)據(jù)綁定 – 是指將控件以觀察者的角色注冊(cè)到數(shù)據(jù)源(往往是經(jīng)過封裝的私有對(duì)象)中。數(shù)據(jù)源成為被觀察者。當(dāng)數(shù)據(jù)源中的數(shù)據(jù)或狀態(tài)發(fā)生改變時(shí)會(huì)主動(dòng)通知所有觀察者(即綁定的控件),然后再由控件自動(dòng)提取數(shù)據(jù)完成展現(xiàn)的更新。這樣一旦綁定建立以后控件就可以實(shí)時(shí)的體現(xiàn)數(shù)據(jù)源中的最新變化。如果用戶利用這些控件對(duì)數(shù)據(jù)或狀態(tài)做了改變,那么這種改變自然也會(huì)通過數(shù)據(jù)源再實(shí)時(shí)的通知給所有其它相關(guān)的控件。這事實(shí)上是從數(shù)據(jù)源到控件的推模式(Push Mode)。
    ?
    回到關(guān)于離散控件集型和數(shù)據(jù)模型驅(qū)動(dòng)型的討論。這兩種開發(fā)框架都有這自己的適用面。筆者認(rèn)為離散控件集型的開發(fā)框架更加適合與一些像論壇這樣更加注重展現(xiàn)的應(yīng)用。而對(duì)于那些具有明顯數(shù)據(jù)庫(kù)應(yīng)用特性的的Web應(yīng)用(例如MIS類應(yīng)用),則數(shù)據(jù)模型驅(qū)動(dòng)型的開發(fā)框架更能發(fā)揮它的優(yōu)勢(shì)。
    得出以上結(jié)論的原因是我認(rèn)為數(shù)據(jù)模型驅(qū)動(dòng)型的開發(fā)框架能夠使開發(fā)人員將更多的精力投入到界面所需要實(shí)現(xiàn)的更能當(dāng)中,至少在制作頁(yè)面的前期階段不必太多的關(guān)注界面的表現(xiàn)形式。同時(shí)如果能夠?qū)⒏嗟慕缑娌僮鬟壿嫹庋b到數(shù)據(jù)模型對(duì)象中,就可以保證在后期當(dāng)最終用戶提出界面的修改要求時(shí),開發(fā)人員可以用更小的代價(jià)來(lái)完成對(duì)界面的重構(gòu)。

    讓我們來(lái)具體分析兩個(gè)場(chǎng)景:

    場(chǎng)景1:一個(gè)用慣了CS應(yīng)用的用戶要求開發(fā)一個(gè)界面來(lái)維護(hù)公司目前擁有的所有書籍。為了方便的完成對(duì)所有書籍的CRUD操作,用戶希望以一個(gè)Grid控件來(lái)完成所有這些操作,同時(shí)用戶希望能夠在界面批量的完成一系列C、U、D操作之后一次性的對(duì)數(shù)據(jù)進(jìn)行保存。每本書籍都有一個(gè)由系統(tǒng)自動(dòng)分配的編碼作為主鍵,因此用戶不需要看到書籍的編碼。
    分析:如果我們現(xiàn)在只有一個(gè)離散的Grid控件。要完成上述功能我們還需要做以下一些工作:

  • 由于編碼不在Grid中顯示,因此找到一個(gè)辦法能夠管理每本書籍的編碼。
  • 由于客戶端需要緩存用戶的一系列C、U、D操作然后作批量的提交處理,因此必須做一些工作以便記錄下哪些書被修改了、哪些是新增的、哪些被刪除了。
  • 在提交時(shí)將所有的數(shù)據(jù)修改信息抽取出來(lái)組裝成可用于提交的格式。

    可見如果使用一個(gè)離散的Grid控件來(lái)制作這個(gè)界面,我們還必須要做不少工作。如果我們能夠選擇一個(gè)數(shù)據(jù)模型驅(qū)動(dòng)型的開發(fā)框架,上面提到的很多功能框架中往往已經(jīng)具備。開發(fā)人員要做的往往只是聲明好一個(gè)數(shù)據(jù)模型然后把它跟Grid關(guān)聯(lián)起來(lái)。如果您以前使用過VB或Delphi這一類開發(fā)功能,應(yīng)該不難想像這個(gè)過程。

    場(chǎng)景2:想像一個(gè)用戶信息的錄入界面,如下圖。使用者需要輸入用戶的身份證,由于什么證的號(hào)碼中包含了很多信息,系統(tǒng)完全有可能從其中解析出出生日期和性別這樣的信息。因此為了方便錄入,我們可以讓表單中的出生日期和性別這兩個(gè)欄位支持自動(dòng)填入缺省值的功能,只要用戶錄入了身份證號(hào)碼,就可以馬上自動(dòng)填充上述兩個(gè)欄位。

    o_user_form1.png
    ?
    在基于離散控件的編程方式中,我們需要知道身份證、出生日期、性別這三個(gè)編輯框的id,并針對(duì)他們進(jìn)行編程。其代碼形式可能如下:

    var?id? = ?inputId.getValue();? // ?獲得身份證號(hào)碼
    ?? // ?對(duì)身份證進(jìn)行解析
    inputBrithday.setValue(brithday);? // ?為出生日期設(shè)置缺省值
    radioGroupSex.setValue(sex);? // ?為性別設(shè)置缺省值

    在基于數(shù)據(jù)模型驅(qū)動(dòng)型框架的編程方式中,我們并不需要關(guān)注界面上擺放了什么控件,只需要知道關(guān)注如何操作數(shù)據(jù)模型對(duì)象。其代碼形式可能如下:

    var?id? = ?dmUser.getValue( " id " );? // ?從數(shù)據(jù)模型(dmUser)中提取身份證號(hào)碼
    ?? // ?對(duì)身份證進(jìn)行解析
    dmUser.setValue( " birthday " ,?brithday);? // ?為出生日期設(shè)置缺省值
    dmUser.setValue( " sex " ,?sex);? // ?為性別設(shè)置缺省值

    可見在這種開發(fā)模式中我們的代碼幾乎完全針對(duì)數(shù)據(jù)模型展開,當(dāng)我們?yōu)閐mUser中的brithday和sex賦值后,相應(yīng)的數(shù)據(jù)敏感控件會(huì)立刻自動(dòng)顯示出這些的數(shù)據(jù)。這樣的編程模式可以讓代碼有高度的一致性,當(dāng)我們制作復(fù)雜的用戶界面時(shí),可以不需要記住諸多的控件id。
    進(jìn)一步假設(shè)。如果用戶有一天覺得這樣的界面并不方便對(duì)多筆數(shù)據(jù)進(jìn)行方便的維護(hù),而要求對(duì)界面進(jìn)行如下調(diào)整。在刪除原先的表單,利用一個(gè)Grid控件來(lái)對(duì)用戶信息進(jìn)行維護(hù)。
    o_user_form2.png
    如果我們的編程方式是基于離散控件的,那么我們不可避免的要對(duì)先前編寫那段代碼做一些調(diào)整了。我需要將那段代碼移植到表格當(dāng)中。
    但是如果我們的編程方式是基于數(shù)據(jù)模型驅(qū)動(dòng)型框架的,那么我們要做的只是將界面上的表單刪掉,然后在放置一個(gè)與現(xiàn)有數(shù)據(jù)模型綁定的Grid控件。至于那段代碼,它完全不需要做任何變動(dòng)。

    綜上可見,在MIS類Web應(yīng)用的表現(xiàn)層開發(fā)方面。數(shù)據(jù)模型驅(qū)動(dòng)型的開發(fā)框架可以為開發(fā)人員帶來(lái)更多的實(shí)惠。不知道隨著時(shí)間的推移這一類的開發(fā)框架會(huì)不會(huì)豐富起來(lái)?

  • posted @ 2006-09-03 00:26 BennyBao 閱讀(2227) | 評(píng)論 (9)編輯 收藏

    2006年8月30日

    本文著重討論的是具有AJAX特征的WEB應(yīng)用表現(xiàn)層的設(shè)計(jì)模式,特別是如何設(shè)計(jì)表現(xiàn)層中展現(xiàn)數(shù)據(jù)的管理模式。同時(shí)本文假設(shè)應(yīng)用的用戶界面是操作性和交互性相對(duì)較強(qiáng)的MIS類應(yīng)用,因此其中的部分觀點(diǎn)可能并不適合以內(nèi)容發(fā)布為主的互聯(lián)網(wǎng)應(yīng)用。

    被過度倚重的AJAX

    自打2005年初第一回聽說(shuō)AJAX以來(lái),這個(gè)名詞以飛快的速度傳播,走紅的速度勘比李宇春。AJAX即不是新技術(shù)也不是很復(fù)雜的技術(shù),它不過是基于WEB的RIA應(yīng)用的一個(gè)操作特性(或技術(shù)特性)而已。這一切的發(fā)生也許因?yàn)槭茿JAX出現(xiàn)的時(shí)機(jī),那正是用戶為了WEB應(yīng)用那令人不堪的操作性即將抓狂,程序員為了難以實(shí)現(xiàn)的頁(yè)面操作邏輯而即將崩潰之際。于是AJAX成了BS應(yīng)用的救命稻草。頹廢的人們看到了希望的曙光。

    不過以鄙人拙見,大家如此熱衷于討論AJAX似乎有點(diǎn)本末倒置了。AJAX本身并不能幫我們上面提到的問題。我們需要應(yīng)該一套完整的UI組件庫(kù),象VB,DELPHI、PB中的我們?cè)?jīng)用過的那種組件庫(kù),一套易于使用有能夠與各種開發(fā)模式的對(duì)接的組件庫(kù)。當(dāng)然最好是帶有AJAX特性的組件庫(kù)。但是現(xiàn)在我們好像還沒有得到一套令大家都滿意的組件庫(kù),于是我們?nèi)匀恢荒苡懻揂JAX聊以充饑。

    言歸正傳,要設(shè)計(jì)這樣的一套UI組件庫(kù)還有很多障礙需要逾越。

    1.?????? DHTML+JavaScript的組件開發(fā)可不像在CS中那樣簡(jiǎn)單。
    2.?????? 如何有效的管理展現(xiàn)數(shù)據(jù)。
    3.?????? 讓性能不在成為瓶頸。
    4.?????? 跨瀏覽器的兼容性。
    5.?????? 好用的設(shè)計(jì)工具。
    … … …

    瀏覽器端的MVC 將部分表現(xiàn)層邏輯推向前端

    在上面提到的幾個(gè)障礙當(dāng)中我感覺最少被大家提及的就是第二條。拜讀過dlee推薦的<Ajax in Action>,其中提到了在瀏覽器端應(yīng)用MVC。不過書中只提到了數(shù)據(jù)與展現(xiàn)的分離,卻并沒有提到如何有效的管理這些用于展現(xiàn)的數(shù)據(jù)。V自不必想,一定是指運(yùn)行于瀏覽器中的各種可視化的控件;M應(yīng)該是指用于展現(xiàn)的數(shù)據(jù);而C應(yīng)當(dāng)是指介于M和V之間的松耦合的關(guān)聯(lián)關(guān)系。我想“瀏覽器端應(yīng)用MVC”在其合理性上應(yīng)該能夠得到大家的共識(shí),如同我們討論Server端的MVC架構(gòu)模式時(shí)一樣,從M的設(shè)計(jì)開始是我個(gè)人的習(xí)慣思維,應(yīng)當(dāng)也是瀏覽器端MVC中的重中之重。首先設(shè)計(jì)出一個(gè)健壯的表現(xiàn)層中的數(shù)據(jù)管理模式將為后面的工作打下一個(gè)良好基礎(chǔ)。
    ?

    參考文檔 : [原創(chuàng)] Web表現(xiàn)層的Client端設(shè)計(jì)模式探討

    這里提到的表現(xiàn)層應(yīng)當(dāng)是指包含Server端的展現(xiàn)相關(guān)的邏輯以及瀏覽器中的邏輯。在傳統(tǒng)的開發(fā)方式中表現(xiàn)層邏輯往往只涉及到Server端,而到了Client端已完全變成了HTML+CSS或XML+XSLT毫無(wú)設(shè)計(jì)模式可言。筆者認(rèn)為隨著技術(shù)的發(fā)展和AJAX的推動(dòng),我們有必要將一部分表現(xiàn)層邏輯推向?yàn)g覽器已進(jìn)一步增強(qiáng)界面的交互能力。

    或許目前大家設(shè)計(jì)的WEB頁(yè)面還很少需要考慮對(duì)展現(xiàn)數(shù)據(jù)的管理。但是一旦有一天我們擁有了一套好用的UI組件庫(kù),那時(shí)我們?cè)O(shè)計(jì)的用戶交互界面的復(fù)雜度也就會(huì)突破目前我們習(xí)慣認(rèn)為的上限。想像一個(gè)稍微有點(diǎn)復(fù)雜的場(chǎng)景,如果我們擁有了一個(gè)像Excel一樣的可以對(duì)任意單元進(jìn)行實(shí)時(shí)編輯的Grid組件,用戶可以對(duì)其中的數(shù)據(jù)做任意的增刪改操作,那么我們就必須要考慮一下如何將用戶所填入的數(shù)據(jù)以合理有效的方式提交回Server端了。
    ?
    CS中的展現(xiàn)數(shù)據(jù)模型對(duì)象

    不過真的要來(lái)設(shè)計(jì)一種在表現(xiàn)層中的數(shù)據(jù)模型,還真是有點(diǎn)千頭萬(wàn)縷、無(wú)從下手。所以在具體考慮如何管理這些數(shù)據(jù)之前,我們先來(lái)看一看在傳統(tǒng)的CS應(yīng)用中數(shù)據(jù)是如何進(jìn)行管理的,有沒有什么可以借鑒的東西?不約而同的,在這些開發(fā)模式中都能找到一種專用的數(shù)據(jù)模型對(duì)象,在VB中它叫ADO.RecordSet、在Delphi中它叫TDataSet、在PB中它叫DataWindow。它們都有一些共同的特點(diǎn):

    1.?????? 表驅(qū)動(dòng)的結(jié)構(gòu), 具有當(dāng)前記錄的概念。
    表驅(qū)動(dòng)的設(shè)計(jì)模式是由關(guān)系型數(shù)據(jù)庫(kù)自然衍生過來(lái)的設(shè)計(jì)方式,這種設(shè)計(jì)非常有利于用戶對(duì)數(shù)據(jù)的瀏覽和編輯,也符合我們對(duì)同結(jié)構(gòu)批量數(shù)據(jù)進(jìn)行瀏覽和編輯的一般理解和習(xí)慣。
    o_grid.PNG

    2.?????? 控件可直接與數(shù)據(jù)模型進(jìn)行綁定。

    數(shù)據(jù)敏感控件與數(shù)據(jù)模型進(jìn)行綁定,并自動(dòng)的展示、修改或控制其中的數(shù)據(jù),這是CS中最常用的一種開發(fā)模式。其核心原理就是設(shè)計(jì)模式中的觀察者模式。數(shù)據(jù)模型是被觀察者,控件是觀察者。當(dāng)數(shù)據(jù)模型中的數(shù)據(jù)發(fā)生變化時(shí),會(huì)主動(dòng)的通知綁定的控件做相應(yīng)的刷新動(dòng)作以實(shí)時(shí)的體現(xiàn)最新的數(shù)據(jù)。對(duì)于支持?jǐn)?shù)據(jù)修改或控制操作(例如:翻動(dòng)記錄的操作)的控件,如果用戶利用其對(duì)綁定的數(shù)據(jù)模型中的數(shù)據(jù)或狀態(tài)做了改變,那么這種改變自然也會(huì)實(shí)現(xiàn)通知給所有其它相關(guān)的控件中。
    o_binding.png?

    但是在現(xiàn)在的
    Java BS
    應(yīng)用開發(fā)過程中我們往往比較少的用到。即使有絕大部分也只是只讀型的綁定。

    3.?????? 弱類型的數(shù)據(jù)管理方式及列描述對(duì)象。
    在上述CS應(yīng)用中,數(shù)據(jù)對(duì)象大都以類似Map的方式對(duì)數(shù)據(jù)進(jìn)行管理,而不是像我們?cè)贘ava中更經(jīng)常討論的VO、PO的數(shù)據(jù)描述方式。對(duì)弱類型的數(shù)據(jù)對(duì)象而言,真正的數(shù)據(jù)類型(相當(dāng)于VO中屬性的類型)是保存在一組列描述對(duì)象當(dāng)中的。
    在Java中我們習(xí)慣的讀取和設(shè)置屬性的方法往往是:
    employee.getName();?
    ?employee.isMarried();?
    ?…?…?…?
    ?employee.setName(“Henry”);?

    而在CS的開發(fā)的代碼中讀取和設(shè)置屬性的方法往往是(以ADO.RecordSet為例):
    ?dsEmployee(“name”);?
    ?dsEmployee(“married”);?
    ?…?…?…?
    ?dsEmployee(“name”)??
    = ??“Henry”;?

    4.?????? 都具有一定的數(shù)據(jù)校驗(yàn)功能及支持一些與展現(xiàn)相關(guān)的屬性。
    數(shù)據(jù)對(duì)象中的列描述對(duì)象在描述屬性名和數(shù)據(jù)類型的同時(shí),往往還包含了其它一些跟顯示和編輯有關(guān)的特性,例如:readOnly、format、validator等。以readOnly屬性為例,當(dāng)我們將數(shù)據(jù)模型中某個(gè)列的readOnly屬性設(shè)置為true后,所有與該列相關(guān)的數(shù)據(jù)敏感控件都將變成只讀的狀態(tài)。這樣的好處在于開發(fā)人員在編寫頁(yè)面邏輯時(shí)不必過多的考慮頁(yè)面上堆砌了那些元素,而之需要關(guān)注他要處理怎樣的數(shù)據(jù)操作邏輯,頁(yè)面上大部分的操作邏輯或顯示邏輯都將圍繞數(shù)據(jù)模型對(duì)象而展開。

    5.?????? 支持事件。它們都擁有類似beforeChange、afterChange、beforeDelete、afterDelete這樣的事件,以便于開發(fā)人員能夠利用這些事件提供一些簡(jiǎn)單的數(shù)據(jù)校驗(yàn)或操作邏輯。

    BS中的展現(xiàn)數(shù)據(jù)模型的初步設(shè)想

    CS下的這些數(shù)據(jù)模型對(duì)象在早些年都有著成功的實(shí)踐。試想,能不能把這種在CS下的表現(xiàn)層設(shè)計(jì)模式移植到BS的開發(fā)當(dāng)中呢?不過鑒于BS架構(gòu)更高的復(fù)雜的這個(gè)任務(wù)并不簡(jiǎn)單,按照我的設(shè)想經(jīng)過移植的系統(tǒng)架構(gòu)大致可能如下:
    o_arch1.png

    圖中數(shù)據(jù)模型對(duì)象被拆分成了兩個(gè)部分,即Server端的實(shí)例和Client端的實(shí)例。當(dāng)我們要將數(shù)據(jù)從Server端傳遞到Client端時(shí),系統(tǒng)首先應(yīng)在Server端構(gòu)建一個(gè)基于Java的數(shù)據(jù)模型,該數(shù)據(jù)模型對(duì)象的數(shù)據(jù)取自BO提供的VO。當(dāng)然,如果Server端原本使用了JSP+Bean的開發(fā)模式,數(shù)據(jù)模型對(duì)象也可能直接取自JDBC的ResultSet。而后數(shù)據(jù)模型對(duì)象將利用一套實(shí)現(xiàn)已封裝好的規(guī)則,將數(shù)據(jù)以XML等方式輸出到Client端。此時(shí)Client端的可視化控件就可以對(duì)數(shù)據(jù)進(jìn)行瀏覽和操作,如果用戶通過可視化控件對(duì)數(shù)據(jù)做了修改,這些臟數(shù)據(jù)也將暫時(shí)被緩存在Client端數(shù)據(jù)模型對(duì)象中,知道用戶最終點(diǎn)擊了提交按鈕,此系統(tǒng)再利用AJAX機(jī)制將數(shù)據(jù)同步回Server端并執(zhí)行進(jìn)一步的后臺(tái)處理。
    ?
    看起來(lái)我們好像已經(jīng)有了一個(gè)很好的開局!不過筆者認(rèn)為在BS架構(gòu)中完全照搬CS中的那套設(shè)計(jì)思路可能并不是最佳的方案。主要原因在CS中的這些數(shù)據(jù)模型都是按照表結(jié)構(gòu)驅(qū)動(dòng)的方式設(shè)計(jì)的,其基本思路類似關(guān)系型數(shù)據(jù)庫(kù)中的表。而我們?cè)贘2EE的設(shè)計(jì)模式中更常使用的卻是模型驅(qū)動(dòng)的設(shè)計(jì)方式。表結(jié)構(gòu)驅(qū)動(dòng)自認(rèn)有它的有點(diǎn),易于理解,方便使用。不過他也有一些致命的缺陷,特別是它不能很好的描述數(shù)據(jù)對(duì)象之間的關(guān)系,每當(dāng)我們?cè)噲D使用表驅(qū)動(dòng)的模型來(lái)描述遞歸,樹,主從關(guān)聯(lián)這樣數(shù)據(jù)關(guān)系,總是會(huì)感覺束手束腳。無(wú)疑,基于OO的對(duì)象模型的結(jié)構(gòu)是一種更好的數(shù)據(jù)描述方式,它往往能夠更加準(zhǔn)確的、真實(shí)的表達(dá)數(shù)據(jù)之間的關(guān)系。?

    (未完待續(xù)...)?
    ?

    posted @ 2006-08-30 01:55 BennyBao 閱讀(1908) | 評(píng)論 (3)編輯 收藏

    主站蜘蛛池模板: 亚洲毛片在线免费观看| 免费大片在线观看网站| 最近免费2019中文字幕大全| 成人免费乱码大片A毛片| 一级做a爱过程免费视| 免费手机在线看片| 美女裸体无遮挡免费视频网站| 国产精品亚洲片在线花蝴蝶| 在线播放亚洲精品| 视频免费1区二区三区| 一本一道dvd在线观看免费视频| 国产特黄特色的大片观看免费视频| 亚洲精品偷拍视频免费观看| 中文日本免费高清| 久草免费福利视频| 91精品啪在线观看国产线免费| 少妇人妻偷人精品免费视频| 1000部啪啪毛片免费看| 99久久国产热无码精品免费| 成人免费一级毛片在线播放视频| 成全视频免费高清| 免费jjzz在线播放国产| 国产成人亚洲综合| 亚洲av鲁丝一区二区三区| 亚洲国产日韩在线一区| 亚洲av中文无码字幕色不卡| 男性gay黄免费网站| a毛片免费观看完整| 亚洲成人在线免费观看| 在线免费观看一区二区三区| 午夜国产羞羞视频免费网站| 中文字幕亚洲综合久久菠萝蜜| 亚洲AV日韩精品久久久久| 91午夜精品亚洲一区二区三区| 亚洲精品成a人在线观看夫| 无码 免费 国产在线观看91| 免费高清国产视频| 黄页网站在线看免费| 国产jizzjizz视频全部免费| 国产精品亚洲A∨天堂不卡| 亚洲人成电影院在线观看|