程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 淺談企業應用架構(二)

淺談企業應用架構(二)

編輯:關於JAVA

五、架構的技術層面

(一)基礎手段

提高開發效率和品質的基本手段是分解——即充分的分離系統中不同的關注點,好處不用說了,可以並發的工作,每個人面對的問題都簡單而容易操作。而與分解對應的集成,只有提供了好的集成能力,分解才成為現實,而只有分解了,才能清晰的提供業務更多適應性。

分解和集成的手段分為編程語言和技術框架兩個層面。所謂語言就是強框架,而框架就是弱語言。

A. 開發語言

現代面向對象的語言提供如下能力:抽象和派生能力,以及接口隔離能力。實際提供兩種分解和集成能力:

1. 把邏輯分解在兩個層次中,而通過繼承的方式把兩個部分集成在一起。

2. 把邏輯的外觀和實現分解在兩個地方,而通過接口實現的方式把兩部分集成在一起。

另一種語言ASPectJ或者C#語言2.0之後提供的特性:把流程邏輯,分解在不同的地方,而通過簽名匹配,利用代碼生成的方式來把幾部分集成在一起。

B. 應用框架

然而語言提供的集成能力,畢竟底層,而且有限,擴展起來也格外小心。因而技術框架提供另外的集成能力就格外重要:

1. 對象關聯關系的分解和集成,如Spring提供容器管理能力

依賴注入對於依賴關系是適合的,對於服務間,技術層次間都是適合的(因為無狀態);但對於聚合(整體和部分)的關系——主要是領域模型(有狀態的)——則不合適;

2. 模塊間關聯關系的分解和集成,如OSGi,ESB等

3. 流程邏輯的分解和集成,如Spring Web Flow以及jBPM.

4. 不同系統的類型分解和集成,如Spring利用動態代理提供的Exporter模式。

5. 模式的封裝集成,設計應當是面向服務的設計,但是服務的暴露方式以及模式可以有很多種,比如API,Web Service,RMI,以及Command模式,Event模式等,框架應該利用動態代理等技術對於這些服務暴露方式,模式進行封裝。

C. 分析設計

設計中涉及到的組合方式,包括類(接口)組合,繼承組合以及產生組合三種。三種組合各有優缺點,設計時適應不同場合。這就涉及到現有面向對象的設計粒度:類(第一公民)和方法(二等公民)。

類(接口)組合實際上復用的是類一級粒度的設計,而繼承組合本質上是一種有方向的組合,復用的方法一級粒度的設計,提供與或非的邏輯操作。而產生組合,例如ASPectJ,也是在方法一級粒度的設計復用。

因為繼承組合復用在方法一級的粒度上,因而其更適合存在嵌入式,最低粒度的差異性的設計中,借助於虛擬機的支持,無需額外工作。而類(接口)在類一級上,更適合在更高一級的邏輯復用上;其實不一定需要接口,普通的類也可以,但是在這一級粒度的差異性替換,采用接口優於類,因此稱為類(接口)組合;接口是類(接口)組合的編碼需要;對於接口一級,需要通過框架的集成和適配來提供差異性的設計。產生組合其實也是在方法一級,不過更關注於廣泛的橫切面,同時由於現有的語言對它的支持不同,Java需要額外的編譯器,而。Net則是在內置編譯器上支持。

更高一級的組合是組件組合。對於組件邊界的設計,遵從兩點:嚴格把關設計和代碼優先。接口優先的設計通常導致成本太高,實踐中會導致開發人員在項目的進度壓力下把代碼寫在不合適的地方。

D. 開發方式

常見的開發方式可以歸結為3類:開發式編程(Programmatic programming),聲明式編程(Declarative programming)和產生式編程(Generative programming)。

開發式編程

聲明式編程

產生式編程

開發手段

編碼。

如:Java, C#

解析。

如:ANT(spring等的XML不一樣,它們是靜態描述型的,不那麼verb)

生成。

如:AOP(ASPectJ),DSL(Drools)

開發性質

聚合

聲明

組合

代表事物

接口

N/A

DSL

自然語言的表達能力很強大,雖然說有時具有二義性,但是在特定領域下是確定的,既然是講DSL,那都是特定領域相關的,一定是明確的。

基礎設施

解析器;

編輯器,如jbpm;

元模型;

生成器;

正統的需要編輯器;

元模型

開發方式

自上向下,聲明式編程是解析概念,用統一的概念來理解,把不同差異性交由具體程序解析;

編輯器生成的是XML文件,將由框架程序解析;

聲明式是粗粒度的(不能直接比較大小,定義的是無差異性的概念);

自底向上,產生式編程用的思路是組合概念(用小粒度的概念組合生成大粒度的概念);

產生式生成程序代碼,不做解析運行;

產生式是相對細粒度的;

E. 小結

通常語言作為架構的基礎,語言的設計帶來的好處遠遠高於框架和模式,但其引入和更換也是有巨大風險的;而通過提供強大的框架能力,框架盡可能多的完成技術問題,並通過元數據,模式以及約定降低業務和框架的耦合。避免因為框架升級帶來不必要的成本。

Meta Programming的最高層次是語言級別直接解決,比如,Smalltalk, Ruby, Python, 還有其他Reflection支持的非常好的語言。甚至STL等template技術,也可以算作語言級別。 Code Generation 是最低級別的Meta Programming解決方案,技術含量也最低。這個級別必須超越,才能夠真正達到質變,完全跳出概念炒作的層次。

從技術手段上,提高開發效率的另外兩個手段是代碼生成和類庫引用。但代碼生成和類庫引用,都只解決了邏輯的分解能力,沒有提供集成能力,所以一般情況下需要提供框架集成,尤其代碼生成需要在系統的最外層,避免集成帶來的問題。

代碼生成也沒有那麼壞,關鍵在於生成什麼,如果是生成結構性的代碼,由於往往不是最終的產物,就存在同步維護問題;同時這種代碼是大都可以用template完成的。

但如果生成的是功能性代碼,這類代碼是最終執行代碼,那麼通常就把用於設計的代碼看作是最終產物,最明顯的例子是DSL.

(二)核心問題

1. 領域化

領域化,即領域建模。通常而言,領域模型設計中,模塊分解,抽象分層和職責分層都是重要手段。問題域為:流程,領域模型和領域服務(包括規則)。

a. 對象的抽象分解和集成

b. 對象的依賴分解和集成(模塊內和模塊外)

c. 流程的分解和集成(頁面流,工作流以及計算流程)

d. 進程邊界:用戶請求重定向,以及業務數據持久化等。

對於中等項目來說,系統中應該有50-100個領域對象代表了業務抽象;

2. 組件化

面向對象語言本身沒有提供的組件級別的依賴關系集成能力。語言不提供,因為領域組件的粒度太大,超越了語言的范疇。但我們可以通過框架提供,在Java體系中,目前已經有兩個較好的解決方案:OSGi(JSR291)和SCA.可以很好的解決組件服務依賴關系管理,包括熱替換。

同時另一個問題——邏輯分層的問題:如保險產品面臨的核心層,國家層以及公司層三個邏輯層次分解和集成能力。這點的解決方案可以通過OSGi + Spring來解決,包括了靜態差異性替換和動態差異性替換。

還有組件邊界保護問題,我們希望限制別的組件訪問本組件內部實現,有兩種手段可以完成,1是提交/部署時,通過在代碼提交時的代碼檢查工具,或者發布時編譯工具完成;2是通過OSGi的邊界限制能力。

3. 產品化

A. 定制化支持

領域定制化涉及到邏輯替換問題。邏輯的替換根據開發方式不同,有兩種類型:基於接口和基於繼承;

A. 基於接口(包括了靜態替換和動態替換)

1. 靜態替換是Override,在OSGi中只要停止原有服務,啟用新服務即可,而在Spring中更改相應配置文件即可;

2. 動態替換,其實是指運行時Condition Service Locator,在OSGi中可以利用Extension Point(Plug-in)解決,而Spring中只要提供一個類似Service Locator就可以。

B. 基於繼承(或者靜態類)

1.開發時,直接修改源代碼編譯;

2.編譯時,采用ASPectJ,在編譯時提供替換;

3.加載時,開發一個新邏輯的同名類,但其加載路徑優先於原有類;

B. 升級支持

主要是增量升級支持,以及有限的降級支持。同時要考慮到對於定制化產品的升級支持。

4. 平台化

A.基礎設施

基礎設施包括:類庫和框架。基礎設施可以自己開發,或者應用第三方(開源商業)實現。

A1. 基礎設施的選型

應考慮幾點:1. 商業角度的可維護性和可升級性;2. 組織的學習和管理能力;3. 基礎設施自身功能以及所支持的開發效率。以下是詳細要求:

客戶角度

成熟度要求

基礎設施是業界成熟方案;

性能要求

基礎設施滿足系統運行的性能要求;

穩定性要求

基礎設施版本穩定,經過大量測試;

環境性要求

基礎設施不會帶來額外的軟硬件兼容要求;

管理角度

開發成本要求

基礎設施的開發維護成本低,最好是業界成熟開源成果;

開發效率要求

基於該基礎設施的應用開發效率高;

維護成本要求

分析設計與開發之間的銜接性好;

測試成本要求

基於該基礎設施的應用測試成本低,效率高;

培訓招聘成本要求

網絡上的參考資料豐富性;基礎設施的流行度;

內部員工學習培訓成本低; 招聘外部員工成本低;

A2. 基礎設施的集成

基礎設施獨立後,出現平台化的發展趨勢,這個趨勢有兩個方向:通用化和專業化。通用化意味著基礎設施和應用的距離加大,易用性減低;而專業化意味著適應性的減少。這是一個矛盾體。在基礎設施選型後,再進行一定集成工作,可以結合當前情況,平衡易用性和適應性;同時合適的集成也有助於隔離技術和業務兩個方面。

從維護升級角度看集成的合適性:對於沒有標准的,不要做不必要的封裝,封裝等於是建立一個標准,而這是不現實的;應當盡可能采用框架方式,屏蔽基礎設施對於應用程序的侵入性。如果是標准,就更沒有必要封裝,畫蛇添足。

B.業務支持

B1. 基本原則和手段

基本原則是:應用程序POJO化。減少技術對於業務侵入性。主要手段是:容器上下文;依賴注入;AOP技術;元數據支持;事件機制;開發工具和代碼生成;

依賴注入+AOP+元數據構成了簡單對象(POJO)的支撐技術。基於此三位一體的技術可以有效的隔離業務問題和技術問題,更為甚者它可以支撐簡單對象體系,每個對象做且只做一件事。

B2. 開發模式與最佳實踐

基礎平台應該提供業務相關的模式封裝。

B3. 關於元數據

元數據有多種:語言級別為Annotation(微軟。NET為Customer Attribute);框架級別可以是XML文件或者其它配置文件。

元數據可以通過以下幾個視角觀察

1. 應用層次:元數據代表了業務含義和技術含義;

2. 技術分析:文檔類型(開發管理型);編譯類型(類加載型);運行期行為。

3. 物理分析,包括Annotation和接口,XML文件,甚至是EL和類。

元數據系統的建立其實是代表了認知過程。

以運行期的元數據為例,代表了系統通過反射獲取相關元數據來自適應系統,其實際意義在於將軟件設計開發人員對於系統的認知通過技術手段固化下來。

元數據系統的開發目的有兩個:

1. 業務應用上,提供業務動態能力;

2. 技術應用上,簡化開發減低成本;

這裡面有一個誤區是:為了技術應用而過分地開發元數據系統,而隨著業務的演化導致為技術應用的元數據迅速被拋棄,導致投入的浪費。實踐中要避免。

(三)應用問題

1.事務管理

A. 成熟的事務技術:如數據庫;

B. 合理的並發設計控制;

C. 完整的業務日志;這也是解決業務回退的主要手段;

D. 輔助的數據校驗能力;

並發設計控制和完整的業務日志,是架構設計中保障數據一致性主要著力點。並發設計控制,需要結合業務,通過悲觀鎖定來保障。

而業務日志的獲取則面臨著諸多困難,主要是業務事務和物理事務的不一致性(即一個業務事務可能橫跨多個物理事務,也可能一個物理事務包括多個業務事務);業務日志控制層面有兩個:應用系統或基礎設計;通過應用系統編碼控制,則不可避免的提高了應用系統開發和測試的成本;通過基礎設施控制,有助於減低成本,但提高基礎設施的設計成本;

2.並發處理

分析業務所涉及的並發場景,制定相應的原則和方法,並合理選用現有的並發處理框架,進行一定程度的剪裁,通過框架支持和簡化這些原則和方法的實踐。

3.系統分解

基於應用的層面的分解,有多個緯度,包括:業務抽象度,業務任務,業務產品線,以及業務領域等等。

4.集成能力

軟件開發的適應性在於分解粒度的大小,而分解粒度大小取決於集成能力。

1)依賴管理

在技術的角度看,軟件系統是一個存在大量依賴關系的對象系統。其中包括了兩種依賴:

1.業務代碼的對象依賴;比如調用一個工廠類創建一個對象。

2.業務代碼的環境依賴;它可能依賴於一個Web環境(讀寫Request和Response流),數據庫系統(讀寫數據記錄),文件系統和網絡系統等。

不幸的事是這種代碼量占據了大量的開發工作。重復的開發工作(對象或者數據的依賴關系維護工作)減低了開發效率和系統適應變化的能力。

而這樣復雜依賴關系也給軟件的測試帶來了相當大的困難需要搭建足夠的依賴環境(如一台Web服務器和數據庫服務器),甚至是硬調試。

於是就有了采用第三方代碼來完成依賴關系維護工作的思路,所謂的依賴注入。業務對象出現Spring等著名框架

動態代理技術則解決了提供支撐環境封裝的問題。比如提供網絡訪問能力(如RMI,URL和Web Services),文件訪問能力(如XML、property文件讀寫)。

由於企業開發中數據庫技術的應用不可避免,因而ORM框架的出現還有特別的意義,在它的支撐下,核心業務西可以嚴格區別領域邏輯和業務邏輯,而這在以前是做不到的。

AOP開發的出現解決了面向對象下的橫向組織關系。從一定程度上看,AOP可以看作是另一種依賴關系,可以另外依賴注入來實現。當然也可以采用編程實現。

2)數據對象

說起集成,就不得不提到一種類型的對象存在——VO對象。

VO對象是為了集成而存在的;其意義是:1. 保護系統的信息邊界,提供一種結構可以使其它系統或者組件通過編碼方式獲取系統內信息的方式;2. 保護系統的事務邊界,領域對象技術上攜帶著持久化信息,通過VO可以屏蔽得以屏蔽。常見的VO對象存在於Web層和Domain層。

因此,VO對象的存在只是為了集成而存在,其是否存在的取決於兩個方面1. 集成的設計結構;2. 框架的兩個能力——對象路徑訪問能力以及事務邊界管理。

Domain層VO對象,通常是用於不同領域組件間的交互,但隨著架構的改進,集成代碼獨立存在而不再嵌入到組件內部,組件的邊界問題保護不復存在;更進一步的是,框架提供自動化的接口適配映射能力的增強。因而VO對象失去存在的意義。

Web層VO對象,以SWF為例,早在SWF 1.x時代,框架就提供了豐富的對象路徑訪問能力,但其Web交互是典型的MVC2方式,事務邊界在view的render前關閉,因而導致需要特定的VO對象來避免持久化信息問題;而SWF 2.x時代,vIEw的render是在事務邊界內,VO不再需要。

系統設計是一種結構化過程,邏輯和數據被分解和集成到系統的各個部分;在運行期,真正重要的是結構化路徑訪問能力,換句話說重要的是結構化後的路徑,而實際用何種數據結構其實不重要。

可以使用數據樹Data Tree形式,提供扁平化的數據訪問能力,是一種較好的開發方式,極大的提升了開發效率。Spring Web Flow以及其它框架廣泛的運用EL提供統一的表達式訪問數據,也大大降低了開發成本。

3)事件機制

事件機制應用非常廣泛,是很重要的集成手段。事件機制的優勢在於其提供了松散耦合而帶來的擴展能力。基於傳統事件模式,可以擴展提供同步/異步,事務隔離等額外控制能力。

4)組件設計

一個組件包括了API和SPI,其中API是用於客戶方編程,SPI用於服務方編程(屬於框架回調)。無論是API和SPI都是該組件所有,體現了一個組件自身的完備性。其與其它組件依賴通過集成模塊完成,依賴解藕。

組件的設計還分層次,上層組件的邏輯依賴下層組件,上層組件直接訪問下層組件的服務和模型,保持單向依賴有助於降低開發和維護成本。而平級組件,由於組件的替換可能性大,因而保障組件邊界完整性尤為重要。

接口的實現是關鍵。面臨的問題是,在開發初期需求不確定和經驗不足的情況下,接口的設計不盡合理,導致需求變動後,所進行的修改將影響三個方面,接口、接口實現對象和測試用例。工作量將可能很大。特別是在並行開發過程中,一個通訊接口的變化將可能引起很大連鎖反應,導致其他成員不得不停下手上的工作。

因而在實際開發中需要做個權衡。不同模塊的通訊接口應該由團隊成員共同負責,一旦接口變化,接口實現成員應該提供相應的假實現。而模塊內部可以由開發人員自行設計,可以在初期不提供接口和簡單的測試用例,在項目具有一定穩定性後,利用重構實現接口和完整的測試用例。

有效定位系統錯誤。尤其在組件化和分層化,以及其它開發手段混合運用情況下。例如,A,B,C.由於C引起的錯誤導致A錯誤是很難查的。代價很高。

5)膠水層

膠水層代碼屬於集成范疇。它是系統開發中不可避免的。膠水層代碼的存在增加了設計、開發和測試的成本。因盡量減少膠水層代碼的人工開發。

膠水層代碼有兩種類型:一是適配器,二是開發模式。

適配器對於集成來說並不陌生。適配器從用途上分可以分為兩種:業務適配和技術適配。業務適配是指處理應用程序接口的適配調用,消除應用程序的耦合度;技術適配是指處理應用程序和技術框架上,消除技術框架的耦合度。

開發模式是指基礎平台對於應用開發的支持減少無效代碼,例如采用ORM系統(如Hibernate)以及有狀態的Web層框架(如Seam和SWF)可以有效減少應用系統處理數據(對象)狀態;以及各種元數據的識別和增強。

6)集成階段

根據階段分為:設計時, 編譯(加載)時和運行時。設計時是由人工編碼,通常就是一些特定業務代碼,完成集成工作;編譯時集成工作通常指配置文件,由程序員提供,但不需要編碼工作;而運行時指通過指定元數據,由框架運行時解析;

5.部署方式

部署有兩種:本地部署和分布式部署。

分布式部署會帶來額外的問題。如果支持分布式部署,有兩種方案:

1. 前後端分離方案

傳統EJB方案就是此種。面臨的問題和風險:

a) 部署成本,即分布部署帶來開發成本;

包括:分布式調用;分布式事務管理;開發模式(即上下文的傳遞)。

b) 運行成本,即分布式數據傳輸性能問題;

2. 采用Portal或類似技術

(四)設計問題

設計文檔依然有用,采用Color UML有助於閱讀。

面向對象提供各種關系的表達能力:關聯,依賴,集成,組合等;類似於數據庫表關系,但是更強烈。在設計時需要注意表現。

新的開發方式,應該可以通過代碼記錄分析設計的成果,形成系統中一個穩定的可發展的抽象層次代碼,而開發實現則繼承或者適配該抽象層次,最終保證系統可運行性。

這樣知識層面的分析設計可以有效貫徹發展,而操作層面的開發實現可以關注於實現過程的工具和手段。這樣就可以確保設計是做正確的事,而開發過程提供各種框架工具則把事做更有效率。

六、架構的展示

1.兩個要素

架構要展示的兩個基本要素是:業務和技術組件。而業務又可分為組件和功能兩個層次,技術又可分為基礎平台與組件所需提供工件兩個部分。

後續所有展示都圍繞此二要素。

2.核心視圖

由RUP貢獻的四個視圖是架構展示的核心視圖。

邏輯視圖(靜態類圖)

關注功能,不僅包括用戶可見的功能,還包括為實現用戶功能而必須提供的"輔助功能模塊";它們可能是邏輯層、功能模塊等。

應映射為業務組件、功能包以及技術工件(分層),以及它們之間關聯依賴關系;

開發視圖(靜態類圖)

關注程序包,不僅包括要編寫的源程序,還包括可以直接使用的第三方SDK和現成框架、類庫,以及開發的系統將運行於其上的系統軟件或中間件。

開發視圖和邏輯視圖之間可能存在一定的映射關系:比如邏輯層一般會映射到多個程序包等。

應映射為具體的SDK和框架等,以及關聯依賴關系;注:開發視圖應盡可能和邏輯視圖一一對應;

處理視圖(動態類圖)

關注進程、線程、對象等運行時概念,以及相關的並發、同步、通信等問題。

處理視圖和開發視圖的關系:開發視圖一般偏重程序包在編譯時期的靜態依賴關系,而這些程序運行起來之後會表現為對象、線程、進程,處理視圖比較關注的正是這些運行時單元的交互問題。

可映射為狀態圖和活動圖(高層和詳細);

物理視圖(部署視圖)

關注"目標程序及其依賴的運行庫和系統軟件"最終如何安裝或部署到物理機器,以及如何部署機器和網絡來配合軟件系統的可靠性、可伸縮性等要求。

物理視圖和處理視圖的關系:處理視圖特別關注目標程序的動態執行情況,而物理視圖重視目標程序的靜態位置問題;物理視圖是綜合考慮軟件系統和整個IT系統相互影響的架構視圖。

可映射為組件圖,部署說明圖;

3.擴展視圖

在核心視圖,針對於不同受眾,還需要提供三個擴展視圖。

非功能視圖

展示非功能性指標的支持能力。通常針對於技術人員。

基礎設施視圖

展示架構所采用基礎設施,以及它們之間的關系。通常針對於技術人員。

數據視圖

關注於數據組織和存儲形式。通常針對於DBA,或者需對數據進行定期維護的用戶。

4.原則和約束

架構因明確說明本架構采用原則、方法論以及相關約束。

5.技術選型分析

由於架構涉及眾多底層技術,也應給出相應的選型分析。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved