從書名可知《Large-Scale Software Architecture: A Practical Guide using UML》 裡頭談的是如何使用 UML 來設計大型軟體的架構,不過,如作者說的,中小型軟體專案也可以採用書中建議的方法,因為很多看似大型的、重量級的方法,都必須從比較小的 case 去實踐、練習(儘管會付出過多 effort,有殺雞用牛刀之嫌),否則一次就從大案子下手,結果恐怕不會太樂觀。
 
這本書共有 11 章,各章標題如下:
  1. Introduction
  2. Roles of the Software Architect
  3. Software Architecture and the Development Process
  4. Example System Overview
  5. UML Quick Tour
  6. System Context and Domain Analysis
  7. Component Design and Modeling
  8. Subsystem Design
  9. Transaction and Data Design
  10. Process and Deployment Design
  11. Applying the Viewpoints
我對第 6 章以後的內容比較感興趣,也就是討論如何找出領域模型,如何設計元件和子系統的部份。如果是開發 data-intensive 的軟體系統,那麼第 9 章應該也是可以看看的。目前只先大概瀏覽了第 6 章,因此這裡只記錄我閱讀第 6 章時做的筆記和心得,主要是物件導向分析設計過程中的 domain analysis 的一些步驟和技巧。
 
基本上,這裡採用的方法,就是以 UML 的圖形記號來捕捉需求,以及呈現分析設計的模型,其主要精神離不開 use case driven、4+1 view 的範疇。不過,書中提的作法還是有些不一樣的地方,例如在捕捉需求時,用來跟開發團隊之外的利害關係人溝通的環境視圖(context view),我覺得也是不錯的表達方式。以下是個簡單的 Context View 範例:
 
 
 
Context View 是用來呈現與系統有關的外部個體(包括使用者以及其他系統),彼此的關係則以連接的線段來表示。Context View 的核心就是我們要開發的系統,我們也可以再往下層展開,為每個子系統畫一個 Context View。
 
Context View 沒有規定太多標準符號,適合用來跟開發團隊以外的利害關係人(非技術人員)溝通及確認系統範圍。如果要用 UML 來呈現類似用途的圖形,通常會採用 Use Case Diagram,如下所示:
 
 
中間的方框代表系統邊界,裡面的標題即為系統名稱,每個橢圓代表一個 use case,而所有跟系統有關的 actors 皆以棒狀小人圖表示。這種方式有時候可能會引起爭議,就是在塑模大型系統時,比較高層次的範圍圖裡面的每個 use case 都是「XX 系統」,這似乎不符合 use case 名稱的命名慣例。不過,正如 Grady Booch 說的:「there really is no 'illegal' UML graphical syntax. (註1)」,其實也不用太計較這些細節。
 
如果不去計較圖形記號本身的所謂標準用法,只要大家看得懂、能溝通就好,其實用這種表現方式也沒什麼問題。只是在討論模型時,儘管與會人員大都 學過 UML,還是可能會有人提出你的圖形記號用得不對、不精確之類的質疑。我覺得,與其浪費時間爭議這些細節,倒不如用 Context View 這樣的圖形,比較不會陷入圖形記號的桎楛,減少溝通上的麻煩。
 
用 use case diagram 表現系統範圍與環境的另一個缺點,就是那些 actors 與 use cases 之間縱橫交錯的線段,有時候會多到連我自己看了都覺得亂到不行。此時要不就把 actor 的角色盡量一般化,以減少 actor 的數量,否則就得拆成多張圖來呈現了。此外,用這種畫法,基本的假設是一開始就知道大概有哪些子系統。稍後在提到分析領域物件的技巧時,會再說明如果一開 始子系統並不明顯,該如何將它們找出來。
 
另外,除了 Context View 和 Use Case Diagram,UML 套件圖也可以用來表現系統範圍的分割、層次、以及跟參與者之間的關係。這次就偷個懶,直接從 Booch 的書上剪下來:
 
 
小結:如果要用一張圖來呈現哪些人或外部系統會跟欲開發的系統扯上關係,Context View 應該是不錯的選擇。再往底下的子系統和 use cases 展開的話,則可以用套件圖或使用案例圖。
 
 
領域分析技巧
 
畫出系統環境視圖(System Context View)之後,接著便要進一步透過 Use Case Diagram 畫出系統範圍,然後針對每個 use case 撰寫使用案例規格(use case specification;亦稱為使用案例描述)。這項撰寫 use case 的工作,通常少不了參考 Cockburn 的經典之作。 使用案例寫完之後呢?我所知道的 OO 分析方法,通常是採用動詞、名詞擷取法,從使用案例描述中抓出關鍵的名詞和動詞,並寫在卡片上,利用腦力激盪法,從一堆名詞當中決定哪些是 domain class,哪些是類別的屬性,並且從一堆動詞當中找出可能成為特定 domain class 的 methods,再據此結果畫出類別圖,然後是循序圖、活動圖...等等。
 
本書建議的作法,基本上跟前面描述的大同小異,只是圖形的表示法有些許變化,圖形的名稱也不同。本書的分析步驟,是寫完使用案例描述之後,要根 據使用案例分別描繪出兩種視圖:Analysis Focused View 和 Analysis Interaction View。簡單地說,前者就是包含 actors 的領域類別圖,屬於領域的靜態結構;後者則是包含 actors 及領域類別的互動圖;屬於動態的圖形。有了這一動一靜的兩種視圖,再根據它們提供的線索描繪出系統的概要視圖(Analysis Overall View),此圖可說是整個系統的領域類別概圖。此分析流程如下圖所示(取自本書的圖 6.2):
 
 
 
上圖是領域分析的基本步驟,從圖中無法看清楚 Analysis Focused View 實際上長什麼樣子,以下是個範例(取自本書的圖 6.4):
 
 
 
從圖中可以看到,基本上它就是個描述 actor 以及各領域物件關係的類別圖。Analysis Interaction View 跟 UML 循序圖長得很像,這裡就不另外貼圖了。至於 Analysis Overall View,前面說過,它是整個系統的領域類別概圖,實際上大概是長成這樣(取自本書的圖 6.5):
 
 
其中用不規則粗線條圈起來的部份,是領域邊界(domain boundaries),這是事後根據各領域物件之間的關聯性,再以手繪的方式將它們的區域圈出來。而這圈出來的每一塊區域,就是候選子系統。也就是說,到這個步驟,就可以逐漸切出子系統了。
 
分析工作進行到這裡,算是完成了領域分析的初步 iteration。為了與開發工作銜接,目前這些高階的領域類別與互動流程還必須再進一步細化,找出 implementation classes,如此反覆進行,直到產生接近可實作的類別圖及互動圖。
 
結語 
 
有的系統分析師可能在寫完 use case 描述之後,就開始抓類別,然後反覆細化,直到貼近可實作的程度(不可能、也不需要達到能完全銜接實作的程度,時間和人力問題,而且有經驗的開發人員會有足 夠的能力自行填補其中的空隙)。有的系統分析師喜歡先從使用者的作業流程下手,也就是先畫出活動圖,再依活動圖去寫 use case 描述,然後抓類別。本書的作法則是根據 use case 描述畫出靜態的 Analysis Focused View(分析類別視圖)以及 Analysis Interaction View(分析互動視圖),再從它們提供的線索抓出整個系統的完整類別,描繪出 Analysis Overall View。
 
無論採用哪種方式,其實都是殊途同歸,重點在於能抓出關鍵的 domain classes 以及它們之間的結構與互動關係,還有,最重要的:責任。
 
以上大概就是本書第 6 章的重點了,其中參雜了一些個人的想法,而且是想到哪寫到哪,讀起來可能有點亂吧。
 
 
註1:這句話出自 Grady Booch 反駁微軟提出的 Software Factories 構想時所作的陳述。Booch 之所以反對軟體工廠的構想,其中一個原因是微軟未全力支持 UML,反而弄了個 DSL(Domain Specific Language)。