![]() | ||||||
![]() |
架構藍圖--軟件架構 "4+1" 視圖模型 | ![]() |
|
![]() | ||
![]() | ||||||
![]() |
![]() |
本文基于多個并發視圖的使用情況來說明描述軟件密集型系統架構的模型。使用多重視圖允許獨立地處理各"風險承擔人":最終用戶、開發人員、系統工程師、項目經理等所關注的問題,并且能夠獨立地處理功能性和非功能性需求。本文分別對五種視圖進行了描述,并同時給出了捕獲每種視圖的表示方法。這些視圖使用以架構為中心的、場景驅動以及迭代開發過程來進行設計。 引言 架構模型 軟件架構 = {元素,形式,關系/約束} 軟件架構涉及到抽象、分解和組合、風格和美學。我們用由多個視圖或視角組成的模型來描述它。為了最終處理大型的、富有挑戰性的架構,該模型包含五個主要的視圖(請對照圖 1):
架構的描述,即所做的各種決定,可以圍繞著這四個視圖來組織,然后由一些用例 (use cases)或場景(scenarios)來說明,從而形成了第五個視圖。正如將看到的,實際上軟件架構部分從這些場景演進而來,將在下文中討論。 我們在每個視圖上均獨立地應用 Perry & Wolf 的公式,即定義一個所使用的元素集合(組件、容器、連接符),捕獲工作形式和模式,并且捕獲關系及約束,將架構與某些需求連接起來。每種視圖使用自身所特有的表示法-藍圖(blueprint)來描述,并且架構師可以對每種視圖選用特定的架構風格(architectural style),從而允許系統中多種風格并存。 我們將輪流的觀察這五種視圖,展現各個視圖的目標:即視圖的所關注的問題,相應的架構藍圖的標記方式,描述和管理藍圖的工具。并以非常簡單的形式從 PABX 的設計中,從我們在Alcatel 商業系統(Alcatel Business System)上所做的工作中,以及從航空運輸控制系統(Air Traffic Control system)中引出一些例子―旨在描述一下視圖的特定及其標記的方式,而不是定義這些系統的架構。 "4+1"視圖模型具有相當的"普遍性",因此可以使用其他的標注方法和工具,也可以采用其他的設計方法,特別是對于邏輯和過程的分解。但文中指出的這些方法都已經成功的在實踐中運用過。 邏輯結構 邏輯架構主要支持功能性需求――即在為用戶提供服務方面系統所應該提供的功能。系統分解為一系列的關鍵抽象,(大多數)來自于問題域,表現為對象或對象類的形式。它們采用抽象、封裝和繼承的原理。分解并不僅僅是為了功能分析,而且用來識別遍布系統各個部分的通用機制和設計元素。我們使用 Rational/Booch 方法來表示邏輯架構,借助于類圖和類模板的手段 4。類圖用來顯示一個類的集合和它們的邏輯關系:關聯、使用、組合、繼承等等。相似的類可以劃分成類集合。類模板關注于單個類,它們強調主要的類操作,并且識別關鍵的對象特征。如果需要定義對象的內部行為,則使用狀態轉換圖或狀態圖來完成。公共機制或服務可以在類功能 (class utilities)中定義。對于數據驅動程度高的應用程序,可以使用其他形式的邏輯視圖,例如 E-R 圖,來代替面向對象的方法(OO approach)。 邏輯視圖的表示法 邏輯視圖的標記方法來自 Booch 標記法4。當僅考慮具有架構意義的條目時,這種表示法相當簡單。特別是在這種設計級別上,大量的修飾作用不大。我們使用 Rational Rose? 來支持邏輯架構的設計。 邏輯視圖的風格 邏輯視圖的風格采用面向對象的風格,其主要的設計準則是試圖在整個系統中保持單一的、一致的對象模型,避免就每個場合或過程產生草率的類和機制的技術說明。 邏輯結構藍圖的樣例 圖 3 顯示了 Télic PABX 架構中主要的類。 圖 3 - a. Télic PABX 的邏輯藍圖 b.空中交通系統的藍圖 PABX 建立終端間的通信連接。終端可以是電話設備、中繼線(例如,連接到中央辦公室)、連接線(PABX 專線到 PABX 線)、電話專線、數據線、ISDN 等等。不同的線路由不同的接口卡提供支持。線路 controller 對象的職責是在接口卡上對所有的信號進行解碼和注入,在特定于接口卡的信號與一致性的小型事件集合之間進行相互轉換:開始、停止、數字化等。controller 對象同時承載所有的實時約束。該類派生出許多子類以滿足不同的接口類型。terminal 對象的責任是維持終端的狀態,代表線路協調各項服務。例如,它使用 numbering plan 服務來解釋撥號。conversation 代表了會話中的一系列終端 。conversation 使用了Translation Service(目錄、邏輯物理映射、路由),以及建立終端之間語音路徑的Connection Service 。 對于一個包含了大量的具有架構重要意義的類的、更大的系統來說,圖 3 b 描述了空中交通管理系統的頂層類圖,包含 8 個類的種類(例如,類的分組)。 進程架構 進程架構考慮一些非功能性的需求,如性能和可用性。它解決并發性、分布性、系統完整性、容錯性的問題,以及邏輯視圖的主要抽象如何與進程結構相配合在一起-即在哪個控制線程上,對象的操作被實際執行。 進程架構可以在幾種層次的抽象上進行描述,每個層次針對不同的問題。在最高的層次上,進程架構可以視為一組獨立執行的通信程序(叫作"processes")的邏輯網絡,它們分布在整個一組硬件資源上,這些資源通過 LAN 或者 WAN 連接起來。多個邏輯網絡可能同時并存,共享相同的物理資源。例如,獨立的邏輯網絡可能用于支持離線系統與在線系統的分離,或者支持軟件的模擬版本和測試版本的共存。 進程是構成可執行單元任務的分組。進程代表了可以進行策略控制過程架構的層次(即:開始、恢復、重新配置及關閉)。另外,進程可以就處理負載的分布式增強或可用性的提高而不斷地被重復。 軟件被劃分為一系列單獨的任務。任務是獨立的控制線程,可以在處理節點上單獨地被調度。 接著,我們可以區別主要任務、次要任務。主要任務是可以唯一處理的架構元素;次要任務是由于實施原因而引入的局部附加任務(周期性活動、緩沖、暫停等等)。它們可以作為 Ada Task 或輕量線程來實施。主要任務的通訊途徑是良好定義的交互任務通信機制:基于消息的同步或異步通信服務、遠程過程調用、事件廣播等。次要任務則以會見或共享內存來通信。在同一過程或處理節點上,主要任務不應對它們的分配做出任何假定。 消息流、過程負載可以基于過程藍圖來進行評估,同樣可以使用啞負載來實現"中空"的進程架構,并測量在目標系統上的性能。正如 Filarey et al. 在他的 Eurocontrol 實驗中描述的那樣。 進程視圖的表示法 我們所使用的進程視圖的表示方法是從Booch最初為 Ada 任務推薦的表示方法擴展而來。同樣,用來所使用的表示法關注在架構上具有重要意義的元素。(圖 4) 我們曾使用來自 TRW 的 Universal Network Architechure Services(UNAS0) 產品來構建并實施過程和任務集合(包擴它們的冗余),使它們融入過程的網絡中。UNAS 包含 Software Architect Lifecycle Environment(SALE)工具,它支持上述表示方法。SALE 允許以圖形的形式來描述進程架構,包括對可能的交互任務通信路徑的規格說明,正是從這些路徑中自動生成對應的 Ada 或 C++ 源代碼。使用該方法來指定和實施進程架構的優點是易于進行修改而不會對應用軟件造成太多的影響。 進程視圖的風格 許多風格可以適用于進程視圖。例如采用 Garlan 和 Shaw 的分類法1,我們可以得到管道和過濾器(Pipes and filters),或客戶端/服務器,以及各種多個客戶端/單個服務器和多個客戶端/多個服務器的變體。對于更加復雜的系統,可以采用類似于 K.Birman 所描述的ISIS系統中進程組方法以及其它的標注方法和工具。 進程藍圖的例子 所有的終端由單個的 Termal process 處理,其中 Termal process 由輸入隊列中的消息進行驅動。Controller 對象在組成控制過程三個任務之中的一項任務上執行:Low cycle rate task 掃描所有的非活動終端(200 ms),將 High cycle rate task(10 ms)掃描清單中的終端激活,其中 High cycle rate task 檢測任何重要的狀態變化,將它們傳遞給 Main controller task,由它來對狀態的變更進行解釋,并通過向對應的終端發送消息來通信。這里 Controller 過程中的通信通過共享內存來實現。 開發架構 開發架構關注軟件開發環境下實際模塊的組織。軟件打包成小的程序塊(程序庫或子系統),它們可以由一位或幾位開發人員來開發。子系統可以組織成分層結構,每個層為上一層提供良好定義的接口。 系統的開發架構用模塊和子系統圖來表達,顯示了"輸出"和"輸入"關系。完整的開發架構只有當所有軟件元素被識別后才能加以描述。但是,可以列出控制開發架構的規則:分塊、分組和可見性。 大部分情況下,開發架構考慮的內部需求與以下幾項因素有關:開發難度、軟件管理、重用性和通用性及由工具集、編程語言所帶來的限制。開發架構視圖是各種活動的基礎,如:需求分配、團隊工作的分配(或團隊機構)、成本評估和計劃、項目進度的監控、軟件重用性、移植性和安全性。它是建立產品線的基礎。 開發藍圖的表示方法 同樣,使用 Booch 方法的變形,僅考慮具有架構意義的項。 來自 Rational 的 Apex 開發環境支持開發架構的定義和實現、和前文描述的分層策略,以及設計規則的實施。Rational Rose 可以在模塊和子系統層次上繪制開發藍圖,并支持開發源代碼(Ada、C++)進程的正向和反向工程。 開發視圖的風格 圖 6 - Hughes 空中交通系統(HATS)的 5 個層 開發架構的例子 圖 6 代表了加拿大的 Hughes Aircraft 開發的空中交通控制系統(Air Traffic Control system)產品線的 5 個分層開發組織結構。這是和圖 3 b 描述的邏輯架構相對應的開發架構。 第一層 和第二層組成了獨立于域的覆蓋整個產品線的分布式基礎設施,并保護其免受不同硬件平臺、操作系統或市售產品(如數據庫管理系統)的影響。第三層為該基礎設施增加了 ATC 框架,形成一個特定領域的軟件架構(domain-specific software architecture)。使用該框架,可以在第四層上構建一個功能選擇板。層次 5 則非常依賴于客戶和產品,包含了大多數用戶接口和外部系統接口。72 個子系統分布于 5 個層次上,每層包含了 10 至 50 個模塊,并可以在其他藍圖上表示。 物理架構 物理架構主要關注系統非功能性的需求,如可用性、可靠性(容錯性),性能(吞吐量)和可伸縮性。軟件在計算機網絡或處理節點上運行,被識別的各種元素(網絡、過程、任務和對象),需要被映射至不同的節點;我們希望使用不同的物理配置:一些用于開發和測試,另外一些則用于不同地點和不同客戶的部署。因此軟件至節點的映射需要高度的靈活性及對源代碼產生最小的影響。 物理藍圖的表示法 大型系統中的物理藍圖會變得非常混亂,所以它們可以采用多種形式,有或者沒有來自進程視圖的映射均可。 TRW 的 UNAS 提供了數據驅動方法將過程架構映射至物理架構,該方法允許大量的映射的變更而無需修改源代碼。 物理藍圖的示例 圖 8 顯示了大型 PABX 可能的硬件配置,而圖 9 和圖 10 顯示了兩種不同物理架構上的進程映射,分別對應一個小型和一個大型 PABX。C、F 和 K 是三種不同容量的計算機,支持三種不同的運行要求。 場景 四種視圖的元素通過數量比較少的一組重要場景(更常見的是用例)進行無縫協同工作,我們為場景描述相應的腳本(對象之間和過程之間的交互序列)。正如 Rubin 和 Goldberg 所描述的那樣6。 在某種意義上場景是最重要的需求抽象,它們的設計使用對象場景圖和對象交互圖來表示4。 該視圖是其他視圖的冗余(因此"+1"),但它起到了兩個作用:
場景的表示法 場景表示法與組件邏輯視圖非常相似(請對照圖 2),但它使用過程視圖的連接符來表示對象之間的交互(請對照圖 4),注意對象實例使用實線來表達。至于邏輯藍圖,我們使用 Rational Rose 來捕獲并管理對象場景。 場景的例子 圖 11 顯示了小型 PABX 的場景片段。相應的腳本是: 1. Joe的電話控制器檢測和校驗摘機狀態的變換,并發送消息喚醒相應的終端對象。 2. 終端分配一些資源,并要求控制器發出撥號音。 3. 控制器接受撥號并傳遞給終端。 4. 終端使用撥號方案來分析數字流。 5. 有效的數字序列被鍵入,終端開始會話。 視圖之間的對應性 從邏輯視圖到過程視圖 我們發現邏輯視架構有幾項重要特性:
在邏輯視圖中,我們認為每個對象均是主動的,具有潛在的"并發性",即與其他對象具有"平行的"行為,我們并不考慮所要達到的確切并發程度。因此,邏輯結構所考慮的僅是需求的功能性方面。 然而,當我們定義進程架構時,由于巨大的開銷,為每個對象實施各自的控制線程(例如,Unix 進程或 Ada 任務),在目前的技術狀況下是不現實的。此外,如果對象是并發的,那么必須以某種抽象形式來調用它們的操作。 另一方面,由于以下幾種原因需要多個控制線程。
我們同時使用兩種策略來決定并發的程度和定義所需的過程集合。考慮一系列潛在的物理目標架構。以下兩種形式我們可以任選其一:
其結果是將類(和它們的對象)映射至一個任務集合和進程架構中的進程。通常,活動類具有代理任務,也存在一些變形:對于給定的類,使用多個代理以提高吞吐量,或者多個類映射至單個代理,因為它們的操作并不是頻繁地被調用,或者是為了保證執行序列。 注意這并不是產生最佳過程架構的線性的、決定性的進程;它需要若干個迭代來得到可接受的折衷。還存在許多其他方法,例如 Birman 等人5 或 Witt 等人7提出的方法。 確切的實施映射的方法不在本文的討論范圍,但我們以一個小的例子來說明一下。 圖 12 顯示了一個小的類集合如何從假想的空中交通控制系統映射至進程。 flight 類映射至一個 flight 代理集合:有許多航班等待處理,外部觸發的頻率很高,響應時間很關鍵,負載必須分布于多個 CPU。并且,航班處理的持久化和分布性方面都取決于 flight server,為了滿足可用性,還是使用 flight server 的一臺備份服務器。 航班的 profile 和 clearance 總是從屬于某個航班,盡管它們是復雜的類,但它們共享 flight 類的進程。航班分布于若干其他進程,特別是對于顯示和外部接口。 sectorization 類,為 controller 的權限分配建立了空域劃分。由于完整性約束,僅能被一個代理處理,但可以與 flight 類共享服務器過程:更新得并不頻繁。 location 和 arispace 及其他的靜態航空信息是受到保護的對象,在幾個類中共享,很少被更新;它們被映射至各自的服務器,分布于其他過程。 從邏輯視圖到開發視圖 類通常作為一個模塊來實現,例如 Ada 包中可視部分的一個類型。密切相關的類(類的種類)的集合組合到子系統中。子系統的定義必須考慮額外的約束,如團隊組織、期望的代碼規模(通常每個子系統為 5 K 或 20 K SLOC)、可重用性和通用性的程度以及嚴格的分層依據(可視性問題),發布策略和配置管理。所以,通常最后得到的不是與邏輯視圖逐一對應的視圖。 邏輯視圖和開發視圖非常接近,但具有不同的關注點。我們發現項目規模越大,視圖間的差距也越大。例如,如果比較圖 3 b 和圖 6,則會發現并不存在逐一對應的類的不同種類到層的映射。而如果我們考慮類的種類的"外部接口"-網關種類時,它的實現遍布若干層:通訊協議在第 1 層或以下的層,通用網關機制在第 2 層,而特定的網關在第 5 層子系統。 從進程視圖到物理視圖 進程和進程組以不同的測試和部署配置映射至可用的物理硬件。Birman 在 ISIS 項目中描述了詳細的映射模式5。 場景主要以所使用類的形式與邏輯視圖相關聯;而與進程視圖的關聯則是考慮了一個或多個控制線程的、對象間的交互形式。 模型的剪裁 迭代過程 場景驅動(scenario-driven)的方法 系統大多數關鍵的功能以場景(或 use cases)的形式被捕獲。關鍵意味著:最重要的功能,系統存在的理由,或使用頻率最高的功能,或體現了必須減輕的一些重要的技術風險。 開始階段:
循環階段: 下一個迭代過程開始進行:
然后:
終止循環 為了實際的系統,初始的架構原型需要進行演進 。較好的情況是在經過 2 次或 3 次迭代之后,結構變得穩定:主要的抽象都已被找到。子系統和過程都已經完成,以及所有的接口都已經實現。接下來則是軟件設計的范疇,這個階段可能也會用到相似的方法和過程。 這些迭代過程的持續時間參差不齊,原因在于:所實施項目的規模,參與項目人員的數量、他們對本領域和方法的熟悉程度,以及該系統和開發組織的熟悉程度等等。因而較小的項目迭代過程可能持續 2-3 周(例如,10 K SLOC),而大型的項目可能為 6-9 個月(例如,700 K SLOC)。 架構的文檔化
結束語 致謝
![]() |