|
http://www.bstek.com/
???
上海銳道的Dorado框架號稱是一個基于構件技術的、面向B/S和多層架構體系的web應用開發平臺,
其前身稱為Extra。從具體功能來看,如果將其看作是一個全功能的web應用開發平臺, 那它現在的功能集顯得就太單薄了一些,
其主要部分還是提供了一些前臺的界面控件, 其他如web框架部分,很像是struts的一個簡化版,沒有什么特異之處。 ??? Dorado的技術特點是大量采用ajax技術來實現前臺控件. 其前后臺交互采用了自定義的基于xml格式的rpc方式, 而數據綁定使用了xml數據島,例如 ??? <xml id="__datasetEmployee" > ??? <records> ??? <record isCurrent="true"? state="none" > ??? <new>,~73~73~73~73~73,~68~68,~44~31~32,true,true,295113600000,2034.0,,</new> ??? </record> ??? </xml> ??? record內部使用的是Dorado私有的編碼/解碼規則, 大概是為了壓縮數據量吧. ???
從Dorado目前提供的界面來看還是比較豐富的,基本滿足了一般信息系統開發的需求, 但是其可擴展性似乎并不是很好.
它雖然號稱是組件式開發,但是其前臺和后臺引擎似乎都沒有提供完善的組件模型支持, 只是實現了一些既定的界面組件而已. ??? 1. 其前臺的js函數中存在著大量針對數據類型的switch語句,似乎其所能夠支持的控件類型已經內置在前臺引擎中, 如果我們要增加一種新的界面組件大概需要在各處修改引擎代碼, 缺乏一種抽象機制. ???
2. 后臺ViewModel模型似乎是想構造出一個Component架構來, 但這個模型目前看起來明顯沒有Echo2這樣的組件模型精致,
似乎缺乏一種一致的組件重組機制.? Dorado的ViewModel是有狀態的, 通過RPC機制,
它實際上可以獨立于系統web層與前臺控件交互. ??? 3.
Dataset是Dorado中最重要的數據供體接口, 從它所提供的方法 getField,deleteRecord,
insertRecord, movePrev, moveNext, getPageSize等可以看出,
這明顯是綁定到了可分頁表格的數據模型上. 實際上整個系統設計似乎都隱含假定了一個Table模型, 例如Validator接口中具有一個函數
ViewField getField(), 這里明確假定了validate只能針對單個字段進行, 而不是屬于某個整體組件的. ??? 4. Dorado中所有組件的界面代碼生成都是以程序方式進行的, 沒有模板機制. 因而增加新的控件的實現時, 需要在后臺通過java代碼輸出一部分界面, 在前臺通過js腳本動態更新界面, 工作量相當大. ??? 5. Dorado中界面輸出應該是通過Outputter接口來進行 ????? public interface Outputter{ ??????? public String getStartOutput(HttpServletRequest req, Object o)throws Exception; ??????? public String getEndOutput(HttpServletRequest req, Object o) throws Exception; ????? } ?????
這里一方面與web層形成了綁定,另一方面它必須在內部完整的生成界面代碼之后一次性傳入response, 這無疑加重了后臺的內存壓力.
輸出分成了StartOutput和EndOutput大概是為了支持布局組件等容器類組件, 相當于是組件內部可以有一個洞, 這與Jsp
Tag模型是匹配的, 但是這種方式很難以高效率實現界面上的結構融合. ??? 7. Dorado似乎沒有直接提供組件的再封裝機制, 在現有組件中作局部修正往往需要通過代碼方式來進行.例如表格中的性別字段需要顯示圖片而不是文字, 則需要在Column的onRefresh事件中寫入下代碼, ??????????? if (record.getValue("sex")){ ??????? cell.innerHTML = "<img src='images/man.gif'>"; ??????? } ??????? else{ ??????? cell.innerHTML = "<img src='images/woman.gif'>"; ??????? } ??? 這明顯已經不是可配置的內容了. 如果我所需要增加的代碼是一個復雜的組件, 這里就很難進行處理了. ??? 6. Dorado的技術綁定在了IE瀏覽器上, 無法兼容其它瀏覽器, 這有些偏離目前的標準化方向.
???
目前的快速開發平臺的一個共同特點是集中在單表的CRUD(Create Read Update Delete)上,
可以快速完成單表或主從表的增刪改查. 這本也是正確方向,畢竟目前系統開發中的大量工作都是重復性的簡單勞動,
但是一般系統設計中為了支持單表操作而在建模的時候引入了對表格模型過強的依賴,? 大大降低了系統的可擴展性.
另外現在一般web組件框架的設計往往是模仿桌面開發領域的組件模式, 希望提供完全黑箱式的組件調用方式, 這其實是放棄了web開發的優勢.?
實際上借助于xml格式的規范性和簡單性, 我們完全可以提供更加強大的結構組件, 并把組件封裝的能力開放給普通程序員.
??? http://www.ezone.com.cn ???
同方這個公司在我的印象中更像是個系統集成商,在軟件方面沒有什么獨特之處。不知道是否是待遇問題,我也未聽說同方旗下招攬過什么軟件高手。同方最近兩年
在軟件平臺方面花了一些氣力,據說有70多個人,干了一兩年,將同方以前的項目進行提煉,開發了ezOne平臺。現在同方各個事業部開發新項目的時候好像
要求使用該平臺,不過可能是涉及到總部和各個部門分錢的問題,下面的人未必有很大的應用積極性。
???
同方的特點是做過大量項目,行業經驗多,所以ezOne中提供了很多行業組件。ezOne的一個核心部分是portal服務器,是基于Apache項目組
的Jetspeed修改而來,應該是符合JSR168標準的,所強調的概念也正是應用集成。以前掃過一眼ezOne的代碼,感覺質量一般,性能可能會有一
些問題,但編碼還算工整。同方握有大量國家資源,應該不至于成為平臺產品開發商,開發平臺的目的大概還是降低自身開發的難度。其產品傾向于符合標準,中規
中矩,大概很難有什么創新之處。ezOne中很多基礎組件都是獨立開發的,例如存儲層,沒有使用hibernate等開源軟件。
?? http://www.kenoah.com
??
前兩天和科諾的研發經理聊了一會,也簡單看了一下他們的演示。因為比較匆忙,沒有談到什么實質性的內容,只是有一個粗淺的印象。科諾目前的發展重點還是國
外的外包業務,其網站上相關介紹材料很少,不過據說今年將投入較大的資源在國內公司建設和市場開拓上。
???
科諾產品的特點是代碼生成。經過可視化配置之后,可以根據模板生成jsp源代碼,程序員可以基于這些代碼進行修改。據說遵守一定的規則之后,自動生成的代
碼與手寫代碼是相互隔離的,自動生成的代碼可以無限多次生成而不影響手寫代碼質量,但我未看到演示。科諾生成的頁面只支持IE,
不支持Firefox等瀏覽器。大概是因為其從事的主要是國外外包業務,其界面的美觀程度一般。雖然可以修改頁面模板來改變界面風格,但從我實際看到的模
板代碼而言,重新寫一套并不太容易。
???
科諾產品的功能大概是可以完成單表或者主從表的增刪改查,并配合一個或者多個業務流程。其工作流引擎據說是符合WFMC規范的,但從實際操作上看,似乎不
是一個通用的工作流引擎。至少給我演示的時候,工作流步驟的每一步,actor所能采取的操作是固定的,如退回,通過等,似乎是為審批定制的。
???
與普元EOS相比,科諾在功能上還是要弱不少。在開發工具上,也顯得要簡單許多。與普元EOS類似的是,科諾的產品似乎也只是利用工具根據現成的模板制造
固定模式的代碼,在設計思想方面并沒有什么本質性的突破,與其宣傳的組件思想相差甚遠。如果要超越自動生成的代碼作一些事情,這些平臺都無法提供什么有力
的支持。科諾所謂的業務組件似乎就是對table的描述,其設計工具不算太好,至少我沒有找到一個匯總視圖讓我可以看到所有已經配置的字段屬性。在設置復
雜字段或者匯總字段方面,科諾的產品也有很多限制,不太靈活。在前臺框架方面,科諾寫了一個類似于struts的框架,其他就乏善可承了。流程方面的設置
被稱為所謂的流程組件,運行時可以通過一個js庫在界面上進行展現。不同的業務組件應該可以對應到同一流程組件,這大概就是科諾所謂的組件重用了吧。開發
工程文件以xml格式進行存儲,看了一眼,相當復雜,竟然還和SOAP有關系,不知道他們為什么這么設計(符合標準?)。
??? 在科諾的另外一個印象是,公司里有不少女性程序員在干活。看來至少他們的產品可以由初級程序員掌握并滿足美國外包開發的需求。
?? 前兩天一位普元的朋友衣風 http://blog.sina.com.cn/u/1495516693在我的blog上留言,談到對數據總線的不同看法. 我本人并未使用過普元EOS,所做的判斷只是基于我個人膚淺的第一印象, 很有可能是不準確的. 不過, 目前我仍然堅持自己對于普元EOS的看法,呵呵.
?? ?
??? 1. EOS產生的xml描述文件中的大量條目都是EOS自身的結構要求,而與實際業務無關,即EOS描述文件中的有效信息量密度很低.
??? 衣風認為條目并不是EOS自身的結構要求,而是業務對象的結構描述.
這里我的看法是業務對象應該盡量通過領域(Domain)語言來描述, 領域信息的外在表象應該盡量是卷縮的,而不是展開的,
應該盡量是抽象的而不是實現細節層面上的.例如:
??? <function class="test.MyFunctionProvider">
??????? <args>
??????????? <arg>
??????????????? <name>argA</name>
??????????????? <value>3</value>
??????????? </arg>
??????? </args>
??? </function>
??? 以上信息可以描述一個方法調用, 這里的function, args, arg, name,
value等標簽的設置都是解析器為了理解該調用的語義而規定的結構元素,這些元素并不屬于函數本身.
例如我們可以規定如下的調用格式來簡化描述文件而不損失信息,
??? <function class="test.MyFunctionProvider">
??????? <arg name="argA">3</arg>
??? </function>
??? 而在我們的工作流引擎中, 業務操作的調用以封裝后的形式出現
??? <BusinessA:DoWorkA argA="3"/>
??? 通過標簽封裝之后, 我們在調用的時候所需要提供的信息是最小化的, 每一個涉及到的元素都是有著業務含義的,
而將解析器本身的結構要求隱蔽在封裝的標簽定義中.此后我們如果更換了實現,而業務需求不變, 則我們的調用處是不會受到影響的.
??? 現在基于xml語法的文件格式很多, 我們的工作流引擎也采用了xml描述. 但是我們的一個基本觀點是,
xml配置文件解析器不應該直接理解文件中所有的標簽, 即它只需要理解自身的結構元素, 而為引入Domain知識保留余地.
???
??? 2. 普元EOS中的結構似乎很難進行有效的擴展。而所謂的xml總線技術更加劇了這一點
???
衣風認為"正是將XML作為數據傳遞的總線,才使應用在數據層次上具有了較強的擴展能力"。從面向對象的觀點看,
程序中普適性的基本基元是數據與行為的集合體, 而程序模塊之間的交互也絕不僅僅是通過數據來進行, 而是往往呈現出一種數據與行為的交織狀況.
普元的模型應該包含了大量發生緊密關聯的局部元素, 它們應該處在同一進程(狀態)空間中, 直接訪問對象應該是最簡單,最經濟,
最完備的信息傳遞方式,
而"xml節點的表達能力遠遠超越了普通的數據類型,但充其量也不過是對現有數據的規整的樹形表示,并不具有動態計算能力(甚至是最簡單的lazy
evaluation)". 實際上對于所謂的總線, 最簡單的模型是一個可以動態管理的變量集合, 那么一個Map就足夠了.
在集合中我們可以保存各種對象, 比如xml節點, 但是又不限于xml節點. 從建模的角度上說,
把xml節點定義為一級集合元素我認為是不合適的. 通過對象的成員函數, 我們在對象圖中可以包含大量的動態計算信息, 例如
???? obj.getSomeCalculatedAttribute().getLazyLoadValue()
??? 這些動態語義在純數據含義的xml總線技術中不知道如何表達.
??? 對象圖表達數據關聯的能力也強于樹形結構的xml節點, 例如 obj.getRefObj().getRefObj() == obj, 不知道這樣的關聯在普元EOS的數據總線中如何表達.
??? 在并發訪問中如果需要同步, 對于對象, 我們可以使用synchronized機制, 但是對于xml節點不知道如何才能有通用的處理方式.?
???? http://www.primeton.com/
??? 普
元軟件公司是國內專業的中間件提供商,從國家得到了不少投資,做出來的東西也是相當的龐大。最近普元EOS的宣傳和發展的勢頭都很盛。其宣傳材料中屢次提
到“軟件的涅磐“這一用語,這明顯是一種危言聳聽之舉,當然這在業內也不算什么新鮮的事情。按照EOS的宣傳,"以圖形化的構件組裝方式“畫”出來的軟件
無論從結構上、形式上還是開發過程上都堪稱簡捷而美的軟件"。這一提法倒是別開生面。圖形化與簡潔,與美竟然還存在著這樣必然的聯系,實在是一種創舉。
????
從普元公開的資料來看,EOS的一個鮮明特征是全面基于xml描述,即所謂的xml數據總線。表面上看起來,xml結構內置于系統內核中似乎很時尚,但實
際上,EOS產生的xml描述文件中的大量條目都是EOS自身的結構要求,而與實際業務無關,即EOS描述文件中的有效信息量密度很低。這是一個危險的信
號。EOS的xml描述本身可以看作是一種完全新的編程語言,但這個語言似乎沒有什么抽象能力和組合能力,對于關聯的表達能力也很弱(到處都是數字
id)。如果直接手工編寫,那是一件要死人的事情。只有通過集成開發環境的可視化界面,EOS才呈現出可理解的一面。
????
EOS的概念與Language
Workbench是不同的,其中的結構似乎很難進行有效的擴展。而所謂的xml總線技術更加劇了這一點。xml數據總線其實與面向過程編程類似,只是過
程變成了service,數據變成了xml節點而已。對象與簡單數據結構在結構表達上的本質差異就在于對象通過成員函數可以封裝動態結構。雖然xml節點
的表達能力遠遠超越了普通的數據類型,但充其量也不過是對現有數據的規整的樹形表示,并不具有動態計算能力(甚至是最簡單的lazy
evaluation)。喪失了動態計算能力,就意味著我們很難在系統中動態引入結構,程序中所操縱的結構都需要事前定義出來,這將極大的限制系統的可擴
展性。另一方面,xml節點受限于自身格式,其描述關聯的能力也要弱于java對象結構本身。對象通過引用訪問相關對象,其隱含意義是對象處于同一地址
(狀態)空間中,可以非常自然的保證對象的唯一性并實現同步訪問。在跨越狀態空間的邊界時,xml表示是有意義的,因為我們需要把所有的結構都暴露出來并
加以描述(外在化)。而在狀態空間內部,我們需要更加緊致有效的表述方式。
???? 在具體的實現中,
EOS暴露給程序員的xml操縱API相當的原始,使用起來很繁瑣。在前臺展示頁面中,如果不使用EOS的界面組件,提取數據本身就是一種不小的困難。
EOS的前臺展示組件與后臺的結合也比較弱,后臺改變之后,缺乏有效的手段來檢測并保證前后臺結構的同步性。所謂的前臺構件層似乎只是提供了一些幫助函數
和功能固化的組件,并沒有提供什么有效的利于結構抽象和結構重組的機制。
???? 整個EOS的構架看起來很象是一個monster, 我很難想象它的各個部分如何才能獨立的,深入的發展下去。
? 在采用AJAX技術的應用中, 常見的是兩種架構設計, 一種是采用RPC(Remote Procedure Call)方案,
后臺應用直接將java對象包裝為service接口, 在js對外暴露(java對象完全不知道web層),
在js中通過類似函數調用的方式訪問后臺服務.而另外一種方案是在后臺維持一個前臺DOM節點的映象,觸發前臺事件之后, 前臺引擎自動截獲該事件,
并翻譯為對后臺事件監聽器的調用, 將請求提交到后臺, 后臺程序處理請求之后更新后臺DOM節點, 然后將頁面變更部分傳回前臺頁面.
這兩種方案一種是傾向于在js中提供自我封閉的程序模型(對遠程服務的調用體現為對一個js函數的調用),
一種是傾向于在后臺提供封閉的程序模型(對前臺頁面的更新體現為對一個后臺java對象的屬性和結構的改變).
這兩種方案的共同之處在于它們都試圖在一定程度上屏蔽前后臺程序的交互細節, 而提供一種統一的程序模型.
? 但是我們需要記住軟件設計的第一要義在于系統的分解,
而Browser和Server之間客觀存在的http信道是天然存在的一種分界線. 任何強迫我們忘記B/S之間的界限的技術都是需要謹慎對待的.
例如控制后臺對象的權限問題, 很多RPC方案限制了應用程序對于web接入層的直接接觸, 而只能通過AOP(Aspect Oriented
Programming)技術來動態織入權限控制代碼. 在實際使用中,
這種方式往往因為service接口函數的多樣化而造成配置上的繁瑣.? 而在我們的體系架構中,
系統邊界劃分在web訪問層上(而不是java service層), 借助于web訪問協議自身的一致性和透明性, 我們只需要如下實現
?? Object invokeWebEvent(){??? ???
???? return new ActionMethodInvocation(getWebObject(), getObjectEvent(), getInterceptors()).proceed();
?? }
就為所有WebObject加入interceptor堆棧, 完全不需要AOP的動態織入技術.
? 在witrix平臺的設計中, 因為大量采用pull方案, 我們對于前后臺交互方式采取的是完全開放的態度,
前后臺的交互接口完全定義在web訪問層上(即前臺程序直接訪問一個url獲取數據), 盡量避免將系統架構的限制引入到應用程序設計中來. 確實,
Browser和Server之間的原始交互方式是受限制的, 狹窄的, 但是從系統設計的角度上說,
這正是異構系統集成和進行系統核心控制的最好場所, 任何試圖獨占該連接信道并在層層封裝之后提供更加豐富的訪問語義的努力在我看來都是可疑的.
?
1. 對象的一個特性是局域化。每一個對象函數(非靜態函數)都是在對象的上下文中調用的,因而隱含假設了一定的環境信息,這些信息以封裝的形式被使用。 ?? 一個具體的體現是函數的命名,如果沒有對象,我們必須給函數進行全局命名,例如 find_friends, find_users, find_departments, 而在對象的環境下,我們可以抽象出一個采用局域化命名的接口 IQueriable.find(),實現系統的深度分解。 ?? 在對象成員函數的內部,我們通過統一預定的名字(this指針)來訪問對象環境中的變量。而在 jsplet web框架中的action和前臺jsp中,我們通過thisObj變量來訪問后臺邏輯對象的上下文,而不需要知道對象的具體名稱 (objectName)。
2. 對象的另一個特性是靜態化。我們從面向過程走向面向對象時,我們思維中的圖像出現了一個重大的變化:在面向過程的程序中,我們想象中存在的是一個個動態的處理過程,它們在時間軸上按照一定的順序依次執行。而在面向對象的圖景中,我們考慮的主要是一個靜態化的世界,系統分解為對象,而對象是同時存在于我們的思維中的。這里一個重要的技術手段就是成員函數。例如我們編寫一個成員函數getChildren(), 這個函數的語義是返回一個數據變量,概念上它是靜態的,但其內部實現其實可能是很復雜的,非常的動態化:可能需要查詢數據庫,可能需要校驗權限等等。 理想的情況下,我們可以利用成員函數封裝可以實現對象圖的遍歷。例如? x.getParent().getChilldren(), 在微軟的COM模型或者Sun的JavaBean標準下,我們可以寫成 x.parent.children。 特別注意這里的屬性語法原則上是與時間無關的,即在同一個時刻我們認為這些屬性同時存在著,是一個靜態的關系。而以下的調用出現了明確的步驟,因而明確引入了時間因素 ITree parent = node.getParent(); if(parent == null) ?? return null; List children = node.getChildren(); return children;
在witrix平臺的tpl模板引擎中使用的EL(Expressin Language)表達式語法會自動處理函數返回值為null的情況,因而維護了對象圖的語義,不需要中斷調用過程來進行異常處理,是簡化界面編程的一個重要方面。
這里順便提一句:人的思維是傾向于靜態化的,但現實世界卻是在不斷的變動中的。正所謂不變的只有變化。Von Neumann體系結構強迫我們在最細節處引入變化過程,很多時候是過分的負擔。我們需要的是識別出各種可以靜態描述的部分,集中精力于那些真正需要隨需應變的應用。
??? 關于DSL(Domain Specific Language)的確切含義紛爭很多,但是其核心觀念還是很明確的。DSL的關鍵是使用領域特定的概念,即它的概念系統中具有一些非General Purpose的基元。但是這種所謂非General Purpose僅是就詮釋層面而言,它所指的并不是DSL對應的形式系統。例如,在物理學中聲波(sonic wave)無疑是對原子系統的集團運動模式的一種抽象,基于wave概念的聲波方程可以看作是對應于原子系統的一個特定領域的DSL。從聲波系統是無法逆推出原子系統的所有行為的,但是理論上量子力學在形式上同樣可以采用wave描述,而它卻可以構成對原子系統的詮釋。 ??? ??? DSL因為基于Domain概念,可以提高理解性是應該的,但是現實中的大多數DSL仍然存在大量技術性的形式要求,它們是很難讓非計算機領域的業務人員掌握的。期待業務專家使用DSL在目前多半只是一種不切實際的幻想。但是如果認為DSL就是更甜的代碼也并不適當。搜索google的時候我們使用的查詢字符串也是一種domain specific language, 很多人都會使用""和-等語法結構。
??? DSL應該關注用的層面(what), 而不是how-to,how-to是DSL的實現問題。從what到how to是我們希望通過DSL解析器屏蔽起來的內容,而不是DSL本身需要表達的內容。
??? 目前的框架設計中,引入元數據(metadata)已經是必然的事情,jdk5.0的annotation機制也為metadata的物理駐留位置提供了新的選擇。常見的一些元數據設計方案中往往是元數據直接驅動系統的展現甚至運行過程(例如普元EOS),大有完全取代程序代碼的趨勢,這無疑是對元數據概念的一種濫用。一般在界面層所使用的元數據其實類似于某種新的界面描述語言,即某種特定目的的DSL(domain specific language). 但這種描述一般是不完備的, 一旦遇到擴展情況, 往往需要很多額外的工作。 ??? 實際上并不是所有信息都要在獨立的xml 中描述, 前臺模板頁面本身就可以是一種元數據, 前臺元素之間的關聯已經隱含表達了多種關系, 不需要把這些關聯再在額外的xml文件中重復.? 比如說一個數據集展現在頁面上的時候需要支持幾種操作,即對應的需要顯示幾個按鈕. 在witrix平臺的tpl模板中, 我們的調用方式大概如下 ??????? <ui:EditTable pager="${pager}" dsMeta="${dsMeta}"> ??????? <buttons> ????????? <ui:RemoveRowButton/> ????????? <ui:EditRowButton/> ??????? </buttons> ??????? </ui:EdiTable> ??? 操作集合這一信息僅在模板中表達一次.? 實際上很多時候, 不同的界面我們需要展示不同的操作集合, 它本身并不一定是數據集內在的性質. 數據集的屬性只能是支持全部操作的集合, 它并不需要直接對應到界面上. 對于多個界面我們需要盡量共用一個meta配置.
??? 在witrix平臺的元數據方案中,關鍵是采用pull mode, 由前臺模板系統驅動, 模板決定使用何種資源(包括元數據),而不是由元數據驅動整個系統的展現。當一個元數據條目不適用的時候我們可以忽略它,但是仍然可以使用元數據配置中的其他部分。這與我們的jsplet web框架的設計是一脈相承的。
??? 元數據的駐留形式本身也是很有意思的問題。假設現在我們需要描述如下信息:本字段采用input框顯示,它有一個參數value. 它的meta形式可以如下, ?????? <inputor type="TextInput"> ????????? <arg name="value" /> ?????? </inputor> ??? 我們也可以選擇如下形式 ?????? <inputor> ??????? <input type="text" value="${value}" /> ?????? </inputor> ??? 第二種方式的特殊之處是它選擇了與html規范本身兼容的表達形式,即寄生于html格式之中。這種設計的好處在于我們只需要一個通用的模板引擎,而不需要任何特定于該控件的解析器,就可以產生最終所需的文本輸出。這種元數據表達方式更重要的地方在于它是導向更高復雜性層次的自然途徑。例如我們現在需要一種更加復雜的自定義控件來顯示該字段,則 ?????? <inputor> ??????? <ui:DateInputor value="${value}" /> ?????? </inputor>
??? 在元數據的設計中,適可而止永遠都是我們需要銘記在心的核心原則。對元數據描述的范圍要適可而止,不要試圖包羅萬象。例如,在界面元數據的設計中不要對于數據供體有任何假定。一個前臺表格,無論它的數據是數據庫中的一組記錄, 還是通過pop3協議收取的一組信件,應該都不影響它對于meta的使用。元數據引擎所能夠直接理解的粒度也要適可而止。在witirx平臺的元數據方案中,viewer和inputor等配置段其實是由tpl模板引擎負責解析的,在DataSourceMeta的解析器并不能識別其中的細節,它也不需要識別其中的細節。
adun今天問我xslt到底有什么用。相對于其他技術,它有什么存在的必要性。
xslt的主要作用是對xml結構的轉換,即它是一種描述結構變換規則的語言。不過也可以將它與我們更熟悉的用于生成html(結構)的模板語言作一個對比。
1. 兩者都能直接生成xml格式的文本(結構)
2. 兩者都有循環和判斷等邏輯處理語句。
3. 模板語言可以通過EL表達式等語言取得源數據, xslt通過xpath語法取得源數據.
4. 模板語言通過自定義tag等機制實現分解和組合, xslt通過xsl:call-template等語法實現分解與組合.
tpl等模板語言直接操縱java中的對象, 體現的是圖(Graph)模型, 并通過對象函數封裝了部分動態性.
一般訪問的時候是通過短程關系逐級訪問,例如x.y.funcA().b。利用apache項目組的jxpath包,我們也可以使用類似于xpath的語
法在對象圖上進行全局訪問。
xslt使用嚴格定義的xpath語法訪問Tree結構,具有很強的數據操縱能力,例如我們可以通過//mynode等語法輕易的實現節點的聚合,構造出
新的結構。在一般xslt包的實現中,都提供了javascript擴展,可以使用javascript構造出的數據節點。
在tpl這樣的模板語言中java中的數據對象結構與tpl中的模板結構(處理規則的結構)是兩分的,而在xslt中輸入數據結構與xslt自身處理規則
的機構卻是統一的。實際上tpl這樣的模板語言主要是基于過程語義,即先做。。。,用到。。。,然后。。。,
而xslt對于輸入數據的結構具有明確的全局性假設,主要是一種轉換語義,即不論在什么情況下,只要遇到。。。,就做。。。。
在xslt中可以通過xpath語法指定處理規則針對數據(輸入結構)的的觸發條件,
而在tpl中只能通過<c:decorator>為tpl標簽指定轉換器,而無法針對數據指定處理規則。
在數據訪問模型這一方面,原則上說xslt與模板語言各有優勢。實際在用于html生成的過程中,xpath的全局訪問和匹配能力一般難以得到發揮,而
xml格式的限制又在一定程度上阻礙了使用靈活的數據供體,這方面模板語言有一定的優勢。但是xslt的約束更強也有本質性的好處,它使用xml數據并輸
出xml數據,維護了結構的同質性,便于管道操作。因為假設更明確,xslt對于xml格式的數據的操縱和封裝能力也要強于模板語言。例如它可以使用來為
節點追加屬性。
xslt在用于xhtml生成時的一個主要劣勢在于它是對變換規則的分解之后的描述,而我們所希望得到的是最終的結果,即這些規則綜合應用所生成的結果。
雖然xslt的語法是xml語言,與xhtml在語法格式上保持了一致性。但是在xslt中,xslt的標簽破壞了xhtml語義上的結構,使得目前無法
做到所見即所得。我們不得不在頭腦中運行xslt規則來想象最終的結果,這無疑是痛苦的。模板語言在這方面要輕松許多。
xslt的另一個問題是有時xml語法顯得過于冗長了。在操縱一些局部結構的時候,xml節點并不一定是合適的表達。例如
<xsl:value-of select="$x"/> 對比 ${x},
<xsl:call-template name="subrule">
<xsl:with-param name="argA"><xsl:value-of select="substring-after($path,'.')"/></xsl:with-param>
</xsl:call-template>
對比
<my:subrule argA="${path.substringAfter('.')}" />
在調用子模板方面,顯然xslt封裝的抽象層次也要弱于tpl模板語言。
xslt作為一種xml格式的結構變換語言,維護了xml世界的概念完整性,其意義無疑是重大的。但并不是所有時候xml都是最適的描述模型。我們最好還
是將它與其他技術結合使用。目前在witrx平臺中,我們對于xslt的使用主要是對tpl模板進行布局和過濾處理,即xslt用于對處理規則進行變換,
而將根據數據生成html這個最細致的工作留給過程處理能力和封裝能力更強的tpl模板語言。
|