文章目錄
這是從原書中第12章到後面的讀書筆記,對於前面的讀書筆記及思考參見UML和模式應用讀書筆記二(做正確的事)
0x2B | ~0x2B
–Hamlet
上面的答案是0xFF
包
logical architecture是軟件類的宏觀組織結構,他將軟件類組織爲包,子系統和層等.
層
layer是對類,包或子系統的粗粒度分組,
OO系統的層一般包括用戶界面,應用邏輯和邏輯對象,技術服務(數據庫和日誌)三層
在嚴格的分層架構中,層只能調用與其相鄰的下層服務.這種設計在網絡協議棧中比較常見,而在信息系統中不太常見.在信息系統中通常使用寬鬆的分層架構,其中較高層可以調用其下任何層的服務.
有的時候我們的確需要反向傳遞信息(例如通知GUI窗口對象改變顏色,這個時候就通過觀察者模式,由GUI監聽來實現)
從UI層發送到領域層的消息是將SSD中所描述的消息,例如enterItem
在開發過程的早期,我們會畫出UML包圖的草圖,然後根據這些草圖來組織代碼.隨着時間的流逝,代碼庫不斷增長,同時我們在編程上花費的時間更多,並減少了建模或繪製UML圖的時間.此時,可以利用UML CASE工具對源代碼進行逆向工程,從而自動生成包圖
內部嵌套包的表示
分包
//—UI層
com.mycompany.nextgen.ui.swing
com.mycompany.nextgen.ui.web
//—領域層
com.mycompany.nextgen.domain.sales
com.mycompany.nextgen.domain.payments
//—技術服務層
com.mycompany.service.persistence
//—第三方
org.apache.log4j
org.apache.soap.rpc
//—基礎層
com.mycompany.util
注意上面有些包名帶了nextgen,有些沒有
最底層
文中建議不要將一些外部資源或服務放到邏輯中低於基礎層的地方,因爲他們不屬於任何邏輯層,層大致上只有上面那幾種
敏捷建模
一些敏捷建模的目標是減少常用圖形,建模的目的是爲了理解和溝通,而不是構建文檔.
敏捷建模還包括
- 與其他人一同建模
- 並行創建若干模型
例如,在牆上用5分鐘畫交互圖,然後再用5分鐘畫相關類圖,反覆交替
準則
應該把時間花費在交互圖(順序圖或通信圖),而不僅是類圖上.
忽視這一準則是十分常見的UML錯誤實踐
文中比較了動態建模和靜態建模,對於我個人而言覺得動態建模更好,更貼近業務並且更容易關聯理解
並且繪製動態圖相對於繪製靜態圖的另一個優勢是動態圖不會出現和代碼矛盾的情況,其可以作爲代碼的補充
CRC卡
人們對不同設計方法各有偏好除了因爲熟悉該種方法外,更重要的是因爲每個人有不同的認知方式.不要假設所有人都認爲圖形優於文本,反之亦然.
文中提到CRC卡應該僅僅是爲了防禦,我baidu了一下沒看到任何資料
interaction diagram
文中提到了兩種交互圖sequence diagram和communication diagram,前者相對於後者更好(Craig Larman也承認這一點),後者的優勢就是在牆上畫圖的時候可以充分利用整個牆面.
順序圖
常見圖框操作符
- alt
選擇性的片段,用於表示保護信息所表達的互斥條件邏輯- loop
用於表示保護信息爲真的循環片段.也可以寫*loop(n)*以指明循環的次數- opt
當保護信息爲真時執行的可選片段- par
並行執行的片段- region
只能執行一個線程的片段
ref
用於交互圖引用
metaclass
對於靜態方法/類方法的調用需要加上<<metaclass>>
多態
在這裏圖表表達細節和多態屏蔽細節出現了矛盾,結果就是要畫多份圖,如下所示
active object
就是不需要從系統外部觸發,能夠自己觸發的對象,一般運行在另一個線程.通過生命線框圖加雙豎線表示
通信圖
並不是每個交互圖都要由系統操作消息開始,可以由設計者希望表示其交互的任何消息開始
消息
對象間的每個消息都可以使用消息表達式和指明消息方向的小箭頭來表示…可以增加順序編號以表示當前控制線程中消息的次序
實例的創建
任何消息都可以用來創建實例,但是在UML中約定使用名爲create的消息來實現這一目的(有人用new)
編號
不爲第一個消息編號
使用核發編號的方案來表示後續消息的順序和嵌套,其中嵌套消息要使用附加數字.通過在外部消息編號後附加引入消息編號來表示嵌套
注意上面英文標出的執行順序
互斥&循環
靜態方法 & 多態 & 同步異步
這些和順序圖類似
類圖
屬性
三種方法
- 屬性文本表示法
- 關聯線表示法
- 兩者皆有
屬性文本格式
visibility name:type multiplicity=default(property-string)
準則:如果沒有給出可見性,則通常假設屬性是私有的
關聯性
- 導航性箭頭 由源對象指向目標對象
- 多重性放置在目標一端,而不是源一端
- 角色名只放置在目標一端,用以表示屬性名稱
集合
composition
組合關係有以下幾層含義
- 在某一時刻,部分的實例只屬於一個組成實例
- 部分必須總是屬於組成(不存在遊離的)
- 組成要負責創建和刪除其部分,既可以自己來也可以與其他對象協作
個人觀點,由於創建時總會有必填項與外鍵關聯,所以上面要求組成要創建部分的限定不夠厲害,而另一方面,幾乎不存在刪除操作,所以組成要刪除部分的約束也沒啥用
限定關聯
當存在一對多,特別是一的一方的主鍵是多的一方的邏輯主鍵時,可以通過補充缺失的字段來鎖定唯一
關聯類
這個在DB中作爲多對多的關係表,由於有了額外的屬性,所以也就需要一個專門的類,爲何不改成兩個一對多的關係呢?我認爲是改了之後就修改了原有的語義.(何況關聯類可能是當初沒有的,後來新增的,當然對設計不能大改)
方法
格式
visibility name(parameter-list):return-type(property-string)
準則:如果沒有表示可見性,則通常假設操作是公共的
create
使用<<contructor>>來標識構造方法
getter
一般省略
關鍵字
關鍵字 | 含義 | 用法示例 |
---|---|---|
<<actor>> | 類元爲參與者 | 置於類名稱之上 |
<<interface>> | 類元爲藉口 | 置於類名稱之上 |
{abstract} | 抽象元素,不能實例化 | 置於類元名稱或操作名稱之後 |
{ordered} | 具有強制順序的一組對象 | 置於關聯的端點 |
單實例類
作圖上就是右上角標個1,我覺得還不如<<singleton>>來的明確,另外單實例類有點違背OO
主動類
active object運行於自己控制的執行線程之上.毫無疑問,主動對象的類即爲主動類.在UML中,主動類使用左右兩邊爲雙豎線的類框來表示
GRASP
對象職責
- 行爲職責
- 自身執行一些行爲,如創建對象或計算
- 初始化其他對象中的操作
- 控制和協調其他對象中的活動
- 認知職責
- 對私有封裝數據的認知
- 對相關對象的認知
- 對其他夠導出或計算的事物的認知
看看上面的列表,創建其他對象也可以是對象職責,未必只能創建自己
職責和方法並非同一事物,職責是一種抽象,而方法實現了職責
RDD是思考OO軟件設計的一般性隱喻.把軟件對象想象成具有某種職責的人,他要與其他人協作以完成工作.
模式
簡單地講,好的模式是成對的問題/解決方案,並且具有廣爲人知的名稱,他能用於新的語境中,同時對新情況下的應用,權衡,實現,變化等給出了建議
術語模式的真實含義是長期重複的事物.設計模式的要點並不是要表達新的設計思想.恰恰相反,優秀模式的意圖是將已有的經過驗證的知識,慣用手法和原則彙總起來.磨礪的越多,越久,使用的越廣泛,這樣的模式就越優秀.
里程碑
全書到了這裏,終於到了OO的起點:
- 迭代過程背景 --有哪些優先製品,他們與OO設計模型有什麼關係?我們應當花費多少時間進行設計建模?
- 作爲對象設計隱喻的RDD:有職責對象協作的共同體
- 作爲OO設計思想命名和解釋方式的模式:分配職責的基本模式是GRASP,對於更爲高級的設計思想則應用GoF模式.模式可以在建模期間和編碼期間應用
- UML用於OO設計的可視建模,在此期間,GRASP和GoF模式都能使用.
書中繼續講下去,但是我覺得在這裏暫停一下是很有必有的,因爲我們有太多的方案只是在解決問題而沒有指出解決問題的環境.而對於從理論走向實踐而複雜而言,這種設身處地的限制解決方案的應用環境是很有必要的,也顯示出自己是一個懂行的實踐者.