走在架構師的大道上 Jack.Wang's home

          Java, C++, linux c, C#.net 技術,軟件架構,領域建模,IT 項目管理 Dict.CN 在線詞典, 英語學習, 在線翻譯

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
          面向組件的架構,這篇文章很不錯,轉載下。。http://yfzhu.itpub.net/post/891/16702

          2004 年 3 月
          在中小規模的軟件中,對象和對象之間的協作關系就能夠滿足需要。但是當軟件規模擴大,復雜度上升的時候,面向對象技術強調的協作卻表現出另一個極端的特點-耦合度太高導致的復雜度。這時候就需要有一種新的方法來彌補面向對象技術的弱點。

          大規模軟件的特點

          大規模軟件主要特點是復雜度。比較典型的例子是集成性的項目。軟件系統需要將各種各樣的硬件、遺留系統、外部接口整合起來。其間可能遇到不同的硬件接口,不同的操作系統,不同的語言,不同的平臺,不同的數據庫,不同的消息中間件,不同的網絡介質。這些都使得系統變得非常的復雜。

          面向對象技術的特點是通過對象之間的職責分工和高度協作來完成任務。這樣的好處是代碼量較少,系統布局合理,重用程度高。但是當對象的個數大量增加的時候,對象之間的高度耦合的關系將會使得系統變得復雜,難以理解。

          以前對于這個問題的方法是采用包(請參考拙作面向對象軟件開發中對包的相關討論)作為容器來組織對象,對象之間的依賴性將轉化為包之間的依賴性。這種方法聽起來有道理,但是在實際中仍會出現難以解決的問題。

          包僅僅只是容器。這意味著對對象的組織可以是任意的,而包之間依賴關系的設計則還是取決于對象的依賴。此外,包的設計和對象一樣,缺乏一個統一的風格。而統一的風格正是大規模軟件設計所必須的,因為這樣可以有效改進系統的可理解性,這一點非常重要。

          面向組件編程

          面向組件編程的縮寫是COP。COP是對OOP的補充,幫助實現更加優秀的軟件結構。組件的粒度可大可小,需要取決于具體的應用。

          在COP中有幾個重要的概念:服務,服務(Service)是一組接口,供客戶端程序使用。例如,驗證和授權服務,任務調度服務。服務是系統中各個部件相互調用的接口;組件,組件(Component)實現了一組服務,此外,組件必須符合容器訂立的規范,例如,初始化,配置、銷毀。

          COP是對一種組織代碼的思路,尤其是服務和組件這兩個概念。在下文會提到的Spring框架中,就采用了COP的思路,將系統看作一個個的組件,通過定義組件之間的協作關系(通過服務)來完成系統的構建。這樣做的好處是能夠隔離變化,合理的劃分系統。而框架的意義就在于定義一個組織組件的方式。

          理解組件

          在我的qca網站上提供了幾篇講解組件的文章,可以通過以下的鏈接訪問: http://qca.cn/common/content.htm

          組件不是一個新的概念,Java中的javaBean規范和EJB規范都是典型的組件。組件的特點在于他定義了一種通用的處理方式。例如,JavaBean擁有內視的特性,這樣就可以通過工具來實現JavaBean的可視化。而EJB規范定義了企業服務中的一些特性,使得EJB容器能夠為符合EJB規范的代碼增添企業計算所需要的能力,例如事務、持久化、池等。

          所以,組件比起對象來的進步就在于通用的規范的引入。通用規范往往能夠為組件添加新的能力(就像上面所討論的),但也給組件添加了限制,例如你需要實現EJB的一些接口。以下我們將討論組件的一些相關問題:

          組件的粒度

          組件的粒度是和系統的架構息息相關的。組件的粒度確定了,系統的架構也就確定了。在小規模的軟件中,可能組件的粒度很小,僅相當于普通的對象,但是對于大規模的系統來說,一個組件可能包括幾十,甚至上百個對象。因此,對使用COP技術的系統來說,需要正確的定義組件的粒度。較好的定義粒度的方法是對核心流程進行分析。

          針對接口

          接口和實現分離是COP的基礎,沒有接口和實現的分離,就沒有COP。接口的高度抽象特性使得各個組件能夠被獨立的抽取出來,而不影響到系統的其它部分。

          接口和實現分離有以下幾個好處:

          1、 在模塊/組件/對象之間解耦。

          2、 輕松的抽換實現,而不用修改客戶端。

          3、 用戶只需要了解接口,而不需要了解實現細節。

          4、 增加了重用的可能性。

          IOC

          IOC是Inversion of Control的簡稱。它的原理是基于OO設計原則的好萊塢原則(The Hollywood Principle):不要訪問我,我們將訪問你。也就是說,所有的組件都是被動的(Passive),所有的組件初始化和調用都由容器負責。

          在Brian Foote的論文(http://www.laputan.org/drc/drc.html)中解釋了IOC的概念。
          qca網站上對IOC的討論(http://qca.cn/common/IOC.htm

          IOC有幾種實現的類型,包括基于方法參數調用的Method-based (M) IoC,它把組件傳遞給每個方法調用;基于接口的Interface-based (I) IoC(通常稱為類型1),它使用接口來聲明組件之間的依賴性,例如,Serviceable, Configurable;基于Setter方法的Setter-based (S) IoC(通常稱為類型2),它使用setter方法來設置組件之間的依賴性;基于構造函數的Constructor-based (C) IoC(通常稱為類型3)。

          在Martin Fowler剛剛完成(2004-1-24)的Inversion of Control Containers and the Dependency Injection pattern一文(http://www.martinfowler.com/articles/injection.html)中,將IOC模式稱為Dependency Injection模式。

          IOC是框架開發的一個基本原理。在開源軟件中,不少的容器類框架都采用了IOC的思路。例如PicoContainer(http://www.picocontainer.org/)和Spring(http://www.springframework.org/

          組件污染

          在IOC的第一類型中,由于組件需要實現一些特定的接口,或是從某個類集成。這將使得組件受到一些約束(稱為Invasive),例如組件移植不便。另一種情況是組件需要依賴于一個特定的容器,最為典型的就是EJB,組件無法脫離容器單獨存在,這也使得組件受到約束。這兩種情況都屬于組件污染。

          最理想的組件是只專注于自身工作的組件,它沒有其它額外的邏輯。不過按照這種標準,目前大部分的代碼都是不符合的。因此,目前在開源軟件界出現了一些輕量級的容器框架,典型的如上文提到的PicoContainer和spring。他們的定位就是提供一個對組件管理的統一模式,而組件可以單獨的使用,也可以放在另一個容器中,容器僅僅只是為組件提供了一些額外的功能,和組件本身沒有直接的依賴。

          為什么我們說接口比繼承好,很重要的一個原因就是接口更加靈活,組件的依賴性更弱,同樣的,目前另一種做法則是采用一些標記性的語言來實現比接口更大的靈活度。例如基于xml的配置文件,以及J2SE1.5中將要引入的屬性。

          組件的測試

          組件和容器的依賴脫離為組件測試提供了一個很好的環境。我們在測試一節中討論過容器內測試往往是比較麻煩的,其原因就是在于上面所說的組件污染問題。例如在spring框架中,組件是一個標準的JavaBean,你可以直接編寫代碼來設置組件的屬性和定義組件之間的依賴關系(適用于自動化測試),也可以把這項工作交給spring容器(適用于開發和部署)。

          組件測試在測試的分類中屬于集成測試。

          理解服務

          在討論組件時我們談論了組件粒度的問題。當組件的粒度不僅僅限于單個對象的時候。在構成組件的多個對象中,有些對象處于組件內部,不和其它的組件交互,有些對象需要和外部組件進行交互。后一種對象起的就是服務的作用。在設計模式中,這種設計被稱為Fa?ade模式。而在OO語言中,他們相當于接口的概念。不管如何比喻,服務訂立了組件和組件之間的契約。這種契約是穩定的(如果業務需求是穩定的),不會隨著組件內部的變化而發生變化。

          要理解這一點也非常的容易。對于一個提供用戶認證的組件,一個可能的服務對用戶進行認證和授權,至于組件內部采用LDAP還是關系數據庫來存放用戶信息,對服務來說沒有任何的差別。

          這樣做的好處有很多,一是組件之間能夠以一種穩定的方式存在,組件內部的變化不至于擴散到整個軟件系統。二是軟件設計將會轉向重點設計組件之間的服務,而組件的實現細節將會隱藏起來,這不但有助于設計者更好的把握軟件的全局架構,而且有助于分工的細化。

          服務并不是什么新穎的概念,RPC、IDL都是類似的技術。但我們談的服務側重架構和理念,不涉及到具體的技術,這一點同SOA和WebService的關系類似-SOA是一個結構性的概念,而WebService是實現SOA的一種適合的技術。 Stairway to Heaven - Service Oriented Architectures(http://www.enterpriseintegrationpatterns.com/docs/stairwaytoheaven.pdf)一文討論了SOA需要注意的問題,并提出了實現SOA的三個階段,本文所討論的服務為文中所討論的階段3,也是最理想的階段。

          服務最好實現為接口。原則上服務可以是任何一種技術:JMS、WebService、RPC、或是簡單方法調用。但是出于服務的穩定性的考慮,我們不應該將一個服務和具體的技術綁定起來,這樣會使的服務發生變化的可能性增大。在Java語言中,接口是具有極大的靈活性的,因此,將接口實現為普通的Java接口是較好的選擇。不過,這樣做的話,我們也許就不能夠使用遠程調用,Web服務之類的功能了,不過這并不要緊,以下就是原因。

          服務適配器

          客戶端可以直接使用接口,也可以通過適當的適配器來將普通的接口服務轉換為特定技術實現的服務。


           

          如上圖所示,一個普通的接口通過適配器模式轉換成和特定技術相關的服務。在JMX技術中,也采用這種方式,JMX平臺能夠將一個普通的服務端口通過適配器進行轉換,以適用于各種的協議,例如http、sock、snmp等等。

          AOP技術對服務的幫助

          由于有很多的文章討論了AOP技術,我們這里就不再重復了,所以以下的內容是假設你已經擁有基本的AOP概念。在qca網站上對AOP做了一些簡單的整理。(http://qca.cn/common/content.htm) AOP作為OO技術的補足,能夠以一種優雅的方式來處理系統的橫切點。服務層面是應用AOP的絕佳位置:


           

          在上圖中,我們看到一個普通的用戶注冊服務通過AOP可以動態的添加各種各樣的能力。AOP提供了幾個好處,一是能夠通過簡單的代碼為所有的服務添加功能,而不用為每個服務編寫代碼,從而大大節省了代碼量;二是把橫切點分離出來,這樣服務僅保留了核心的代碼,提高了系統的模塊化程度;最后一點是模塊化的增加使得為服務動態的增加或刪除功能成為可能,例如,可以通過配置動態的將新的Aspect添加到用戶注冊服務上。

          服務的測試

          服務測試在測試的分類中屬于接受測試。服務概念的引入使得自動化的接受測試變得容易了。在大規模的軟件設計中,業務流程往往涉及到各種組件通過服務介面的相互協作。所以這就是測試的重點。回到我們之前討論的組件粒度問題,如果此時你編寫出的測試代碼過于繁瑣,說明組件的設計粒度太小了,如果組件的粒度太大,你會發現有些測試代碼根本無法編寫。

          服務的管理

          服務的管理是一個比較大的話題。一方面,在一個大規模的系統中,雖然通過組件和服務的形式能夠降低系統的復雜度,但是服務仍然很多,需要進行管理;另一方面,服務的狀態,服務的可用性需要監控和管理,這對于大規模應用來說是必須的。因此,服務需要一種管理形式。

          JMX規范提出的目的也是一個對各種不同的組件進行統一管理。和我們所闡述的有類似之處。JMX分為規范和遠程接口兩個部分,在J2SE1.5版本中,JMX已經納入到J2SE的范疇中了,有興趣的讀者可以參考sun的相關文檔。

          軟件總線和軟件工廠

          直到目前為止,軟件開發仍然屬于手工作坊階段,如果要和制造業的水平相對應的話,基本上是處于蒸氣機發明之前的水平。隨著軟件開發技術的發展,軟件開發也將象制造業一樣,步入"工業"時代。不過對于軟件開發來說,機器仍然是代碼,只不過這些代碼是用來代替開發人員的編碼活動的,他具有比手工編碼更高的生產力。我們把這些高產量的"機器"描述成現代化的軟件工廠。那么,軟件工廠到底是什么?要了解軟件工廠,我們需要先了解軟件總線的概念。

          COP僅僅只是提出了一個系統劃分的基礎,要構成一個完整應用,光有組件和服務還不夠,還需要將組件和服務以一種有效的方式組織起來,有些文章把這種組織性的代碼稱為 Fabric,有結構和組織的意思。而在我們的文章中,稱之為軟件總線(bus)。

          軟件總線是什么?他和計算機的總線一樣,它負責在各個組件中傳遞信息流,將各個組件組織起來,完成一個具體的任務。總線是一個抽象的概念,在實際中總線也是由具體的技術構成。例如,一個總線可能是一段代碼,負責調用各個組件;總線也能是一個消息系統,負責收集和分派消息;總線也可能是一個工作流系統,負責系統信息的流轉;總線還可能是一個JMX,負責將消息路由到目標組件。但無論總線的實現技術是什么,總線的特點就是采用一種松耦合的方式將組件組織起來。這樣,總線本身和掛接在總線上的組件就是松耦合的,至于組件掛接到總線的形式,也就是我們之前討論過的服務和服務適配器要做的事情了。

          例如,目前的軟件總線有三種可能的實現:直接調用/遠程調用/WebService,MOM,以及工作流,根據應用系統的特點可以采用不同的總線實現。例如以調用為主的總線適用于那些流程比較明確的應用,因為流程是硬編碼的,變化起來相對麻煩一些。工作流為主的總線適用于流程比較靈活,需要復雜的分支和人為的干預。MOM為主的總線則適用于大型的分布式,或是異構的應用,不同的應用之間以一種松散的方式進行協作。但是無論采取哪一種的總線實現方式,組件和服務是不變的,變化的是服務適配器,MOM的服務適配器和工組流的服務適配器是不同的。MOM的服務適配器主要的工作是將消息中的內容翻譯為POJO,并調用服務;而工作流的服務適配器可能就只是一個基于當前工作流狀態的調用。這樣形成的系統架構就是相對穩定、松散耦合的,不論是組件發生變化,還是總線的技術發生變化,只要服務和總線的規范是穩定的,整體的軟件系統就是穩定的。而服務和總線規范才是軟件組織的核心競爭力所在,而這也正是軟件總線的主要目的。

          Patterns and Best Practices for Enterprise Integration (http://www.enterpriseintegrationpatterns.com/)中收集整理了大量有價值的和消息相關的企業集成模式

          軟件工廠在組件和軟件總線的基礎上發展,并根據組件和軟件總線的技術特點,定義了一系列的管理活動,以提高開發效率。軟件工廠是我們定義的軟件質量框架的一種實現方式。對于不同的軟件組織來說,根據自身的研發特點來定義軟件工廠的構成是非常重要的。具體的內容包括管理實踐的選擇,組件的積累,軟件總線的技術實現。在本系列文章中推薦的前兩項實踐都屬于管理實踐范疇的內容,而第三項實踐則偏重于建立軟件工廠的底層支撐框架。

          軟件工廠的概念代表了一種新的軟件開發模式。他的優勢在于能夠把技術和管理結合起來,提高生產力。

          關于作者
          林星,致力于研究敏捷理論和優秀的軟件設計思想,并將之應用于國內的軟件組織??梢酝ㄟ^ iamlinx@21cn.com 和他聯系,也可以通過訪問 www.qca.cnwww.aglichina.org 來獲得更多的信息。




          本博客為學習交流用,凡未注明引用的均為本人作品,轉載請注明出處,如有版權問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學習進步。
          posted on 2008-08-11 11:41 Jack.Wang 閱讀(430) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 德惠市| 上高县| 疏勒县| 梧州市| 昌宁县| 太湖县| 株洲市| 邻水| 温宿县| 阿鲁科尔沁旗| 崇左市| 博兴县| 黄大仙区| 乐平市| 来凤县| 鄄城县| 无棣县| 榆树市| 石城县| 玉山县| 新绛县| 大港区| 延长县| 唐河县| 和顺县| 泽库县| 新安县| 定边县| 清丰县| 宁晋县| 绥阳县| 林西县| 茂名市| 班戈县| 城市| 汝南县| 革吉县| 玉树县| 苏尼特右旗| 鄯善县| 元江|