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

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

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

    隨筆-14  評論-25  文章-1  trackbacks-0
      2006年5月30日
    在一個項目里面有這么一個技術需求:
    1.集合中元素個數,10M
    2.根據上限和下限從一個Set中過濾出滿足要求的元素集合.

    實際這個是個很典型的技術要求, 之前的項目也遇見過,但是因為當時的類庫不多, 都是直接手寫實現的. 方式基本等同于第一個方式.

    在這個過程中, 我寫了四個方式, 基本記錄到下面.
    第一個方式:對Set進行迭代器遍歷, 判斷每個元素是否都在上限和下限范圍中.如果滿足則添加到結果集合中, 最后返回結果集合.
                測試效果:集合大小100K, 運算時間 3000ms+
    過濾部分的邏輯如下:
     1     void filerSet(Set<BigDecimal> targetSet, String lower, String higher) {
     2         BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
     3         BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
     4 
     5         Set<BigDecimal> returnSet = new HashSet<BigDecimal>();
     6         for (BigDecimal object : targetSet) {
     7             if (isInRange(object, bdLower, bdHigher)) {
     8                 returnSet.add(object);
     9             }
    10         }
    11     }
    12 
    13     private boolean isInRange(BigDecimal object, BigDecimal bdLower,
    14             BigDecimal bdHigher) {
    15         return object.compareTo(bdLower) >= 0
    16                 && object.compareTo(bdHigher) <= 0;
    17     }
    第二個方式: 借助TreeSet, 原始集合進行排序, 然后直接subset.
                測試效果: 集合大小10M, 運算時間: 12000ms+(獲得TreeSet) , 200ms(獲得結果)
    過濾部分的邏輯如下(非常繁瑣):
      1     Set<BigDecimal> getSubSet(TreeSet<BigDecimal> targetSet, String lower,
      2             String higher) {
      3 
      4         BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
      5         BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
      6 
      7         if ((bdHigher.compareTo(targetSet.first()) == -1)
      8                 || (bdLower.compareTo(targetSet.last()) == 1)) {
      9             return null;
     10         }
     11 
     12         boolean hasLower = targetSet.contains(bdLower);
     13         boolean hasHigher = targetSet.contains(bdHigher);
     14         if (hasLower) {
     15             if (hasHigher) {
     16                 System.out.println("get start:" + bdLower);
     17                 System.out.println("get end:" + bdHigher);
     18                 return targetSet.subSet(bdLower, true, bdHigher, true);
     19             } else {
     20                 BigDecimal newEnd = null;
     21                 System.out.println("get start:" + bdLower);
     22                 SortedSet<BigDecimal> returnSet = null;
     23                 if (bdHigher.compareTo(targetSet.last()) != -1) {
     24                     newEnd = targetSet.last();
     25                 } else {
     26                     SortedSet<BigDecimal> newTargetSet = targetSet
     27                             .tailSet(bdLower);
     28                     for (BigDecimal object : newTargetSet) {
     29                         if (object.compareTo(bdHigher) == 1) {
     30                             newEnd = object;
     31                             break;
     32                         } else if (object.compareTo(bdHigher) == 0) {
     33                             newEnd = object;
     34                             break;
     35                         }
     36                     }
     37                 }
     38                 returnSet = targetSet.subSet(bdLower, true, newEnd, true);
     39                 if (newEnd.compareTo(bdHigher) == 1) {
     40                     returnSet.remove(newEnd);
     41                 }
     42                 return returnSet;
     43             }
     44 
     45         } else {
     46             if (hasHigher) {
     47                 System.out.println("get end:" + bdHigher);
     48                 TreeSet<BigDecimal> newTargetSet = (TreeSet<BigDecimal>) targetSet
     49                         .headSet(bdHigher, true);
     50                 BigDecimal newStart = null;
     51                 SortedSet<BigDecimal> returnSet = null;
     52 
     53                 if (bdLower.compareTo(targetSet.first()) == -1) {
     54                     newStart = targetSet.first();
     55                 } else {
     56                     for (BigDecimal object : newTargetSet) {
     57                         if (object.compareTo(bdLower) != -1) {
     58                             newStart = object;
     59                             break;
     60                         }
     61                     }
     62                 }
     63                 returnSet = targetSet.subSet(newStart, true, bdHigher, true);
     64 
     65                 return returnSet;
     66             } else {
     67                 System.out.println("Not get start:" + bdLower);
     68                 System.out.println("Not get end:" + bdHigher);
     69                 BigDecimal newStart = null;
     70                 BigDecimal newEnd = null;
     71                 if (bdHigher.compareTo(targetSet.last()) != -1) {
     72                     newEnd = targetSet.last();
     73                 }
     74                 if (bdLower.compareTo(targetSet.first()) == -1) {
     75                     newStart = targetSet.first();
     76                 }
     77                 for (BigDecimal object : targetSet) {
     78                     if (newStart == null) {
     79                         if (object.compareTo(bdLower) != -1) {
     80                             newStart = object;
     81                             if (newEnd != null) {
     82                                 break;
     83                             }
     84                         }
     85                     }
     86 
     87                     if (newEnd == null) {
     88                         if (object.compareTo(bdHigher) != -1) {
     89                             newEnd = object;
     90                             if (newStart != null) {
     91                                 break;
     92                             }
     93                         }
     94                     }
     95                 }
     96 
     97                 if (newStart == null) {
     98                     if (newEnd == null) {
     99                         if ((bdHigher.compareTo(targetSet.first()) == -1)
    100                                 || (bdLower.compareTo(targetSet.last()) == 1)) {
    101                             return null;
    102                         }
    103                         return targetSet;
    104                     } else {
    105                         SortedSet<BigDecimal> newTargetSet = targetSet.headSet(
    106                                 newEnd, true);
    107                         if (newEnd.compareTo(bdHigher) == 1) {
    108                             newTargetSet.remove(newEnd);
    109                         }
    110                         return newTargetSet;
    111                     }
    112                 } else {
    113                     if (newEnd == null) {
    114                         SortedSet<BigDecimal> newTargetSet = targetSet.tailSet(
    115                                 newStart, true);
    116                         return newTargetSet;
    117                     } else {
    118                         SortedSet<BigDecimal> newTargetSet = targetSet.subSet(
    119                                 newStart, true, newEnd, true);
    120                         if (newEnd.compareTo(bdHigher) == 1) {
    121                             newTargetSet.remove(newEnd);
    122                         }
    123                         return newTargetSet;
    124                     }
    125                 }
    126             }
    127         }
    128     }
    第三種方式: 使用Apache Commons Collections, 直接對于原始Set進行filter.
                測試效果:集合大小10M,過濾結果1M, 運算時間: 1000ms+
    過濾部分的代碼如下:
     1 //過濾的主體邏輯
     2     void filterSet(Set<BigDecimal> targetSet, String lower, String higher) {
     3         final BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
     4         final BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
     5 
     6         Predicate predicate = new Predicate() {
     7             public boolean evaluate(Object object) {
     8                 BigDecimal bDObject = (BigDecimal) object;
     9                 return bDObject.compareTo(bdLower) >= 0
    10                         && bDObject.compareTo(bdHigher) <= 0;
    11             }
    12         };
    13 
    14         CollectionUtils.filter(targetSet, predicate);
    15     }

    第四種方式:使用Guava(google Collections), 直接對于原始Set進行Filter
                測試效果:集合大小10M,過濾結果1M, 運算時間: 100ms-
    過濾部分的代碼如下:
     1 //guava filter
     2 
     3     Set<BigDecimal> filterSet(Set<BigDecimal> targetSet, String lower,
     4             String higher) {
     5         final BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
     6         final BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
     7 
     8         Set<BigDecimal> filterCollection = Sets.filter(targetSet,
     9                 new Predicate<BigDecimal>() {
    10                     @Override
    11                     public boolean apply(BigDecimal input) {
    12                         BigDecimal bDObject = (BigDecimal) input;
    13                         return bDObject.compareTo(bdLower) >= 0
    14                                 && bDObject.compareTo(bdHigher) <= 0;
    15                     }
    16                 });
    17 
    18         return filterCollection;
    19     }


    四種方式對比如下:
    第一種方式:  僅依賴于JAVA原生類庫 遍歷時間最慢, 代碼量很小
    第二種方式:  僅依賴于JAVA原生類庫 遍歷時間比較慢(主要慢在生成有序Set), 代碼量最多
    第三種方式:  依賴于Apache Commons Collections, 遍歷時間比較快, 代碼量很少
    第四種方式:  依賴于Guava, 遍歷時間最快, 代碼量很少

    基于目前個人的技術水平和視野, 第四種方式可能是最佳選擇.

    記錄一下, 以后可能還會有更好的方案.




    posted @ 2014-06-21 23:33 混沌中立 閱讀(7371) | 評論 (10)編輯 收藏
    在幾年之前,在大學里面的時候,認為系統的架構設計,就像建筑設計一樣,會把骨架搭成,然后有具體人員進行詳細的開發.

    在后來,工作中,慢慢有了一些變化,因為原先的想法不太切合實際,系統就是在變化之中的,如果固定了骨架,那就很難的敏捷面對變化.
    所以,系統的架構設計,應該是面向接口的設計,確定各個部分之間的數據接口和方法接口.這樣,即使有了變化,只要遵循接口的定義,就還是可以面對變化.


    最近,又有了想法的變化.架構的設計,應該就是規則和規約的設計.設計出一系列,統一的,和諧的規則,在這些規則之前圈住的部分,實際就是系統的全貌.
    接口的設計,實際只是規則和規約設計的一個部分.
    架構的設計,不應該只是程序方面的事情,同時也包含了心理學方面和社會學方面的一些規則.例如:團隊在面對變化時候,需要采用的規則和流程.
    只有包含了這些非程序上的規則之后,才能保證架構風格的統一協調.


    以上,是我對系統設計的想法的轉變過程.記錄于此,以供回溯.




    posted @ 2009-09-02 10:53 混沌中立 閱讀(247) | 評論 (0)編輯 收藏
    面對著滿屏幕的程序
    是三年前,項目剛剛啟動的時候,同事寫的代碼.
    三年過去了,項目由第一期變成了第七期.

    這段代碼還是在這里,有個屬性是list,其中每個cell都是一個長度18的String數組.
    數組里面放置了所需要導出到頁面table的內容.

    現在要開始修改了,需要向頁面的table中增加4列.
    繁瑣的讓人要命的工作,需要跟蹤這個循環,判斷每個pattern下面,這個長度18的數組里面放了哪些內容.

    好吧,對象化維護從數組開始,把數組對折,因為這個數組時一個比較數組,前面9個元素是之前的情況,后面9個事之后的情況.
    用一個bean,放入兩次就可以了.但是bean中,需要一個標志,標識是之前的情況還是之后的情況.

    同時需要一個transform方法,把之前從幾個來源過來的情況,變成bean的屬性.
    接下來需要一個values方法,把bean里面的屬性直接按順序轉化成數組.
    本期新增的4個屬性,直接放入bean中就可以了.

    這樣原來很復雜的數組,就可以簡單的用對象來解決.外部的接口完全沒有變化.

    維護程序,從把數組(特別是異型數組)對象化開始.

    posted @ 2009-08-20 13:43 混沌中立 閱讀(1353) | 評論 (1)編輯 收藏
    這個小的project是前一個階段,待業在家的時候,迷戀sudoku的時候,自己寫來玩的。
    正好當時在看Uncle Bob的《Agile Software Development: Principles, Patterns, and Practices》 (敏捷軟件開發:原則、模式與實踐),所以就按照自己對書中的一些概念和方法的理解,結合自己之前的開發經驗寫出來一段小的代碼。

    代碼行數: < 900
    類的個數: 18
    抽象類的個數:2
    工廠類的個數:1
    包的個數:5

    一些關于類和包作用的說明:
    1.Cell:表示一個Cell,是一個游戲中的一個單元格。
    ? Cell主要由3個部分組成,Point,Value,Status.
    2.Point:表示一個坐標,主要格式為:(2,3).
    ? !!!注意:由于個人比較懶,所以開始的錯誤被貫徹了下來。
    ? 這個錯誤就是(2,3)表示的是由最左上的位置為坐標原點,第二行和第三列所確定的那個單元格。也就是縱坐標在前,橫坐標在后了。
    3.Value:表示一個值
    4.Status:表示Cell的狀態,只有兩個狀態,一個是NotSure,另一個是Sure.

    5.AbstractCells:表示一些cell的集合,主要有三個子類
    ???? BlockCells:表示一個由多個Cell組成的塊,例如一個2*2由4個Cell組成的塊,或者一個2*3由6個Cell組成的塊
    ???? HorizonCells:表示一個橫行,即:從(0,0)到(0,n)坐標確定的所有Cell的集合。
    ???? VerticalCells:表示一個縱行,即:從(0,0)到(n,0)坐標確定的所有Cell的集合。
    6.AbstractPolicy:就是游戲的策略。
    ?? 這個主要表示的是:4*4的游戲,還是9*9的游戲。
    ?? 可以在以后對此類進行繼承和擴展,例如16*16的游戲我就沒有實現。
    ?? 主要擴展3個方法:
    ????????????????? 1)getValueRange,返回當前policy的value的個數。4*4的游戲的getValueRange返回的就應該是4。
    ??? ??? ? 2)getStep:表示當前policy中相鄰的兩個BlockCells的坐標差。
    ??? ??? ? 3)getIncrease:說不明白了:)(只可意會不可言傳。)
    7.Game:進行Policy的場所(我一直想拋棄這個類)
    8.TestGame:游戲運行的地方,包括從PolicyFactory取得指定的Policy,設置輸入輸出文件的路徑。
    9.PolicyFactory:取得Policy的工廠。
    ??? getPolicy(int x) :這個方法獲得的是正方形的sudoku的策略。例如:4*4的,9*9,16*16。
    ??? getPolicy(int x, int y):這個方法獲得的是長方形的Sudoku的策略。例如:9*12的。


    雖然是盡量避免bad code smell,但是由于能力有限,還是出現了一些不好的地方。
    例如:之間的關聯關系還是很多,而且很強;抽象的方法和抽象類的個數偏少等等。

    里面實現了三個解決sudoku的方法:
    1.在一個Cell中出現的Value,不會在和這個Cell處在同一個AbstractCells中的所有Cell中出現;
    2.如果一個Cell中,所有可能出現的Value的個數為1,那么Cell的Value必然是這個最后的Value;
    2.如果一個Value,如果在當前AbstractCells的所有其他的Cell中都不可能出現,那么它必然是最后一個Cell的Value。

    附件1:src code
    http://www.tkk7.com/Files/GandofYan/sudoku.rar
    附件2:輸入輸出文件的example
    http://www.tkk7.com/Files/GandofYan/temp.rar

    posted @ 2006-07-13 16:19 混沌中立 閱讀(2163) | 評論 (4)編輯 收藏
    如同Tom DeMacro說的:無法控制的東西就不能管理,無法測量的東西就無法控制。
    軟件的度量對于設計者和開發者非常重要,之前只是對這些有一個簡單的了解。今天看來,了解的還遠遠不夠。
    • Cyclomatic Complexity (圈復雜性)
    • Response for Class (類的響應)
    • Weighted methods per class (每個類重量方法)
    一個系統中的所有類的這三個度量能夠說明這個系統的設計上的一些問題(不是全部),這三個度量越大越不好。
    如果一個類這三個度量很高,證明了這個類需要重構了。

    以第一個度量來說,有下面的一個表格:

    CC Value

    Risk

    1-10

    Low risk program

    11-20

    Moderate risk

    21-50

    High risk

    >50

    Most complex and highly unstable method


    CC數值高,可以通過減少if else(switch case也算)判斷來達到目的;
    可以通過減少類與其他類的調用來減少RFC;
    通過分割大方法和大類來達到減少WMPC.

    而Uncle Bob和Jdepend的度量標準應該算是另一個度量系統。

    • 關系內聚性(H)
    用包中的每個類平均的內部關系數目作為包內聚性的一種表示方式。用于表示包和它的所有類之間的關系。
    H=(R+1)/N
    R:包內類的關系數目(與包外部的類沒有關系)
    N:包內類的數量

    • Number of Classes (Cc)
    被分析package的具體和抽象類(和接口)的數量,用于衡量package的可擴展性。

    • Afferent Couplings (Ca)
    依賴于被分析package的其他package的數量,用于衡量pacakge的職責。
    • Efferent Couplings (Ce)
    被分析package的類所依賴的其他package的數量,用于衡量package的獨立性。
    • Abstractness (A)
    被分析package中的抽象類和接口與所在package所有類數量的比例,取值范圍為0-1。
    A=Cc/N
    • Instability (I)
    用于衡量package的不穩定性,取值范圍為0-1。I=0表示最穩定,I=1表示最不穩定。
    I=Ce/(Ce+Ca)
    • Distance (D)
    ??? ??? ? 被分析package和理想曲線A+I=1的垂直距離,用于衡量package在穩定性和抽象性之間的平衡。理想??? ??? ? 的package要么完全是抽象類和穩定(x=0,y=1),要么完全是具體類和不穩定(x=1,y=0)。
    ??? ??? ? 取值范圍為0-1,D=0表示完全符合理想標準,D=1表示package最大程度地偏離了理想標準。
    ??? ?? ?? D = |A+I-1|/0.70710678
    ??? ?? ?? 注:0.70710678*0.70710678 =2,既為“根號2“

    我認為D是一個綜合的度量,架構和設計的改善可以通過D數值的減少來體現,反之就可以認為是設計和架構的退化。


    讀過http://javaboutique.internet.com/tutorials/metrics/index.html之后的一些想法

    另一篇中文的內容相近的文章可以參考http://www.jdon.com/artichect/coupling.htm

    不過第二篇的中文文章中間關于Cyclomatic Complexity,有一個情況遺漏了
    public void findApplications(String id, String name){

    if(id!=null && name!=null) {
    //do something
    }else{
    //do something
    }
    }
    這種情況的CC不是2+1,而是2+1+1,依據是公式(1)。公式(2)應該是公式(1)的簡化版。
    Cyclomatic ComplexityCC) = no of decision points + no of logical operations +1        (1)

    Cyclomatic Complexity (CC) = number of decision points +1 (2)

    參考了JDepend的參數和Uncle Bob的《
    Agile Software Development: Principles, Patterns, and Practices(敏捷軟件開發:原則、模式與實踐)
    posted @ 2006-06-07 10:52 混沌中立 閱讀(1513) | 評論 (3)編輯 收藏
    轉自:http://www.keyusoft.cn/Contentview.aspx?year=2005&month=$10&day=$6&postid=123

    通過一周左右的研究,對規則引擎有了一定的了解。現在寫點東西跟大家一起交流,本文主要針對RETE算法進行描述。我的文筆不太好,如果有什么沒講明白的或是說錯的地方,請給我留言。
    首先申明,我的帖子借鑒了網上很流行的一篇帖子,好像是來自CSDN;還有一點,我不想做太多的名詞解釋,因為我也不是個研究很深的人,定義的不好怕被笑話。
    好現在我們開始。
    首先介紹一些網上對于規則引擎比較好的帖子。
    1、 來自JAVA視頻網
    http://forum.javaeye.com/viewtopic.php?t=7803&postdays=0&postorder=asc&start=0
    2、? RETE算法的最原始的描述,我不知道在哪里找到的,想要的人可以留下E-mail
    3、? CMU的一位博士生的畢業論文,個人覺得非常好,我的很多觀點都是來自這里的,要的人也可以給我發mail? ?mailto:ipointer@163.com
    ?
    接著統一一下術語,很多資料里的術語都非常混亂。
    1、? facts 事實,我們實現的時候,會有一個事實庫。用F表示。
    2、? patterns 模板,事實的一個模型,所有事實庫中的事實都必須滿足模板中的一個。用P表示。
    3、 ? conditions 條件,規則的組成部分。也必須滿足模板庫中的一條模板。用C表示。我們可以這樣理解facts、patterns、conditions之間的關系。 Patterns是一個接口,conditions則是實現這個接口的類,而facts是這個類的實例。
    4、? rules 規則,由一到多個條件構成。一般用and或or連接conditions。用R表示。
    5、? actions 動作,激活一條rule執行的動作。我們這里不作討論。
    6、? 還有一些術語,如:working-memory、production-memory,跟這里的概念大同小異。
    7、? 還有一些,如:alpha-network、beta-network、join-node,我們下面會用到,先放一下,一會討論。
    ?
    引用一下網上很流行的例子,我覺得沒講明白,我在用我的想法解釋一下。
    ?
    假設在規則記憶中有下列三條規則
    ?
    if A(x) and B(x) and C(y) then add D(x)
    if A(x) and B(y) and D(x) then add E(x)
    if A(x) and B(x) and E(x) then delete A(x)
    ?
    RETE算法會先將規則編譯成下列的樹狀架構排序網絡

    而工作記憶內容及順序為{A(1),A(2),B(2),B(3),B(4),C(5)},當工作記憶依序進入網絡后,會依序儲存在符合條件的節點中,直到完全符合條件的推論規則推出推論。以上述例子而言, 最后推得D(2)。
    ?
    讓我們來分析這個例子。
    ?
    模板庫:(這個例子中只有一個模板,算法原描述中有不同的例子, 一般我們會用tuple,元組的形式來定義facts,patterns,condition)
    P: (?A , ?x)? 其中的A可能代表一定的操作,如例子中的A,B,C,D,E ; x代表操作的參數。看看這個模板是不是已經可以描述所有的事實。
    ?
    條件庫:(這里元組的第一項代表實際的操作,第二項代表形參)
    C1: (A , <x>)
    C2: (B , <x>)
    C3: (C , <y>)
    C4: (D , <x>)
    C5: (E , <x>)
    C6: (B , <y>)
    ?
    事實庫:(第二項代表實參)
    F1: (A,1)
    F2: (A,2)
    F3: (B,2)
    F4: (B,3)
    F5: (B,4)
    F6: (C,5)
    ?
    ?????? 規則庫:
    ?????? ? R1: c1^c2^c3
    ?????? ? R2: c1^c2^c4
    ?????? ? R3: c1^c2^c5
    ?
    ??????
    ?????? 有人可能會質疑R1: c1^c2^c3,沒有描述出,原式中:
    if A(x) and B(x) and C(y) then add D(x),A=B的關系。但請仔細看一下,這一點已經在條件庫中定義出來了。
    ?
    ?????? 下面我來描述一下,規則引擎中RETE算法的實現。
    ?????? 首先,我們要定一些規則,根據這些規則,我們的引擎可以編譯出一個樹狀結構,上面的那張圖中是一種簡易的表現,其實在實現的時候不是這個樣子的。
    ?????? 這就是beta-network出場的時候了,根據rules我們就可以確定beta-network,下面,我就畫出本例中的beta-network,為了描述方便,我把alpha-network也畫出來了。
    ??????
    ?
    上圖中,左邊的部分就是beta-network,右邊是alpha-network,圓圈是join-node.
    從上圖中,我們可以驗證,在beta-network中,表現出了rules的內容,其中r1,r2,r3共享了許多BM和join-node,這是由于這些規則中有共同的部分,這樣能加快match的速度。
    右 邊的alpha-network是根據事實庫構建的,其中除alpha-network節點的節點都是根據每一條condition,從事實庫中 match過來的,這一過程是靜態的,即在編譯構建網絡的過程中已經建立的。只要事實庫是穩定的,即沒有大幅度的變化,RETE算法的執行效率應該是非常 高的,其原因就是已經通過靜態的編譯,構建了alpha-network。我們可以驗證一下,滿足c1的事實確實是w1,w2。
    下 面我們就看一下,這個算法是怎么來運行的,即怎么來確定被激活的rules的。從top-node往下遍歷,到一個join-node,與AM for c1的節點匯合,運行到match c1節點。此時,match c1節點的內容就是:w1,w2。繼續往下,與AM for c2匯合(所有可能的組合應該是w1^w3,w1^w4,w1^w5,w2^w3,w2^w4,w2^w5),因為c1^c2要求參數相同,因此, match c1^c2的內容是:w2^w3。再繼續,這里有一個扇出(fan-out),其中只有一個join-node可以被激活,因為旁邊的AM只有一個非空。 因此,也只有R1被激活了。
    解決扇出帶來的效率降低的問題,我們可以使用hashtable來解決這個問題。
    RETE算法還有一些問題,如:facts庫變化,我們怎么才能高效的重建alpha-network,同理包括rules的變化對beta-network的影響。這一部分我還沒細看,到時候再貼出來吧。
    posted @ 2006-05-30 15:30 混沌中立 閱讀(1048) | 評論 (2)編輯 收藏
    最近插件又加多了,eclipse老是死掉
    ?
    一怒之下,刪除重裝
    ?
    以前因為懶,沒有把插件的目錄和主體的目錄分開,這次也給它分開了
    ?
    ?
    插件少了之后,eclipse確實快了不少
    ?
    附eclipse啟動參數: -nl en_US vmargs -Xverify:none -Xms256M -Xmx1024M -XX:PermSize=50M? -XX:+UseParallelGC
    posted @ 2006-05-30 13:48 混沌中立 閱讀(568) | 評論 (0)編輯 收藏
    freemind一個比較不錯free的 mind map 軟件,很多人建議使用這個來管理自己的思路.
    ?
    mind manager另一個比較不錯的mind map的軟件,可以和office兼容.不過是商業的
    ?
    visio,就不介紹了.office里面有的東西.做流程圖來說,確實是比較好的軟件.但是在思路不清楚的時候,很難畫出什么有用的東西來.這點就比不上前面兩個東西了.不過對我來說visio可能更順手,因為我經常畫的是軟件流程圖........
    posted @ 2006-05-30 13:36 混沌中立 閱讀(1755) | 評論 (2)編輯 收藏
    總結一下最近關于domain object以及相關的討論
    ?
    在最近的圍繞domain object的討論中浮現出來了三種模型,(還有一些其他的旁枝,不一一分析了),經過一番討論,各種問題逐漸清晰起來,在這里我試圖做一個總結,便于大家了解和掌握。

    第一種模型:只有getter/setter方法的純數據類,所有的業務邏輯完全由business object來完成(又稱TransactionScript),這種模型下的domain object被Martin Fowler稱之為“貧血的domain object”。下面用舉一個具體的代碼來說明,代碼來自Hibernate的caveatemptor,但經過我的改寫:

    一個實體類叫做Item,指的是一個拍賣項目
    一個DAO接口類叫做ItemDao
    一個DAO接口實現類叫做ItemDaoHibernateImpl
    一個業務邏輯類叫做ItemManager(或者叫做ItemService)

    java代碼:?

    public class Item implementsSerializable{
    ? ? privateLong id = null;
    ? ? privateint version;
    ? ? privateString name;
    ? ? private User seller;
    ? ? privateString description;
    ? ? private MonetaryAmount initialPrice;
    ? ? private MonetaryAmount reservePrice;
    ? ? privateDate startDate;
    ? ? privateDate endDate;
    ? ? privateSet categorizedItems = newHashSet();
    ? ? privateCollection bids = newArrayList();
    ? ? private Bid successfulBid;
    ? ? private ItemState state;
    ? ? private User approvedBy;
    ? ? privateDate approvalDatetime;
    ? ? privateDate created = newDate();
    ? ? //? getter/setter方法省略不寫,避免篇幅太長
    }



    java代碼:?

    public interface ItemDao {
    ? ? public Item getItemById(Long id);
    ? ? publicCollection findAll();
    ? ? publicvoid updateItem(Item item);
    }



    ItemDao定義持久化操作的接口,用于隔離持久化代碼。

    java代碼:?

    public class ItemDaoHibernateImpl implements ItemDao extends HibernateDaoSupport {
    ? ? public Item getItemById(Long id){
    ? ? ? ? return(Item) getHibernateTemplate().load(Item.class, id);
    ? ? }
    ? ? publicCollection findAll(){
    ? ? ? ? return(List) getHibernateTemplate().find("from Item");
    ? ? }
    ? ? publicvoid updateItem(Item item){
    ? ? ? ? getHibernateTemplate().update(item);
    ? ? }
    }


    ItemDaoHibernateImpl完成具體的持久化工作,請注意,數據庫資源的獲取和釋放是在ItemDaoHibernateImpl 里面處理的,每個DAO方法調用之前打開Session,DAO方法調用之后,關閉Session。(Session放在ThreadLocal中,保證一次調用只打開關閉一次)

    java代碼:?

    public class ItemManager {
    ? ? private ItemDao itemDao;
    ? ? publicvoid setItemDao(ItemDao itemDao){ this.itemDao = itemDao;}
    ? ? public Bid loadItemById(Long id){
    ? ? ? ? itemDao.loadItemById(id);
    ? ? }
    ? ? publicCollection listAllItems(){
    ? ? ? ? return? itemDao.findAll();
    ? ? }
    ? ? public Bid placeBid(Item item, User bidder, MonetaryAmount bidAmount,
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? Bid currentMaxBid, Bid currentMinBid)throws BusinessException {
    ? ? ? ? ? ? if(currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0){
    ? ? ? ? ? ? throw new BusinessException("Bid too low.");
    ? ? }
    ? ?
    ? ? // Auction is active
    ? ? if( !state.equals(ItemState.ACTIVE))
    ? ? ? ? ? ? throw new BusinessException("Auction is not active yet.");
    ? ?
    ? ? // Auction still valid
    ? ? if( item.getEndDate().before(newDate()))
    ? ? ? ? ? ? throw new BusinessException("Can't place new bid, auction already ended.");
    ? ?
    ? ? // Create new Bid
    ? ? Bid newBid = new Bid(bidAmount, item, bidder);
    ? ?
    ? ? // Place bid for this Item
    ? ? item.getBids().add(newBid);
    ? ? itemDao.update(item);? ? ?//? 調用DAO完成持久化操作
    ? ? return newBid;
    ? ? }
    }



    事務的管理是在ItemManger這一層完成的,ItemManager實現具體的業務邏輯。除了常見的和CRUD有關的簡單邏輯之外,這里還有一個placeBid的邏輯,即項目的競標。

    以上是一個完整的第一種模型的示例代碼。在這個示例中,placeBid,loadItemById,findAll等等業務邏輯統統放在ItemManager中實現,而Item只有getter/setter方法。

    ?

    ?

    第二種模型,也就是Martin Fowler指的rich domain object是下面這樣子的:

    一個帶有業務邏輯的實體類,即domain object是Item
    一個DAO接口ItemDao
    一個DAO實現ItemDaoHibernateImpl
    一個業務邏輯對象ItemManager

    java代碼:?

    public class Item implementsSerializable{
    ? ? //? 所有的屬性和getter/setter方法同上,省略
    ? ? public Bid placeBid(User bidder, MonetaryAmount bidAmount,
    ? ? ? ? ? ? ? ? ? ? ? ? Bid currentMaxBid, Bid currentMinBid)
    ? ? ? ? ? ? throws BusinessException {
    ? ?
    ? ? ? ? ? ? // Check highest bid (can also be a different Strategy (pattern))
    ? ? ? ? ? ? if(currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0){
    ? ? ? ? ? ? ? ? ? ? throw new BusinessException("Bid too low.");
    ? ? ? ? ? ? }
    ? ?
    ? ? ? ? ? ? // Auction is active
    ? ? ? ? ? ? if( !state.equals(ItemState.ACTIVE))
    ? ? ? ? ? ? ? ? ? ? throw new BusinessException("Auction is not active yet.");
    ? ?
    ? ? ? ? ? ? // Auction still valid
    ? ? ? ? ? ? if( this.getEndDate().before(newDate()))
    ? ? ? ? ? ? ? ? ? ? throw new BusinessException("Can't place new bid, auction already ended.");
    ? ?
    ? ? ? ? ? ? // Create new Bid
    ? ? ? ? ? ? Bid newBid = new Bid(bidAmount, this, bidder);
    ? ?
    ? ? ? ? ? ? // Place bid for this Item
    ? ? ? ? ? ? this.getBids.add(newBid);? // 請注意這一句,透明的進行了持久化,但是不能在這里調用ItemDao,Item不能對ItemDao產生依賴!
    ? ?
    ? ? ? ? ? ? return newBid;
    ? ? }
    }



    競標這個業務邏輯被放入到Item中來。請注意this.getBids.add(newBid); 如果沒有Hibernate或者JDO這種O/R Mapping的支持,我們是無法實現這種透明的持久化行為的。但是請注意,Item里面不能去調用ItemDAO,對ItemDAO產生依賴!

    ItemDao和ItemDaoHibernateImpl的代碼同上,省略。

    java代碼:?

    public class ItemManager {
    ? ? private ItemDao itemDao;
    ? ? publicvoid setItemDao(ItemDao itemDao){ this.itemDao = itemDao;}
    ? ? public Bid loadItemById(Long id){
    ? ? ? ? itemDao.loadItemById(id);
    ? ? }
    ? ? publicCollection listAllItems(){
    ? ? ? ? return? itemDao.findAll();
    ? ? }
    ? ? public Bid placeBid(Item item, User bidder, MonetaryAmount bidAmount,
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? Bid currentMaxBid, Bid currentMinBid)throws BusinessException {
    ? ? ? ? item.placeBid(bidder, bidAmount, currentMaxBid, currentMinBid);
    ? ? ? ? itemDao.update(item);? ? // 必須顯式的調用DAO,保持持久化
    ? ? }
    }



    在第二種模型中,placeBid業務邏輯是放在Item中實現的,而loadItemById和findAll業務邏輯是放在 ItemManager中實現的。不過值得注意的是,即使placeBid業務邏輯放在Item中,你仍然需要在ItemManager中簡單的封裝一層,以保證對placeBid業務邏輯進行事務的管理和持久化的觸發。

    這種模型是Martin Fowler所指的真正的domain model。在這種模型中,有三個業務邏輯方法:placeBid,loadItemById和findAll,現在的問題是哪個邏輯應該放在Item 中,哪個邏輯應該放在ItemManager中。在我們這個例子中,placeBid放在Item中(但是ItemManager也需要對它進行簡單的封裝),loadItemById和findAll是放在ItemManager中的。

    切分的原則是什么呢? Rod Johnson提出原則是“case by case”,可重用度高的,和domain object狀態密切關聯的放在Item中,可重用度低的,和domain object狀態沒有密切關聯的放在ItemManager中。

    我提出的原則是:看業務方法是否顯式的依賴持久化。

    Item的placeBid這個業務邏輯方法沒有顯式的對持久化ItemDao接口產生依賴,所以要放在Item中。請注意,如果脫離了Hibernate這個持久化框架,Item這個domain object是可以進行單元測試的,他不依賴于Hibernate的持久化機制。它是一個獨立的,可移植的,完整的,自包含的域對象

    而loadItemById和findAll這兩個業務邏輯方法是必須顯式的對持久化ItemDao接口產生依賴,否則這個業務邏輯就無法完成。如果你要把這兩個方法放在Item中,那么Item就無法脫離Hibernate框架,無法在Hibernate框架之外獨立存在。

    ?

    ?

    第三種模型印象中好像是firebody或者是Archie提出的(也有可能不是,記不清楚了),簡單的來說,這種模型就是把第二種模型的domain object和business object合二為一了。所以ItemManager就不需要了,在這種模型下面,只有三個類,他們分別是:

    Item:包含了實體類信息,也包含了所有的業務邏輯
    ItemDao:持久化DAO接口類
    ItemDaoHibernateImpl:DAO接口的實現類

    由于ItemDao和ItemDaoHibernateImpl和上面完全相同,就省略了。

    java代碼:?

    public class Item implementsSerializable{
    ? ? //? 所有的屬性和getter/setter方法都省略
    ? ?privatestatic ItemDao itemDao;
    ? ? publicvoid setItemDao(ItemDao itemDao){this.itemDao = itemDao;}
    ? ?
    ? ? publicstatic Item loadItemById(Long id){
    ? ? ? ? return(Item) itemDao.loadItemById(id);
    ? ? }
    ? ? publicstaticCollection findAll(){
    ? ? ? ? return(List) itemDao.findAll();
    ? ? }

    ? ? public Bid placeBid(User bidder, MonetaryAmount bidAmount,
    ? ? ? ? ? ? ? ? ? ? Bid currentMaxBid, Bid currentMinBid)
    ? ? throws BusinessException {
    ? ?
    ? ? ? ? // Check highest bid (can also be a different Strategy (pattern))
    ? ? ? ? if(currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0){
    ? ? ? ? ? ? ? ? throw new BusinessException("Bid too low.");
    ? ? ? ? }
    ? ? ? ?
    ? ? ? ? // Auction is active
    ? ? ? ? if( !state.equals(ItemState.ACTIVE))
    ? ? ? ? ? ? ? ? throw new BusinessException("Auction is not active yet.");
    ? ? ? ?
    ? ? ? ? // Auction still valid
    ? ? ? ? if( this.getEndDate().before(newDate()))
    ? ? ? ? ? ? ? ? throw new BusinessException("Can't place new bid, auction already ended.");
    ? ? ? ?
    ? ? ? ? // Create new Bid
    ? ? ? ? Bid newBid = new Bid(bidAmount, this, bidder);
    ? ? ? ?
    ? ? ? ? // Place bid for this Item
    ? ? ? ? this.addBid(newBid);
    ? ? ? ? itemDao.update(this);? ? ? //? 調用DAO進行顯式持久化
    ? ? ? ? return newBid;
    ? ? }
    }



    在這種模型中,所有的業務邏輯全部都在Item中,事務管理也在Item中實現。

    ?

    ?

    在上面三種模型之外,還有很多這三種模型的變種,例如partech的模型就是把第二種模型中的DAO和 Manager三個類合并為一個類后形成的模型;例如frain....(id很長記不住)的模型就是把第三種模型的三個類完全合并為一個單類后形成的模型;例如Archie是把第三種模型的Item又分出來一些純數據類(可能是,不確定)形成的一個模型。

    但是不管怎么變,基本模型歸納起來就是上面的三種模型,下面分別簡單評價一下:

    第一種模型絕大多數人都反對,因此反對理由我也不多講了。但遺憾的是,我觀察到的實際情形是,很多使用Hibernate的公司最后都是這種模型,這里面有很大的原因是很多公司的技術水平沒有達到這種層次,所以導致了這種貧血模型的出現。從這一點來說,Martin Fowler的批評聲音不是太響了,而是太弱了,還需要再繼續吶喊。

    第二種模型就是Martin Fowler一直主張的模型,實際上也是我一直在實際項目中采用這種模型。我沒有看過Martin的POEAA,之所以能夠自己摸索到這種模型,也是因為從02年我已經開始思考這個問題并且尋求解決方案了,但是當時沒有看到Hibernate,那時候做的一個小型項目我已經按照這種模型來做了,但是由于沒有O/R Mapping的支持,寫到后來又不得不全部改成貧血的domain object,項目做完以后再繼續找,隨后就發現了Hibernate。當然,現在很多人一開始就是用Hibernate做項目,沒有經歷過我經歷的那個階段。

    不過我覺得這種模型仍然不夠完美,因為你還是需要一個業務邏輯層來封裝所有的domain logic,這顯得非常羅嗦,并且業務邏輯對象的接口也不夠穩定。如果不考慮業務邏輯對象的重用性的話(業務邏輯對象的可重用性也不可能好),很多人干脆就去掉了xxxManager這一層,在Web層的Action代碼直接調用xxxDao,同時容器事務管理配置到Action這一層上來。 Hibernate的caveatemptor就是這樣架構的一個典型應用。

    第三種模型是我很反對的一種模型,這種模型下面,Domain Object和DAO形成了雙向依賴關系,無法脫離框架測試,并且業務邏輯層的服務也和持久層對象的狀態耦合到了一起,會造成程序的高度的復雜性,很差的靈活性和糟糕的可維護性。也許將來技術進步導致的O/R Mapping管理下的domain object發展到足夠的動態持久透明化的話,這種模型才會成為一個理想的選擇。就像O/R Mapping的流行使得第二種模型成為了可能(O/R Mapping流行以前,我們只能用第一種模型,第二種模型那時候是不現實的)。

    ?

    ?

    既然大家都統一了觀點,那么就有了一個很好的討論問題的基礎了。Martin Fowler的Domain Model,或者說我們的第二種模型難道是完美無缺的嗎?當然不是,接下來我就要分析一下它的不足,以及可能的解決辦法,而這些都來源于我個人的實踐探索。

    在第二種模型中,我們可以清楚的把這4個類分為三層:

    1、實體類層,即Item,帶有domain logic的domain object
    2、DAO層,即ItemDao和ItemDaoHibernateImpl,抽象持久化操作的接口和實現類
    3、業務邏輯層,即ItemManager,接受容器事務控制,向Web層提供統一的服務調用

    在這三層中我們大家可以看到,domain object和DAO都是非常穩定的層,其實原因也很簡單,因為domain object是映射數據庫字段的,數據庫字段不會頻繁變動,所以domain object也相對穩定,而面向數據庫持久化編程的DAO層也不過就是CRUD而已,不會有更多的花樣,所以也很穩定。

    問題就在于這個充當business workflow facade的業務邏輯對象,它的變動是相當頻繁的。業務邏輯對象通常都是無狀態的、受事務控制的、Singleton類,我們可以考察一下業務邏輯對象都有哪幾類業務邏輯方法:

    第一類:DAO接口方法的代理,就是上面例子中的loadItemById方法和findAll方法。

    ItemManager之所以要代理這種類,目的有兩個:向Web層提供統一的服務調用入口點和給持久化方法增加事務控制功能。這兩點都很容易理解,你不能既給Web層程序員提供xxxManager,也給他提供xxxDao,所以你需要用xxxManager封裝xxxDao,在這里,充當了一個簡單代理功能;而事務控制也是持久化方法必須的,事務可能需要跨越多個DAO方法調用,所以必須放在業務邏輯層,而不能放在DAO層。

    但是必須看到,對于一個典型的web應用來說,絕大多數的業務邏輯都是簡單的CRUD邏輯,所以這種情況下,針對每個DAO方法,xxxManager都需要提供一個對應的封裝方法,這不但是非常枯燥的,也是令人感覺非常不好的。


    第二類:domain logic的方法代理。就是上面例子中placeBid方法。雖然Item已經有了placeBid方法,但是ItemManager仍然需要封裝一下Item的placeBid,然后再提供一個簡單封裝之后的代理方法。

    這和第一種情況類似,其原因也一樣,也是為了給Web層提供一個統一的服務調用入口點和給隱式的持久化動作提供事務控制。

    同樣,和第一種情況一樣,針對每個domain logic方法,xxxManager都需要提供一個對應的封裝方法,同樣是枯燥的,令人不爽的。


    第三類:需要多個domain object和DAO參與協作的business workflow。這種情況是業務邏輯對象真正應該完成的職責。

    在這個簡單的例子中,沒有涉及到這種情況,不過大家都可以想像的出來這種應用場景,因此不必舉例說明了。

    通過上面的分析可以看出,只有第三類業務邏輯方法才是業務邏輯對象真正應該承擔的職責,而前兩類業務邏輯方法都是“無奈之舉”,不得不為之的事情,不但枯燥,而且令人沮喪。




    分析完了業務邏輯對象,我們再回頭看一下domain object,我們要仔細考察一下domain logic的話,會發現domain logic也分為兩類:

    第一類:需要持久層框架隱式的實現透明持久化的domain logic,例如Item的placeBid方法中的這一句:

    java代碼:?

    this.getBids().add(newBid);


    上面已經著重提到,雖然這僅僅只是一個Java集合的添加新元素的操作,但是實際上通過事務的控制,會潛在的觸發兩條SQL:一條是insert一條記錄到bid表,一條是更新item表相應的記錄。如果我們讓Item脫離Hibernate進行單元測試,它就是一個單純的Java集合操作,如果我們把他加入到Hibernate框架中,他就會潛在的觸發兩條SQL,這就是隱式的依賴于持久化的domain logic
    特別請注意的一點是:在沒有Hibernate/JDO這類可以實現“透明的持久化”工具出現之前,這類domain logic是無法實現的。

    對于這一類domain logic,業務邏輯對象必須提供相應的封裝方法,以實現事務控制。


    第二類:完全不依賴持久化的domain logic,例如readonly例子中的Topic,如下:

    java代碼:?

    class Topic {
    ? ? boolean isAllowReply(){
    ? ? ? ? Calendar dueDate = Calendar.getInstance();
    ? ? ? ? dueDate.setTime(lastUpdatedTime);
    ? ? ? ? dueDate.add(Calendar.DATE, forum.timeToLive);
    ? ?
    ? ? ? ? Date now = newDate();
    ? ? ? ? return now.after(dueDate.getTime());
    ? ? }
    }



    注意這個isAllowReply方法,他和持久化完全不發生一丁點關系。在實際的開發中,我們同樣會遇到很多這種不需要持久化的業務邏輯(主要發生在日期運算、數值運算和枚舉運算方面),這種domain logic不管脫離不脫離所在的框架,它的行為都是一致的。對于這種domain logic,業務邏輯層并不需要提供封裝方法,它可以適用于任何場合。
    posted @ 2006-05-30 13:31 混沌中立 閱讀(3058) | 評論 (1)編輯 收藏

    原文地址:http://www.cnblogs.com/idior/archive/2005/07/04/186086.html

    近日?有關o/r?m的討論突然多了起來.?在這里覺得有必要澄清一些概念,?免的大家討論來討論去,?才發現最根本的理解有問題.

    1.?何謂實體?
    實體(類似于j2ee中的Entity?Bean)通常指一個承載數據的對象,?但是注意它也是可以有行為的!?只不過它的行為一般只操作自身的數據.?比如下面這個例子:


    class?Person
    {
    ??string?firstName;
    ??string?lastName;

    ??public?void?GetName()
    ??{
    ?????return??lastName+firstName;
    ??}???
    }


    GetName就是它的一個行為.

    2?何謂對象?
    對象最重要的特性在于它擁有行為.?僅僅擁有數據,你可以稱它為對象,?但是它卻失去它最重要的靈魂.?


    class?Person
    {
    ??string?firstName;
    ??string?lastName;
    ??Role?role;
    ??int?baseWage;
    ??public?void?GetSalary()
    ??{
    ?????return?baseWage*role.GetFactory();
    ??}???
    }

    這樣需要和別的對象(不是Value?Object)打交道的對象,我就不再稱其為實體.?領域模型就是指由這些具有業務邏輯的對象構成的模型.

    3.?E/R?M?or?O/R?M?!!
    仔細想想我們為什么需要o/r?m,無非是想利用oo的多態來處理復雜的業務邏輯,?而不是靠一堆的if?else.?
    而現在在很多人的手上o/r?m全變成了e/r?m.他們不考慮對象的行為,?而全關注于如何保存數據.這樣也難怪他們會產生將CRUD這些操作放入對象中的念頭.?如果你不能深刻理解oo,?那么我不推薦你使用o/r?m,?Table?Gateway,?Row?Gateway才是你想要的東西.


    作為一個O/R?M框架,很重要的一點就是實現映射的透明性(Transparent),比較顯著的特點就是在代碼中我們是看不到SQL語句的(框架自動生成了)。這里所指的O/R?M就是類似于此的框架,

    4.?POEAA中的相關概念
    ??很多次發現有人錯用其中的概念,?這里順便總結一下:
    ??1.?Table?Gateway
    ????以表為單位的實體,基本沒有行為,只有CRUD操作.
    ??2.?Row?Gateway
    ????以行為單位的實體,基本沒有行為,只有CRUD操作.
    ??3.?Active?Record
    ????以行為單位的實體,擁有一些基本的操作自身數據的行為(如上例中的GetName),同時包含有CRUD操作.
    其實Active?Record最符合某些簡單的需求,?接近于E/R?m.
    通常也有很多人把它當作O/R?m.不過需要注意的是Active?Record中是充滿了SQL語句的(不像orm的SQL透明),?所以有人想起來利用O/R?m來實現"Active?Record",?雖然在他們眼里看起來很方便,?其實根本就是返祖.
    用CodeGenerator來實現Active?Record也許是一個比較好的方法.
    ??4.?Data?Mapper
    這才是真正的O/R?m,Hibernate等等工具的目標.

    5.O/R?M需要關注的地方?(希望大家幫忙完善一下)
    ?1.?關聯,?O/R?M是如何管理類之間的關聯.當然這不僅于o/r?m有關與設計者的設計水平也有很大關系.
    ?2.?O/R?M對繼承關系的處理.
    ?3.?O/R?M對事務的支持.
    ?4.?O/R?M對查詢的支持.
    ?
    以上觀點僅屬個人意見,?不過在大家討論有關O/R?m之前,?希望先就一些基本概念達成共識,?不然討論下去會越離越遠.?


    (建議:?如果對oo以及dp沒有一定程度的了解,?最好別使用o/r?m,?dataset?加上codesmith或許是更好的選擇)
    posted @ 2006-05-30 13:20 混沌中立 閱讀(380) | 評論 (0)編輯 收藏

    from http://www.code365.com/web/122/Article/17927.Asp


    Thomas Bayes,一位偉大的數學大師,他的理論照亮了今天的計算領域,和他的同事們不同:他認為上帝的存在可以通過方程式證明,他最重要的作品被別人發行,而他已經去世241年了。

    18世紀牧師們關于概率的理論成為應用發展的數學基礎的一部分。

    搜索巨人Google和Autonomy,一家出售信息恢復工具的公司,都使用了貝葉斯定理(Bayesian principles)為數據搜索提供近似的(但是技術上不確切)結果。研究人員還使用貝葉斯模型來判斷癥狀和疾病之間的相互關系,創建個人機器人,開發 能夠根據數據和經驗來決定行動的人工智能設備。

    雖然聽起來很深奧,而這個原理的意思--大致說起來--卻很簡單:某件事情發生的概率大致可以由它過去發生的頻率近似地估計出來。研究人員把這個原理應用在每件事上,從基因研究到過濾電子郵件。

    在明尼蘇達州大學的網站上能夠找到一份詳細的數學概要。而在Gametheory.net上的一個Bayes Rule Applet程序讓你能夠回答諸如“如果你測試某種疾病,有多大風險”之類的問題。

    貝葉斯理論的一個出名的倡導者就是微軟。該公司把概率用于它的Notification Platform。該技術將會被內置到微軟未來的軟件中,而且讓計算機和蜂窩電話能夠自動地過濾信息,不需要用戶幫助,自動計劃會議并且和其他人聯系。

    如果成功的話,該技術將會導致“context server”--一種電子管家的出現,它能夠解釋人的日常生活習慣并在不斷變換的環境中組織他們的生活。

    “Bayes的研究被用于決定我應該怎樣最好地分配計算和帶寬,” Eric Horvitz表示,他是微軟研究部門Adaptive Systems & Interaction Group的高級研究員和分組管理者。“我個人相信在這個不確定的世界里,你不能夠知道每件事,而概率論是任何智能的基礎。”

    到今年年底,Intel也將發布它自己的基于貝葉斯理論的工具包。一個關于照相機的實驗警告醫生說病人可能很快遭受痛苦。在本周晚些時候在該公司的Developer Forum(開發者論壇)上將討論這種發展。

    雖然它在今天很流行,Bayes的理論并不是一直被廣泛接受的:就在10年前,Bayes研究人員還在他們的專業上躊躇不前。但是其后,改進的數學模型,更快的計算機和實驗的有效結果增加了這種學派新的可信程度。

    “問題之一是它被過度宣傳了,” Intel微處理器實驗室的應用軟件和技術管理經理Omid Moghadam表示。“事實上,能夠處理任何事情的能力并不存在。真正的執行在過去的10年里就發生了。”

    Bayes啞元
    Bayes的理論可以粗略地被簡述成一條原則:為了預見未來,必須要看看過去。Bayes的理論表示未來某件事情發生的概率可以通過計算它過去發生的頻率來估計。一個彈起的硬幣正面朝上的概率是多少?實驗數據表明這個值是50%。

    “Bayes表示從本質上說,每件事都有不確定性,你有不同的概率類型,”斯坦佛的管理科學和工程系(Department of Management Science and Engineering at Stanford)的教授Ron Howard表示。

    例如,假設不是硬幣,一名研究人員把塑料圖釘往上拋,想要看看它釘頭朝上落地的概率有多大,或者有多少可能性是側面著地,而釘子是指向什么方向的。形狀,成型過程中的誤差,重量分布和其他的因素都會影響該結果。

    Bayes技術的吸引力在于它的簡單性。預測完全取決于收集到的數據--獲得的數據越多,結果就越好。另一個優點在于Bayes模型能夠自我糾正,也就是說數據變化了,結果也就跟著變化。

    概率論的思想改變了人們和計算機互動的方式。“這種想法是計算機能夠更象一個幫助者而不僅僅是一個終端設備,” Peter Norvig表示。他是Google的安全質量總監。他說“你在尋找的是一些指導,而不是一個標準答案。”

    從這種轉變中,研究獲益非淺。幾年前,所謂的Boolean搜索引擎的一般使用需要把搜索按照“if, and, or but”的語法進行提交,然后去尋找匹配的詞。現在的搜索引擎采用了復雜的運算法則來搜索數據庫,并找出可能的匹配。

    如同圖釘的那個例子顯示的那樣,復雜性和對于更多數據的需要可能很快增長。由于功能強大的計算機的出現,對于把好的猜測轉變成近似的輸出所必須的結果進行控制成為可能。

    更重要的是,UCLA的Judea Pearl這樣的研究人員研究出如何讓Bayes模型能夠更好地追蹤不同的現象之間條件關系的方法,這樣能夠極大地減少計算量。

    例如,對于人口進行大規模的關于肺癌成因的調查可能會發現它是一種不太廣泛的疾病,但是如果局限在吸煙者范圍內進行調查就可能會發現一些關聯性。對于肺癌患者進行檢查能夠幫助調查清楚習慣和這種疾病之間的關系。

    “每一個單獨的屬性或者征兆都可能取決于很多不同的事情,但是直接決定它的卻是為數不多的事情,”斯坦佛計算機科學系(computer science department at Stanford)的助理教授Daphne Koller表示。“在過去的15年左右的時間里,人們在工具方面進行了改革,這讓你能夠描繪出大量人群的情況。”

    和其他一些項目一樣,Koller是使用概率論技術來更好地把病癥和疾病聯系起來,并把遺傳基因和特定的細胞現象聯系起來。

    記錄演講
    一項相關的技術,名為Hidden Markov模型,讓概率能夠預測次序。例如,一個演講識別應用知道經常在“q”之后的字母是“u”。除了這些,該軟件還能夠計算“Qagga”(一種滅絕了的斑馬的名稱)一詞出現的概率。

    概率技術已經內置在微軟的產品中了。Outlook Mobile Manage是一個能夠決定什么時候往移動設備上發出一封內勤的電子郵的軟件。它是從Priorities發展而來的,Priorities是微軟在 1998年公布的一個實驗系統。Windows XP的故障檢修引擎也依賴于概率計算。

    隨著該公司的Notification Platform開始內置在產品中,在未來的一年中會有更多的應用軟件發布,微軟的Horvitz這樣表示。

    Notification Platform的一個重要組成部分名為Coordinate,它從個人日歷,鍵盤,傳感器照相機以及其他來源收集數據,來了解某個人生活和習慣。收集的 數據可能包括到達的時間,工作時間和午餐的時間長度,哪種類型的電話或電子郵件被保存,而哪些信息被刪除,在某天的特定時間里鍵盤被使用的頻率,等等。

    這些數據可以被用來管理信息流和使用者收到的其他信息。例如,如果一位經理在下午2:40發送了一封電子郵件給一名員工, Coordinate可以檢查該員工的日歷程序,然后發現他在下午2:00有一個會議。該程序還可以掃描關于該員工習慣的數據,然后發現該員工通常會在有 會議之后大約一個小時才重新使用鍵盤。該程序可能還能夠發現該名員工通常會在5分鐘之內回復該經理的電子郵件。根據上面這些數據,該軟件能夠估計出該員工 可能至少在20分鐘之內不可能回復該電子郵件,該軟件可能會把這條信息發送到該員工的手提電話上。同時,該軟件可能會決定不把別人的電子郵件也轉發出去。

    “我們正在平衡以打攪你為代價所獲得信息的價值,” Horvitz表示。使用這個軟件,他堅持道,“能夠讓更多的人跟上事情的發展,而不被大量的信息所淹沒。”

    Horvitz補充道,隱私和對于這些功能的用戶控制是確定的。呼叫者并不知道為什么一條信息可能會被優先或推遲處理。

    微軟還把Bayes模型使用在其他的一些產品上,包括DeepListener 以及Quartet (語音激活),SmartOOF 以及TimeWave (聯系控制)。消費者多媒體軟件也獲益非淺,Horvitz表示。

    Bayes技術不僅僅被應用在PC領域。在University of Rochester,研究人員發現一個人的步伐可以在一步前發生改變。雖然這種改變對于人類來說太過于細微,一臺和電腦連接在一起的照相機可以捕捉并跟蹤 這種動作。如果行走異常出現,計算機就能夠發出警報。

    一個實驗用的安全照相機采用了同樣的原理:大部分到達機場的人都會在停車以后直接走向目的地,所以如果有人停了車,然后走向另一輛車就不太正常,因此就可能引發警報。今年秋天一個創建Bayes模型和技術信息的基本引擎將會公布在Intel的開發者網站上。

    理論沖突
    雖然該技術聽起來簡單易懂,關于它的計算可能卻比較慢。Horvitz回憶說他是斯坦佛20世紀80年代僅有的兩個概率和人工智能的畢業生之一。其他所有的人學習的是邏輯系統,采用的是“if and then”的模式和世界互動。

    “概率論那時候不流行,” Horvitz表示。但是當邏輯系統不能夠預測所有的意外情況時,潮流發生了轉變。

    很多研究人員開始承認人類的決策過程比原來想象的要神秘的多。“在人工智能領域存在著文化偏見,” Koller表示。“人們現在承認他們并不知道他們的腦子是如何工作的。”

    即便在他的時代,Bayes發現他自己置身于主流之外。他于1702年出生于倫敦,后來他成為了一名Presbyterian minister。雖然他看到了自己的兩篇論文被發表了,他的理論很有效,但是《Essay Toward Solving a Problem in the Doctrine of Chances》卻一直到他死后的第三年,也就是1764年才被發表。

    他的王室成員身份一直是個謎,直到最近幾年,新發現的一些信件表明他私下和英格蘭其他一些思想家看法一致。

    “就我所知,他從來沒有寫下貝葉斯定理,” Howard表示。

    神學家Richard Price和法國的數學家Pierre Simon LaPlace成為了早期的支持者。該理論和后來George Boole,布爾數學之父,的理論背道而馳。George Boole的理論是基于代數邏輯的,并最終導致了二進制系統的誕生。也是皇室成員之一的Boole死于1864年。

    雖然概率的重要性不容置疑,可是關于它的應用的爭論卻沒有停止過。批評者周期性地聲稱Bayes模型依賴于主觀的數據,而讓人類去判斷答案是否正確。而概率論模型沒有完全解決在人類思維過程中存在的細微差別的問題。

    “兒童如何學習現在還不是很清楚,”IBM研究部門的科學和軟件副總裁 Alfred Spector這樣表示。他計劃把統計學方法和邏輯系統在他的Combination Hypothesis之中結合起來。“我最初相信是統計學的范疇,但是從某方面說,你將會發現不僅僅是統計學的問題。”

    但是,很有可能概率論是基礎。

    “這是個基礎,” Horvitz表示。“它被忽略了一段時間,但是它是推理的基礎。”

    posted @ 2006-05-30 12:51 混沌中立 閱讀(435) | 評論 (0)編輯 收藏
    主站蜘蛛池模板: 免费一级毛片正在播放| 污污网站18禁在线永久免费观看| 亚洲欧洲免费无码| 麻豆狠色伊人亚洲综合网站| 亚洲一区电影在线观看| 亚洲人成在久久综合网站| 亚洲午夜精品国产电影在线观看| 91嫩草亚洲精品| 99999久久久久久亚洲| 日韩亚洲不卡在线视频中文字幕在线观看 | 亚洲人成电影网站免费| 亚洲熟女综合色一区二区三区| 亚洲色大成网站www尤物| 亚洲精品理论电影在线观看| 亚洲av无一区二区三区| 精品久久亚洲一级α| 免费一级做a爰片久久毛片潮| 又硬又粗又长又爽免费看| 久久WWW免费人成—看片| 国产在线观看免费av站| 日本视频在线观看永久免费| 亚洲黄色免费在线观看| 毛片免费观看的视频在线| 国产免费人成视频在线观看 | 中文字幕无码播放免费| 午夜免费福利网站| 亚洲毛片网址在线观看中文字幕 | 亚洲电影日韩精品| 久久精品国产亚洲麻豆| 亚洲美女大bbbbbbbbb| 亚洲a∨无码男人的天堂| 国产精品亚洲色图| 免费在线黄色电影| free哆啪啪免费永久| 日韩伦理片电影在线免费观看| 亚洲精品人成无码中文毛片| 亚洲国产精品高清久久久| 亚洲男女一区二区三区| 欧美激情综合亚洲一二区| 成人无码区免费A∨直播| 免费观看美女用震蛋喷水的视频|