多維度的軟體架構分解

王國波發表於2013-12-24

  對複雜的大規模軟體系統,軟體架構分解是架構設計中必不可少的關鍵步驟。通過分解識別架構元素,同時也是解決非功能需求的重要手段之一。本文從架構的定義出發,對架構形而上的本質給出了自己獨特的理解。在架構設計上提出了架構分解過程模型和多維度多層次分解模型。

 什麼是軟體架構

  如果期望有一個權威統一的標準定義,那答案是沒有,目前存在多種軟體架構的定義,可以說百花齊放,百家爭鳴。其中 IEEE1471-2000 的定義是這樣的:系統的架構是系統元件的基本組織形式,它們之間的關係以及和環境之間的關係,以及指導其設計和演化的原則。該定義中的系統元件可以理解為架構元素,根據涉及到的系統範圍和層次,架構元素可以是子系統、模組、類等等。從架構設計的動態角度出發,我們可以這樣來定義軟體架構:通過一系列架構決策,將系統分解為一些架構元素,並定義這些元素之間的介面和互動關係、整合機制。架構決策就是在架構設計過程中做出的一系列全域性的決定和權衡取捨,例如將系統拆分成幾個子系統、子系統的職責是什麼、子系統之間的介面是什麼、採用什麼通訊方式和整合機制、採用的開發語言和技術框架等。

 架構形而上的本質

  除了軟體架構,眾所周知,在建築行業中也存在架構,而且建築架構比軟體架構歷史要悠久得多;在公司中存在組織架構。這就引發了我們的思考,對這些不同的架構,它們的本質是什麼?

  從抽象的形而上的角度來看,架構是架構作用力的平衡,如圖 1。

  圖 1 中左側一個最初混沌的系統在架構作用力的相互作用下達到足夠程度的平衡。右側的橢圓蘊含的意思是架構應該是有彈性的,裡面的多個小圓表示在力的作用下分解產生的架構元素。

  圖 1.形而上的架構

形而上的架構

  什麼是架構作用力

  對一個建築工程專案,會涉及到多方涉眾,如建設單位、勘察單位、設計單位、施工單位、工程監理單位、使用單位等等,他們對工程專案存在各種需求;同樣在一個軟體系統中也會有多種涉眾,例如系統使用者、投資人、需求分析師、架構師、開發人員、測試人員、客服人員、運維人員等等。這些涉眾在架構層面有各自的架構需求,例如系統使用者除了要求滿足他們的功能需求外,還有對系統的易用性、效能、可用性等非功能性存在要求;開發設計人員希望系統架構清晰,便於理解,關注程式碼重用性、擴充套件性、可維護性。架構師更關注於系統可伸縮性、可用性、效能等非功能需求。這些需求必須在架構層面加以考慮,使這些涉眾的需求在架構層面得到足夠的滿足。

  從抽象的層次來看,涉眾在架構層面的上述各種需求就是架構作用力,它們直接影響和驅動架構設計。大師 Grady Booch 在他的<<The architecture of Web applications>>一文中就已經關注軟體中的作用力(Forces in software)。在架構中除了存在這些外力外,在架構中也存在內力,就是架構元素之間的相互作用力,這裡不展開討論。

  一個架構要滿足所有的需求通常是不可能的,因為不同的涉眾,他們之間的需求可能是相互衝突的,也就是作用力的方向是相反的。作用力的大小主要體現在需求的優先順序上。

  架構設計過程中,架構師運用自己的經驗,結合當前的技術,從全域性考慮需求和約束,進行折中和取捨,平衡這些涉眾的作用力。

  在 IEEE1471-2000 規範中,將涉眾在架構層面的各種需求稱為關注點,從這個概念來說架構分解就是關注點分離。

 架構分解

  當我們看到一個複雜系統的架構檢視時,可能會思考這些檢視中的架構元素是怎麼來的。如何從混沌的鐵板一塊的整體架構演變成一個可伸縮高效能的分散式系統?

  分而治之是一種處理複雜問題的通用方法,在軟體架構中,它也是一種很重要的手段,例如多層架構、OSI 七層模型都體現了分而治之思想。在架構設計過程中,通過將關注點分離對架構進行多層次分解,將系統層層分解為多個架構元素,進而識別架構元素。

  可以說架構中的很多元素都是在架構分解的過程中識別產生的。

  架構分解的作用

  萬事開頭難,架構分解是架構設計過程中非常關鍵的一步。除了識別架構元素,對大規模的軟體系統,分解還是解決非功能需求的重要手段。eBay 為了解決可伸縮性、可用性、可管理性等問題,在架構的多個層面進行了分解:

  • 在應用層面,按照功能或 SOA 服務進行分解,將系統垂直拆分為多個應用池(應用池中的服務是無狀態的)。每個應用池中有多個應用(水平拆分),可以獨立靈活地進行伸縮。見圖 2 所示。
  • 在資料層面,對資料進行垂直拆分(分庫)和水平拆分(資料分片 DB Sharding);將分散式事務拆分成多個本地事務獨自提交,避免分散式事務。見圖 3 所示。

  圖 2.應用的垂直和水平拆分

應用的垂直和水平拆分

  圖 3.資料的垂直和水平拆分

資料的垂直和水平拆分

  架構分解的原則

  德國哲學家、數學家萊布尼茲一針見血地指出:“不講分解技巧,分而治之就不大有用。無經驗者對問題分解不當,反而會增加困難“。為了正確的進行分解,需要遵循一些分解原則:

  • 低耦合、高內聚:萊布尼茲指出:“分解的主要難點在於怎麼分。分解策略之一是按容易求解的方式來分,之二是在弱耦合處下手,切斷聯絡”。在弱耦合處下手,切斷聯絡。太精闢了!高內聚、低耦合也是軟體設計的基本原則,軟體設計中的很多設計原則其實都可以認為它的派生或具體化,如單一職責原則、依賴倒置原則、模組化封裝原則,這些原則在架構分解中也是適用的。
  • 層次性:分解通常是先業務後技術,循序漸進,先邏輯後物理,從上到下逐級進行分解展開:系統->子系統->模組->元件->類。
  • 正交原則:和物理學中的正交分解類似,架構分解出的架構元素應是相互獨立的,在職責上沒有重疊。
  • 抽象原則:架構元素識別,在較大程度上是架構師抽象思維的結果,架構師應該具備在抽象概念層面進行架構構思和架構分解的能力。
  • 穩定性原則:將穩定部分和易變部分分解為不同的架構元素,穩定部分不應依賴易變部分。根據穩定性原則,將通用部分和專用部分分解為不同的元素;將動態部分和靜態部分分解為不同的元素;將機制和策略分離為不同的元素;將應用和服務分離。
  • 複用性原則:就是對知識的重用.重用類似系統已有的架構設計、設計經驗、成熟的架構模式或參考模型、設計模式、領域模型、架構思想等,因為它們已經在不同的層次上分解識別出了許多架構元素,或者指出了一些分解方向,對我們的架構分解具有借鑑和指導作用。例如 IBM SOA 解決方案參考模型對 SOA 服務化具有重要的指導意義,我們可以參照它對系統進行初步的架構分解。

  圖 4 IBM SOA 解決方案參考模型

圖 4 IBM SOA 解決方案參考模型

  架構分解的過程模型

  對複雜的系統,特別是前人沒有做過的新系統,通常難以一下子設計出合適的架構。在架構設計的初期,通常都要經歷一個不斷探索的階段。

  在架構設計過程中,架構分解是必不可少的的關鍵步驟。如何進行架構分解?從哪裡入手開始進行分解?我們需要有一個架構分解的過程模型來指導分解過程,啟發和探索架構分解的維度和線索,提高架構分解的效率。

  架構分解過程模型如圖 3 所示,是一個迭代的模型。通過這個迭代的分解,從無到有、從粗到細、從模糊到清晰,一步步精(細)化、豐富架構。迭代的過程也是一個否定之否定的過程,隨著分解的逐步推進或系統的架構演化,後面的分解除了會識別出新的架構元素,也可能會對先前識別出的架構作出調整。

  圖 5.架構分解過程模型

架構分解過程模型

  依次在 4 個域中進行架構分解,基本順序是先業務後技術,通過多維度多層次的分解將關注點分離。

  • 業務域分解:先從業務域進行分解,狹義的業務域具有商業的概念,從這個概念來看,有的系統沒有業務域,但如果寬泛一點來看,業務域就是問題域(問題空間),問題域總是存在的。

  首先是從系統需求入手,尋找業務域中的分解維度,將架構從業務域層面進行大尺度(大粒度)的分解。在業務域中進行分解,通常採用的分解維度是根據業務主題,將系統分解為多個子系統,每個子系統聚焦於一個獨立的業務主題,子系統間具有清晰的邊界。例如對某電商系統,我們可以根據業務主題維度進行架構分解,初步劃分出:會員子系統、交易(訂單)子系統、產品子系統、搜尋子系統、物流子系統、支付子系統等。

  領域驅動設計(DDD)中的邊界上下文(context boundary)是一種根據業務相關性進行大尺度分解的方法,它和基於業務主題的分解是類似的。

  圖 6 基於業務主題的分解

圖 6 基於業務主題的分解

  對業務域分解不應只侷限於基於業務主題的分解,根據具體情況,還可能有其他的分解維度。一個通用的發現分解維度的方法是試著從領域模型和需求分析文件中尋找名詞和形容詞,將文件中的核心概念(名詞和形容詞)作為分解的候選分解維度或分解線索。

  在業務域的分解中,我們要和業務(行業)專家密切交流,多研究業務架構、適當考慮企業戰略,這樣可在一定程度上保證架構分解的合理性。

  • 業務功能域分解:通過對業務流程和用例進行分析,根據功能職責,進行垂直和水平分解,識別出業務功能或業務服務,將它們歸類到子系統中相應模組中去。

  對業務域功能域分解,一個通用的方法是試著通過動詞來將子系統拆分為多個服務;另一個是根據資源型別(名詞)來將系統拆分為服務,每個服務負責實現對應資源上的一組操作。例如根據資源型別(會員、商品等),對電商系統,可分解識別出會員查詢服務和會員管理模組、商品服務等。

  這兩步的架構分解都是純業務上的,不涉及技術,但要這兩步分解出的架構元素要對映到技術域中去實現,或用來幫助架構師推匯出技術域的對應架構元素。

  • 技術域分解:是從技術角度對系統和模組進行分解。在該階段,通常會選取關鍵的需求(包括功能需求和非功能性需求)和已分解出的模組或子系統,結合當前的 IT 技術(技術框架、架構模式、參考架構、中介軟體、業務平臺)和架構思想、架構經驗、開發人員的技能以及系統的上下文環境等,進一步進行架構分解。

    例如很多系統採用 MVC、多層架構模式、SOA、事件驅動架構等技術或思想進行技術域中的架構分解。對電商交易子系統的訂單流程,考慮到要需要靈活支撐多種交易流程和解耦流程層與業務邏輯層的需要,按照 IBM SOA 的參考架構(圖 4)可以分拆出流程層、服務層等,在流程層中採用流程引擎技術。

    在技術域分解中,對功能需求,橫切(分層)豎割是一種常用的分解手法。對非功能需求,可將效能、伸縮性、可用性等作為維度對系統進行分解,在非功能需求分解戰術中將專門說明這些維度的分解技術(稱為戰術)。

    在業務域和業務功能域中分解出來的架構元素,考慮到技術實現,在對映到技術域時,可能要對架構元素進行修改或作一些微調,業務域和業務功能域中分解出的架構元素通常會進一步分解為技術域中的多個架構元素。例如在業務功能域分解出的會員查詢服務模組,在技術域中分解時,考慮到有多個不同型別的呼叫方會使用該服務,並且這些呼叫方需要的查詢介面差異較大,呼叫頻率等也不一樣,那我們可能會對每個呼叫方拆分出獨立的查詢介面模組,這樣也避免了胖介面,相關的 DAO 類也是在技術域中新產生的。

    在從模組分解到類的過程中(假設有些模組要分解到類級別),需要進行靜態和動態的分析以便識別出類元素。首先是根據業務域需求,建立領域模型,識別出領域(概念)類,再將領域類對映到技術域中的設計類(實體類),也就是領域類可幫助我們識別推匯出部分設計類。再基於具體用例,進行魯棒分析和序列圖設計,考慮技術上的實現和採用的技術架構,例如採用一些技術框架和類庫或工具類,如 ibatis 框架,就會識別出另一些設計類(邊界類、控制類)或引入一些新的設計類,這些引入的類可能直接來自框架或類庫,或是繼承框架中的類(成為框架類的子類)。通常設計過程不會就此結束,考慮到開發維護和設計質量等因素,我們會運用一些設計原則(如高內聚低耦合、單一職責、資訊專家等)、設計模式、重構模式等對設計進行進一步的優化,這時又會產生識別出一些設計類,通常在這一步會對我們的設計進行一些修改和調整,例如採用工廠方法設計模式,會引入工廠方法類,我們的序列圖就要修改。這樣我們最終完成了一個完整的設計。因為要考慮技術域,所以對整個分析設計來說,它是源於業務但要高於業務。

    在技術域的分解中,對公共的技術需求應全盤考慮,抽象出底層的公共技術基礎設施,例如定時任務在許多子系統中都存在,此時可能會規劃一個定時任務框架和定時任務執行系統。也可能會採用一些成熟的框架和中介軟體技術,如訊息中介軟體、ESB 等。

    技術域的分解通常是比較複雜的,這一方面來源於問題域的本質複雜性,特別是各種非功能性需求的複雜性,需要架構師掌握應對這些需求的常見模式。另一方面也是由於 IT 新技術的日新月異,要求架構師對技術敏感,與時俱進。

    要注意的是,當在技術域分解中碰到困難時,可以再回到業務域中去尋找答案和線索。例如為了解決某計費系統中的效能和可伸縮性問題,可在業務域中尋找名詞和形容詞,發現可以根據付費型別(預付費和後付費)將系統初步分拆為預付費系統和後付費系統。對網路通訊系統,可以根據請求訊息中的某些屬性對訊息處理系統進行拆分或根據客戶端型別等進行拆分。

  • 涉眾域分解:全面考慮各類涉眾在架構層面的關鍵需求,特別是非功能需求,例如效能需求、可伸縮性需求等,進一步對系統進行分解。

    涉眾域分解包括了前面說的業務域分解、業務功能域分解、技術域分解,通常涉眾域分解和它們有部分是重疊的,例如在技術域和涉眾域中都有效能方面的架構分解。涉眾域分解保證我們的分解是完備的,沒有遺漏。

    在涉眾域的分解過程中,很可能會產生新的子系統,例如考慮使用者的效能方面的需求,可能會分解出分散式資料快取子系統(也可能在技術域分解中就已經考慮到了)。

    涉眾域分解的一個可能的維度是根據涉眾型別,基於他們的關注點來進行架構分解,試著為某類涉眾劃分出對應的子系統或模組(架構元素),例如考慮到前臺涉眾和後臺涉眾的使用者型別、關注點差別較大等因素,可能會將系統劃分為前臺系統和後臺系統兩大類。對第三方涉眾(外部系統),考慮到接入認證授權、安全性和互操作性,可能會分解出閘道器子系統。

    為何首先從業務域開始分解,其實很好理解,我們開發一個系統肯定是為了解決業務問題,是為業務服務的,不可能脫離業務去設計一個空洞的無目標的系統和架構。

  架構分解維度

  從上面的描述可以看出,架構分解就是從多個維度多層次對系統進行分解,識別出架構元素,逐步精化、豐富系統架構的過程。圖 4 形象地表示了架構分解的多維度立體拆分。

  圖 7.多維度分解

多維度分解

  這 4 個域中除了分解過程模型一節中提及的一些分解維度,根據具體的系統,還可發掘出許多分解維度,如時間維度、物理空間維度、優先順序維度、職責角色維度(不同的角色)、客戶端維度、呼叫方維度(不同的呼叫方)、請求型別維度、資料維度、資料處理維度(OLAP、OLTP)等。

  有幾個要指出的問題是:

  • 分層和分解的不同,分層只是分解的手段之一,是一種有層次的分解,還有很多分解手段不屬於分層,例如基於業務主題的分解和各種資料分解。
  • 橫切豎割式的二維分解是一種分解形式,對複雜系統,可能要從 4~5 個或更多維度對系統進行較大尺度的分解。
  • 授人以魚,不如授人以漁。本文列出的一些分解維度只是為了幫助闡釋多維度多層次分解的方法,重點是分解方法和一些發現分解維度的策略,不是列出的分解維度,不要本末倒置。在運用多維度分解方法時,不要侷限於這些維度,也有可能這些分解維度不適合你的產品或專案,應根據實際情況,去發現合適的分解維度。
  • 在架構設計中,除了分解,還有集(合)成,在分解時要有整體思維,在分解的過程中要考慮到和其他架構元素的整合,保證分解出的架構元素最終能整合在一起。
  • 軟體架構中科學與藝術並存,註定了架構設計(包括架構分解)沒有銀彈,但我們可以不斷努力探索架構設計中的科學成分,欣賞偉大架構師的設計藝術。

  非功能需求的分解戰術

  對非功能性分解維度,在具體的分解過程中,可以藉助一些成熟的模式來實現架構元素的識別,在<<軟體構架實踐>>中,將在架構層面應對非功能需求特性的架構模式或架構策略稱為戰術,例如對可用性,常用的戰術包括:冗餘、錯誤檢測。

  在<< The Art of Scalability >>中,對可伸縮性,提出了一個伸縮立方模型(Scale Cube),如下圖 5。

  圖 8.伸縮立方模型

伸縮立方模型

  這是一個三維的立方模型,表示可在三個維度上實現可伸縮性:

  • X 軸表示水平復制(克隆),就是在負載均衡器後面部署多個相同的應用來進行水平伸縮;
  • Y 軸表示功能分解,按不同的功能對應用進行分解。也可用於資料,就是分庫,不同型別的資料在不同的庫中。
  • Z 軸表示資料分片(sharding),每個資料分片有單獨的應用負責訪問。也可表示應用分片,每個應用只負責提供部分資料服務,多個應用合起來提供完整的服務。

  這三個維度可以結合在一起使用,也可單獨使用。

  可以看出,前面提到的 eBay 可伸縮性實踐應用了該模型。

  部分非功能需求的常用戰術如下表 1:

  表 1. 非功能需求戰術

 

非功能需求型別 戰術
可用性
  • 高可用叢集
  • 服務降級
  • 非同步訊息
效能
  • 負載均衡叢集
  • 快取(頁面、資料)
  • 資料讀寫分離、資料分片 、分庫、分表
  • 併發處理
  • 非同步處理
可伸縮性
  • 採用彈性雲端計算平臺
  • 資料層面:快取、垂直伸縮、讀寫分離、資料分片、分庫、分表
  • 應用層面:垂直伸縮、水平復制(水平伸縮)、功能分解(服務無狀態)、應用分片

  分解維度與戰術的關係

  戰術除了應用在非功能需求上,在架構層面應對功能性需求的架構模式、架構策略和其他技術手段也可稱為戰術。例如分層模式、AOP(面向切面程式設計)技術等都是戰術。

  分解維度和戰術的關係,就是戰略和戰術的關係,分解維度指明分解的位置和目標所在,戰術是實現該分解的手段。例如在森林裡伐木,分解維度指出砍哪顆樹,戰術指出是用斧頭砍還是鋸子鋸。沒有戰略,就不知道目標和方向,成為無頭蒼蠅;沒有戰術,戰略就成空想,不能落地實現。對軟體系統中的橫切關注點,在 AOP 技術出現之前,知道要進行分離,但一直沒發現實現分離的完美戰術,直到 AOP 技術出現後,才較為完美的實現了橫切關注點分離,可見戰術和機制也很重要。

  對簡單的系統或有經驗的類似系統,也可直接應用成熟的戰術,不需在架構分解上過多投入。

  架構分解的粒度

  多維度多層次分解到什麼粒度才停止?這個沒有統一的標準,通常要能進行並行開發,能指導後續的詳細設計。需要根據具體的產品或專案來定,有的到模組級別就行,對關鍵的部分,可以到類級別。

  架構分解的時機

  架構分解的時機通常就是架構改造演化的時機。當架構出現腐化和臭味,已經難以滿足關鍵涉眾的關鍵需求,例如使用者的響應速度越來越慢已經接近臨界值,並且根據預見,響應速度還有可能繼續較低;開發人員越來越難以維護,這個時候可以考慮進行架構演化,對架構進行改造。當然如果能提前預見系統的問題,經過慎重評估後,在問題發生之前,提前一段時間進行架構演化也是可以的。

  要注意的問題是不要過度分解,過早分解,這樣做除了增加成本,還可能帶來風險。例如很多系統在建設初期,考慮到規模較小和快速上線,通常都是一個整體的系統,不會進行大的架構分解,以後隨著需求和規模的逐漸增加,會逐步進行架構改造和架構分解。

 架構檢視和架構視點

  在 IEEE1471-2000 規範中對檢視和視點的定義如下:

  • 檢視:是從相關的一組關注點投射的整個系統的一個表示。為了捕獲或表示系統架構的設計,架構設計師一般會建立一個或多個架構模型,可能用不同的工具。檢視由這其中選擇出來的一個或多個模型組成,選擇這些模型是為了展示個一個或一組利益相關人,以便他們的關注點在設計系統架構的過程中獲得了足夠的關注。
  • 視點:架構視點是用於構建和利用一個檢視的約定規範,它是一個模式或模版,可以用來確定一個檢視的目標、使用者以及建立和分析的技術,從而建立一個獨立的檢視。

  視點可理解為觀察系統的一個角度,每個系統有多個視點,每個視點都有一個涉眾;該類涉眾從某個角度觀察系統,所看到的系統的部分資訊就是該視點對應的檢視,系統有多個檢視。

  檢視和視點通常用在架構文件中,作為描述架構的重要手段,在架構分解過程中,可用來作為發現架構分解維度的一種輸入,幫助進行架構分解。

  在 RUP 中定義了“4+1“檢視,其中的開發檢視就是開發人員從開發視點出發,用來為開發人員提供切實的指導。

  除此之外,在企業架構 TOGAF 框架和 RM-ODP 也定義了視點和檢視來建模和描述各種型別的架構。

 總結

  對複雜的軟體系統,其架構設計是一項複雜的系統工程,架構分解作為架構設計中的關鍵步驟,在軟體行業中還沒有成熟的系統的架構分解方法論來指導架構分解。本文對此問題做了初步的探討,提出了架構分解的過程模型和架構分解多維度模型,用來幫助架構師逐步進行架構分解,識別出其中的架構元素。對架構分解,關鍵在於找到合適的架構分解維度和分解戰術。

相關文章