天天看點

《領域驅動設計:軟體核心複雜性應對之道(修訂版)》—第2章 2.4節文檔和圖

本節書摘來自異步社群《領域驅動設計:軟體核心複雜性應對之道(修訂版)》一書中的第2章,第2.4節文檔和圖,作者【美】埃裡克•埃文斯(eric evans), 馬利偉 , 萬龍,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

2.4 文檔和圖

每當我參加讨論軟體設計的會議時,如果不在白闆或畫闆上畫圖,我就很難讨論下去。我畫的大部分是uml圖,主要以類圖和對象互動圖為主。

有些人天生是視覺動物,圖可以幫助人們掌握某些類型的資訊。uml圖在傳達對象之間的關系上真是遊刃有餘,而且也很擅長表現互動。但它們卻無法給出這些對象的概念定義。在會議中,我會一邊畫圖一邊用語言來豐富它們的意義,或者在與其他參與者讨論時進行解釋。

簡單、非正式的uml圖能夠維系整個讨論。繪制一幅包含目前問題最關鍵的3~5個對象的圖,這樣每個人都可以集中注意力。所有人就對象關系會達成一緻的認識,更重要的是,他們将使用相同的對象名稱。如此,口頭讨論會更加高效。當人們嘗試不同的想法時,圖也随之改變,草圖在某種程度上可以反映讨論的變化,這是讨論中真正重要的部分。畢竟,uml就是統一模組化語言。

當人們必須通過uml圖表示整個模型或設計時,麻煩也随之而來。很多對象模型圖在某些方面過于細緻,同時在某些方面又有很多遺漏。說它們過于細緻是因為人們認為必須将所有要編碼的對象都放到模組化工具中。而細節過多的結果是“隻見樹木,不見森林”。

盡管存在所有這些細節,但屬性和關系隻是對象模型的一部分。這些對象的行為以及這些對象上的限制就不那麼容易表示了。對象互動圖可以闡明設計中的一些複雜之處,但卻無法用這種方式來展示大量的互動,就是工作量太大了,既要制作圖,還要學習這些圖。而且互動圖也隻能暗示出模型的目的。要想把限制和斷言包括進來,需要在uml圖中使用文本,這些文本用括号括起來,插入到圖中。

35

操作名稱可能會暗示出對象的行為職責,對象互動圖(或序列圖)中也會隐含地展示出這些職責,但無法直接表述。是以,這項任務就要靠補充文本或對話來完成。換言之,uml圖無法傳達模型的兩個最重要的方面,一個方面是模型所表示的概念的意義,另一方面是對象應該做哪些事情。但是,這并不是大問題,因為通過仔細地使用語言(英語、西班牙語或其他任何一種語言)就可以很好地完成這項任務。

uml也不是一種十分令人滿意的程式設計語言。我從未見過有人使用模組化工具的代碼生成功能達到了預期目的。如果uml的能力無法滿足需要,通常人們就不得不忽略模型最關鍵的部分,因為有些規則并不适合用線框圖來表示。當然,代碼生成器也無法使用上面所說的那些文本注釋。如果确實能使用uml這樣的繪圖語言來編寫可執行程式,那麼uml圖就會退化為程式本身的另一種視圖,這樣,“模型”的真正含義就丢失了。如果使用uml作為實作語言,則仍然需要利用其他手段來表達模型的确切含義。

圖是一種溝通和解釋手段,它們可以促進頭腦風暴。簡潔的小圖能夠很好地實作這些目标,而涵蓋整個對象模型的綜合性大圖反而失去了溝通或解釋能力,因為它們将讀者淹沒在大量細節之中,加之這些圖也缺乏目的性。鑒于此,我們應避免使用包羅萬象的對象模型圖,甚至不能使用包含所有細節的uml資料存儲庫。相反,應使用簡化的圖,圖中隻包含對象模型的重要概 念——這些部分對于了解設計至關重要。本書中的圖都是我在項目中使用過比較典型的圖。它們很簡單,而且具有很強的解釋能力,在澄清一些要點時,還使用了一些非标準的符号。它們顯示了設計限制,但它們不是面面俱到的設計規範。它們隻展現了思想綱要。

36

設計的重要細節應該在代碼中展現出來。良好的實作應該是透明的,清楚地展示其背後的模型(下一章及本書其他許多章節的主題就是闡述如何做到這一點)。互為補充的圖和文檔能夠引導人們将注意力放在核心要點上。自然語言的讨論可以填補含義上的細微差别。這就是為什麼我喜歡把典型的uml使用方法颠倒過來的原因。通常的用法是以圖為主,輔以文本注釋;而我更願意以文本為主,用精心挑選的簡化圖作為說明。

務必要記住模型不是圖。圖的目的是幫助表達和解釋模型。代碼可以充當設計細節的存儲庫。書寫良好的java代碼與uml具有同樣的表達能力。經過仔細選擇和構造的圖可以幫助人們集中注意力,并起到指導作用,當然前提條件是不能強制用圖來表示全部模型或設計,因為這樣會削弱圖的清晰表達的能力。

2.4.1 書面設計文檔

口頭交流可以解釋代碼的含義,是以可作為代碼精确性和細節的補充。雖然交談對于将人們與模型聯系起來是至關重要的,但書面文檔也是必不可少的,任何規模的團隊都需要它來提供穩定和共享的交流。但要想編寫出能夠幫助團隊開發出好軟體的書面文檔卻是一個不小的挑戰。

一旦文檔的形式變得一成不變,往往會從項目進展流程中脫離出來。它會跟不上代碼或項目語言的演變。

書面文檔有很多編寫方法。本書第四部分将介紹幾種滿足特定需要的具體文檔,但不會列出項目需要使用的所有文檔,而是給出兩條用于評估文檔的總體原則。

文檔應作為代碼和口頭交流的補充

每種靈活過程在編寫文檔方面都有自己的理念。極限程式設計主張完全不使用(多餘的)設計文檔,而讓代碼解釋自己。實際運作的代碼不會說謊,而其他文檔則不然。運作代碼所産生的行為是明确的。

37

極限程式設計隻關注對程式及可執行測試起作用的因素。由于為代碼添加的注釋并不影響程式的行為,是以它們往往無法與目前代碼及其模型保持同步。外部文檔和圖也不會影響程式的行為,是以它們也無法保持同步。另一方面,口頭交流和臨時在白闆上畫的圖不會長久保留而産生混淆。依賴代碼作為交流媒介可以促使開發人員保持代碼的整潔和透明。

然而,将代碼作為設計文檔也有局限性。它可能會把讀代碼的人淹沒在細節中。盡管代碼的行為是非常明确的,但這并不意味着其行為是顯而易見的。而且行為背後的意義可能難以表達。換言之,隻用代碼做文檔與使用大而全的uml圖面臨着差不多相同的基本問題。當然,團隊進行大量的口頭交流能夠為代碼提供上下文和指導,但是,口頭交流很短暫,而且範圍很小。此外,開發人員并不是唯一需要了解模型的人。

文檔不應再重複表示代碼已經明确表達出的内容。代碼已經含有各個細節,它本身就是一種精确的程式行為說明。

其他文檔應該着重說明含義,以便使人們能夠深入了解大尺度結構,并将注意力集中在核心元素上。當程式設計語言無法直接明了地實作概念時,文檔可以澄清設計意圖。我們應該把書面文檔作為代碼和口頭讨論的補充。

文檔應當鮮活并保持最新

我在為模型編寫書面文檔時,會仔細選擇一個小的模型子集來畫圖,然後讓文字放置在這些圖周圍。我用文字定義類及其職責,并且像自然語言那樣把它們限定在一個語義上下文中。而圖顯示了在将概念形式化和簡化為對象模型的過程中所做的一些選擇。這些圖可以随意一些,甚至是手繪的。手繪圖除了節省工作量,也讓人們一看就知道它們是不正式、臨時的。這些優點都非常有利于交流,因為它們适用于我們的模型思想。

38

設計文檔的最大價值在于解釋模型的概念,幫助在代碼的細節中指引方向,或許還可以幫助人們深入了解模型預期的使用風格。根據不同的團隊理念,整個設計文檔可能會十分簡單,如隻是貼在牆上的一組草圖,也可能會非常詳盡。

文檔必須深入到各種項目活動中去。判斷是否做到這一點的最簡單方法,是觀察文檔與ubiquitous language之間的互動。文檔是用人們(目前)在項目上講的語言編寫的嗎?它是用嵌入到代碼中的語言編寫的嗎?

注意聽ubiquitous language,觀察它是如何變化的。如果設計文檔中使用的術語不再出現在讨論和代碼中,那麼文檔就沒有起到它的作用。或許是文檔太大或太複雜了,或許是它沒有關注足夠重要的主題。人們要麼不閱讀文檔,要麼覺得它索然無味。如果文檔對ubiquitous language沒有影響,那麼一定是出問題了。

相反,我們會注意到ubiquitous language随着文檔漸漸過時而自然地改變。顯然,要麼人們不再關心文檔,要麼認為它不重要而不再去更新它。這時可以将它作為曆史檔案安全地歸檔,如果繼續使用這樣的文檔可能會産生混淆并損害項目。如果文檔不再擔負重要的作用,那麼純粹靠意志和紀律保持其更新就是浪費精力。

ubiquitous language可以使其他文檔(如需求規格說明)更簡潔和明确。當領域模型反映了與業務最相關的知識時,應用程式的需求成為該模型内部的場景,而ubiquitous language可直接用model-driven design(模型驅動設計)的方式描述此類場景(參見第3章)。結果就是規格說明的編寫更簡單,因為它們不必傳達模型背後隐含的業務知識。

39

通過将文檔減至最少,并且主要用它來補充代碼和口頭交流,就可以避免文檔與項目脫節。根據ubiquitous language及其演變來選擇那些需要保持更新并與項目活動緊密互動的文檔。

2.4.2 完全依賴可執行代碼的情況

現在,我們來考查一下xp社群和其他一些人為何選擇幾乎完全依賴可執行代碼及其測試。本書主要讨論了如何通過model-driven design使代碼表達出設計的含義(參見第3章)。良好的代碼具有很強的表達能力,但它所傳遞的資訊不能確定是準确的。一段代碼所産生的實際行為是不會改變的。但是,方法名稱可能會有歧義、會産生誤導或者因為已經過時而無法表示方法的本質含義。測試中的斷言是嚴格的,但變量和代碼組織方式所表達出來的意思未必嚴格。好的程式設計風格會盡力使這種聯系直接化,但其仍然主要靠開發人員的自律。編碼時需要一絲不苟的态度,隻有這樣才能編寫出“言行全部正确”的代碼。

消除這些差異是諸如聲明式設計(參見第10章)這樣的方法的最大優點,在這類方法中,程式元素用途的陳述決定了它在程式中的實際行為。從uml生成程式的部分動機就來源于此,雖然目前看來這通常不會得到好的結果。

盡管代碼可能會産生誤導,但它仍然比其他文檔更基礎。要想利用目前的标準技術使代碼所傳達的消息與它的行為和意圖保持一緻,需要紀律和思考設計的特定方式(第三部分将詳細讨論這些問題)。要有效地交流,代碼必須基于在編寫需求時所使用的同一種語言,也就是開發人員之間、開發人員與領域專家之間進行讨論時所使用的語言。