需求描述了軟件系統(tǒng)是什么欢际,架構(gòu)則提供了系統(tǒng)的低成本實現(xiàn)方案,回答了軟件系統(tǒng)如何做的問題矾兜。架構(gòu)依賴需求损趋,需求驅(qū)動架構(gòu)。
目前椅寺,用例是大多數(shù)項目描述需求的方法浑槽,軟件分析設(shè)計活動(包括架構(gòu))的輸入就是用例需求規(guī)約或者其衍生品(用戶故事)。作為架構(gòu)或者開發(fā)人員返帕,我們需要懂得如何從這些規(guī)約和故事中獲取有用信息桐玻,驅(qū)動我們的分析設(shè)計。
這里根據(jù)自己的學(xué)習(xí)理解荆萤,結(jié)合以往的實踐镊靴,總結(jié)了幾點如何從用例開始架構(gòu)設(shè)計的方法。
從用例開始推導(dǎo)系統(tǒng)結(jié)構(gòu)
系統(tǒng)結(jié)構(gòu)是指系統(tǒng)由哪些組件構(gòu)成链韭,這些組件的職責(zé)以及它們之間的關(guān)系偏竟。
系統(tǒng)結(jié)構(gòu)是我們通過架構(gòu)活動創(chuàng)造出來的,沒有一個簡單敞峭、直接踊谋、通用的套路得到結(jié)構(gòu)中的組件,但是用例可以啟發(fā)我們的探索旋讹。
用例是從用戶和涉眾角度對系統(tǒng)的描述殖蚕,它天然就是對系統(tǒng)的一種劃分:每個用例代表了系統(tǒng)的一部分需求轿衔,代表了涉眾/參與者使用系統(tǒng)的一類場景,從場景的層面看睦疫,用例之間沒有交集害驹。而在用例內(nèi)部,場景笼痛、業(yè)務(wù)規(guī)則等元素共同定義了一組強耦合的功能需求裙秋。
如果我們繼續(xù)把用例按照參與者進行分組,每個用例組對應(yīng)一個或若干個類似的參與者缨伊。由于參與者是業(yè)務(wù)領(lǐng)域中的由人或者其它系統(tǒng)扮演的角色摘刑,相似的角色意味著它們提出的功能被組織在一起可能是合理的。
每個用例組我們引入一個組件(可能是子系統(tǒng)刻坊、也可能是模塊)枷恕,它們實現(xiàn)了用例組包含的用例,這些組件構(gòu)成了系統(tǒng)谭胚。這個時候得到的系統(tǒng)結(jié)構(gòu)實際上就是所謂的“功能架構(gòu)”徐块,經(jīng)常出現(xiàn)在系統(tǒng)的售前和宣傳文檔中。但是我們要認識到灾而,由于“功能架構(gòu)”沒有考慮重用和非功能屬性胡控,它不是最終的,可以用于指導(dǎo)開發(fā)架構(gòu)旁趟。
但是從用例組得到的“功能架構(gòu)”在系統(tǒng)劃分上有一定的合理性昼激,我們把它作為架構(gòu)設(shè)計的出發(fā)點,逐步演進锡搜。比如:我們選擇一個功能組件(某個子系統(tǒng)或者模塊)橙困,從對應(yīng)的用例組中找到若干個用例,分析它們的功能需求和非功能需求耕餐,引入新的組件實現(xiàn)公共的功能需求凡傅;引入新的組件或者精化已有組件實現(xiàn)非功能需求。
從用例推導(dǎo)領(lǐng)域模型
我之前參加過UMLChina潘加宇的“軟件方法”培訓(xùn)肠缔,里面介紹了由用例建模的方法夏跷。這里簡單介紹下。
我們要明確這里的領(lǐng)域模型只描述領(lǐng)域概念桩砰,不考慮具體的技術(shù)要素(比如:并發(fā)拓春、事務(wù)等)。
從用例可以推導(dǎo)出邊界類亚隅、控制類和多個實體類硼莽,它們之間的關(guān)系如下:
這些類之間的協(xié)作如下:
為用例定義控制類
一個用例最多一個控制類,一個控制類只關(guān)聯(lián)一個用例,負責(zé)接收所在用例對應(yīng)的業(yè)務(wù)事件懂鸵,協(xié)調(diào)內(nèi)部的處理偏螺。是業(yè)務(wù)用例的調(diào)用入口。
這個控制類不是必須的匆光,如果發(fā)現(xiàn)不需要協(xié)調(diào)套像,所有邏輯可以由實體類完成,可以不需要這個控制類终息。
從業(yè)務(wù)實體夺巩、業(yè)務(wù)處理功能和業(yè)務(wù)約束條件推導(dǎo)實體類
用例和實體類之間是多對多的關(guān)系。從用例中獲得實體類的方法這里不展開了周崭,直接由業(yè)務(wù)實體映射可以作為一個起點柳譬。但是要得到高質(zhì)量的領(lǐng)域模型,還需要在這個基礎(chǔ)上進行抽象和挖掘续镇,這個過程我總結(jié)不出美澳,不過這里給大家推薦幾本書:
- 軟件方法(下)(潘加宇)
- 彩色UML建模(Perter Coad)
- Domain driven design(Eric Evans)
另外,還可以參考一下別人在分析和概念層面總結(jié)的領(lǐng)域設(shè)計模式摸航。
為參與者定義邊界類
邊界類對應(yīng)用例的參與者制跟。
從我自己的體會來看,有必要為每一個輔助參與者(Supporting Actor)建立一個邊界類酱虎,這個邊界類的職責(zé)是和系統(tǒng)依賴的外部系統(tǒng)通信雨膨,比如:發(fā)送通知、調(diào)用某個功能等读串。
對于主動參與者哥放,只有這個參與者是由時間系統(tǒng)承擔(dān)的角色時,為這個角色建立一個邊界類才是有價值的爹土。
從用例推導(dǎo)設(shè)計
當我們用具體的語言/框架去實現(xiàn)之前推導(dǎo)出的領(lǐng)域模型時,必須考慮具體的技術(shù)問題踩身,包括:并發(fā)胀茵、事務(wù)、性能等挟阻,實際上這些就是用例的質(zhì)量屬性琼娘。
如何實現(xiàn)這些非功能需求呢?肯定有很多方法附鸽。我個人比較傾向于通過增加一些新的類/組件脱拼,在不修改之前的的領(lǐng)域?qū)嶓w類的前提下實現(xiàn)。實際上在目前的領(lǐng)域驅(qū)動設(shè)計的相關(guān)書籍里坷备,有很大一部分就是介紹如何在技術(shù)層面實現(xiàn)領(lǐng)域模型熄浓,幫助領(lǐng)域模型落地。
比如:我們要實現(xiàn)數(shù)據(jù)庫的訪問省撑,不是在領(lǐng)域?qū)嶓w類增加類似查詢赌蔑、保存的方法俯在,而是增加一個形如:xxxRepository
的類。
再比如:某個功能需要可伸縮娃惯,這個時候可以在架構(gòu)層面引入新的組件負責(zé)該功能跷乐,組件支持多實例部署,組件內(nèi)部仍然使用原有的相關(guān)領(lǐng)域模型趾浅。