2007
年
3
月
21
日星期三
第三章??
發現對象
尋找和評定候選對象的步驟
詳情見本書第
66
頁,其實這些內容和好多方法論的思想差不多,核心不過就是“是什么”“做什么”“怎么做”的不同版本。這些步驟只是思考方法,并未指明工具,其基本思路其實很簡單,就是先對領域進行描述(設計提綱),從描述中發現重要的主題(主題就是討論問題的角度,比如從分布式式系統的角度來考慮需要什么對象,從業務角度考慮需要什么對象),再從主題中發現對象(描述關鍵概念的對象,描述軟件外部特征的對象和描述附加機制和結構的對象),然后再細化對象,進而對已有的對象進行分析,尋找共性,進行進一步抽象和合并。最后一步很有意義,自問每個對象是否有存在的必要。
受到
Larman
對于用例的深刻理解的影響,我越發覺得文字是描述一個系統概貌很好的工具,而不是圖。而且我也覺得
XP
中的
User Story
是很好的實踐,這些用自然語言寫出的東西很方便與領域專家和業務人員進行交流。但是所有這些都有一個統一的原則,就是簡單!夠用就好,不要寫太多,而且以后可能會增加,一次寫太多也理解不了,人的知識是需要一個滿滿的積累過程的,你一天能讀完《史記》嗎?一天讀完之后你還能分得清司馬相如和藺相如嗎?
?
?
找尋對象、角色和類
P67
我們建議你先尋找那些候選角色和對象。一旦你決定在設計中保留它們,再考慮使用接口還是類來實現它們。
?
?
???
我覺得上面這段話對我而言相當有啟發,以前看
Rod Johnson
的《
J2EE
設計開發編程指南》時,對“實現依賴于接口,而非接口依賴于實現”覺得很疑惑,總是覺得我們應該設計好類,然后再將那些公共方法用接口的形式對外公開,怎么才能先把公共方法先寫出來呢?不過現在終于明白這一順序了。
???
實際上接口或是類的定義是通過角色和對象來的,它們的本質都是責任,角色是一組可以由不同對象承擔的責任,對象通過承擔責任來表現它扮演什么角色。而這些責任有些就會變成未來接口中的方法簽名了。等于是說,我們先來討論系統中有哪些角色,哪些對象,然后再考慮是通過接口還是類來實現它們,類是使用抽象類還是具體類。
?
直觀的來看,我們最先能找到的對象肯定是領域對象。因此作者給出的步驟是這樣的:
l????????
尋找第一批對象——代表系統中的概念、結構、機制等重要元素的對象
l????????
然后思考對象的共性,定義公共角色
l????????
然后將對象轉化成類或接口。可以使用繼承、抽象、接口和協作等手段來構造合理、靈活的設計。
?
很喜歡作者對于抽象類、具體類和接口的描述,作者對于面向對象核心概念的闡述都讓我覺得很深刻,而不像閱讀狠多高深的教材那樣——不知道作者在說什么!
P67
抽象類提供了責任的部分實現,并制定了子類必須實現的責任規范
(或許說的是鉤子函數或回調函數)。具體類提供了責任的完整實現,而接口使用一組方法簽名(
method signatures
)更精確的定義了責任,但沒有為其指定實現。
?
?
候選對象特征
???
作者接下來在“尋找的策略”這個子標題下介紹了候選對象代表的內容,我覺得這又是一份充滿了作者經驗的清單,它為我們提供了尋找對象的方法,它的意思就是說:“如果看到這些內容,那么就把它看成候選對象”。而且作者還強調了這份清單與領域另一份清單要契合,那份清單就是角色分類(角色構造型,我不太喜歡這個譯法,它總讓我想到構造器)。我將候選對象包含的內容叫做候選對象的特征:
l????????
系統完成的工作
(應該指的是領域概念,比如銷售,付款等)
l????????
直接受應用程序影響或與其有關聯的東西(其他軟件、物理及期或硬件設備)
l????????
軟件中的信息流
l????????
決策、控制和協調的行為
l????????
結構和對象群
l????????
對應用程序有意義,代表現實事物的對象。
?
候選對象應該指的就是領域模型,更準確地說應該是其中包含領域模型,我想在這里可以跟
Larman
的書中的方法做個統一,描述主題可以使用用例文本,而現在要做的就是發現領域模型或者說是候選對象。
?
我覺得作者的經驗分享應該受到重視,下面摘錄了作者對于某些應用應該選擇的對象的經驗:
l????????
如果應用程序的中心任務是計算
,那么將其分解為多個服務供應者對象,這些對象分別具有計算、轉換和演算等功能。你或許還要設計出代表算法或控制工作流程的對象。
l????????
如果你的應用程序的主要行為是進行信息收集和傳送
,則對象通常是信息及其傳送操作的模型
l????????
如果應用程序與其它系統相連
,設計代表連接的外部接口則成為了工作的重點。大部分設計都需要進行控制和協調的對象,根據控制的復雜度,設計這些對象或許成為整個設計工作的主要部分。
l????????
如果應用程序需要徹底地分類、組織和建立相關對象間的聯系
,那么就應該有構造者對象。
?
P72
在你所尋找的對象和應用軟件所完成的工作的本質之間通常都會存在著某些直接關聯。
作者這段或許是過去經驗的總結,然而并沒有在文中用特殊的字體來表示,我想我也應該按照
Rod Johnson
所說的“循證”原則,對這些進行一番實踐再下結論
~
?
關于命名
????
?
我也一向主張,要給對象、方法、屬性等賦以有意義的名字,作者在“”名字到底有何內涵,給出了好的建議:
1)???????
修飾通用名字。
也就是在通用的名字前面加上表示該特定對象的特征的修飾詞,比如
Calendar
類表示日期和時間系統。
ChineseCalendar
自然就表示中國日歷了。
2)???????
名字里只能包含將最有啟迪性和最突出的因素
。意思是說不要把任何細節都寫道名字里,要不然這名字也忒長了。
3)???????
給服務提供者以“
worker
”式命令。
并不是說名字后面都要用
worker
,而是說加上
er
,表示服務,比如
SystemClassLoader
等;如果某些情況下
er
表服務聽起來不太舒服就用
Service
也行,比如
NamingService
4)???????
為那些名字暗示了廣泛責任的對象尋找輔助對象。
5)???????
選擇不限制行為的名字
。
6)???????
選擇一個適合對象生存期的名字。
7)???????
選擇一個適合當前設計背景的名字。
8)???????
不要重載名字。
9)???????
通過添加形容詞來消除名字沖突。
10)????
通過選擇相似意義的名字來消除沖突。
11)????
選擇容易被理解的名字。
?
描述候選對象
???
本書作者建議通過確定對象的構造型來確定其意圖,即找到一個對象,首先為它命名,然后用合適的一個或多個構造型來刻畫它。
其中,服務提供者、控制者、協調者通過他們所完成的功能來進行區分,描述這些構造型的方法如下:
P79
服務提供者(或者控制者,或協調者)是完成某種功能的一類事物。首先,簡單的描述這些功能。然后指出與功能相關的重要的、有意義的信息,或其協作者。
?
有一條有意義的建議是命名與熟悉的或其概念是廣泛認可的事物關聯起來,以便于不同的人對其進行理解。
?
連接候選對象
把完成相似任務或相互關聯的對象放在一起,將其組織起來,這一步如何去做,作者給出了如下建議:
l????????
依據應用層
l????????
依據用例
l????????
依據構造型角色
l????????
依據鄰域
l????????
依據抽象層
l????????
依據應用主題
?
?
保留和拋棄候選對象?
??????????
做什么事情都不能過度,因此尋找候選對象也要適可而止,在某一個階段,什么樣的候選對象應該保留,什么樣的候選對象應該拋棄,作者給出了一個列表。
保留的候選對象的特征:
l????????
為它起個好名字
l????????
定義它
l????????
確定其構造型
l????????
確定它可以支持某個特殊用例
l????????
確定它是體系結構中的一個重要元素
l????????
賦予它一或兩個初始責任
l????????
理解其外在視圖
l????????
確定其重要性
l????????
把它與相似的對象區分開來
?
拋棄的候選對象的特征:
l????????
所擁有的責任與你更認可的候選對象的責任重疊。
l????????
對象的責任、角色都比較含糊
l????????
對象所持有的功能存放于軟件需求之外
l????????
對于軟件系統來說無特別價值
l????????
對于軟件實現來說似乎無足輕重或又太過復雜。