你是一個優秀軟體開發人員嗎?你知道GRASP嗎?GRASP軟體開發模式,全稱通用職責分配軟體模式(General Responsibility Assignment Software Patterns),是與著名的軟體模式GoF(Gang of Four,即我們常說的那23種軟體開發模式)齊名的另一種軟體開發模式。但是與GoF不同的是,它並不是提出一些具體的軟體組織圖,而是提出,在將現實世界的業務功能抽象成軟體開發中具體對象的過程中,我們應當遵循的一些基本原則。遵循這些基本原則,我們才可以開發出高品質的軟體出來。對於我們要開發的軟體項目,我們可以不使用原廠模式、可以不使用單例模式、我們也可以不使用觀察者模式,但是我們不可能不將現實世界的業務功能抽象成軟體開發中具體對象。從這個角度說,我們要提高自己的軟體開發品質,深入理解GRASP比深入理解GoF更重要。但是我看到現在介紹GoF的文章多,介紹GRASP文章少。正因為如此,我現在把GRASP介紹給大家。
GRASP包含了9個模式,也就是9個基本原則。這在軟體設計大師Craig Larman的經典著作《UML和模式應用》中進行了深入地講解。GRASP叫通用職責分配軟體模式,要理解GRASP,我們首先必須理解的一個問題是,我們在對象分析和設計過程中為什麼要進行職責分配。
一.職責分配和職責驅動設計
在一個軟體項目開始的時候,我們通常需要進行需求分析,瞭解客戶需要設計一個什麼樣的軟體,這個軟體中應當有什麼功能。需求分析瞭解到的是現實世界中客戶需求的業務功能,每個業務功能往往是一個商務程序,即客戶在日常工作中不斷在完成的商務程序。同時,在使用者的問題世界中,必然有一些東西或者說事物,它們之間存在著相互的關聯。
拿一個軟體評審管理系統作為一個例子吧。評審管理系統的業務需求如下:
1.評審召集人制訂評審計劃,提交領導審批,然後通過郵件通知評審者。
2.評審者接到通知,分別對評審對象進行評審,填寫評審表,並可以對評審對象提出疑問。
3.評審召集人匯總評審者的疑問,召開評審會議討論這些疑問。在會上,有些疑問變為問題,有些疑問不是問題,有些則依然不能夠確認。
4.會後,評審召集人整理疑問,形成評審報告,然後由評審者分別表決該評審是否通過。最後評審召集人匯總表決結果,形成評審結論。
5.評審召集人跟蹤問題的解決。
通過以上需求的描述,我們不難發現整個問題世界中的相關事物:評審召集人、評審計劃、評審者、評審對象、評審表、疑問、評審報告、評審結論、問題。我們也不難分析出這些事物相互關係,比如評審計劃與評審者是一對多,而評審報告與評審結論是一對一。
在RUP中,業務需求將形成用例模型及其描述文檔中的用例,事物及其關係將形成領域模型中的對象,當然如何製作用例模型和領域模型超出了本文討論的範圍,有興趣的朋友可以看看相關文章。
領域模型中的對象將成為軟體開發中形成具體對象的基礎(軟體開發中形成什麼對象是根據軟體開發的具體需求而定的,並不一定要與領域模型的對象一致)。用例模型中的用例,將通過賦予這些對象行為而得以實現。現在的問題就出來了,用例模型中的功能,或者說一系列行為,應當如何分配給這些對象呢。也就是說,為了完成同一個任務,我可以將行為A交給對象X,也可以交給對象Y。雖然交給對象X與交給對象Y,我對行為A的具體實現不一樣,但是都可以完成行為A的任務。那麼,我到底應當交給對象X還是對象Y呢?有沒有一個基本原則呢?有,那就是按照職責分配任務。雖然從理論上說,我可以任意定義對象,可以讓對象沒有任何意義,或者去完成任意的工作,但是通常我們不會這樣去設計。通常我們會將對象與現實世界的對象聯絡起來,比如設計一個評審計劃對象、評審者對象。並且我們在設計對象的時候應當做到“低表示差異”。低表示差異就是我們設計的對象應當與現實世界的對象盡量一致。比如說我們設計一個對象叫“評審者”,是因為我們在現實世界中有評審者。同時,我們為評審者對象賦予的行為也應當盡量與現實世界一致,比如增加評審者、修改評審者、得到評審者資訊。那麼哪些是這個對象應當賦予的行為呢,這應當由職責來決定。
我們通過對現實世界的分析,或者說對於領域模型的分析,設計出了軟體系統中的對象,這時候我們應當為每一個對象分配職責。什麼是對象的職責呢,當然是通過對現實世界的分析,定義的這個對象應當完成的任務。比如評審者對象的職責是存取與評審者相關的資料。當然對象的職責不一定是一個,比如評審計劃包含了評審對象和評審者的子項,所以它在工作不繁忙的情況下可以代理處理評審對象和評審者的資訊存取。但是一個對象的職責不應當過多(也就2、3個就行了)並且高度相關。比如評審表對象如果分配職責處理評審表的同時,又去處理評審計劃的資料,這就叫職責無關。
職責分配現在已經被普遍認為是一個優秀的軟體設計應當遵循的原則,它有以下好處:
1.低表示差異使軟體結構清晰,易於理解,因為軟體開發並不是一個人的事情。在多人共同開發的軟體項目中,一目瞭然的軟體結構可以避免開發人員因誤解而造成的不必要錯誤。
2.易於維護和變更。假如評審計划出了問題或需要修改,我們就去找評審計劃,如果是評審者的問題我們就去找評審者,而絕對不會與其它對象有關。
這種通過考慮對象、職責、協作的對象設計及構件方式,被稱為“職責驅動設計(RDD,Responsibility Drive Design)”。職責驅動設計是通過先設計用例模型、用例模型描述、操作契約、系統順序圖、領域模型、詞彙表,再一步步製作分析模型、設計模型,寫出每個功能的互動圖、類圖的很複雜的過程,我在這裡就不再詳述了。但是請大家注意一個非常重要的細節,前面我們說,軟體系統中的對象是根據現實世界抽象得到,對象職責的分配是根據對象的定義,分配一些不多並且高度相關的任務。然而我們即使遵照這些原則,也有相當大的設計彈性空間,不同人根據自己的理解,對於同一個功能依然有各自不同的設計。GRASP中文譯為“通用職責分配軟體模式”,就是對對象分析和設計中職責分配問題提出數個基本原則。同時,這幾個基本原則也應當掌握一個度,即並不是所有情況下都適用,也不是一個絕對的指標。比如低耦合,並不是絕對的不耦合,不耦合軟體就沒法設計了;高內聚也不能無限度地高內聚,否則系統就繁複異常了。
二.GRASP模式挨個析
GRASP軟體設計模式包括9個模式:建立者、資訊專家、低耦合、控制器、高內聚、多態性、純虛構、間接性、防止變異。