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

            AOP(Apsect Oriented Programming)概念的正式出現也有一些時日了,但是它在程序構造過程中似乎仍未找到合適的切入點,一般系統的設計實現很少將AOP作為必要的技術元素。AOP作為一種普適的技術思想,它所代表的是程序結構空間中的定位和組裝技術。http://canonical.javaeye.com/blog/34941 AOP使我們可以通過非侵入性的方式動態修改“任意”已經構建好的程序,而不需要事前有大量的設計準備。原則上說,這種技術思想是可以在任何程序語言基礎上進行表達的,并不是只有java, C#這樣的面向對象語言才允許AOP操作. Witrix平臺中所應用的部分技術與AOP有些類似,只是大量的結構調整表現為xml生成和xml變換,在具體的使用方式上也有一些微妙的差異。http://canonical.javaeye.com/blog/126467

            相對于通用程序語言,xml語言其實是AOP技術的一個更加合適的形式載體。
          1. xml格式特殊的規范性確保了在最細的邏輯粒度上,程序結構也是可識別的,可操縱的(在這一點上非常類似于函數式語言)。而所有的命令式語言(imperative language)中,函數內部的結構都是很難采用統一方式進行描述和定位的。
             <ns1:loop>
               
          <rpt:Row/>
             
          </ns1:loop>

          2. xml節點的坐標可以采用xpath或者css選擇符等通用方式進行描述,而一般程序結構無法達到xml格式這樣的均一性,其中的坐標定位方式要復雜得多。
          3. xml節點上可以增加任意屬性,不同的屬性可以屬于不同的命名空間(namespace),這些屬性可以輔助AOP的定位機制。而一般程序語言中如果沒有Annotation機制, 則定位只能依賴于函數名和類名(函數參數只有類型沒有名稱),而類名和函數名隨時可能因為業務變化而調整(不是專為定位而存在), 由此構建的切點描述符是不穩定的。
           
          <ui:PageTable pager="${pager}" cache:timeout="1000" />
          4. xml節點的增刪改查顯然要比字節碼生成技術要簡單和直觀得多。
             

             AOP技術難以找到應用的一個重要原因在于很多人機械式的將它定位為一種橫切技術,認為它的價值完全在于某個確定的切面可以插入到多個不同的切點,實現系統的橫向分解。而在實際應用中,業務層面上很少具有可抽象的固定的共同性,我們所迫切需要的一般是對已有程序結構進行動態擴展的一種能力。橫切是AOP的一種特殊的應用,但不是它的全部。相對于繼承(inheritance)等依賴于概念詮釋的結構擴展機制,AOP所代表正是對程序結構空間進行任意操縱的一種能力。AOP可以為基礎結構增加功能,改變原有功能實現,也可以取消原有功能實現,它不需要把所有的擴展邏輯按照樹形結構進行組織,不要求在基礎結構中為擴展編寫特殊的代碼。這種自由的結構擴展能力在Witrix平臺中被發展為“實現業務代碼與平臺基礎架構之間的動態融合”。

             在Witrix平臺的實際應用中,AOP的切點匹配能力并不是十分重要。一般情況下我們主要通過整體結構規劃來確??刂泣c意義明確且相對集中,因此不需要額外通過切點匹配進行業務功能的再組織,不需要再次從雜亂的程序邏輯中重新發現特殊的控制點。例如在Witrix平臺的Jsplet框架中所有后臺事件響應都通過objectName和objectEvent參數觸發,在觸發后臺事件響應函數之前都會調用bizflow文件中的beforeAction段。
             在bizflow文件中,aop操作是明確指定到具體函數的,使用模糊匹配在一般情況下只會使問題變得不必要的復雜化。例如擴展actQuery函數
             <action id="aop-Query-default">
              
          <source>
                 通過自定義標簽抽象出多個Action之間的共用代碼
                
          <app:DoWorkA/>
              
          </source>
            
          </action>

             
             在Witrix平臺中結構組裝主要是通過自定義標簽庫和extends算子來實現,它們都依賴于xml格式的規范性。
          1. 通過在custom目錄下實現同名的自定義標簽,即可覆蓋Witrix平臺所提供的缺省標簽實現,這里所依賴的并不是復雜的匹配過程,而是自然直觀的映射過程。http://canonical.javaeye.com/blog/196826
          2. 所有的xml配置文件支持extends操作,它允許定制兩個具有業務含義的xml節點之間的結構融合規則。例如<biz-flow extends="docflow">。

             實際使用中, AOP技術的一個應用難點在于狀態空間的管理問題。一般interceptor中所能訪問的變量局限為this指針所攜帶的成員變量,以及函數調用時傳入的調用參數。interceptor很難在狀態空間中創建新的變量,也很難讀取在其他地方所產生的狀態變量。例如對于如下擴展 A(arg1); B(arg2); C(arg3); =〉 Ax(arg1); B(arg2); Cx(arg3); 因為原有的調用序列中沒有傳遞額外的參數,因此A和C的擴展函數之間很難實現共享內部變量x。在TPL模板語言中,tpl本身是無狀態的,狀態變量通過外部的$thisContext對象統一管理。通過這種行為與狀態的分離,結合靈活的變量作用域控制機制,可以以比較簡單的方式實現擴展函數之間的信息共享。

          posted @ 2008-07-07 00:12 canonical 閱讀(1692) | 評論 (0)編輯 收藏

              說到分解,很多人心中的意象大概只有正交分解。正交分解無疑是最重要的一種分析方法,它也是所謂“分而治之”思想最常見的實現策略。但是正交分解一般潛在的假定是分解后的子部分是大致均衡的,它們是相對具有獨立價值的,可以彼此脫離獨立發展。這是分解后實現系統解耦的重要原因。http://canonical.javaeye.com/blog/33885 但是物理學中另一種重要的分析學思想是微擾論(Perturbation). 針對一個復雜的物理現象,首先建立一個全局的規范的模型,然后考慮各種微擾條件對原有模型的影響。在小擾動情況下,模型的變化部分往往可以被線性化,被局域化,因而問題得到簡化。微擾分析得到的解依賴于全局模型的解而存在,因而這是一種主從關系的分解方式。但是如果主體模型是我們已經熟知的物理現象,則我們關注的重點可以全部放在擾動解上,認為所有特定的物理規律都體現在擾動解中。如果微擾分析得到的物理元素足夠豐富,則微擾模型本身可以成為獨立的研究對象,在其中我們同樣可以發現某種普適的結構規律。
              Witrix平臺中系統化的應用主從分解模式,通過類似AOP的技術實現了業務模型與平臺技術的自然結合。http://canonical.javaeye.com/blog/126467 最近我們的一個產品的新版本即將在全國范圍內部署,如何有效的控制眾多相近的二次開發版本,同時確保主版本的快速升級,是在架構層面必須解決的問題。http://canonical.javaeye.com/blog/73265 在Witrix平臺中,各部署版本并不是直接修改主版本源代碼得到,而是將差異化代碼放在單獨的目錄中進行管理,由系統運行平臺負責將差異化定制代碼與主版本代碼進行動態融合,實現部署版本的客戶化。在這一過程中,系統模型本身支持逆元結構至關重要,否則某些多余的元素無法通過差異性描述去除,則將出現局部模型失效的情況。
              Witrix平臺定義了特殊的_custom目錄,它的內部目錄結構與defaultroot目錄相同,系統平臺優先使用該目錄下文件所提供的功能實現。同時定義了系統參數global.app_id和global.default_app_id,它們分別用來區分當前程序版本以及程序主版本代碼。例如當global.app_id=beijing,global.default_app_id=main的時候,系統中裝載ui.xml這個標簽庫時經歷如下過程,
          1.    裝載平臺內置的標簽庫,文件路徑為 /_tpl/ui.xml.
          2.    根據global.default_app_id設置,裝載/_custom/main/_tpl/ui.xml, 其中定義的標簽實現將覆蓋平臺缺省提供的標簽實現。對于那些不需要特殊定制的標簽,繼續使用平臺提供的缺省實現。
          3.    根據global.app_id設置,裝載/_custom/beijing/_tpl/ui.xml, 其中定義的標簽實現將覆蓋產品主版本的標簽實現。

          基礎平臺中對于代碼動態融合定義了精細的融合策略,將通過編譯技術檢查擴展標簽的接口與缺省實現的接口相兼容,由此確保代碼擴展后不會破壞主版本中的已有調用代碼。
              在基礎平臺的實現中,很多實現代碼都是類似
                    <df:WhenAllowFinishWf>
                      
          <df:FinishWfButton />
                    
          </df:WhenAllowFinishWf>

          這樣的類似廢話的標簽調用。但是通過這些標簽的標記,我們確立了系統的邏輯結構,標定了系統中可以被安全替換的邏輯片斷。

          posted @ 2008-05-26 00:41 canonical 閱讀(1745) | 評論 (0)編輯 收藏

               在與一些年歲較大的C程序員接觸的過程中,可以比較明顯的感受到C的思維方式與面向對象思想的不同。C的世界很清澈,先做A, 再做B, 我們所期待發生的計算過程與源代碼的結構是直接一一對照的。這意味著程序將要執行的計算過程在編寫代碼的時刻就已經確定下來。面向對象首先需要確定的是類,對象等中間元素,而并不是最終的計算過程。對象可以之間可以產生很復雜的結構關系,透過這種中間邏輯結構我們來理解最終要發生的計算過程。在事件驅動的應用場景下,面向對象是一種更加有效的描述,
            o.someFunc()                  o.onEventA();
              sub1.someFunc();      ==>     sub1.onEventA();
              sub2.someFunc();              sub2.onEventB();
          如果把對象看作是函數+狀態的集合,則對象組裝的關系實際上是函數集合之間的一種組裝關系。當具體的事件發生的時候,將觸發對象上確定的響應函數,此時在各個層面上所實際發生的計算才能被確定下來。



          posted @ 2008-03-16 15:04 canonical 閱讀(464) | 評論 (0)編輯 收藏

             所謂WebMVC即Model2模型是目前Web開發領域的主流模型,Struts/Struts2框架是其典型實現。在概念層面上,這種程序組織模型是怎樣建立起來的?與其他Web開發模型(如面向對象模型)具有怎樣的聯系? 它未來可能的發展方向在哪里? 結合Witrix開發平臺的具體實踐,基于級列設計理論我們可以看到一條概念發展的脈絡。http://canonical.javaeye.com/blog/33824

             1. 外部視角:原始的servlet規范提供了一個簡單的面向IO的程序響應模型。一次前臺訪問由一個特定的servlet負責響應,它從request中讀取輸入流,在全局session中保持臨時狀態,向response中寫入輸出流。在此基礎上,JSP提供的模板概念翻轉了程序和輸出文本之間的相對地位,簡化了文本輸出過程。至此,這種整體的程序模型基本上只是規范化了外部系統訪問Web服務器的響應模型,并沒有對后臺程序的具體實現制定明確的約束條件。因此在最粗野的后臺實現中,讀取參數,業務處理,生成頁面等處理步驟是糾纏在一起的,很難理解,也很難重用。每一個后臺頁面都是一個不可分析的整體。
          <%
             String paramA 
          = request.getParameter("paramA");
             ResultSet rsA 
          = 
          %>
             result 
          = <%=rsA.getString(0%>
             String paramB 
          = request.getParamter("paramB");
             ResultSet rsB 
          = 
          <%
             rsB.close();
             rsA.close();
             conn.close();
          %>


          2. 自發分離:在復雜的程序實踐中,我們會自發的對業務處理代碼和界面代碼進行一定程度的分離。因為我們可以直觀的感受到這兩種代碼的穩定性并不匹配。例如不同業務處理過程產生的結果都可以用一個html表格來展現,而同一個業務處理過程產生的結果頁面可能經常發生變化。一般我們傾向于將業務代碼寫在頁面上方,而界面代碼寫在頁面下方,并使用一些原始的分解機制,例如include指令。這種分離是隨意的,缺乏形式邊界的。例如我們無法表達被包含的頁面需要哪些參數,也難以避免全局變量名沖突。需要注意的是,分層的一般意義在于各個層面可以獨立發展,它的隱含假定是各層面之間的交互是規范化的,只使用確定的數據結構,按照確定的方式進行交互。例如業務層和界面層通過標準的List/Map等數據結構交互,而不是使用具有無限多種樣式的特殊的數據結構。(在弱類型語言環境中,實體對象的結構和Map是等價的).
          <%
             List header 
          = 
             List dataList 
          = 
          %>
          <%@ include file="/show_table.jsp" %>


             3. 規范分離:JSP所提供的useBean和tag機制,即所謂的Model1模型,是對程序結構分離的一種規范化。業務代碼封裝在java類中,一般業務函數與web環境無關,即不使用request和response對象, 允許單元測試。tag機制可以看作是對include指令的增強,是一種代碼重用機制。tld描述明確了調用tag時的約束關系。調用tag時需要就地指定調用參數,而include頁面所依賴的參數可能是在此前任意地方指定的,是與功能實現分離的。此外tag所使用的參數名是局部對象上的屬性名,從而避免了對全局變量的依賴。很遺憾的是,jsp tag所封裝的仍然是原始的IO模型,對程序結構缺乏精細的定義,在概念層面上只是對文本片段的再加工,難以支撐復雜的控件結構。早期jsp tag無法利用jsp模板本身來構造,無法構成一個層層遞進的概念抽象機制,更是讓這種孱弱的重用模型雪上加霜。在其位卻無能謀其政,這直接造成了整個j2ee前臺界面抽象層的概念缺失,以致很多人認為一種前臺模板重用機制是無用的。在Witrix平臺中所定義的tpl模板語言,充分利用了xml的結構特點,結合編譯期變換技術,成為Witrix平臺中進行結構抽象的基本手段。實際上,xml能夠有效表達的語義比一般人所想象的要多得多。
           <jsp:useBean id="myBiz" class="" />
            
          <% List dataList = myBiz.process(paramA) %>
            
          <ui:Table data="<%= dataList %>" />

            
            4. 框架分離:在Model1模型中,頁面中存在著大量的粘結性代碼,它們負責解析前臺參數,進行類型轉換和數據校驗,定位特定的業務處理類,設置返回結果,控制頁面跳轉等。一種自然的想法是定義一個全局的程序框架,它根據集中的配置文件完成所有的粘結性操作。這也就是所謂面向action的WebMVC模型。這一模型實現了服務器端業務層和界面層在實現上的分離,但是對于外部訪問者而言,它所暴露的仍然是原始的自動機模型:整個網站是一個龐大的自動機,每次訪問都觸發一個action,在action中可能更改自動機的狀態(作為全局狀態容器的session對象或者數據庫)。struts作為面向action框架的先驅,它也很自然的成為了先烈。struts中所引入的FormBean, 鏈接管理等概念已經在實踐中被證明是無益的。一些新興的框架開始回歸到通用的Map結構,直接指定跳轉頁面,或者利用CoC(Convention Over Configuration)缺省映射.
          public class RegisterAction extends Action {
              
          public ActionForward perform (ActionMapping mapping,
                                            ActionForm form,
                                            HttpServletRequest req,
                                            HttpServletResponse res)
          {
              RegisterForm rf 
          = (RegisterForm) form;
              
              
          return mapping.findForward("success");
          }

            
          5. 橫向延展:分層之后必然導向各個層面的獨立發展,我們的視野自然也會擴大到單個頁面之外,看到一個層面上更多元素之間的相互作用.在面向對象語言大行其道的今天,繼承(inheritance)無疑是多數人首先想到的程序結構組織手段.后臺action可以很自然的利用java語言自身的繼承機制,配置文件中也可以定義類似的extends或者parent屬性.但是對于前臺頁面一般卻很少有適用的抽象手段,于是便有人致力于前臺頁面的對象語言化:首先將前臺頁面采用某種對象語言表達,然后再利用對象語言內置的結構抽象機制.放棄界面的可描述性,將其轉化為某種活動對象,在我看來是一種錯誤的方向.而JSF(JavaServerFace)規范卻似乎想在這個方向上越走越遠.JSF早期設計中存在的一個嚴重問題是延續了面向對象語言中的狀態與行為綁定的組織方式.這造成每次訪問后臺頁面都要重建整個Component Tree, 無法實現頁面結構的有效緩存.而Witrix平臺中的tpl模板語言編譯出的結構是無狀態的,可以在多個用戶之間重用.

            6. 相關聚合:對象化首先意味著相關性的局域化,它并不等價于對象語言化. 當面對一個大的集合的時候,最自然的管理手段便是分組聚合:緊密相關的元素被分配到同一分組,相關性被局域化到組內.例如,針對某個業務對象的增刪改查操作可以看作屬于同一分組. struts中的一個最佳實踐是使用DispatchAction, 它根據一個額外的參數將調用請求映射到Action對象的子函數上.例如/book.do?dispatchMethod=add. 從外部看來,這種訪問方式已經超越了原始的servlet響應模型,看起來頗有一些面向對象的樣子,但也僅僅局限于樣子而已.DispatchAction在struts框架中無疑只是一種權宜之計,它與form, navigation等都是不協調的,而且多個子函數之間并不共享任何狀態變量(即不發生內部的相互作用),并不是真正對象化的組織方式.按照結構主義的觀點,整體大于部分之和.當一組函數聚集在一起的時候,它們所催生的一個概念便是整體的表征:this指針.Witrix平臺中的Jsplet框架是一個面向對象的Web框架,其中同屬于一個對象的多個Action響應函數之間可以共享局部的狀態變量(thisObj),而不僅僅是通過全局的session對象來發生無差別的全局關聯.http://canonical.javaeye.com/blog/33873 需要注意的是,thisObj不僅僅聚集了后臺的業務操作,它同時定義了前后臺之間的一個標準狀態共享機制,實現了前后臺之間的聚合.而前臺的add.jsp, view.jsp等頁面也因此通過thisObj產生了狀態關聯,構成頁面分組.為了更加明確的支持前臺頁面分組的概念,Witrix平臺提供了其他一些輔助關聯手段.例如標準頁面中的按鈕操作都集中在std.js中的stdPage對象上,因此只需要一條語句stdPage.mixin(DocflowOps);即可為docflow定制多個頁面上的眾多相關按鈕操作.此外Witrix平臺中定義了標準的url構建手段,它確保在多個頁面間跳轉的時候,所有以$字符為前綴的參數將被自動攜帶.從概念上說這是一種類似于cookie,但卻更加靈活,更加面向應用的狀態保持機制.

            class DaoWebAction extends WebContext{
               IEntityDao entityDao;
               String metaName;

               
          public Object actQuery(){
                 
                 thisObj.put(
          "pager",pager);
                 
          return success();
               }

               
          public Object actExport(){
                 Pager pager 
          = (Pager)thisObj.get("pager");
                 
                 
          return success();
               }
              }


            7. 描述分離:當明確定義了Action所聚集而成的對象結構之后,我們再次回到問題的原點:如何簡化程序基元(對象)的構建?繼承始終是一種可行的手段,但是它要求信息的組織結構是遞進式的,而很多時候我們實際希望的組織方式只是簡單的加和。通過明確定義的meta(元數據),從對象中分離出部分描述信息,在實踐中被證明是一種有效的手段。同樣的后臺事件響應對象(ActionObject),同樣的前臺界面顯示代碼(PageGroup),配合不同的Meta,可以產生完全不同的行為結果, 表達不同的業務需求。http://canonical.javaeye.com/blog/114066 從概念上說,這可以看作是一種模板化過程或者是一種復雜的策略模式 ProductWebObject = DaoWebObject<ProductMeta>。當然限于技術實現的原因,在一般框架實現中,meta并不是通過泛型技術引入到Web對象中的。目前常見的開發實踐中,經??梢钥匆婎愃艬aseAction<T>, BaseManager<T>的基類,它們多半僅僅是為了自動實現類型檢查。如果結合Annotation技術,則可以超越類型填充,部分達到Meta組合的效果。使用meta的另外一個副作用在于,meta提供了各個層面之間新的信息傳遞手段,它可以維系多個層面之間的共變(covariant)。例如在使用meta的情況下,后臺代碼調用requestVars(dsMeta.getUpdatableFields())得到提交參數,前臺頁面調用forEach dsMeta.getViewableFields()來生成界面. 則新增一個字段的時候,只需要在meta中修改一處,前后臺即可實現同步更新,自動維持前后臺概念的一致性。有趣的是,前后臺在分離之后它們之間的關聯變得更加豐富。

          8. 切面分離: Meta一般用于引入外部的描述信息,很少直接改變對象的行為結構。AOP(Aspect Oriented Programming)概念的出現為程序結構的組織提供了新的技術手段。AOP可以看作是程序結構空間中定位技術和組裝技術的結合,它比繼承機制和模板機制更加靈活,也更加強大。http://canonical.javaeye.com/blog/34941 Witrix平臺中通過類似AOP的BizFlow技術實現對DaoWebAction和前臺界面的行為擴展,它可以在不擴展DaoWebAction類的情況下,增加/修正/減少web事件響應函數,增加/修正/減少前臺界面展現元素。當前臺發送的$bizId參數不同的時候,應用到WebObject上的行為切片也不同,從而可以自然的支持同一業務對象具有多個不同應用場景的情況(例如審核和擬制)。在BizFlow中定義了明確的實體化過程,前臺提交的集合操作將被分解為針對單個實體的操作。例如前臺提交objectEvent=Remove&id=1&id=2,將會調用兩次<action id="Remove-default">操作。注意到AOP定位技術首先要求的就是良好的坐標定義, 實體化明確定義了實體操作邊界,為實體相關切點的構造奠定了基礎。http://canonical.javaeye.com/blog/33784

          9. 背景消除:在Witrix平臺中, (DaoWebAction + StdPageGroup + Meta + BizFlow)構成完整的程序模型,因此一般情況下并不需要繼承DaoWebAction類,也不需要增加新的前臺頁面文件,而只需要在BizFlow文件中對修正部分進行描述即可。在某種程度上DaoWebAction+StdPageGroup所提供的CRUD(CreateReadUpdateDelete)模型成為了默認的背景知識。如果背景信息極少泄漏,則我們可以在較高抽象層次上進行工作,而不再理會原始的構造機制。例如在深度集成hibernate的情況下,很少會有必須使用SQL語句的需求。BizFlow是對實體相關的所有業務操作和所有頁面展現的集中描述,在考慮到背景知識的情況下,它定義了一個完整的自給自足的程序模型。當我們的建模視角轉移到BizFlow模型上時,可以發展出新的程序構造手段。例如BizFlow之間可以定義類似繼承機制的extends算子,可以定義實體狀態驅動的有限自動機,可以定義不同實體之間的鉤稽關系(實體A發生變化的時候自動更新實體B上的相關屬性),也可以定義對Workflow的自然嵌入機制。從表面上看,BizFlow似乎回歸到了前后臺大雜燴的最初場景(甚至更加嚴重,它同時描述了多個相關頁面和多個相關操作),但是在分分合合的模型建立過程中,大量信息被分解到背景模型中,同時發展了各種高級結構抽象機制, 確保了我們注意力的關注點始終是有限的變化部分。而緊致的描述提高了信息密度,簡化了程序構造過程。http://canonical.javaeye.com/blog/126467
            <bizflow extends="docflow"> <!-- 引入docflow模型,包括一系列界面修正和后臺操作 -->
          <biz id="my">
               
          <tpls>
                 
          <tpl id="initTpl">
                    
          <script src="my_ops.js" ></script>
                    
          <script>
                      stdPage.mixin(MyOps); // 引入多個頁面上相關按鈕對應的操作
                    
          </script>
                 
          </tpl>
               
          </tpls>
              
          </biz>
            
          </bizflow>



          posted @ 2008-02-18 22:02 canonical 閱讀(1824) | 評論 (0)編輯 收藏

            自從離開學校就基本上不再使用C++了,最近卻又因為項目上的原因重新走入這一迷失的世界, 感覺很是缺乏一些順手的工具。首先就是做配置管理有點麻煩, 因為缺乏反射機制, 無法直接映射, 所以一般需要手工書寫配置設置功能.
            我們希望配置類在配置階段能夠支持動態屬性名,
            GConfig cfg;
            cfg.set(
          "bgColor.b",3.0);
            cfg.set(
          "lightEnabled",false);

            t_float b 
          = cfg.get("bgColor.b");
            bool l 
          = cfg.get("lightEnabled");

              但是內部使用時支持直接的屬性訪問,便于編譯器檢查, 也提高運算速度。
                  t_float b = cfg.bgColor.b;
                  bool l 
          = cfg.lightEnabled;


          所幸C++的類型系統能夠偷偷的去干很多見不得人的勾當,因此便有了下面這個簡易機制。

          #define S_P(x) do{if(strcmp(name,#x) == 0) { x = value; return; } } while(0)
          #define G_P(x) 
          do{if(strcmp(name,#x) == 0) { value = x; return; } } while(0)

          class _GConfig{
          public:
            bool lightEnabled;

            t_float minX;
            t_float maxX;
            t_float minY;
            t_float maxY;

            _GConfig(){
              
          // initialize all primitive members
              memset(this,0,sizeof(_GConfig));
            }
          };

          class GConfig: public _GConfig{
          public:
            GColor bgColor;

            GConfig(){
            }

            _variant_t get(
          const char* name){
              _variant_t value;
              get(name,value);
              
          return value;
            }

            
          void get(const char* name,_variant_t& value){
              G_P(lightEnabled);

              G_P(minX);
              G_P(maxX);
              G_P(minY);
              G_P(maxY);
             
              G_P(bgColor.r);
              G_P(bgColor.g);
              G_P(bgColor.b);
              G_P(bgColor.a);
            }

            
          void set(const char* name, _variant_t value){
              S_P(lightEnabled);

              S_P(minX);
              S_P(maxX);
              S_P(minY);
              S_P(maxY);
             
              S_P(bgColor.r);
              S_P(bgColor.g);
              S_P(bgColor.b);
              S_P(bgColor.a);
            }
          };

          _variant_t是VC++在<comdef.h>中提供的對變體數據類型的封裝。使用S_P和G_P這樣的宏可以由編譯器檢查變量名的正確性。

          posted @ 2008-01-12 20:58 canonical 閱讀(1803) | 評論 (0)編輯 收藏

              關系數據庫模型在理論上主要解決的是消除數據冗余的問題。關系模型的數學基礎是所謂的集合論,而集合的基本含義正是一組具有某種原子性的互不相同的元素。面向對象技術是對相關性進行局域化的一種手段(相關的數據和操作聚集到同一對象名義下),在這一局域化過程中,相同的元素被識別出來,成為獨立的對象。從某種意義上說,關系模型與對象模型是殊途同歸的過程,是從不同側面對同一事物的反映。關系模型中,我們關注的重點是元素組成的集合,允許的連接關系定義在集合之上。而在對象模型中,我們關注的首先是橫向關聯的實體,實體之間具有穩定的聯系。在概念層面上,從對象模型映射到一種關系存儲模型只是一個分組問題。為了斷開實體之間的直接聯系,關系模型創造了一個id字段,而對象模型并不是需要顯式id的。在關系模型中,關聯并不是通過某種存在的結構來表達的(一個實體持有另一個實體的指針,擁有直接聯系),而是將直接關聯問題弱化為某種計算過程,我們必須檢查id的值(不是某種直接的存在性),通過某種運算過程才能重新發現數據之間的關聯。
             
              通過id(伴隨一個匹配計算過程)來進行間接關聯對于保證模型的一致性是非常關鍵的。在ORM中恢復了對象的強關聯其實會造成很多潛在的復雜性。例如為了維護對象層面結構的一致性,在更新父子關系的時候,我們需要同時調用 child.setParent(parent); parent.getChildren().remove(child); 當關聯結構更加復雜的時候,這里所需要的維護工作是隨之增加的。不過,在ORM中,對象的形態是暫時性的。在ORM的一次session的操作過程中,對于對象狀態的修改可以是不一致的。例如我們可以只調用child.setParent(parent); 而不需要同時  parent.getChilren().remove(child); 只要我們在此次session操作中,不需要同時用到parent.getChildren(). 這種關聯的暫時性對于很多ORM應用來說是必不可少的。
             
              對象模型中可以直接表達的結構關系比關系模型要豐富一些,例如繼承關系,many-to-many, one-to-list等。但是所有這些都不是真正本質性的差異。拋棄概念詮釋,基類與眾多派生類之間的關系基本上可以等價于一組one-to-one關系。而當關聯對象本身的重要性凸現出來的時候,當我們無法把它約化為對象上的一些附屬特性的時候(例如數組的下標),我們必然要建立相應的關聯對象,而這正對應于關系模型中的中間關聯表。中間關聯表上增加額外的字段是一個自然的擴展過程,而對象模型上做這樣的擴充往往表現為形態上的重大的不兼容的變化,例如從getManyToManyEntity() -> getToManyRelation(), 這實際上意味著這里的對象形式是偶然的,簡化的。
             
              在原始的關系數據庫模型中,所有的表之間的地位是平等的,所有字段之間的地位是平等的(主鍵和外鍵在參與數據關聯時和其他字段的處理方式一致)。這種概念上的均一性和普遍性往往被認為是理論的優美之處。但是現實世界是復雜的,發展的方向就是逐步識別出不同之處,并找出自然的表達形式將這些不同表達出來。均勻的關系模型是對稱性最高的,最簡化的模型。在面對物理約束時,它隱含的假設是集合之間很少發生相互作用,單表(表單到數據表之間的映射)和主從表是最廣泛的情況。試著想象一下關系模型,在思維中一般我們只能看到兩個數據表,當考慮到多個表的時候,因為這些表之間沒有明確的可區分性,因此它們的意象是模糊的。只有明確意識到主鍵,外鍵,主表,從表,字典表,事實表,緯度表這些不同的概念的時候,當對稱性出現破缺的時候,我們思維中的模型才能夠豐富化起來。
             
              關系模型理論應用到數據庫具體應用中時,并不需要死守關系范式教條,它們只是描述了某種極端化的對唯一性的追求。面對具體應用的時候,理論本身也在不斷豐富化。我并不把現實應用中必然需要增加冗余字段看作是關系理論失效的結果。從關系完全分解,到關系完全不分解之間,我們可以建立大量的模型。建立冗余字段的時候,我們存在著大量可能的選擇,到底哪一種選擇是最優的,理論方面仍然可以給我們以具體的指導。理論在各種不同純化程度的關系模型中都可以給我們以直觀的建議。數據倉庫理論中建立的snowflake模式和star模式,強調了針對主題域的允許部分冗余的關系分解。這里實際上是強調了表之間的不同性。不再是所有的表都處于同一地位。Fact Table和Dimension Table之間的區別被識別出來,并被明確處理。在我看來,這是原始關系模型的一種自然發展,它也是關系模型理論的一部分。理論不應該是單一的,而是提供一個模型級列,在不同的復雜性層次上,我們可以根據理論的指導選擇具體的實現模型。
             
              關于ORM http://canonical.javaeye.com/blog/111500
              關系模型中的所謂關系是在使用時刻才定義的,所有建立關系的方式在某種程度上都是等價的,也是外在的。而在ORM中主鍵與外鍵之間的關聯被獨立出來,成為模型內置的部分。這在很多時候簡化了數據查詢的結構構造過程。
              在ORM中主鍵因為緩存的存在而顯出與其他字段的區別。ORM的使用使得數據存儲的分解策略得到擴充。并不是所有的表的更新頻度都是一致的,而且表中的數據量大小也不同。字典表一般較小,而且很少更新,可以安全的復制。在整個數據存儲框架中,ORM作為獨立的技術元素參與數據存儲過程,通過主鍵提供緩存服務,產生了新的數據分布模型,提供了新的性能優化契機。


          posted @ 2008-01-06 19:04 canonical 閱讀(3177) | 評論 (3)編輯 收藏

              我平時Kill Time的主要方式是閱讀各類學術書籍。但是學習本身只是了解前人的發現,間或鍛煉一下自己的思維能力,對自己的工作和生活并沒有什么直接的助益。學習本身無論如何深入,多半也只是采用前人的話語復現前人思考的歷程。在我們通過獨立的思考獲得直觀的體驗之前,在我們將所學到的知識應用到書本之外的場景之前,我們所學習的知識只是考試的工具,只是可供欣賞的對象,卻不能成為我們思考中活躍的因素,無法參與我們思維的進程。別人只能給你思想的引子,并不能給你真正的思想。只有自己找到了所學知識的超出書本的非顯然的應用,只有獨立建立了不同概念之間未曾闡明的聯系,我們才能真正獲得對于真理的體悟。無論我們自己的發現是如何的微不足道,無論它是否只是重復發現了劣質的輪子,它唯一的意義只在于它是我們獨立思考的結果,是我們自己的創造。即使它是卑微的,是重復的,它對我們的理解的作用仍然是任何外在的教誨都無法比擬的。

              現代社會中創造所需的成本已經被空前降低了。想想百年前的天才們,他們缺少信息來源,只能一頁頁翻查文獻,反復謄寫文稿來保存知識,大量的時間被花費在了與思考完全無關的事情上。同時,他們所處的時代存在著更多的不確知性,他們的思考所能夠憑依的事實更少,做出錯誤判斷的可能性與今天相比也更大。即使Bill Gates這樣的掙錢能手在1981年也能放出"640k ought to be enough for anybody"的厥詞,顯示出我們在預測未來的時候是何等的乏力。當我們今天站在人類文明的巔峰,擁有前人無法想象的工具,并不斷制造著從未經歷過的實踐的時候,我們理應擁有超越歷史上任何天才的,更加寬廣的眼界。

              現代社會中的創造看似簡單了,但從另一個方面看,卻又是大大的復雜化了。前人的成就成為了難以逾越的豐碑,而為了進入科學殿堂,我們需要的準備工作也變得異常的繁復。這里有科學內在的規律,但也有人為制造的障礙,而這其中最主要的是數學障礙。只要想一想,針對軟件工程,經濟運行,企業管理,每個參與其中的實踐者都可以提出一些自己的意見,但是如果涉及到數學,為什么大多數人只有三緘其口了?現代抽象數學取得了輝煌的成就,但是它也可能毀掉了更多學生創造的激情。宏偉精深的大廈讓人敬畏,卻無法激發我們任何直觀的共鳴。甚至Arnold這樣的數學大師也坦承讀不懂當代數學家們的著述:因為他們從不說“彼嘉洗了手”,而只是寫道:存在一個t1<0,使得t1在自然的映射t1->彼嘉(t1)之下的像屬于臟手組成的集合,并且還存在一個t2,t1<t2<=0,使得t2在上面提到的映射之下的像屬于前一句中定義的集合的補集。當Bourbaki學派致力于在課本上消滅所有圖示的時候,理性達到了非理性的彼岸。

              有時我在想為什么現在的程序員似乎對于程序的理解能力降低了。排除教學水平的降低和個人努力的不足之外,是否是因為現在需要學習的內容過多,以至于喪失了自我思考的勇氣?在C的時代,每個程序員對于程序的理解都是直接的,原始的,對程序結構的把握都是充滿自信的。當新的概念不斷涌現的時候,人們總是說,Object不過是..., Component不過是..., AOP不過是..., ORM不過是..., IoC不過是.... 這體現了人們試圖把新的概念融入自己原有知識體系的一種努力。雖然仔細考究起來,這里的理解很多時候都是似是而非的,未必掌握了新技術真正創新的思想方向,但是這里的思考總是獨立進行的,總是對我們的理解和工作有所助益的。而新一代的程序員生活在Object, Pattern等概念已經無需饒舌來證明自己的時代,他們是否在思想中獨自評估過所有概念的意義,是否建立了概念和實現之間直觀的聯系,是否在統一的思維世界中為所有的概念找到了合適的坐標?這一切,我不得而知。
              
          推薦:Arnold 論數學教育 http://www.ieee.org.cn/dispbbs.asp?boardID=64&ID=25892

          posted @ 2007-12-24 01:10 canonical 閱讀(2051) | 評論 (6)編輯 收藏

              我在各種場合一直都在強調結構問題是獨立的,在程序語言之外存在著獨立的,可研究的,富有成效的結構問題。http://canonical.javaeye.com/blog/147424 在這個方向上更進一步,我們注意到所有的代碼并不是天然出現的,而是由人所編制的,因此代碼世界內部并不構成封閉的,自足的某個世界。代碼中的結構問題并不是由代碼本身完全解決的,即在代碼之外仍然存在著技術上可研究的結構問題。
              我們在編制代碼的同時也在編制著大量的說明文檔。這些文檔描述了代碼片斷之間的相互關系,描述了代碼未來的擴展方向,描述了代碼之間的可能的交互方式,同時也描述了針對現有代碼實現的很多具體約束。例如我們在文檔中約定某個量要在10和20之間,但在代碼中卻不一定顯式進行了判斷。針對代碼結構的很多具體約束條件和相關性描述可能只在文檔中體現,只在程序員的頭腦中存在,而并不一定忠實的在代碼結構中得到表達。
              我在設計領域基本持有一種物理實在論,即某種技術相關的約束應該在技術世界中通過技術手段得到表達。只是這里的技術手段卻不一定指在應用中加上特定的代碼實現,雖然我們在代碼實現中更直接的表達設計要求無疑是需要提倡的。為了在程序中有效的維護結構相關性,我們并不一定需要抽象出所有可能重用的代碼,并不一定需要確保某一概念在程序中只有精確的唯一的表達。程序中難以直接精確表達的弱關聯,仍然可以通過開發/設計工具等技術手段得到有效的維護。我們需要保證的是代碼世界中知識的自恰性,而自恰性并不等于唯一性。http://canonical.javaeye.com/blog/33788
              在Witrix中我們采用一種物理模型驅動的開發方式,http://canonical.javaeye.com/blog/29412 由pdm模型出發,自動生成hibernate的hbm文件,java實體類,元數據meta文件,前臺Action注冊文件等。生成的配置文件通過syncWithModel標記與模型保持著穩定的關聯。所有配置文件都支持手工修改,開發工具識別syncWithModel標記,當pdm模型發生變化的時候,工具自動將變化信息同步到各個配置文件中。注意到這里并不是采用一個統一的元數據模型的方式,各個配置文件所表達的信息在一定程度上是重復的,也可能是不一致的。例如后臺數據庫允許保存100個字節,但是前臺meta中我們可能配置只允許錄入20個字節。根據不同應用場景的需要,我們可以在各個層面對每個配置文件進行獨立的調節. 當然,在一般情況下并不存在這種需要。整個開發過程中,信息表達的自恰性并不是在應用程序代碼中得到定義的,而是因為開發工具的存在而在技術上得到保證的。放松模型之間的唯一匹配要求,我們可以得到更加豐富,更加靈活的軟件結構。實際上我認為RoR(RubyOnRails)采用直接映射的ActiveRecord的方式雖然有效保證了系統變動中知識的一致性,但是如果不允許在各個層面上都能夠自然的定義某種偏離,它在復雜應用中的價值就要打上大大的折扣。

          posted @ 2007-12-15 19:46 canonical 閱讀(1418) | 評論 (0)編輯 收藏

             設計考慮的是最終需要什么,最終我們要提供的調用接口是什么,我們所直接需要的某個有價值的,直接存在的,直接可以接觸的結構是什么,而不是它所依據的原理是什么,不是它的具體構造過程或者構造方法是什么。比如說我們在程序中完全不需要內置Map這一結構,因為它可以通過列表等結構組合構建出來,但是很顯然,Map這一概念的直接存在對我們來說是方便的,是經濟的,是有效的。我們在思考的時候并不需要考慮它是采用List實現還是采用Set實現,或者任何它本身的構造結構。這一概念在我們的思想中成為某種原子化的東西。

              那么,我們到底需要構建哪些概念,才能夠最方便的基于這些概念應對萬千應用系統的開發呢。 這是我們需要在結構空間作出探索的。 這里的思維方向不是把系統推向某種純粹化,某種極致的簡單化,而是讓它更加物理化,揭示出更多的層次,更加關切在物理約束情況下如何實現靈活性的最大化。一種概念在物理上如果被證明能夠在很多場景下成為不變的基元,則它便是有價值的,是可以進行物理詮釋的。

             很多人習慣于接受語言存在的現實,接受設計后的結果,但是作為程序語言設計者,他們又是如何工作的?他們是否真的是從純粹的數學關系推演得到所有的語法特征,還是他們預先已經在心中設定了應該出現的語法特征,然后去尋找它的數學表達,只是借此清除思維中潛在存在的矛盾性呢?

              語言中存在的所有特征是經過全局考慮的,是清除了所有概念的矛盾沖突的。但是在現實中,我們偶然構造的結構卻可能是局限于當下的信息構造的,因此它們相會的時候,可能會出現不協調,可能會出現結構障礙。例如同樣是關閉操作,有些人命名為close, 另一些人命名為destroy. 可能一個具有額外參數,另外一個沒有。這里可能需要一種adaptor接口的封裝,也可能使用ruby那種method-missing的動態判斷。對于更加錯綜復雜的結構問題,其解決方案就不是那么顯然的了,但這并不意味著我們無辦法可想。究竟設計何種結構邊界才能最小化結構融合時所要付出的代價呢?結構被識別并表征出來以后,是否允許它在一定范圍內有所變形?在變形中我們需要保持的拓撲不變量是什么?結構動態調整的時候,我們是否需要定義調整的物理代價,是否能夠定義某種動力學?

             我所闡述的只是在計算機理論中從數學視角向物理視角的轉換,它不是必然給你提供某種超越當下的能力,而是提供一種不同的眼光看待所有的一切。視角變換后,我們發現了一些新的命題,而在原先的視角下在我們的話語體系中原本是無法表達這些命題的。串行程序假設了只有1顆CPU, 而函數式語言假設了可以有無限多個CPU, 你不覺得1至無窮之間缺點什么嗎。我們可以創造一些東西把1至無窮之間的空白補齊,概念空間是連續的。
           

          posted @ 2007-12-10 23:57 canonical 閱讀(1319) | 評論 (1)編輯 收藏

              沒有人否認抽象的意義,但是抽象是否就是抽象到無窮大,這是個可以明確定義的問題,也是數學領域正在解決的問題。在我們的思考中沒有明確定義何處是邊界, 沒有明確的限制,這便是導向無窮的一種思維方式,它和現實中是否真的允許消耗無限多的資源,創建無限多的對象無關。當我們認為自己明白了終極的意義,明白 了一種推向無窮的抽象,這并不是理解了世界的全部,我們仍然要明白如何解決一些更加小范圍,但是卻又普遍發生的事情。
          例如現在我的系統中只需要10個相互依賴的線程,如果我們定死了10這個數字,顯然我們可以發展一種這個領域特有的高效的一些算法結構。而抽象到通用語言 中的時候,顯然我們只能假設線程數是任意大,或者是充分大的,而無法充分利用10這一領域信息,因此在這個意義上我說通用語言不是有效的。
          說到10這個確定的數字,不過是一種極端化的比喻。我常說概念是連續的,并不是非此即彼的,因此并不是從一種普遍情況到一種最特殊的情況之間不再有其他情 況了。在這中間環節,存在著非常深刻的復雜的物理事實。但是這些事實卻又是某種有限性向我們揭示出來的。(請不要把這里的有限性理解為算術中的10以內)

          現在來一個理論推演吧:
          1. 任何系統都在一定約束下運行,即它們需要符合某些約束條件
          2. 通用語言描述了某些結構,但是這些結構是充分通用的,能夠應用到盡可能廣泛的領域的
          3. 線程數=10這個約束過份特殊,顯然通用語言是不會考慮這個約束。實際上目前在通用語言設計中,無限資源假定基本都是默認的。
          4. 我們承認某些現實的約束通用語言是不會考慮的
          5. 在最特殊的,明顯不會考慮的約束以及非常通用,一般通用語言必然考慮的約束之間,是否存在著更多的,非平凡的結構呢
          6. 假如10年以內我們所有的硬件都只能支持10個內核,在我的產品研發中假定10個線程有問題嗎。難道我在開發的時候就不再需要抽象了嗎。我在其他方面仍然是需要建立抽象的。
          7. n個抽象約束+1個具體約束,以及 n個無限約束+1個有限約束 仍然是有效的抽象形式。原諒我在這里又使用了有效一詞,它真的很難理解嗎。
          8. 不是在我們的思維中存在著具體的或者有限的物理量,就意味著這種思維是不抽象的.

          函數式語言或者任何一種其他我們已知的與Turing機等價的語言,它們在某種數學的含義上說是"沒有差別的"。但是在我們的實際使用過程中,顯然我們是 能夠感受到它們之間的結構差異的。否則那些不斷發明新的函數式語言的人的大腦都進水了嗎?在具體使用中,總有人偏好這個語言,有人偏好那個語言, 總是某種情況下應用某個語言會方便一些,另一些麻煩一些。難道在所有函數式語言中開發類似ErLang解決的那些程序結構都是一樣方便的嗎?

          有些人的論調是無論啥都逃不出函數式語言的思想。但是假如現在限定你必須使用java語言來開發商業應用,難道你罷工嗎?如果你不使用函數式語言,你所做 的工作就不是程序工作了?你所解決的難道不是程序結構問題了嗎?現在就是有一個結構問題要解決, 它是和語言無關的. 語言提供了就可以直接用, 語言沒有提供我們可以寫代碼構造. 難道除了語言直接體現的結構之外, 程序本身就無法構造任何具有通用價值的結構了嗎?

          我在說到函數式語言的時候,基本的態度只是說不要太沉迷于一種特殊的抽象方式,應該多看看別的視角。在不同的情況下存在著做事情的不同的最優方式。思維中不要只允許永遠,而容不下現在。

          非此即彼,天下唯我,是我們思維中經常陷入的一個誤區?,F在計算機領域所謂的理論主要是基于數學視角的,沒有考慮物理世界因為我們觀察的有限性,因為資源 的有限性所造成的種種約束,此外數學中目前也沒有考慮到物理世界真實的各種復雜性的存在。在我們想到一種計算機理論的時候,圖像過于簡單化,這種簡單化被 認為是優美的全部。其實我們應該思維更加開放一些。

          posted @ 2007-12-09 22:25 canonical 閱讀(1205) | 評論 (5)編輯 收藏

          僅列出標題
          共18頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
          主站蜘蛛池模板: 邯郸市| 唐海县| 葵青区| 剑川县| 徐闻县| 隆林| 凭祥市| 合肥市| 兴业县| 大同县| 调兵山市| 高邮市| 宁德市| 涡阳县| 河南省| 六盘水市| 内丘县| 关岭| 汉阴县| 宣汉县| 保靖县| 余姚市| 东光县| 依兰县| 三河市| 岳阳市| 蕲春县| 江阴市| 本溪| 泰和县| 龙陵县| 泰兴市| 凤庆县| 河西区| 白朗县| 疏勒县| 舒兰市| 南靖县| 武夷山市| 博罗县| 随州市|