{程序員邀稿} 以架構為中心的主要設計產出(2)

全文均刊登於北京「程序員(Programmer)」雜誌(台灣天瓏書局可購得), 2007 7月刊, p67~p69。 感謝朱海豔(helenna)小姐用心將文稿轉為簡體專業術語,以及將 Model 重新美編,並轉為簡體。

結構面的設計產出

關於軟體結構

所謂的系統結構(System Structure)分析與設計(Analysis and Design),係指如何正確、有效地分解設計範圍內系統的元素(Element,一般泛指物件(Object)),指派每一個物件所應有的屬性(attributes)與行為(behavior, 責任的分派),抽象表達靜態類別之間的關係,動態組合物件在執行期間(run-time)的訊息(Message)傳遞,以履行系統的功能需求(ex. 來自於 Use Case 的功能分析)...。做好結構分析、捕捉有效的領域概念,以成為系統的主結構,才能建構出堅若磐石的軟體系統,來應付現實複雜系統的善變,甚而讓系統呈現有機的次序成長、生生不息。

如何找出問題領域(Problem)的概念具化成為企業物件(Business Object)、指派每一個物件應盡的責任,並以此來建構系統中的軟體規格模型,已是高階系統分析與設計人員最大的挑戰與應具備的本質學能。更為難的是,如何將企業物件配合現實面的平台,例如如何活用 J2EE Spring and Hibernate 系統框架。因為,現實上,物件的狀態(state)就是被永續(persistent)儲存在資料庫系統內,而在需要用到(企業邏輯的運算)的時候才被活化(activate)起來;同時因為物件共用的議題而需要 AP 應用伺服器的系統支援,包括交易(transaction)控管、安全性(security)、效能(performance)、分散(distribution)等議題的設計考量。兩個層次(高階概念性的分析設計;細部平台面的設計),互補且缺一不可。

系統的內,也就在於分析所組成的內部結構元素,套現在 IT 的術語來說,也就是所謂的物件導向分析與設計(Object-Oriented analysis and design)。相對於系統的外,是著重在功能性的需求分析(也就是前一期內容所介紹如利用使用案例建構的需求模型)。兩者是互補—找出內部穩定的結構元素(物件,Object),來應變外部的功能需求。

而系統的結構分析,正是現今軟體人員們最大的罩門所在。在速成短線的專案開發生態,軟體人員只會看到現在所看到的—找出一個一個的功能,快速地利用所提供的平台技術(如 .NET, J2EE),疊床架屋的方式,Quick and Dirty 快速的給開發出來。不要以為利用 .NET 或 Java 等 OOP 語言,就是所謂的物件導向開發模式,這是兩回事,如果沒有用心地萃取具本質性(Essential)的物件(再一次強調,源自於問題領域的概念術語),而只是看到一個功能就成為一個 Class,那麼,這樣的系統完全會受限於需求性的變動而導致震盪不穩,是不會具軟體系統的彈性(flexibility)、穩定性(stability)與延展性(extensibility)!

什麼是軟體的結構?

軟體系統的整體呈現是來自於問題領域(Problem Domain),也就是把該領域中經常溝通的術語(terminology) 對映至軟體系統的物件,稱之為領域物件(Domain Object)或企業物件(Business Object)。 例如,”人事資源(Human Resource) 管理” 系統的開發,其核心的問題領域當然是以 “人事” ,經常溝通的術語會有 “員工(Employee)”、”部門(Department)”、”請假”、”請假細項(AskLeave Lineitem)”、”考績” …等,而這些術語自然地就會被捕捉(capture)至軟體系統內,而成為構成軟體系統主結構(main-structure)的成分元素了。

將組成軟體系統結構的元素組織在一起,並利用視覺化的方式來呈現,稱之為 “領域模型(domain model)”。領域模型代表真實世界中的概念性類別,呈現的是領域中的概念性類別或真實世界中的物件。在 UML 的模型中,最重要也是最必要的一張結構圖也就是類別圖(Class Diagram)。

參考下圖 1,通常使用 UML 表示法呈現的領域模型,凸顯的是概念(concept),再來則是以及概念之間的關連(association)與屬性(attributes)。例如 “Order”, “OrderLineItem”, “Customer” 都是屬於在該領域中的概念; Customer 與 Order 之間則存在著 1 對 1..多 的關連(一個客戶會有 1到 1..多筆訂購交易); Product(產品) 具有 description, price 的屬性。在概念性的分析時,細節(包括操作,屬性,資料型態等)在目前並不重要,最重要的是能突顯出概念的呈現,也就是找出類別(Class)。

圖 1、範例—訂購系統的類別圖(Class Diagram)
(點擊圖片鏈接看原圖)圖 1、範例—訂購系統的類別圖(Class Diagram)

那個時候最能表現出結構設計的應變能力? 筆者常說,當 SA(System Analyst) 遇到 有點像又不太像 這類的需求時,也就是結構設計發揮的時機了。 舉個例,訂購 若會視訂購的類型,可能是書籍、雜誌、百貨商品等,而有不同的訂購流程與處理邏輯,此時,懂得虛與實互補設計之道的 SA,會很自然地把訂購分為一般化與特殊化(generalization-specialization)—把已知的部分放在一般化;而未來要具體實現的部分放在特殊化。事實上,這也才只是利用到多型(polymorphism)的基本技巧而已,就已經足以解決為何程序員經常會為了訂購類型寫了一堆的 switch, if…then…else 這種的條件敘述,而造成程式碼混雜,難以維護了。

如何找出軟體的穩定結構元素,是系統分析人員最大的挑戰。SA 並不需要具備領域知識(Domain Knowledge),但卻要懂得如何與領域專家(Domain Expert)溝通合作,萃取其知識,並抽象(abstract)成為軟體的主結構。這相當不容易,那並非是純技術面,真正的軟體設計行家,絕對是具高度的抽象的能力,要能懂得從多個構面觀察,時常在反思與找問題(不是找答案)。筆者正是被這在 虛 與 實 均要能互補、一輩子也學不完的軟體設計領域,給深深地著迷,才從原來是系統管理與 Oracle 資料管理師,而至中年才轉到軟體一職來,並已把此視為是終身之職,是要窮究一輩子、甚至帶至下一輩子繼續來修行的。

回歸正題,關於結構設計的好書相當稀少,筆者這裡特別推薦 Peter Coad 軟體大師,從早期 1990年的 “Object-Oriented Analysis”,“Object-Oriented Design”,至 1998 年的 “Object Models”、1999年 ” Java Modeling In Color with UML” 等著作。尤其是 “Object Models” 一書所揭露出以交易為核心的 交易樣式(Transaction Pattern),更是軟體結構分析人員必讀的聖經。在筆者經常訪問與輔導各領域的公司時,經常在當場就直接展現與證明不用懂領域知識,也能馬上抓出該領域的核心結構,所使用的利器即是 交易樣式(Transaction Pattern)

另一個結構利器—複合結構圖

複合結構圖 (Composite Structure Diagram)是 UML 2.0 規格所新增的視圖,它相當具有價值,因為它同時融合了 類別圖 與 元件(Component)圖的特質—對外凸顯的是元件所提供(provide)與需要(require)的介面(interface);對內則表達了元件內部的組件(part)結構;以及介面是由哪些組件所委託(delegate)處理的。

參考下圖 2,即是利用複合結構圖來呈現 BPM (business process management)系統與外部的溝通介面,以及系統內部的結構組件。筆者經常看到諸多由 Workflow 所演進的 BPM 產品,都是將 已知 的功能部分給一窩蜂地 塞 進系統內,但是客戶永遠有第 101 種需求,此時 BPM 廠商就是隨便 跳線(從資料庫整合) 給硬兜實做出來,當然就會造成 連體嬰 式的系統,永遠都綁在一起,剪不斷、理還亂了。BPM 系統內部當然可以有預設好的服務,如 組織(Organization)結構、規則引擎(Rule Engine)等,但也應該定義標準的溝通介面,來連接外部如 Directory Server、Rule Engine 等;甚而,流程定義 (process definition)也是可以透過 OMG 的 WFMC 國際工作流組織所定義的 Interface-1,來連接外部的 流程定義 的服務系統。

複合結構圖能讓架構師一目了然即在於:瞭解系統內部的結構組件,以及系統的介面定義,來與其它的外部系統溝通。請記得,不要再尋求資料庫的資料整合方式了,那是 草本植物 的作法,是會導致系統的盤根錯節,Design for interface,這可以說是軟體設計的根本真理了。

圖 2、範例—BPM 系統的複合結構圖
(點擊圖片鏈接看原圖)圖 2、範例—BPM 系統的複合結構圖

實做面的設計產出

關於實體系統的分層結構

以往 IT 技術人員所認知的架構,即是在實體層次中的分層結構,例如 Client-Server, 3-tier 等。實體的分層結構,僅算是在整體架構其中之一環,是屬於與技術平台相關連的實做層次。在實做面,分層結構當然非常重要,這決定了爾後程序員寫碼的規範,而且是絕對不可違背的原則。例如,在分層結構中已規範定義了:WebUI 表單(Form) 只能呼叫 控制(control)物件,而不允許直接連結資料庫,那麼,程序員無論如何就不能在 WebUI 內寫 SQL 相關的程式碼。

筆者規劃實體的分層結構,並不一定要使用 UML 的部署圖(deploy diagram),可能就是非標準的圖形表示,但最主要的兩個要素:套件(package)與相依性(dependency) 絕對要能表達清楚,並且在專案開發初期就要能與團隊所有開發成員取得共識,均認同這樣的分層結構,後續才不致引起紛爭。

領域模型具體化到資訊系統的實現,必須配合現實的技術平台,包括系統廠商所提供的 圖形使用者介面(GUI, Graphic User Interface)的使用、開發與呈現(例如 Browser, Struts/ASP.NET, Web Server)、資料永續儲存的儲存庫(一般泛稱資料庫, Database,如 Oracle, MySQL)、應用程式伺服器(Application Server, 又可稱之為 Middleware, 提供包括如交易, 權限控管, 分散, 資源控管等系統服務,如 MTS, JBoss, WebLogic),尤其是為了能完整實現領域模型的建構與實現,更需要能讓程式開發人員有物件導向程式語言(OOP, Object-Oriented Programming)的開發機制,例如 .NET 平台所提供的 VB.NET, C#.NET,以及 J2EE 平台的 Java 語言,甚而 PHP, Ruby 等,也都是提供物件化的開發機制。只是後者與前兩者的差別在於,PHP, Ruby 等所提供的系統框架(System Framework)偏於 Web 端的開發,而 .NET 與 J2EE 則在UI端、中間層(Middleware)等均提供了適合於企業層級系統開發的 Frameworks,得以享有諸多便利的系統服務機制。

參考下圖 3,典型的所謂物件導向式資訊系統在設計時會分成幾個分層的結構與模組(modules),幾個主要的分層結構如下:

  • 表達層(Presentation):圖形使用者操作介面,包括 Windows Form, Web Form, Java Swing 等,都是屬於系統廠商所提供給圖形介面開發人員來使用的工具與框架。
  • 中間層:領域物件模型主要所在的位置。為了應付功能性需求,UI 端的功能性呼叫(functional call)是透過中間層的控制物件(Co, Control Object)來控制與協調為完成該功能所需要相關領域物件互動參與的資訊與企業邏輯(business logic)運算;為了隔離外部系統(包括資料庫與外部系統)的變動性,控制物件會透過 邊界類型的物件(boundary object),如 永續性物件(PO, Persistent Object),連結資料庫系統、調變性物件(AO, Adapter Object),連結外部系統,如 Mainframe, Message Quese System, 其它需透過介面(interface)傳遞的系統等,來取得外部系統的資訊。而真正軟體的主結構,其實就是落在 Domain 物件(在中間層稱之為企業物件,Bo, Business Object)上,也就是源自於問題領域的概念性物件,以滿足應用程式的需求。所謂的軟體結構分析設計人員,其實就是應該要聚焦在如何作好領域物件的結構分析與設計!

    三種類型的物件(Control, Entity, Boundary),均會呼叫系統平台所提供的技術層級服務,瞭解平台特性的系統設計人員,會透過系統框架(System Frameworks)所提供的 APIs(Application Programming Interfaces),來呼叫取得所需要的系統服務。這些服務通常與應用領域無關,例如與資料庫之間的溝通介面或記錄程式執行與錯誤的紀錄(log),這些是系統廠商(.NET or J2EE),甚至是 3rd party 的工具廠商,所會提供的。請注意! 不要把這些類型的系統物件當作是要 “可重用(reuse)” 的對象,領域物件才是! 它們只是便於取得系統服務的工具物件而已,會隨著技術的規格變動而變動,甚至有更好用的工具出現,就要換掉原來在用、卻不會影響到系統的主結構。

  • 資料層:中間層領域物件在妥協於現實(記憶體容量與揮發性問題)的技術環境下,需把其狀態(state)永續(persistent)儲存於資料庫內,並且需要使用資料時再透過永續性的機制,將其取出至中間層的領域物件,運算取得結果,並送達至客戶端呈現。現今對於企業層級主流的資料庫系統是以 關連式(Relation)DB 為主,例如 Oracle, MySQL, SQL Server 等。同時關連式資料庫也是最有效可以完整表達問題領域的資料模型,它運用 E-R(Entity-Relationship)的分析技術,就可以呈現為資料庫的 Table Schema,而且其分析的手法與在中間層對於領域物件的分析方式是一致的,可以說 領域物件模型 與 E-R 模型 是 “本是同根生(源自於問題領域)”,而兩者主要的差別只在於,E-R 呈現的是領域概念的資料層,而領域物件(企業物件)則再加上物件應有的行為(behavior),在軟體模型中,是稱之為操作(operation),而在程式語言中,則稱之為 方法(method)。
  • 圖 3、資訊系統的分層結構圖
    (點擊圖片鏈接看原圖)圖 3、資訊系統的分層結構圖

表達物件互動合作的循序圖

筆者是覺得,要與程序員溝通,最有效的一張圖就是循序圖(sequence diagram)了,因為它直接表達了在系統執行期間 (run-time)時,一組物件之間的訊息(message)傳遞。每一張循序(Sequence)圖,均代表一個情節或劇本(Scenario),情節內描述了所參與的物件,以及物件之間的訊息(Message)傳遞。軟體設計師如同電影導演,依照劇本(使用案例),安排適當的演員(物件)照劇本演戲。軟體設計人員在規劃循序圖時,非常重要的一個想像是:物件是活的,是有生命的。

物件導向分析與設計其中一項重要的範疇在於:指派責任(Responsibility)給物件。利用循序圖,就是設計創意最有價值的開發步驟。因為,當設計師畫循序圖,從某物件傳遞訊息給另一物件時,發現到給現在已存的物件均不恰當,這也就代表了,還有潛伏尚未被探索出來的物件,作適切的分類後,再行修正更新類別圖。

基本上,畫循序圖主要的前導來源有:由使用案例(Use Case)所提供的功能案例,也就是劇本(scenario);以及由類別圖所提供的參與物件(Participant Object)。

觀察下圖 4,是一個實現(realize) 填寫請假單 使用案例的循序圖範例。在中間層(middleware)所參與的物件共有四個:處理請假_Uco (Use case control), 請假, 請假_PO(persistent object), workflow_adaptor 等。在此循序圖並沒有表達 UI 表單物件,筆者是給直接隱含在 申請者 這個參與者(actor);另外,在本案例中,也需要與兩個外部系統連結,一為 HR RDB,另一為 Workflow 系統。

圖 4、範例—填寫請假單的循序圖
(點擊圖片鏈接看原圖)圖 4、範例—填寫請假單的循序圖

請注意,SA 所設計的循序圖不一定會是正確的,這需要透過實體技術平台的實做驗證。例如,UCO 物件(亦即為控制物件)會把請假資料透過 PO 與 Adaptor 物件寫入到資料庫與 Workflow 系統,而且也加了註解(note),說明兩者的寫入必須能達成 2-phase commit,也就是要嘛就全部寫入正確,而若有其一寫入失敗就要執行 rollback 的動作。但現實上,workflow 系統可能是外購的,整個系統是被視為黑箱(black-box),是需要透過 workflow 所提供的 APIs 介面來連結。若其本身並不支援 “支援(support)” 的交易屬性,那麼在現實上兩個系統的整合是無法達成 2-phase commit 的。怎麼辦? 從程式的實做驗證,將其結果與意見回饋給 SA 後,循序圖就需要作修正,例如使用 沖銷 的手法,也就是若第一個系統寫入成功,但第二個系統寫入失敗,丟回一個例外(exception)錯誤後,就必須再回去第一個系統將原先所寫入的刪除掉。當然麻煩多了,但設計並非是昧於現實的,當現實的技術尚未能達成設計的理念時,那麼勢必就需要作一些妥協性的設計修正。

結語

軟體架構師,要能具備大局觀,要能知道在不同層次的構面中,應該利用什麼樣的工具與設計圖來與各類開發職的軟體人員溝通討論,更要能懂得如何調和諸多不同面向的觀點。軟體架構師是近年來國外才興起的熱門角色嗎? 不然,請參考「古文觀止」,柳宗元所寫的一篇「梓人傳」,即是在闡述擔任架構師一職所需具備的本職素養。

文章導覽

   

共有 4 則迴響

  1. 您好

    無意間看到您的網站

    感覺很幸運 不過我不懂程式

    只是開始從html and css自己看書學起

    等熟悉了再請教朋友教我PHP的程式

    所以看到您的網 站 就想馬上分享給我的朋友

  2. Hello Dale:
    可不能這麼想喔。 個人的歷程與職志,不一定非得要與公司的發展劃上等號。

    自己選擇要走的路,就是走下去即可,可不能去怨嘆環境,那會造成給自己的藉口而懷憂喪志的。 ^^

  3. 沒錯,台灣的軟體產業只注重快,近來我終於等到機會可以替公司的軟體轉換成平台,因此要重視軟體架構,虛實互補之道是一種藝術,然而正要大展身手時,公司又面臨市場需求與時間的挑戰,感覺逐漸走回原路,…唉!這可能只軟體架構師在台灣最大的挑戰。

發佈回覆給「Kenming Wang」的留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *