2009年5月28日 星期四

深入淺出物件導向分析與設計

深入淺出物件導向分析與設計(Head First Object-Oriented Analysis and Design)



01 偉大軟體由此開始:良好應用程式之基石


(吉它)

P.12
偉大軟體
一、偉大軟體必須讓客戶滿意,做客戶要它做的事。
Bear: 這是以客戶面而言,客戶要的就是這樣的結果。
二、偉大軟體是設計良好(well-designed)、編程良好(well-coded)、並且易於維護、重利用、及擴展。
Bear: 這是以自已公司而言,要如何降低維護成本與應付所有可能的變更才是重點。

P.13
偉大軟體的三步驟
1.確認你的軟體做客戶要它做的事。
2.應用基本的OO原則,增加軟體的彈性。
3.努力達成可維護、可重利用的設計。



P.26
為正在試圖解決的問題,以文字清楚描述,確保你的設計與應用程式想達成的功能一致。
Bear: 當能以文字清楚描述後,如果能用圖解方式當然更棒了,一圖勝千字咩

P.28
封裝(encapsulation)讓你將應用程式分成一組一組合乎邏輯的零件。

P.31
任何時候看到重複程式碼,就找個地方進行封裝。
Bear: Martin Foller的說法是看到重複程式碼,就找個地方進行重構(refactoring)。

P.43
委派: 一個物件將操作轉交給另一個物件的動作,第二個物件代表第一物件執行該項操作。
Bear: C# delegate三步驟: 1.declare delegate 2.define delegate 3.assign delegate

P.50
要點
01.脆弱的應用程式是很容易出錯的。
02.你能運用像是封裝與委派的OO原則建造有彈性的應用程式。
03.封裝將你的應用程式分解成合乎邏輯的零件。
04.委派將處理特定工作的責任轉交給另一個物件。
05.總是透過整理出客戶要什麼來啟動你的專案
06.一旦完成基本功能,就重新精煉你的設計,讓它有彈性。
07.有了符合功能並具有彈性的設計,便能運用設計模示,進一步改善你的設計,讓應用程式更容易重利用。
08.找出應用程式經常改變的部分,試著將它們與其它不改變的地方相分離
09.建造運作無誤但設計不良的應用程式,滿足了你的客戶,卻留給自已痛苦,以及無數個修正問題的不眠夜。
10.物件導向分析與設計(OOA&D)提供一種產生設計良好之應用程式的方法,同時滿足客戶與程式設計師。

02 給客戶所需之物:收集需求


(狗門)

P.62
it's a specific thing your system has to do to work correctly.
需求: 需求是單一的需要,詳細說明特定產品或服務應該做的事。最常用在系統工程或軟體工程的正式用語中。

P.67
取得好需求的最佳方式,就是瞭解系統應該做什麼。
在本章裡,"出錯"是指使用案例裡"替代路徑"的情況,也就是當事情不循"主要路徑"進行的情況。

P.70
替代路徑(alternate path)處理系統的出錯狀況
Bear: Bear的看法是除了主要路徑外的可行方法都稱為替代路徑,這裡作者所謂的替代路徑應該是指其它的可行解,而非會出錯的解。因此,可以說主要路徑+替代路徑+錯誤解=解集合。

P.71
使用案例是捕捉新系統或軟體變更的潛在需求之技術。每個使用案例提供一或多個使用情節(scenario),傳達系統如何與終端使用者(end user)或其它系統互動,完成特定目標。

P.74
一個使用案例,三個部分
一、清楚的價值
每個使用案例都必須對系統有清楚的價值(clear value),假如使用案例無助於客戶達成目標,這個使用案例便沒有什麼價值。
二、起點與終點
每個使用案例都必須有明確的起點(starting point)與終點(stopping point)。某件事開始此流程,然後要有條件(condition)指明流程已完成。
三、外部啟動者
每個使用案例由外部啟動者(external initiator)開啟,有時,啟動者是人,有時,可能是系統外的任何事物。

P.85
替代路徑與主要路徑兩者都需要測。
..所以,要為事情出錯的情況,進行規劃與測試。

P.106
需求
1.好的需求確保你的系統如客戶所預期地那樣運作。
2.確認需求涵蓋系統的所有使用案例。
3.運用使用案例找出客戶忘了告訴你的事。
4.使用案例將揭露任何不完整、闕漏的需求,你可能必須將它們加到你的系統裡。

要點
01.需求是系統為了正確運作所要做的事。
02.最初的需求通常來自客戶。
03.為了確保你有一組好需求,要發展出系統的使用案例。
04.使用案例詳述系統確切應該做什麼。
05.一個使用案例具有單一的目標,但內含多重的路徑,到達此目標。
06.好的使用案例具有起始與終止條件、外部啟動者,並且對使用者具有清楚的價值。
07.一個使用案例就是一則系統如何運作的故事。
08.對系統要達成的每一個目標,你至少會有一個使用案例。
09.在使用案例完成後,你可藉由它精煉並增加你的需求。
10.確保所有使用案例皆可行的需求清單是一組好的需求。
11.你的系統必須運作在真實世界裡,而不是在你預期的狀況中。
12.當事情有錯時你必須有替代路徑,到達你的目標。

03 山可移,此情永不渝?現在,情況有變:需求變更


P.115
需求總是在變。然而,假如有很好的使用案例,你通常能快速地改變你的軟體,適應那些新需求。

P.120
Bear: 這裡教你如何區分選擇性(optional)路徑與替代(alternate)路徑

P.125
從第一步到最後一步通過使用案例的完整路徑,稱為使用情節。
大部分的使用案例有一些不同的使用情節,但總是共有相同的使用者目標。

P.129
任何時候你的使用案例改變,你必需回頭檢查你的需求。

P.141
有時候,需求的變更揭露出關於系統你所不知道的問題
變更是常態,隨著你每次的實作,系統總是隨之改變。

P.142
需求
01.好的需求確保你的系統如客戶所預期地那樣運作。
02.確認需求涵蓋系統的所有使用案例。
03.運用使用案例找出客戶忘了告訴你的事。
04.使用案例將揭露任何不完整、闕漏的需求,你可能必須將它們加到你的系統裡。
05.需求將總是隨著時間改變(及成長)。

原則
01.將變化之物封裝起來。

要點
01.需求將總是隨著專案推行而改變。
02.當需求變更時,你的系統必須隨之演進,處理新需求。
03.當你的系統需要以新的或不同的方式運作時,就從更新你的使用案例開始。
04.一個使用情節是通過使用案例的單一路徑,從開始到結束。
05.單一使用案例可以有多重使用情節,只要每個使用情節都具有相同的客戶目標。
06.替代路徑可以是只發生在某些情況下,或者提供完全不同路徑通過使用案例的一部分的步驟。
07.假如步驟在系統裡的運作方式是選擇性的,或者是提供替代路徑通過系統,就使用次編號,像是3.1, 4.1 及 5.1 或者 2.1.1, 2.2.1及2.3.1。
08.你應該總是試著避免重複程式碼。那是維護工作的夢魘,並且是系統設計的問題點。

04 將你的軟體帶進現實的世界:分析


(狗門)

P.147
分析幫助你確保系統運作在真實世界的情境裡。

P.162
委派保護你的物件免於軟體裡其他物件之實作改變的干擾。

P.169
查看使用案例裡的名詞(與動詞),並整理出類別與方法的動作,叫做文本分析(textual analysis)。

P.173
好的使用案例以容易瞭解的語言,清楚且準確地解釋系統在做什麼。
有了良好、完整的使用案例,文本分析是整理出系統所需類別簡單且快速的方式。

P.174
文本分析告訴你焦點在哪裡,而不只是你該建立什麼類別。

P.175
注意使用案例裡的名詞,即使它們不是系統裡的類別。
想想看你確實有的類別如何支援使用案例所描述的行為。

P.191
要點
01.分析幫你確保軟體在真實世界的情境裡運作,而不只是在完美的環境裡。
02.使用案例意圖被你自己、你的經理、你的客戶、和其他程式設計師所瞭解。
03.你應該以任何對你與其他觀看者最有用的格式,撰寫使用案例。
04.好的使用案例準確地描述系統做的事,但並未指出系統怎樣完成這些工作
05.每個使用案例應該只聚焦在一個客戶目標。假如有多個目標,你將需要撰寫多個使用案例。
06.類別圖以一萬呎的概觀,給你一個簡單方式,顯示你的系統以及它的程式碼構想。
07.類別圖裡的屬性通常對映代表類別的成員變數
08.類別圖裡的操作通常代表類別的方法
09.類別圖漏掉許多細節,就像類別建構子、某些型別資訊、以及類別裡操作的目的。
10.文本分析幫你將使用案例轉換成程式碼層次的類別、屬性、與操作。
11.使用案例裡的名詞是系統的類別候選人,而動詞是系統的類別上的方法候選人。

P.196
勘誤表 標題《連連看—我是誰》中,〔屬性〕與〔操作〕的連結錯誤:

原為:屬性→這是 UML 的術語,通常代表類別裡的方法。
改為:屬性→等同於類別裡的成員變數。

原為:操作→等同於類別裡的成員變數。
改為:操作→這是 UML 的術語,通常代表類別裡的方法。

05 第一部:諸行無常:良好的設計


(吉它)

P.201
抽象類別是實際實作類別的佔位器(PlaceHolder)。
抽象類別定義行為,而子類別實作該行為。

P.205
每當你在兩個或兩個以上的地方找到共同行為時,小心將該行為抽取到一個類別裡,然後以此共用類別,重利用這項行為。

P.207
UML小抄

P.217
要看看軟體是否設計良好的最佳方式之一,是試著改變它

P.224
對介面撰碼,而不是對實作,讓你的軟體更容易被擴展。
透過對介面撰碼,你的程式碼將使用該介面的所有子類別-甚至還沒被建立的那些。

P.232
OO原則
01.將變化之物封裝起來。
02.對介面撰碼,而不是對實作。
03.應用程式裡的每一個類別只有一個理由改變。

05 第二部:給你的軟體 30 分鐘的伸展操:彈性的軟體


P.242
應用基礎的OO原則增加彈性

P.246
因為當時它似乎很合理,而且改變某件你認為已經運作正常的事是很困難的!
撰碼一次,查看兩次(或更多次)!
當你遇到問題時,持續檢視你的設計。你稍早做的決策可能是現在讓你頭痛的原因。
自尊心扼殺良好的設計
別害怕檢視自己的設計決策及改善它們,即使那意味著進度倒退。

P.249
透過封裝變化之物,你讓應用程式更有彈性,更易於改變。

P.251
當你有一組特性跨物件在變化,使用群集(collection),像是Map,動態儲存那些特性。
你將從你的類別裡移除許多方法,並且在新特性加入應用程式時,免於改變你的程式碼。

P.255
大多數的好設計都是透過分析壞設計而來的。
不要害怕犯錯及改變。

P.269
A cohesive class does one thing really well and does not try to do or be something else.
內聚力(cohesion),內聚力度量個別的模組、類別、與物件內各元素的連接度(degree of connectivity)。軟體的內聚力越高,應用程式裡每個類別的責任就定義得愈好且愈相關(well-defined and related),每個類別就具有特定一組緊密相關的動作要執行。

P.274
偉大的軟體通常就是"夠好"的軟體

P.275
知道何時喊"夠好了!":確認客戶高興、確認你的設計具有彈性。假如你已經完成這兩件事,可能就是往前走的時候了。

P.276
OO原則
01.將變化之物封裝起來。
02.對介面撰碼,而不是對實作。
03.應用程式裡的每一個類別只有一個理由改變。
04.類別是關於行為與功能性。

分析與設計
01.設計良好的軟體容易改變與擴展。
02.使用像是封裝與繼承的基本OO原則,確保你的軟體有彈性。
03.如果設計沒有彈性,就改變它!
04.別與壞設計妥協,即使那是你自己的壞設計,要改就是要改。
05.確認你的每一個類別都具有內聚性;每一個類別都應該聚焦在把一件事情做得很好。
06.隨著軟體的設計生命週期進行,要持續努力提升內聚力。

06 「假如我是真的」:解決真正的大問題


(電玩大亂鬥)

P.280
用解決小問題的相同方式解決大問題

P.281
關鍵在於你如何看待大問題
看待大問題的最佳方式,就是化整為零,將它視為許多個別的功能性片段(pieces of functionality)。你可以將那些片段的每一個視為個別要解決的問題,並且運用你已經知道的每一件事。
你能將大問題分解成許多功能性片段,接著,就每個個別的片段分別解決。

P.291
從客戶取得功能,接著整理出實作這些功能所需要的需求。

P.294
只要可以,就把細節往後遞延

P.297
使用功能清單,確認使用案例圖是完整的。

P.305
使用功能或需求清單來捕捉系統需要做的"大事"。
繪製使用案例圖,顯示你的系統是什麼,無需深入不必要的細節。

P.306
領域分析讓你檢查你的設計,並且是以客戶所用的語言。

P.307
領域分析。辨識、收集、組織、及表示領域相關資訊的流程,根據的是既有系統與其開發歷程的研究、領域專家捕捉到的知識、潛在的理論、領域裡新興的技術。
Bear: 可以參考MS的DSL(Domain Specific Language, 特定領域的解決方案)

P.313
領域分析幫你避免建造不屬於你的責任範圍的系統部分。

P.320
解決大問題
01.聆聽客戶,找出他們要你建造什麼。
02.用客戶瞭解的語言組合功能清單。
03.確認你的功能是客戶真正想要的東西。
04.運用使用案例圖(以及使用案例)建立系統的藍圖。
05.將大系統分解成許多較小的部分。
06.應用設計模示到系統裡較小的部分。
07.運用基本的OOA&D原則為每一個較小的部分設計程式。

要點
01.看待大問題的方式,是將它視為一組較小問題的集合。
02.就像在較小的專案,從收集功能與需求開始進行大專案。
03.功能通常是系統做的"大"事,而且能夠與"需求"一詞互換使用。
04.共通性與變化性給予你在新系統與已知事物之間相互比較的觀點。
05.使用案例是細節導向,使用案例圖則是比較聚焦在整體概廓上。
06.你的使用案例圖應該顧及系統所有的功能。
07.領域分析以客戶瞭解的語言表示系統。
08.行為者是與系統互動,但不屬於系統一部分的任何事。
Bear: 錯字 具 >> 聚

07 為混沌帶來次序:架構


(電玩大亂鬥)

P.326
架構。架構是系統的組織結構,包含分解開來的各個零件、連接性、互動機制、以及你在系統設計中使用的指導原則與決策。

P.331
應用程式真正重要的事情是架構上重要的(architecturally significant)你應該先把焦點置於其上。
Bear: 譯的語意有點不通,他的意思是要你把焦點放在architecturally significant上面。

P.332
架構三問
01.它是系統本質(essence)的一部分嗎?
02.這到底是什麼意思?
03."到底"如何做?

P.335
系統的本質是指在最基本的層次上系統是什麼。

P.338
這些功能之所以在架構上重要(architecturally significant)的理由,是因為它們全都為專案引進風險,你要從哪一個開始都沒有關係--只要你能減少後續的風險。
這裡的重點是減少風險,不必爭論應該先從哪個關鍵功能開始。你可以從中任選一個開始,只要你把焦點放在建造你應該建造的東西上。

P.349
一次把焦點放在一個功能上,減少專案的風險。
不要為無助於減少風險的功能分心。

P.361
共通性分析:通往彈性軟體之路

P.362
好設計總是會減少風險。

P.363
我們只聚焦在會減少風險的事。

P.364
有時候,撰寫偉大程式碼的最佳方式,是在允許的情況下,將程式碼的撰寫往後遞延。
Bear: 儘量把實作拖到最後才做,把最前面的分析設計的時間拉長

P.366
什麼意思?問客戶吧。

P.367
01.詢問客戶
02.共通性分析
03.實作計劃

P.369
關於功能,當你發現不同之事比相同之事還多時,可能就沒有一個良好、通用的解法。

P.370
客戶不為偉大的程式碼付你錢,而是為偉大軟體付你錢
絕對是的!記住,偉大軟體不只是偉大程式碼。

P.371
減少風險有助於偉大軟體的撰寫。

P.372
要點
01.架構幫你將所有的圖型、計畫、及功能清單,轉化成井然有序(well-ordered)的應用程式。
02.系統中對專案最重要的功能是在架構上重要的(architecturally significant)。
03.聚焦在這些功能上--系統的本質、你不確定其意義為何、以及不清楚一開始要怎麼實作的。
04.在專案架構階段中,你所做的每一件事,都應該減少專案的風險。
05.假如你不需要使用案例的所有細節,撰寫詳述軟體能如何被運用的使用情節,可幫你快速收集好需求。
06.當你不確定某項功能是什麼時,你應該詢問客戶,然後,試著把答案歸納出來,你會對該功能取得良好的理解。
07.運用共通性分析,建造具有彈性的軟體解法。
08.客戶對做他想要之事、準時交付的軟體,遠比你認為程式碼寫得很酷的軟體更有興趣。

08 原創性被高估:設計原則


P.377
OCP(Open-Close Principle)

P.380
OCP關乎彈性,而不只是繼承。

P.382
DRY(Donnt Repeat Yourself Principle)

P.385
DRY是關於讓系統裡每一個資訊與行為的片段都存在於單一合理的地方

P.390
SRP(Single Responsibility Principle)
當你的每一個物件都只有一個理由改變時,你已經正確地實作單一責任原則。

P.392
找出多重責任
萬一你出來的東西不合理,你的方法可能違反SRP。該方法很可能屬於別的類別....考慮移掉它吧。

P.400
LSP(Liskov Substitution Principle)
LSP全然關乎設計良好的繼承。當你從一個基礎類別繼承下來,你必需能用你的子類別替代該基礎類別,而不會把事情弄糟,否則,你已經錯誤地使用繼承。

P.402
LSP揭露繼承結構所隱藏的問題。

P.407
假如你需要使用另一個類別的功能性,但不想要改變該功能性,考慮以委派代替繼承。

P.408
使用合成(composition)將來自其他多個類別的行為組合起來。

P.409
合成讓你使用來自"一組其它類別"的行為,並且可以在執行期間切換該行為。
披薩事實上是合成的好例子:它可由各種不同餡料組成,你可以變換。

P.410
當披薩沒了,餡料也沒了....

P.411
在合成中,由其他行為所組成的物件擁有(own)那些行為。當物件被摧毀時,其所有行為也是。在合成裡的行為不存在於合成本身以外。

P.412
聚合:合成,但沒有突然的結束。
聚合是當一個類別是另一個類別的一部分,但仍然可以存在於該類別之外。

P.414
假如你偏好委派、合成、與聚合,勝過繼承,你的軟體通常會較有彈性、較易維護、擴展、與重利用。

P.417
要點
01.透過讓類別"允許擴充而開放,禁止修改而關閉",開閉原則(OCP)讓你的軟體可重利用且具有彈性。
02.透過單一責任原則(SRP),讓類別做單一之事,甚至讓應用OCP到你的程式碼變得更簡單。
03.當你在試著決定某一個方法是否為某一個類別的責任時,問問你自己,做此特定之事是此類別的責任嗎?如果不是,就將此方法移到其他類別去。
04.當你幾乎完成OO程式碼時,務必確認"不自我重複"。避免重複程式碼,確保程式碼裡的每一個行為只出現在單一地方。
05.DRY同時適用在需求以及程式碼:你應該讓軟體裡的每一項功能和需求,在單一地方被實作。
06.透過要求子型別能替代其基礎型別,Liskov替代原則確保你正確使用繼承。
07.假如你發現程式碼違反LSP,考慮利用委派、合成、或聚合,使用來自其他類別的行為,無需訴諸繼承。
08.假如你需要來自其他類別的行為,但不需改變或修改該行為,你能簡單地委派給該類別,使用想要的行為。
09.合成讓你從一整群行為中選擇行為,常常是透過介面的一些實作。
10.當你使用合成,組合物件(composing object)擁有(own)它所使用的行為,若組合物件停止存在,這些行為也會停止存在。
11.聚合讓你使用來自其他類別的行為,但沒有限制這些行為的生命週期。
12.即使在聚合物件(aggregating object)被摧毀之後,被聚合的行為仍繼續存在。

P.418
OO原則
01.將變化之物封裝起來。
02.對介面撰碼,而不是對實作。
03.應用程式裡的每一個類別只有一個理由改變。
04.類別是關於行為與功能性。
05.類別應該允許擴充而開放,禁止修改而關閉(OCP)
06.透過抽取出共通之事,並將它們放在單一位置,避免重複程式碼(DRY原則)
07.系統裡的每一個物件都應該具有單一責任,所有的物件服務都應聚焦在實現該單一責任上(SRP)
08.子類別應該能替代其基礎類別(LSP)

09 軟體終究為客戶服務:反覆與測試


(電玩大亂鬥)

P.426
偉大軟體的撰寫是反覆進行的。
先針對整體概廓作業,接著,反覆進行應用程式的每個片段,直到完成。

P.427
更深入的地反覆:兩種基本選擇
01.功能驅動開發(Feature Driven Development):挑出應用程式的特定功能,並且規劃、分析、及開發該功能,直到完成。
你可以選擇聚焦在應用程式的特定功能(feature)上,此方式全然關乎取出客戶想要的一個功能性片段,並且進行該功能性,直到它完成。
02.使用案例驅動開發(Use Case Driven Development):挑出通過使用案例的情節(scenario),並且撰寫程式碼支援通過該使用案例的完整情節。
你也可以選擇聚焦在通過應用程式的特定流程(flow)上,此方式取出通過應用程式的完整路徑(具有清楚的開始與結束),並且在你的程式碼裡實作該路徑(path)。
兩種反覆進行(iterating)的方式皆由良好的需求(requirement)所驅動。
因為需求源自於客戶,兩種方式都是聚焦在交付客戶要的東西上。
Bear: 功能(feature)和流程(flow)兩種開發方式的基本定義

P.430
兩種開發方式的比較

P.439
你應該為所有能想到的可能使用狀況,測試你的軟體,要有想像力。
也別忘了測試軟體不正確的使用狀況,你將在早期捕捉住錯誤,讓你的客戶高興。

P.440
測試驅動開發聚焦在讓類別的行為正確。

P.451
良好的軟體是經由反覆進行打造而成。分析、設計、再一次反覆進行,一次一次進行應用程式更小更小的部分。
每當你反覆進行時,重新評估你的設計決策,假如對你的設計合理,就別害怕改變。

P.454
測試案例剖析
01.每個測試案例應該有ID與名稱。
02.每個測試案例應該有一件特定的事要測。
03.每個測試案例應該有你提供的輸入。
04.每個測試案例應該有你預期的輸出。
05.大部分的測試案例具有起始狀態。

P.461
當你按契約編程(program by contract)時,你與軟體的使用者正同意該軟體將以特定方式運作。

P.471
當你按契約編程時,你正在與客戶的程式碼合作,協議你將如何處理有問題的狀況。
當你採取防禦性編程時,你正在確保客戶獲得"安全的"回應,不管客戶要什麼。

P.475
要點
01.撰寫良好軟體的第一步,是確保你的應用程式像客戶預期的或想要的那樣運作。
02.客戶通常不在乎圖表與清單;他們想要看你的軟體實際在做事情。
03.使用案例驅動開發一次把焦點放在應用程式之使用案例的一個情節。
04.在使用案例驅動開發裡,你一次把焦點放在單一情節上,然而,在進行其他使用案例的其他情節之前,你通常為單一案例中的所有情節撰碼。
05.功能驅動開發讓你在進行任何其他事情之前,為完整的功能撰碼。
06.在功能驅動開發裡,你所進行的功能可大可小,只要你一次處理一個功能。
07.軟體開發總是反覆式的,你看見整體概廓,接著反覆進行深入較小的功能性片段。
08.在開發循環裡的每一個階段,你必須進行分析與設計,包括當你開始進行新功能或使用案例時。
09.測試讓你確保軟體沒有臭蟲,讓你向客戶證明軟體能運作。
10.好的測試案例只測試一個特定功能片段。
11.測試案例可能只牽涉到單一類別裡的一個或一些方法,或者牽涉到多個類別。
12.測試驅動開發的基本想法是:先撰寫你的測試,再開發你的軟體,通過那些測試,結果是功能完整、有效運作的軟體。
13.按契約編程假定協議雙方瞭解什麼動作會產生什麼行為,並且遵守該契約。
14.當錯誤發生在按契約編程的環境時,方法通常會回傳null或非檢查的例外(unchecked exception)。
15.防禦性編程尋找會出錯的事,廣泛地測試,避免出錯的狀況。
16.在防禦性編程的環境裡,方法通常會回傳"空的"(empty)物件,或者丟出檢查的例外(checked excetion)。

P.478
編程實務
01.按契約編程在你與軟體使用者同意遵守的軟體行為上,建立一個共同的協議。
02.防禦性編程不信任其他軟體,進行廣泛的錯誤及資料檢查確保其他軟體不會給你不良的或不安全的資訊。

開發方式
01.使用案例驅動開發在進行應用程式的任何其他事之前,取出系統的單一使用案例,並且聚焦在完成整個使用案例的程式碼實作上,包含它所有的使用情節。
02.功能驅動開發在進行應用程式的任何其他事之前,把焦點放在單一功能上,並且為該功能的所有行為撰碼。
03.測試驅動開發在為功能性撰碼之前,先為功能性片段撰寫測試情節,接著,撰寫軟體通過所有測試。
04.良好軟體的開發通常在開發循環的不同階段,結合所有這些開發模型。

10 機械獸....組合:OOA&D 生命週期


(物件村地鐵網)

P.495
你的功能清單全然關乎瞭解你的軟體應該做什麼。
使用案例圖讓你開始思考你的軟體將如何被使用,而不需深入一堆不必要的細節。

P.500
系統的功能是系統所做的事,並且,不總是直接反映在你的使用案例裡,使用案例顯示系統如何被使用。
功能與使用案例一起工作,但它們不是相同的東西。

P.514
你的設計決策應該根據你的系統如何被使用以及良好的OO原則。

P.523
你應該只將客戶需要與之互動的類別暴露給客戶。
不與客戶互動的類別可以在對客戶端程式碼影響最少的情況下被改變。

P.535
你的職責是在"確認客戶得到想要的功能性",與"確保程式碼具有彈性且設計良好"之間,取得平衡。

P.543
有時候,完成工作的最佳方式就是找到其他人已經完成該工作的成果。
有時候,特定問題的最佳程式碼已經被撰寫過了。假如某人已經擁有有效的解法,別硬是要自已撰寫。

P.550
OOA&D關乎許多選擇。絕對沒有唯一正確的方法解決問題,因此,擁有的選擇越多,就越有機會為每個問題找到好解法。


----------------------------------------
目錄
----------------------------------------
1 偉大軟體由此開始:良好應用程式之基石

永遠的搖滾樂
Rick 金光閃閃的新應用程式
什麼是你要改變的第一件事
偉大軟體是?
偉大軟體三步驟
先聚焦在功能性
測試驅動
尋找問題
分析
應用基礎的 OO 原則
設計一次,設計二次
改變你的應用程式有多簡單?
封裝變化之物
委派
最後的偉大軟體(就現在而言)
OOA&D 關乎撰寫偉大軟體
要點

2 給客戶所需之物:收集需求

大顯身手的機會來了
測試驅動
不正確的使用(有一點)
什麼是需求
建立需求清單
為錯誤預作規劃
替代路徑處理系統的疑難問題
介紹使用案例
一個使用案例,三個部分
按照使用案例檢查需求
你的系統必須運作在現實世界裡
認識快樂路徑
OOA&D 工具箱

3 山可移,此情永不渝?現在,情況有變:需求變更

英雄!
犧牲品?
軟體分析與設計的不變真理
是選擇性路徑?是替代路徑?誰能分得清?
使用案例對你必須合理
從開始到完成:單一使用情節
替代路徑的真心話
完成需求清單
重複程式碼,遜!
最後的測試驅動
撰寫你自己的設計原則
OOA&D 工具箱

4 將你的軟體帶進現實的世界:分析

一隻狗,二隻狗,三隻狗,四隻?
你的軟體有其情境
識別問題
規劃解法
兩個程式人員的故事
委派繞道
鬆弛耦合應用程式的威力
注意使用案例裡的名詞
從好分析到好類別
類別圖剖析
類別圖不是一切
要點

5 第一部:諸行無常:良好的設計

Rick 的吉他事業蒸蒸日上
抽象類別
類別圖剖析(再一次)
UML 小抄
設計原則秘辛
通往偉大軟體的三步驟(重訪)
插曲:OO 大災難

第二部:給你的軟體 30 分鐘的伸展操:彈性的軟體

回到 Rick 的搜尋工具
仔細瞧瞧 search() 方法
分析的好處
類別與行為有關
設計之死(決策)
將壞的設計決策轉變成好的
Rick 軟體裡的「雙封裝」
千萬不要怕犯錯
瞧!Rick 具有彈性的應用程式
測試驅動「設計良好的軟體」
改變 Rick 的軟體有多容易?
「變更容易性」的大挑戰
具有內聚力的類別善於處理單一事情
設計/內聚力生命週期
偉大軟體是「夠好」
OOA&D 工具箱

6 「假如我是真的」:解決真正的大問題

解決大問題
關鍵在於你如何看待大問題
需求與使用案例是個好起點
共通性與變化性
整理功能
功能與需求的差別
使用案例不總是幫你看出整體概廓
使用案例圖
小小行為者
行為者也是人(好吧,不全然)
做點領域分析吧
化整為零,個個擊破
別忘了真正的客戶是誰
何謂設計模式?
OOA&D 的威力(以及一點基本常識)
OOA&D 工具箱

7 為混沌帶來次序:架構

感覺有點頭昏嗎?
我們需要架構
從功能性開始
什麼是架構上重要?
架構三問
減少風險
使用情節有助於減少風險
一次把焦點放在一個功能上
架構是你的設計結構
再訪共通性
共通性分析:通往彈性軟體之路
什麼意思?問客戶吧
減少風險有助於偉大軟體的撰寫
要點

8 原創性被高估:設計原則

設計原則大集合
開閉原則(OCP)
OCP,一步一步來
不自我重複原則(DRY)
DRY 全然關乎一個地方一個需求
單一責任原則(SRP)
找出多重責任
從多重責任到單一責任
Liskov 替代原則(LSP)
子類別化之誤用:誤用繼承的案例研究
LSP 揭露繼承結構所隱藏的問題
子型別必須能替代其基礎型別
違反 LSP 造成令人困惑的程式碼
將功能委派給其他類別
使用合成組合來自其他類別的行為
聚合:合成,但沒有突然的結束
聚合 vs. 組合
繼承只是選項之一
要項
OOA&D 工具箱

9 軟體終究為客戶服務:反覆與測試

你的工具箱滿了
偉大軟體的撰寫是反覆進行的
更深入地反覆:兩種基本選擇
功能驅動開發
使用案例驅動開發
兩種開發方式
功能分析
撰寫使用情節
測試驅動開發
共通性分析(再探)
強調共通性
強調封裝
比對你的測試與設計
測試案例剖析 ...
向客戶證明
我們一直在按契約編程
按契約編程關乎信任
防禦式編程
將應用程式分解成較小的功能性團塊
要點

10 機械獸?組合:OOA&D 生命週期

開發軟體,OOA&D 風格
物件村的地鐵問題
物件村地鐵圖
功能清單
使用案例反映使用性;功能反映功能性
現在開始反覆
仔細看看地鐵的表示
使用或不使用 Line 類別
物件村地鐵的關注要點(類別)
保護你的類別
中場休息
回歸需求階段
聚焦在程式,然後聚焦在客戶
反覆讓問題變得比較容易
路徑看起來像什麼?
讓自己看看物件村
第 3 次反覆,有人要試試嗎?
路未央?

附錄一:本書遺珠

#1. IS-A 與 HAS-A
#2. 使用案例格式
#3. 反設計模式
#4. CRC 卡
#5. 統計數據
#6. 循序圖
#7. 狀態圖
#8. 單元測試
#9. 撰碼標準與可讀的程式碼
#10. 重構

附錄二:歡迎光臨物件村

UML 與類別圖
繼承
多型
封裝
要點