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

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

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

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

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

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

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

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

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

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

    ? http://partech.blogdriver.com/partech/1217744.html
    ? partech基于AspectJ對于AOP的深入應用作了一些有益的探索。ORM的價值之一正在于通過ORM引擎對于對象上的局部操作作出持久化詮釋(參見 面向對象之形式系統 )。在partech的方案中,對象刪除操作(destroy)的引入顯得有些勉強:因為我們需要標記一個刪除的時刻,所以調用了一次空的destroy()方法。但是如果在事件驅動的應用場景中,調用時刻唾手可得,這樣的問題便很少出現了。
    ? 我個人所關心的方向主要是框架層面上對于AOP概念的應用。在Witrix平臺的BizFlow方案中,借助于框架技術的支撐,我們甚至連new和set 調用都不需要,例如在biz文件中只需要聲明相應的事件響應函數,框架負責生成界面從用戶處收集信息,負責創建對象,負責執行保存和刪除操作: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的實作中是實現為DaoWebAction的一個interceptor。

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

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

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

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

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


    ? 實現是一種具體的東西,對于同一種實現可以有不同層面的各異的詮釋,而每一種詮釋都可能對應于不同的概念體系。對于一種具體的技術實現,總有人爭論說這樣這樣一下,不是也可以做到什么什么效果嗎。但這只是實現上在某種程度上可以達到目標,并不意味著該實現基于的概念體系自身直接體現了我們所需要的結構。這就如同我們可以用匯編實現一切,但并不意味著匯編語言本身的結構包含了所有高級程序結構一樣。同樣,說到一種失敗的技術的時候,也需要區分清楚問題是出在實現細節上還是對應的概念體系上。

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

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

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

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

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

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

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

    僅列出標題
    共18頁: First 上一頁 3 4 5 6 7 8 9 10 11 下一頁 Last 
    主站蜘蛛池模板: 亚洲国产一区视频| 麻豆成人精品国产免费| 久久乐国产精品亚洲综合| 亚洲av无码兔费综合| 巨胸喷奶水视频www网免费| 亚洲人成小说网站色| 成年在线观看免费人视频草莓| 亚洲大片免费观看| 免费大片黄在线观看yw| 亚洲日韩国产精品乱-久| 好男人看视频免费2019中文 | 免费人成网上在线观看| 成人伊人亚洲人综合网站222| eeuss影院ss奇兵免费com| 亚洲日韩国产二区无码| CAOPORM国产精品视频免费| 国产综合亚洲专区在线| 亚洲人成www在线播放| 四虎影视大全免费入口| 免费在线观看自拍性爱视频| 国产亚洲精品无码拍拍拍色欲 | 日韩电影免费在线观看网址| 亚洲国产综合精品中文字幕 | 亚洲最新视频在线观看| 免费A级毛片无码免费视| 欧美亚洲国产SUV| 亚洲成Av人片乱码色午夜| 很黄很黄的网站免费的| 精品国产亚洲第一区二区三区 | 成年人免费的视频| 亚洲AV无码一区二区三区电影| 久久夜色精品国产亚洲av| 久艹视频在线免费观看| 国产亚洲色婷婷久久99精品91| 久久国产乱子伦精品免费强| 亚洲xxxxxx| 亚洲中文字幕无码久久综合网| **实干一级毛片aa免费| 人妻巨大乳hd免费看| 亚洲精品影院久久久久久| 免费欧洲美女牲交视频|