posts - 176, comments - 240, trackbacks - 0, articles - 7

          ?????? 代碼生成現(xiàn)在已經(jīng)逐漸成為軟件開發(fā)中的一種標(biāo)準(zhǔn)技術(shù),在眾多的軟件領(lǐng)域都大大減輕了我們重復(fù)勞動(dòng)的工作量。程序中總是存在著這樣那樣的隱蔽的關(guān)聯(lián),它們無法在通用的程序語言框架下得到明確的表達(dá),代碼生成是我們突破既定的語言和框架限制的一種重要手段。但是代碼生成也存在著嚴(yán)重的弊病,一方面一般的程序語言在設(shè)計(jì)時(shí)沒有考慮到和代碼生成工具的相互配合,因此生成代碼是一次性的,代碼生成工具無法以增量的方式修正已經(jīng)生成的代碼。另一方面,程序的結(jié)構(gòu)是復(fù)雜的,代碼生成工具一般基于某種簡(jiǎn)化的通用的程序模型(例如CRUD)來產(chǎn)生代碼,它無法承載完整的程序結(jié)構(gòu),因此代碼生成后手工調(diào)整量仍然很大,有的時(shí)候甚至為了微小的界面調(diào)整,將生成的代碼修改的面目全非,無法發(fā)揮代碼生成的優(yōu)勢(shì)。
          ?????? 在witrix平臺(tái)中主要使用meta generation而不是code generation. meta實(shí)際上是對(duì)一種定制模型(model)的描述,它在某種意義上可以看作是完整程序的簡(jiǎn)化版本,但它本身并不意味著最終的程序結(jié)構(gòu)。在witrix平臺(tái)各處meta的使用都是可選的, 特別是在多變的前臺(tái)頁面,我們可以選擇根據(jù)meta描述自動(dòng)生成界面,也可以選擇通過<df:Field name="字段名"/>來引用單個(gè)字段的meta數(shù)據(jù). 在witrix平臺(tái)中, meta可以看作是系統(tǒng)運(yùn)行的內(nèi)核, 它通過syncWithModel等屬性與設(shè)計(jì)工具發(fā)生耦合. 當(dāng)設(shè)計(jì)模型修改之后, 這種修改能夠以增量的形式通過可控制(修改)的信道傳播到系統(tǒng)各處.

          posted @ 2007-01-21 18:11 canonical 閱讀(2531) | 評(píng)論 (5)編輯 收藏

          ??? 目前的AOP(Aspect Oriented Programming)技術(shù)雖然以動(dòng)態(tài)代碼織入為核心,但是這種織入仍然是一次性的。一般在系統(tǒng)構(gòu)造的時(shí)候(例如ClassLoader裝載Class的時(shí)候)實(shí)現(xiàn)類和成員函數(shù)的增強(qiáng)。此后在運(yùn)行時(shí)刻代碼結(jié)構(gòu)是固定的而不再發(fā)生變化。但是在真正的業(yè)務(wù)處理過程中,我們?cè)诓煌膽?yīng)用場(chǎng)景下可能要求織入不同的Aspect。例如基本的權(quán)限Aspect, 如果在不同的應(yīng)用場(chǎng)景有不同的權(quán)限設(shè)定,則我們顯然希望進(jìn)入一個(gè)確定的操作場(chǎng)景的時(shí)候就指定一整套的權(quán)限策略,而不是在每個(gè)函數(shù)調(diào)用時(shí)刻寫上一大堆的if/else(這種分離的條件判斷正是AOP試圖從結(jié)構(gòu)上消除的)。
          ??? 為了實(shí)現(xiàn)AOP的二級(jí)動(dòng)態(tài)化,我們首先需要約定一些公共標(biāo)記(坐標(biāo)),便于在標(biāo)記處插入Aspect Container, 其次我們需要在系統(tǒng)中建立一個(gè)隱蔽的信道,可以通過該信道傳遞一個(gè)標(biāo)志符(Aspect的id),用于在各處選擇特定的Aspect. 建立這種動(dòng)態(tài)特性之后,我們就可以據(jù)此發(fā)展出Aspect組的概念,并實(shí)現(xiàn)Aspect組之間的繼承關(guān)系等高階結(jié)構(gòu),從而最大限度的限制程序結(jié)構(gòu)的分散化。
          ??? Witrix平臺(tái)的BizFlow設(shè)計(jì)在概念上可以看作是AOP的一種二級(jí)動(dòng)態(tài)化織入設(shè)計(jì),它通過$bizId這一特定參數(shù)來選擇織入的Biz。一個(gè)BizFlow對(duì)象是一組Biz(Aspect)的集合, BizFlow可以通過extends機(jī)制實(shí)現(xiàn)集合之間的合并等(BizFlow實(shí)現(xiàn)的合并策略其實(shí)是非常復(fù)雜的)。一個(gè)簡(jiǎn)單的應(yīng)用就是流程支持,例如一個(gè)普通的實(shí)體對(duì)象對(duì)應(yīng)的bizflow只需要加上如下代碼即可獲得流程相關(guān)的代碼,前臺(tái)菜單等。
          ? <bizflow extends="testflow.biz.xml">

          posted @ 2007-01-14 17:04 canonical 閱讀(1101) | 評(píng)論 (2)編輯 收藏

          ? 幾年前Michael Atiyah受邀在浙江大學(xué)做過一個(gè)講演,題目是Mathematics in the 20th Century,
          http://www.cnw3.org/smth/Mathematics/historiesandmathmaticians/goodessays/00000035.htm, 在其中他回顧了二十世紀(jì)的主要的數(shù)學(xué)發(fā)展。被他列在第一條的進(jìn)展就是From Local To Global. 在傳統(tǒng)上,數(shù)學(xué)的主要研究對(duì)象是一些得到顯性表達(dá)的局部公式,而拓?fù)鋵W(xué)對(duì)于整體性的“不變性質(zhì)”的研究最終將我們對(duì)于數(shù)學(xué)和物理學(xué)的理解推進(jìn)到一個(gè)新的高度。我想在其他領(lǐng)域中,這種認(rèn)識(shí)上的深化也將是一個(gè)必然的過程。隨著AOP這種大范圍結(jié)構(gòu)操縱技術(shù)的興起,軟件技術(shù)是否也發(fā)展到了可以對(duì)程序的整體結(jié)構(gòu)做一些反思的時(shí)候?
          ? 面向?qū)ο笥惺裁从茫克窃诟鱾€(gè)層面都可以使用的一種描述工具。從一些早期的文獻(xiàn)我們可以看出一些端倪,一種整體性的均一的概念是我們迫切需要的。對(duì)象可以構(gòu)成對(duì)象,Everything is Object. 只是因?yàn)槲覀儗?duì)這些太熟悉以致于在今天看來顯得有些陳腐。很多人現(xiàn)在津津樂道于CoC(Convention over Configuration)作為一種局部程序設(shè)計(jì)技巧所帶來的可以少些一些代碼的經(jīng)濟(jì)性,卻沒有看到CoC更大的作用在于在大范圍內(nèi)保持了程序結(jié)構(gòu)的一致性,使得某些輕靈的設(shè)計(jì)可以在框架層面得以展現(xiàn)。目前的框架技術(shù)更多的是在各個(gè)層面各自為戰(zhàn),如何將同樣的信息從局部傳播到整體是一個(gè)耐人尋味的問題。
          ?? 傳統(tǒng)上的程序世界缺乏一些具體的技術(shù)手段使得我們可以方便的觸及到程序的整體結(jié)構(gòu)部分,這些整體性的關(guān)聯(lián)更多的是存在于文檔中,存在于我們的思想中,存在于程序表達(dá)世界之外。而AOP技術(shù)從本質(zhì)上說也只是方便在各個(gè)層面實(shí)現(xiàn)某種局域化的抽象。 當(dāng)某些東西被拘束在某個(gè)具體的孤立的點(diǎn)中的時(shí)候,我們似乎就可以松一口氣了。但是在程序中仍然存在著大量"弱"的關(guān)聯(lián),它們很難被清晰的局域化。模型(Model)和Meta必然在程序構(gòu)建的過程中扮演愈加重要的角色。AOP只是一種技術(shù)手段,它必須和更加寬廣的框架技術(shù)和模型構(gòu)建技術(shù)結(jié)合才能起到最大的作用。???

          posted @ 2007-01-03 16:10 canonical 閱讀(846) | 評(píng)論 (1)編輯 收藏

          ? http://partech.blogdriver.com/partech/1217744.html
          ? partech基于AspectJ對(duì)于AOP的深入應(yīng)用作了一些有益的探索。ORM的價(jià)值之一正在于通過ORM引擎對(duì)于對(duì)象上的局部操作作出持久化詮釋(參見 面向?qū)ο笾问较到y(tǒng) )。在partech的方案中,對(duì)象刪除操作(destroy)的引入顯得有些勉強(qiáng):因?yàn)槲覀冃枰獦?biāo)記一個(gè)刪除的時(shí)刻,所以調(diào)用了一次空的destroy()方法。但是如果在事件驅(qū)動(dòng)的應(yīng)用場(chǎng)景中,調(diào)用時(shí)刻唾手可得,這樣的問題便很少出現(xiàn)了。
          ? 我個(gè)人所關(guān)心的方向主要是框架層面上對(duì)于AOP概念的應(yīng)用。在Witrix平臺(tái)的BizFlow方案中,借助于框架技術(shù)的支撐,我們甚至連new和set 調(diào)用都不需要,例如在biz文件中只需要聲明相應(yīng)的事件響應(yīng)函數(shù),框架負(fù)責(zé)生成界面從用戶處收集信息,負(fù)責(zé)創(chuàng)建對(duì)象,負(fù)責(zé)執(zhí)行保存和刪除操作:no new ,no set, no save, no load, no remove.
          java 代碼
          ? <action id="Add-default">
          ??? <source>
          ?????? do anything on entity to be added
          ??? </source>
          ? </action>
          ? <action id="Remove-default">
          ? </action>
          ? <action id="ViewDetail-default">
          ??? <source>
          ????? entity is accessible here
          ??? </source>
          ? </action>

          BizFlow的實(shí)作中是實(shí)現(xiàn)為DaoWebAction的一個(gè)interceptor。

          posted @ 2006-12-05 00:40 canonical 閱讀(1376) | 評(píng)論 (0)編輯 收藏

          ??? 面向?qū)ο蠹夹g(shù)中最重要的概念是什么?在面向?qū)ο罄碚摪l(fā)展的初期,幾乎所有的正統(tǒng)聲音都在鼓吹繼承(inheritance)概念,言必稱虛擬函數(shù)和多態(tài)性。但是依賴?yán)^承這種推導(dǎo)關(guān)系來構(gòu)建龐大系統(tǒng)的弊病在實(shí)踐中逐漸暴露出來,隨著組件(Component)技術(shù)的發(fā)展,所謂的封裝概念逐漸被推崇為面向?qū)ο笏枷氲木A。在此過程中,接口(interface)概念作為系統(tǒng)細(xì)粒度正交分解的手段也逐漸發(fā)展起來。在軟件系統(tǒng)結(jié)構(gòu)的日益復(fù)雜化的今天,封裝概念開始成為了質(zhì)疑的對(duì)象。是否與一個(gè)概念相關(guān)的所有實(shí)現(xiàn)都要統(tǒng)一封裝到一個(gè)具體的對(duì)象中?伴隨著Java,C#等語言進(jìn)入主流程序界的AOP(Aspect Oriented Programming)給出了不同的答案。在AOP的環(huán)境中,Object不再是牢不可破的黑箱模型,而是成為了外部嵌入的方面(Aspect)的容器。在應(yīng)用AOP這種大范圍結(jié)構(gòu)操縱技術(shù)的對(duì)象構(gòu)成體系中,封裝不再是問題的核心,我們所關(guān)注的是面向?qū)ο蠹夹g(shù)中更為本原的概念:this指針。
          ??? 在純粹的技術(shù)層面上,面向?qū)ο笏傅氖紫仁且唤M相關(guān)性的聚集:它指代了一組相關(guān)的數(shù)據(jù)和函數(shù)。為了配合這種相關(guān)性的表達(dá),在調(diào)用形式上發(fā)生了重大變化。從全局函數(shù)的調(diào)用方式轉(zhuǎn)變到了基于對(duì)象指針的調(diào)用方式:
          ??? func(this) ==> this.func();
          ??? 這里關(guān)鍵性的區(qū)別在于從全局性的,絕對(duì)的表達(dá)方式轉(zhuǎn)變?yōu)榫钟蚧模鄬?duì)的表達(dá)方式。this指針限定了一個(gè)知識(shí)域(domain),調(diào)用對(duì)象函數(shù)是在限定知識(shí)域的情況下提供一些相對(duì)信息,即調(diào)用的時(shí)候只需要相對(duì)知識(shí)。例如現(xiàn)在界面上有兩個(gè)按鈕,其中一個(gè)跳轉(zhuǎn)到編輯頁面,另外一個(gè)跳轉(zhuǎn)到列表頁面。為了表達(dá)出這兩個(gè)按鈕的不同,我們只需要提供非常少的信息。
          ??? 〈input value="編輯" onclick="stdPage.gotoEditPage('${pkValue}')" /〉
          ??? 〈input value="列表" onclick="stdPage.gotoListPage()" /〉
          所有的公共知識(shí)集中在stdPage這個(gè)對(duì)象指針中。所謂組件技術(shù),關(guān)鍵點(diǎn)也正在于這里。基于一個(gè)給定的組件對(duì)象,我們只需要知道如何調(diào)用它的函數(shù),就可以使系統(tǒng)呈現(xiàn)不同的表現(xiàn)形態(tài)。我們所關(guān)心的并不是如何構(gòu)造這個(gè)知識(shí)域(對(duì)象本身),而是如何使用相對(duì)知識(shí)構(gòu)造出我們最終所需的系統(tǒng)。封裝性使我們擺脫了對(duì)系統(tǒng)全局知識(shí)的依賴。
          ?? 從形式主義的角度上說,任何一種調(diào)用方式都只是一種表達(dá),它的具體含義需要一個(gè)詮釋的步驟。基于對(duì)象指針的調(diào)用形式直接導(dǎo)向了詮釋的多樣化:我們只需要替換this指針,就可以改變整個(gè)一組調(diào)用的具體含義。傳統(tǒng)上,對(duì)象指針是封閉的,指代的是具體的實(shí)現(xiàn),所有的信息都必須來自于對(duì)象指針本身,這造成詮釋的局限性。但是在AOP的支持下,詮釋可以不僅僅是源于其內(nèi)的,而且可以是發(fā)自其外的。例如基于POJO的ORM框架中,我們只需要純粹的基于對(duì)象自身的知識(shí)對(duì)其進(jìn)行操作,ORM引擎通過enhance POJO對(duì)象來重新將其詮釋為對(duì)數(shù)據(jù)庫的持久化操作。

          posted @ 2006-12-04 00:15 canonical 閱讀(1395) | 評(píng)論 (2)編輯 收藏

          ? 隨著IoC(Inversion of Control)容器的流行,AOP(Apsect Oriented Programming)似乎逐漸成為了主流技術(shù)的一部分,但是除了Transaction, Lazy Load, Cache, Log等少量樣板應(yīng)用之外,AOP的技術(shù)價(jià)值究竟何在? 它能否在廣泛的領(lǐng)域發(fā)揮作用? 為什么考慮到傳統(tǒng)領(lǐng)域之外的應(yīng)用時(shí),我們的想象力是如此的貧乏?回答這些問題需要對(duì)AOP的技術(shù)實(shí)質(zhì)作詳細(xì)的審視.
          ? 傳統(tǒng)上, 程序的結(jié)構(gòu)是靜態(tài)的. 定義了一個(gè)類, 它的成員變量和成員函數(shù)就是確定的了,定義了一個(gè)函數(shù), 它的具體實(shí)現(xiàn)也是確定的. 傳統(tǒng)程序設(shè)計(jì)主要定義了一些固化的規(guī)則來規(guī)范這些確定性組分的組合關(guān)系,如類繼承體系所表達(dá)的推理關(guān)系. 而AOP是一種動(dòng)態(tài)代碼織入技術(shù), 抽象的說, 一維拓?fù)涞幕驹厥蔷€段與邊, 而AOP通過mixin, interceptor等機(jī)制可以自由的實(shí)現(xiàn)這些元素之間的自由組合而不拘泥于預(yù)制的規(guī)則. AOP就像是一把鋒利的砍刀, 我們用它從最終所期望的程序結(jié)構(gòu)中隨意的砍下一部分來, 起個(gè)名字,就叫Aspect吧. 實(shí)際上AOP技術(shù)本身并沒有限定程序中哪些部分可以作為Aspect, 這種技術(shù)本身并不保證你可以抽象得出真正有價(jià)值的Aspect, 它只是一種純粹的程序結(jié)構(gòu)操縱技術(shù)而已.
          ? AOP技術(shù)有兩個(gè)主要組成部分: 定位技術(shù)和定位后的組裝技術(shù). 定位技術(shù)是AOP所宣稱的無侵入性的關(guān)鍵所在. 如果我們使用interface等機(jī)制來實(shí)現(xiàn)功能,則要在程序各處寫下調(diào)用語句:
          ??? interfaceA.methodA();
          ??? ...
          ??? interfaceA.methodB();
          這可以看作是一種占位技術(shù). 定位技術(shù)則一般不需要預(yù)先在程序中寫下什么調(diào)用語句, 根據(jù)外部的某些定位規(guī)則,我們可以在基礎(chǔ)的程序結(jié)構(gòu)中搜索到適當(dāng)?shù)奈恢? 在理論上說,這種定位方式非常靈活, 即可以是非常精準(zhǔn)的定位到某個(gè)點(diǎn),也可以是非常寬泛的定位到一組切入點(diǎn). 但是, 這里的一個(gè)隱含假設(shè)是程序基礎(chǔ)結(jié)構(gòu)本身已經(jīng)具備了良好的,具有某種均一性的坐標(biāo)系, 只有這樣我們才能夠擁有定位所需的基本信息. 想象一下,如果整個(gè)程序只有一個(gè)函數(shù), 所有功能的實(shí)現(xiàn)通過傳入不同的參數(shù)值來實(shí)現(xiàn), 則這樣的程序結(jié)構(gòu)中是沒有什么可定位性而言的. 早期AOP定位所能夠依賴的坐標(biāo)只有類,方法名稱, 方法參數(shù)類型等, 而這些信息本身又具有自己的業(yè)務(wù)含義,隨著業(yè)務(wù)的發(fā)展,它們本身的名稱也可能需要不斷的變化,這直接造成AOP所依賴的坐標(biāo)系的不穩(wěn)定性.今天還有效的位置描述, 明天也許就突然包括了某些不應(yīng)該包含進(jìn)來的程序位置或者排除了某些應(yīng)在其中的位置. 在JDK5.0中補(bǔ)充的annotation機(jī)制為程序補(bǔ)充了新的坐標(biāo)維度, 基于它無疑可以建立更加靈活而且專用的坐標(biāo)系統(tǒng), 它對(duì)于AOP的價(jià)值必然會(huì)逐漸被發(fā)掘出來. 在javascript這樣的動(dòng)態(tài)語言中,雖然它們內(nèi)置的動(dòng)態(tài)性直接支持程序結(jié)構(gòu)的動(dòng)態(tài)組裝, 但是在定位支持方面卻要比java這樣的語言弱上很多, 在其上建立AOP應(yīng)用未見得比java更具優(yōu)勢(shì). 從另外一個(gè)角度上說, 定位方式也并不總比占位方式優(yōu)越. 我們需要牢牢記住"一次描述"的優(yōu)勢(shì)在于可以"多次應(yīng)用". 有的時(shí)候我們用很多唇舌去描述一個(gè)物品看起來像什么什么樣, 有多么大, 多么重, 還不如直接拿給人看, 說:嘿, 就是這個(gè)(this).同樣在程序中, 占位方式可能更加直接簡(jiǎn)單,甚至因?yàn)榇a明確寫在那里,概念也更加明確,更加完整. 此外, 在一些特定的程序結(jié)構(gòu)中, 需要定位的位置大大減少, 我們也不需要復(fù)雜的定位機(jī)制. 例如在witrix的jsplet框架中, 因?yàn)樗厥獾囊?guī)范一致性造成程序的處理點(diǎn)只有一個(gè), 應(yīng)用AOP是一個(gè)非常直接的過程.
          ? AOP的第二個(gè)組成部分是組裝技術(shù). 程序結(jié)構(gòu)的組裝在java中早已不是什么技術(shù)難點(diǎn), 很多人干起這活來都是輕車熟路. 但是組裝不僅僅意味著程序結(jié)構(gòu)的融合, 它同時(shí)意味著程序運(yùn)行時(shí)狀態(tài)空間的融合. 在AOP的基礎(chǔ)模型中, 在切入點(diǎn)可以得到的變量有this指針,調(diào)用函數(shù)對(duì)象和傳入?yún)?shù)列表, 但是AOP本身并沒有進(jìn)一步規(guī)范化這些變量的具體形式, 因此在一般情況下, 這些變量對(duì)于interceptor來說是只讀的, interceptor之間也無法通過這些變量交換信息并協(xié)同運(yùn)行. 這實(shí)際上意味著在切點(diǎn)處inteceptor的狀態(tài)空間是極端受限的. 而當(dāng)一個(gè)切面橫跨很多切點(diǎn)的時(shí)候, 在interceptor中一般只能對(duì)切點(diǎn)處狀態(tài)空間的共性部分進(jìn)行操作, 這進(jìn)一步限制了interceptor的能力.實(shí)際上目前AOP的主要應(yīng)用都是無狀態(tài)的,或者是基于全局狀態(tài)空間的(例如transaction interceptor只訪問線程上下文), 這反映出對(duì)于AOP的primitive方式的應(yīng)用的一種局限性. 在witrix平臺(tái)的BizFlow設(shè)計(jì)中,通過對(duì)狀態(tài)空間明確建模, 實(shí)現(xiàn)了基于AOP概念的一種新的應(yīng)用方式.
          ? AOP需要對(duì)程序坐標(biāo)空間和狀態(tài)空間的良好規(guī)劃, 才能保證無縫的織入, 保證信息交互通道的通暢.應(yīng)用AOP所指的不僅僅是配置使用現(xiàn)有的AOP實(shí)現(xiàn), 基于這種程序結(jié)構(gòu)操控技術(shù)我們所需要做的抽象工作還很多.
          ?

          posted @ 2006-11-19 19:59 canonical 閱讀(2742) | 評(píng)論 (6)編輯 收藏


          ? 實(shí)現(xiàn)是一種具體的東西,對(duì)于同一種實(shí)現(xiàn)可以有不同層面的各異的詮釋,而每一種詮釋都可能對(duì)應(yīng)于不同的概念體系。對(duì)于一種具體的技術(shù)實(shí)現(xiàn),總有人爭(zhēng)論說這樣這樣一下,不是也可以做到什么什么效果嗎。但這只是實(shí)現(xiàn)上在某種程度上可以達(dá)到目標(biāo),并不意味著該實(shí)現(xiàn)基于的概念體系自身直接體現(xiàn)了我們所需要的結(jié)構(gòu)。這就如同我們可以用匯編實(shí)現(xiàn)一切,但并不意味著匯編語言本身的結(jié)構(gòu)包含了所有高級(jí)程序結(jié)構(gòu)一樣。同樣,說到一種失敗的技術(shù)的時(shí)候,也需要區(qū)分清楚問題是出在實(shí)現(xiàn)細(xì)節(jié)上還是對(duì)應(yīng)的概念體系上。

          posted @ 2006-11-12 14:04 canonical 閱讀(378) | 評(píng)論 (0)編輯 收藏

          ? 按照Tim Berners-Lee的原始設(shè)想,互聯(lián)網(wǎng)的核心概念是超鏈接(hyperlink), 每一個(gè)可訪問的資源都具有自己的URI(Universal Resource Identifier), 我們通過唯一的url可以訪問到這些資源。從概念上說,每一個(gè)頁面可以由一個(gè)兩元組[title, url]來進(jìn)行描述,title是url顯示在界面上時(shí)的可讀表述。在這一描述下,我們可以建立基本的頁面瀏覽模型,包括瀏覽歷史模型:我們可以把瀏覽過的頁面保存在瀏覽歷史列表中,通過選擇歷史列表中的條目實(shí)現(xiàn)頁面跳轉(zhuǎn)。但是隨著網(wǎng)頁的動(dòng)態(tài)性不斷增加,頁面的資源語義逐漸喪失,url所對(duì)應(yīng)的不再是一種靜態(tài)的資源表述概念,而逐漸演變成為一種動(dòng)態(tài)的訪問函數(shù). 例如
          ? /view.jsp?objectName=MyObj&objectEvent=ViewDetail&id=1
          ? 一個(gè)url模式所對(duì)應(yīng)的網(wǎng)頁個(gè)數(shù)在理論上可能是無限多的. 從單一數(shù)據(jù)值到函數(shù)是系統(tǒng)復(fù)雜性本質(zhì)上的一種飛躍. 為了不致在這種無限的世界中迷失方向,我們顯然需要對(duì)于瀏覽過程進(jìn)行更加有效的組織,建立更加有約束性的導(dǎo)航模型. 一種常見的導(dǎo)航模式是在頁面的上方顯示一條線性的導(dǎo)航路徑, 與瀏覽歷史模型不同的是, 頁面轉(zhuǎn)換時(shí)不是
          ? list > view item 1 ==>? list > view item 1 > view item 2
          而是
          ?? list > view item1 ==> list > view item2
          ? 為了支持導(dǎo)航路徑, 最簡(jiǎn)單的方式是將頁面模型擴(kuò)展為三元組[id, title, urlExpr], 其中urlExpr是動(dòng)態(tài)表達(dá)式, 而id是固定的值. 例如 id=view, urlExpr=/view.jsp?objectName=MyObj&objectEvent=ViewDetail&id=${id}
          ? 導(dǎo)航路徑的變化規(guī)則為navHistory.removeAfter(newPage.id).add(newPage)
          ? 為了進(jìn)一步約化導(dǎo)航路徑, 可以將頁面模型擴(kuò)展為
          ? [id, title, urlExpr, group, before, beforeGroup],
          ? 其中g(shù)roup定義了頁面的分組, 同組的頁面在導(dǎo)航路徑中相互替代, 而before和beforeGroup定義了頁面在導(dǎo)航路徑中的相對(duì)順序. 例如對(duì)于
          ? [id='list' beforeGroup="detail"] [id='view' group='detail'] [id='update' group='detail']
          在頁面轉(zhuǎn)換時(shí), 導(dǎo)航路徑變化不是
          ? list > view item1 ==> list > view item1 > update item1
          而是
          ? list > view item1 ==> list > update item1
          ? 在以上的頁面模型中, 每一個(gè)id對(duì)應(yīng)的是一個(gè)不同的頁面模板(頁面布局), 但是有時(shí)我們也需要在同一個(gè)頁面布局中瀏覽無限分級(jí)的欄目, 此時(shí)可以將頁面模型擴(kuò)展為
          ? [id, title, urlExpr, group, before, beforeGroup, path]
          ?
          ? 將以上的導(dǎo)航模型應(yīng)用于一般的web應(yīng)用時(shí)還需要克服一個(gè)小小的困難: 動(dòng)態(tài)url的副作用. 例如/update.do?id=1&value=2這種具有動(dòng)作語義的url訪問直接破壞了頁面的瀏覽模型,例如現(xiàn)在我們不再能夠按F5鍵刷新頁面,不能通過window.location=window.location調(diào)用來刷新頁面,在頁面回退時(shí)我們也將遇到種種困難。為了防止重復(fù)提交,一種常見的設(shè)計(jì)模式是分離POST和GET方法,即通過Form POST向上提交數(shù)據(jù),處理完畢后通過redirect指令通知瀏覽器再次發(fā)起GET方法得到新的頁面.具體做法如下??
          ??? /redirect_after_action.do?id=1&value=2
          ? 在執(zhí)行完action之后, 服務(wù)器調(diào)用response.sendRedirect(get_url), 通知前臺(tái)瀏覽器使用新的url重新取回頁面. 這樣最終我們可以確保所有頁面都是可以通過url直接訪問的(沒有隱含的post參數(shù)),而且是可以重復(fù)訪問的(無副作用因而可以反復(fù)刷新)!
          ? 另一種方式是使用ajax方式提交更新請(qǐng)求,當(dāng)ajax訪問成功后, 在回調(diào)函數(shù)中進(jìn)行頁面跳轉(zhuǎn).例如:
          ? new js.Ajax().setObjectName('Test')
          ????? .setObjectEvent('Update').addForm(myForm)
          ????? .callRemote(function(returnValue){
          ??????? window.location = '/view.jsp?id=1';
          ????? })??
          這里我們也可以根據(jù)returnValue的不同選擇跳轉(zhuǎn)到不同頁面.
          ? 在Witrix平臺(tái)中, 基于Jsplet框架我們定義了PageFlow對(duì)象, 它將可配置的導(dǎo)航模型引入到任意頁面的組織過程中. 在跳轉(zhuǎn)到一個(gè)新的頁面的時(shí)候, 訪問url如下:
          ? /pageflow.jsp?objectName=MyNav&objectEvent=NavToPage&_pageId=view&id=3
          在重新訪問歷史頁面的時(shí)候,只需要
          ?/pageflow.jsp?objectName=MyNav&objectEvent=NavToHistoryPage&_pageId=view
          ? 基于jsplet框架的對(duì)象化特性,MyNav對(duì)象在session中保持了flow的所有狀態(tài)變量,不需要任何框架上特殊的支持。我們可以在任意頁面跳出pageflow, 并在任何時(shí)刻選擇跳回pageflow, 這些動(dòng)作不會(huì)影響到flow對(duì)象的狀態(tài)。而通過objectScope的設(shè)置我們可以精細(xì)的控制flow對(duì)象的生命周期。同時(shí)基于對(duì)象化設(shè)置,訪問頁面時(shí)我們只需要資源的相對(duì)名稱(relative identifier), 例如對(duì)于各種不同的flow, 頁面id都可以叫做view, 通過_pageId=view來訪問。
          ? Apache軟件基金會(huì)旗下有一個(gè)beehive項(xiàng)目, http://beehive.apache.org/docs/1.0m1/pageflow/pageflow_overview.html, 其中也定義了所謂pageflow的概念, 這是始創(chuàng)于BEA的一項(xiàng)技術(shù). 但是與Witrix Page Flow不同的是, Beehive Page Flow的核心概念仍然是從struts引申而出的action的概念,所謂的flow是action的連接,而不是通過資源id之間的連接。雖然beeive宣稱支持各種對(duì)象injection, 并且管理了flow對(duì)象的生命周期,但是它并沒有規(guī)范出this指針這一面向?qū)ο笞钪匾母拍钪弧itrix Page Flow關(guān)注的重點(diǎn)是已存在的頁面之間的有效組織, 它所描述的是某種具有靜態(tài)資源語義的頁面模板之間的關(guān)聯(lián), 這種關(guān)聯(lián)是較松散的,而不是通過action強(qiáng)關(guān)聯(lián)的. 實(shí)際上基于Ajax技術(shù)和jsplet框架的消息路由機(jī)制, 在每一個(gè)頁面上都可以進(jìn)行多種業(yè)務(wù)操作,甚至更換頁面,而不發(fā)生pageId的變動(dòng), 并不是所有的操作過程都需要在page flow描述中對(duì)外暴露。另外一個(gè)比較細(xì)節(jié)化的不同之處是Beehive使用Java Annotation, 而Witrix PageFlow使用xml描述文件, 并實(shí)現(xiàn)了pageflow的繼承和部分覆蓋等高級(jí)構(gòu)造方法. 使用xml描述文件的必要性在于需要復(fù)用WebAction, 支持復(fù)雜的變換操作, 并集成tpl模板引擎等. Annotation的方式看似簡(jiǎn)單,但這種簡(jiǎn)單性同時(shí)將系統(tǒng)中的所有組分綁定到了一起, 它也不允許復(fù)雜的變換操作的存在. 實(shí)際上Beehive的目標(biāo)并不是真正支持頁面編制(包括頁面上的頁面操作)和頁面組織的分離.

          posted @ 2006-11-05 20:35 canonical 閱讀(2317) | 評(píng)論 (7)編輯 收藏

          ? IoC(Inversion of Control)是一個(gè)很寬泛的概念,對(duì)于我們常說的IoC容器(如spring)所做的工作,一個(gè)更加準(zhǔn)確一些的說法是依賴注入(Dependency Injection), 即容器將一個(gè)對(duì)象所依賴的其他對(duì)象push到該對(duì)象中,而不是該對(duì)象從外界環(huán)境pull相關(guān)的依賴對(duì)象. 不過, 細(xì)究起來這種依賴注入仍然只是DI的一種特殊形式, 可以將它稱之為data dependency injection, 因?yàn)镮oC容器所許諾的是: "啊哈, 當(dāng)我們需要對(duì)象A的時(shí)候,它就在這兒". 雖然IoC容器管理的不僅僅是數(shù)據(jù),而是具有行為的對(duì)象,但是如果要讓這些行為具體發(fā)生, 我們?nèi)匀恍枰~外的調(diào)用步驟.
          ? 對(duì)于一個(gè)自動(dòng)觸發(fā)behaviour的系統(tǒng), 我們一般將之稱之為引擎(Engine). 例如工作流引擎在處理完本步驟的業(yè)務(wù)邏輯之后會(huì)自動(dòng)觸發(fā)流程流轉(zhuǎn)操作. 一個(gè)引擎對(duì)于我們的承諾是: "當(dāng)我們需要某個(gè)behaviour的時(shí)候, OK, 它會(huì)在適當(dāng)?shù)臅r(shí)候發(fā)生的". 對(duì)于一個(gè)軟件開發(fā)框架或者更宏大的軟件開發(fā)平臺(tái)而言, 如果我們以業(yè)務(wù)邏輯為主體來審視整個(gè)程序運(yùn)行過程, 則它們的核心價(jià)值也在于在適當(dāng)?shù)臅r(shí)候?qū)⑦m當(dāng)?shù)牟僮鱅nject到業(yè)務(wù)邏輯中. 對(duì)于目前所謂的軟件開發(fā)平臺(tái)而言, 除了工作流的內(nèi)容之外, 一個(gè)主要部分就是CRUD(Create/Read/Update/Delete) Ready. 一個(gè)開發(fā)平臺(tái)的優(yōu)劣往往直接體現(xiàn)在它在多大程度上能夠?qū)RUD操作剝離出主體程序邏輯, 這不僅僅涉及到數(shù)據(jù)庫存取操作, 同時(shí)還包含界面交互, 數(shù)據(jù)邏輯關(guān)聯(lián)等.
          ? 除了引擎,框架,平臺(tái)等應(yīng)用層面的實(shí)現(xiàn)之外, AOP(Aspect Oriented Programming)在語言層面為behaviour注入也提供了一種特定的實(shí)施手段. 在AOP的概念中, 往往作為切點(diǎn)的函數(shù)被認(rèn)為是基礎(chǔ)的部分, 而interceptor是在基礎(chǔ)藍(lán)圖上的一種擴(kuò)展. 這也體現(xiàn)在基礎(chǔ)函數(shù)定義了當(dāng)時(shí)執(zhí)行環(huán)境中可以訪問的狀態(tài)變量(參數(shù)/屬性),而interceptor則依附于pointcut處所能得到的狀態(tài)變量, 它本身一般并不維護(hù)獨(dú)立的狀態(tài)變量(不產(chǎn)生也不消滅狀態(tài)變量). 從數(shù)學(xué)上看, base function和interceptor之間構(gòu)成一種對(duì)偶(dual)關(guān)系, 當(dāng)我們的關(guān)注重點(diǎn)轉(zhuǎn)移到interceptor上來之后, 它本身也應(yīng)該具有完整的業(yè)務(wù)語義, 這需要對(duì)AOP的執(zhí)行過程做小小的偏置處理.
          ? 在witrix平臺(tái)的BizFlow設(shè)計(jì)中,BizFlow是通過類似AOP的方法作為CRUD操作的Filter實(shí)現(xiàn)的, 但是從bizflow本身的配置文件來看,它可以構(gòu)成一個(gè)完整的業(yè)務(wù)描述, 而CRUD成為某種自動(dòng)注入的behaviour.例如對(duì)于新增操作, BizFlow中的配置可以如下
          ? <action id="Add-default">
          ? </action>
          雖然沒有寫任何代碼, 新增操作(包括從request中讀取操作并做有效性校驗(yàn)等操作)是自動(dòng)進(jìn)行的. 我們也可以在新增前和新增后分別執(zhí)行一些操作
          ? <action id="Add-default">
          ??? <source>
          ????? some operation before add
          ????? <biz:Proceed/>
          ????? some operation after add
          ??? </source>
          ? </action>
          與AOP中的常見做法不同, 這里并沒有明確定義新增前和新增后這樣的切點(diǎn), 而只是定義了Add-default這樣一個(gè)action. 在BizAction的source段可以執(zhí)行任何tpl代碼, 而tpl代碼的執(zhí)行上下文可以看作一個(gè)Map, tpl代碼執(zhí)行過程中可以獲取變量, 也可以設(shè)置任意變量, 因而bizFlow擁有對(duì)于狀態(tài)空間的完全的控制權(quán).

          posted @ 2006-10-22 18:44 canonical 閱讀(1267) | 評(píng)論 (0)編輯 收藏

          ? 對(duì)于目前MDA(Model Driven Architecture)的理論和實(shí)現(xiàn),我一直持一種消極態(tài)度。以前和hotman_x的討論中,我也明確表述過對(duì)于MDA的看法。
          ? MDA:以有限搏無限 http://canonical.blogdriver.com/canonical/787637.html
          ? 圖形 vs. 文本 http://canonical.blogdriver.com/canonical/1090209.html
          ? 所謂的MDA一般總是從高層抽象模型出發(fā),希望通過預(yù)定的建模過程推導(dǎo)出底層的全部實(shí)現(xiàn)細(xì)節(jié)。但是implementation is also interpretation. 實(shí)現(xiàn)過程本身也是對(duì)高層模型的一種詮釋過程, 是一個(gè)逐步明晰并逐漸消除概念之間矛盾沖突的過程。從高層模型到底層實(shí)現(xiàn)并不是一個(gè)同構(gòu)(isomorphism)的過程,甚至一般情況下也不是同態(tài)(homomorphism)的。在概念模型到具體代碼實(shí)現(xiàn)的過程中,總是存在著需要不斷補(bǔ)充的細(xì)節(jié)。這些細(xì)節(jié)如何才能成為高層模型的一種自然的衍生部分是一個(gè)非常復(fù)雜的問題。如果考慮得太細(xì)(需要指定過多難以從整體上進(jìn)行控制的參數(shù)),似乎就會(huì)喪失高層模型的抽象性和概括性,而如果不深入到細(xì)節(jié),則難以平衡高層模型之間的互相沖突的屬性。隨著細(xì)節(jié)的不斷增加,試圖維持高層模型在各個(gè)層面的統(tǒng)一性無疑將變得異常困難。實(shí)際上在每一個(gè)抽象層面概念都可能出現(xiàn)重組和混合的情況,試圖統(tǒng)一建模在目前的技術(shù)水平下是不太現(xiàn)實(shí)的。
          ? MDA所需要解決的一個(gè)核心問題是維護(hù)模型的持續(xù)有效性, 即當(dāng)根據(jù)模型構(gòu)造出實(shí)際系統(tǒng)之后, 對(duì)模型的修改仍可以自動(dòng)反映到已實(shí)現(xiàn)的系統(tǒng)中, 而不是每次重新生成一個(gè)新的系統(tǒng). 或者說MDA應(yīng)當(dāng)如何支持實(shí)現(xiàn)層面的重構(gòu). 為了解決這個(gè)問題, 一般的實(shí)現(xiàn)策略是建立完整的程序模型, 提供一個(gè)強(qiáng)大的集成開發(fā)工具, 可以在一個(gè)特意構(gòu)造出的IDE環(huán)境中對(duì)模型進(jìn)行調(diào)試, 修正, 盡量避免程序員直接接觸實(shí)現(xiàn)代碼, 確保一切細(xì)節(jié)盡在單一開發(fā)工具(單一信息驅(qū)動(dòng)源)的掌握之中. 但是很顯然, 這樣一個(gè)大一統(tǒng)的開發(fā)工具在各個(gè)層面(如數(shù)據(jù)庫設(shè)計(jì), 表單設(shè)計(jì)等)都只能是專業(yè)工具的一個(gè)簡(jiǎn)化版. too simple, sometimes naive. 當(dāng)我們需要對(duì)程序有較深入的控制力的時(shí)候, 這些工具往往就很難起什么作用了, 甚至?xí)蔀槟撤N障礙.
          ? 在witrix平臺(tái)的設(shè)計(jì)中, 也有部分"MDA"的內(nèi)容. 只是我們的設(shè)計(jì)思想是Physical Model Driven(物理模型驅(qū)動(dòng)), 而不是Logical Model Driven(邏輯模型驅(qū)動(dòng)). 具體做法是
          1. 采用power designer建立數(shù)據(jù)庫物理模型(PDM 而不是 CDM), 然后根據(jù)一些命名約定和附加注釋(例如pdm中的package映射為java實(shí)體類的package, pdm的domain指定字段是否附件字段等)來標(biāo)注出物理元素的邏輯含義.
          2. 解析pdm文件, 生成hibernate映射文件(.hbm.xml), meta文件(.meta.xml), spring注冊(cè)文件(.action.xml)等
          3. 通過jboss的hibernate-tools工具生成java實(shí)體類.
          ???
          ? 根據(jù)自動(dòng)生成的配置文件, 可以直接完成對(duì)于數(shù)據(jù)庫的增刪改查操作, 包括維護(hù)一對(duì)多,多對(duì)多等關(guān)聯(lián)關(guān)系. 此后我們可以根據(jù)程序具體需求, 對(duì)生成的文件進(jìn)行修改. 通過一些程序設(shè)計(jì)技巧, 我們可以實(shí)現(xiàn)手工修改的代碼與工具自動(dòng)生成的代碼之間始終有明確的邊界, 從而可以做到pdm與代碼的自動(dòng)同步, 不需要手工進(jìn)行任何調(diào)整.
          ? 我們選擇從PDM出發(fā)的一個(gè)基本理由在于, 從高層模型向下, 路徑是不確定的,而從物理模型向上,路徑是確定的. 在pdm中我們需要做的不是補(bǔ)充細(xì)節(jié)(增加新息)而是標(biāo)注出已經(jīng)存在的邏輯概念。選擇PDM建模也集中體現(xiàn)了我所一直倡導(dǎo)的Partial Model的概念. PDM模型并不包含界面的具體展現(xiàn)方式, 也不包含更加復(fù)雜的業(yè)務(wù)處理過程, 它只是完整程序模型的一部分. 我們不試圖建立一種完全的模型,追求概念上的一種自我完備性, 而只是關(guān)注當(dāng)某些被共享的模型元素發(fā)生變化的時(shí)候, 這些變化如何以保真的方式傳播到系統(tǒng)各個(gè)角落. 實(shí)際上一旦獲得物理實(shí)現(xiàn),高層模型在某種意義上就變得不再那么重要了. 為了支持模型的局部修改, 我們只需要從物理模型中提取部分信息,而不需要恢復(fù)出一個(gè)完整的業(yè)務(wù)模型。我們不需要把一個(gè)高層概念在各個(gè)層面的表達(dá)都考慮清楚,我們只需要知道某一特定的物理模型應(yīng)該對(duì)應(yīng)的部分高層模型即可。
          ? 目前國(guó)內(nèi)一些軟件開發(fā)平臺(tái)也包含所謂MDA的部分, 例如浪潮Loushang MDA (www.loushang.com)號(hào)稱不需要寫一行代碼,定制出所需應(yīng)用系統(tǒng). 可從其技術(shù)白皮書來看, 它所謂的Model雖然是使用UML來建立, 但是大家似乎故意忘記了對(duì)象是成員變量+行為構(gòu)成,不包含行為模型的對(duì)象模型不過是數(shù)據(jù)模型的一種翻版而已. 從Loushang MDA的元模型對(duì)象的UML圖可以看出, MofTab, MofReference等固定了幾種界面顯示模式, 似乎其MDA只是針對(duì)既定場(chǎng)景應(yīng)用的一種預(yù)制代碼框架. 從我們的實(shí)踐來說, 數(shù)據(jù)模型驅(qū)動(dòng)的應(yīng)用并不需要限制在基礎(chǔ)數(shù)據(jù)對(duì)象維護(hù)這一非常特定的領(lǐng)域,而可以在通用應(yīng)用領(lǐng)域發(fā)揮作用。

          posted @ 2006-09-10 22:19 canonical 閱讀(1590) | 評(píng)論 (4)編輯 收藏

          僅列出標(biāo)題
          共18頁: First 上一頁 3 4 5 6 7 8 9 10 11 下一頁 Last 
          主站蜘蛛池模板: 闸北区| 汕头市| 通河县| 旬邑县| 广东省| 蒙阴县| 那曲县| 稷山县| 景洪市| 黄山市| 马龙县| 灵台县| 高台县| 阿克陶县| 汪清县| 集安市| 晋中市| 中卫市| 石泉县| 平乐县| 丘北县| 洪雅县| 马尔康县| 象山县| 乌鲁木齐县| 南平市| 巴里| 安康市| 邵阳市| 黔西县| 西宁市| 阳东县| 柘荣县| 古丈县| 鹰潭市| 琼中| 新和县| 上饶市| 正镶白旗| 六安市| 乌审旗|