Você está na página 1de 5

敏捷軟體開發:原則、樣式及實務 / Robert Cecil Martin

敏捷開發宣言
• 個人及互動勝於流程與工具
• 可用的軟體勝於詳盡的文件
• 與客戶合作勝於合約談判
• 回應變更勝於墨守計畫

Martin's First Law of Documentation


“除非對文件有立即且重大的需求,否則不產出文件。”

敏捷開發原則
1. 經由及早與持續的交付有價值軟體以滿足客戶需求是我們最優先順序。
2. 竭誠歡迎改變需求,甚至已於開發後期亦然。敏捷流程掌控變更以維護客戶的競爭優勢。
3. 經常交付可用的軟體,頻率可以是數週到數個月,以較短時間間隔為佳。
4. 業務人員與開發人員必須在專案全程中天天一起工作。
5. 用動機強的人來建構專案,給予他們適當的環境、充分的資源,並相信他們可以完成工作。
6. 開發團隊之內與團隊之間,效率最高且效果最佳傳遞資訊的方法是面對面溝通。
7. 可用的軟體是最主要的進度量測方法。
8. 敏捷開發提倡能持續的開發步調,贊助者、開發人員以及使用者應當能維持一個穩定而恆久的步調。
9. 持續追求優越的技術與優良的設計以強化敏捷性。
10. 簡單化﹝如何擴大不需要處理之工作的技巧﹞是不可或缺的。
11. 最佳的架構,需求與設計皆源自於自身組織良好的開發團隊。
12. 在規律的時間間隔中,開發團隊因應如何變得更有效率,然後據之適當地調整與修正自己的行為。

極限編程 (Extreme Programming, XP)


• 客戶團隊成員 (Customer Team Member)
◦ 客戶是“定義特性”,並為它們“設定優先權”的人或團體。
◦ 不論客戶是誰,它們都是團隊的成員,並和團隊一起工作。
• 使用者事例 (User Stories)
• 短週期 (Short Cycles)
◦ 反覆週期計畫 (The Iteration Plan)
◦ 發行計畫 (The Release Plan)
▪ 反覆週期一旦開始,客戶就不得改變該次反覆週期內使用者事例的定義或優先順序。
▪ 客戶可以在任何時間改變發行計畫的內容。
• 驗收測試 (Acceptance Test)
• 搭檔編程 (Pair Programming)
◦ 搭檔編程不僅不會降低程式員的效率,還會顯著地減少缺陷率。
• 測試驅動開發法 (Test-Driven Development)
• 程式碼共享 (Collective Ownership)
• 持續整合 (Continuous Integration)
• 持久穩定的步調 (Sustainable Pace)
◦ XP 不允許團隊超時工作,只有一個例外,就是發行前的最後一週。
• 開放的工作空間 (Open Workspace)

1/5
敏捷軟體開發:原則、樣式及實務 / Robert Cecil Martin

• 規劃遊戲 (The Planning Game)


• 簡單設計 (Simple Design)
1. 只做可行的最簡單設計。
2. 你將用不著它。
3. 僅止一份﹝程式碼﹞
▪ 去除重覆最好的方法就是建立抽象化。
• 重構 (Refactoring)
◦ 透過重構,持續保持程式碼近可能的乾淨、簡單並兼具可讀性。
• 隱喻 (Metaphor)

敏捷規劃
• 使用者事例
◦ 事例太大或太小都難以評估。
◦ 過大的事例應該被分割為小一點的事例。
◦ 太小的事例應該和其他小事例合併。

• 速度 (Velocity)

• 版本規劃
◦ 由客戶決定在此版本中想要實作的事例和大略的實作順序。
◦ 客戶不得挑選超過目前速度所能完成的事例。

• 反覆規劃
◦ 由客戶挑選在反覆週期實作的事例,但是不能挑選超過目前速度所能完成的事例。
◦ 反覆週期內事例的實作順序是一種技術的決策。
◦ 反覆週期一旦開始,客戶就不得改變該週期內的事例。但是他們可以任意重排或改變專案中期它的事例。

• 任務規劃
◦ 在反覆週期開始時,開發人員將事例分解成開發任務 (Development Task) 。
◦ 開發人員簽認 (Sign in) 想要實作的任務,當開發人員簽認一件任務時,用任務點數 (Task Point) 加以評估。
◦ 開發人員可以簽認任何種類的任務。
◦ 每個開發人員在上一個反覆週期完成的任務點數就是他這一次的預算 (Budge) 。每個人都不能簽認超過自己預
算的點數。
◦ 當所有開發人員的預算都用完,還有任務尚未被挑選,開發人員會要求客戶移除一些事例或任務。如果所有任
務都被簽認而還有預算,就可以要求客戶增加事例。

• 中途點
◦ 在反覆週期的中途,團隊會召開一次會議。如果團隊沒有完成一半的任務,就要試著重新分配任務與職責。如
果無法重新分配,客戶應該被告知,而決定將某個任務或事例移出當次的反覆週期。

• 進行反覆
◦ 在反覆週期結束,下一次反覆週期開始前,都會對客戶展示目前正常運作的程式。而客戶提出新的使用者事例
作為回饋。

2/5
敏捷軟體開發:原則、樣式及實務 / Robert Cecil Martin

更多細節請參考:“Planning Extreme Programming”, Kent Beck, Martin Fowler and Jennifer Kohnke

敏捷測試
• 測試驅動開發方法
◦ 先編寫聲稱該功能已經存在的失敗測試,然後增加功能到程式中使測試通過。
◦ 好處:
▪ 程式的每一個單一功能都有一組運算來驗證。
▪ 先寫測試強迫設計者從使用者的角度思考介面。
▪ 先寫測試強迫設計者設計出可測試的程式,進一步消除耦合。
▪ 測試可作為文件。

• 驗收測試
◦ 雖然單元測試不可或缺,但並不足以作為驗證的工具。
◦ 單元測試在驗證系統的小元件是否如預期方式運作,但不驗證系統整體是否運作正常。
◦ 驗收測試在驗證客戶需求有被滿足 (Acceptance Test)。

重構
• 以“不改變程式的行為,卻改善其內部架構”的方式來改變軟體的過程。

更多細節請參考:“Refactoring: Improving the Design of Existing Code”, Martin Fowler, Kent Beck, John
Brant, William Opdyke and Don Roberts

敏捷設計
• 不良設計症狀
1. 僵化性 (Rigidity): 設計難以修改。
◦ 如果單一的變更引起了相依模組隨後一連串的變更,那麼設計就是僵化的。
2. 脆弱性 (Fragility): 設計易於遭受破壞。
◦ 做了一個變更時,程式在許多地方就會出問題的傾向。
3. 固定性 (Immobility): 設計難以再利用。
◦ 如果設計中含有其他系統派的上用場的部份,但是將這些部份從原系統分離出來所牽涉的心力與風險卻太
過高昂。
4. 黏滯性 (Viscosity): 難以作出正確的事。
◦ 軟體的黏滯性:當面臨變動時,如果維持原設計的方法比胡砍亂劈難利用,黏滯性就越高。
◦ 環境的黏滯性:當開發環境緩慢且效率不彰時。
◦ 黏滯性高的專案就是軟體設計難以維持的專案。
5. 不必要的複雜度 (Needless Complexity):過度設計 。
6. 設計包含有目前用不上的元素,就是包含了不必要的複雜度。
7. 不必要的重複 (Needless Repetition): 濫用滑鼠。
◦ 當使同的程式碼以些微不同的形式一再出現,開發人員就看不到其抽象性。
◦ 當系統中有重複的程式碼,那麼修改系統的工作就會變的困難重重。
8. 晦澀性 (Opacity): 雜亂無章的表達。

3/5
敏捷軟體開發:原則、樣式及實務 / Robert Cecil Martin

◦ 晦澀性是指模組難以理解的傾向,為了使晦澀程度減至最低,就需要持續花費心力來保持程式碼既清晰又
富表達力。開發人員必須花費一定的力氣來重構程式碼,並且讓別人來審查他們的程式碼。

敏捷原則
1. 單一職責原則 (The Single Responsibility Principle, SRP)
2. 開放封閉原則 (The Open-Closed Principle, OCP)
3. Liskov 替代原則(The Liskov Substitution Principle, LSP)
4. 相依性反向原則 (The Dependency Inversion, DIP)
5. 介面切割原則 (The Interface Segregation Principle, ISP)

• 設計壞味是一種症狀,敏捷團隊運用原則來消除壞味;如果沒有壞味道,它們就不會運用原則。

單一職責原則 (The Single Responsibility Principle, SRP)


“類別變更的原因應僅只有一種。”

• 每一個職責都是一個改變的軸心,當需求變更時,這種改變會透過類別間的職責變化而顯露出來。
• 如果類別有一個以上的職責,這些職責就會耦合在一起,改變一個職責就有可能損害或抑制此類別滿足其他職責的
能力。
• 唯有改變真正發生,改變的軸心才可稱為改變的軸心。如果毫無症狀的事而採用 SRP 是個不智之舉,而引發“不
必要的複雜度”的壞味道。
• 測試驅動開發的開發方式經常會在設計開始發出壞味道前就迫使兩個職責被分離開來。
• 如果測試未迫使職責分離,而“僵化性”和“脆弱性”的壞味道變得越來越強,就應該用 Facade 或 Proxy 樣式重
構設計。

開放封閉原則 (The Open-Closed Principle, OCP)


“軟體實體﹝如類別、模組、函式等等﹞對擴充應保持開放性,而對修改應維持封閉性。”

• 當一個單一的變更引發了相依模組一連串的變動,那麼設計就具有“僵化性”的壞味。
• OCP 運用得宜,變更是以增添新程式碼的方式達成,而不是修改運作正常的舊程式碼。
1. 對擴充開放 (Open for extnsion)
◦ 可以擴充模組,使它具有能夠滿足這些變更的新行為。
2. 對修改封閉 (Close for modification)
◦ 擴充模組的功能並不會對模組的原始碼或二進位碼造成改變。
• 抽象化是關鍵所在。
• 模組可以操作抽象概念,模組相依於固定的抽象概念,所以可以對修改保持封閉,而模組的行為可以透過創造抽象
概念的新衍生類別加以擴充。
• OCP 是物件導向設計的核心,遵循 OCP 會帶來“彈性”、“可復用性”以及“可維護性”。
• 抗拒草率的抽象化和抽象化本身一樣重要。

Liskov 替代原則(The Liskov Substitution Principle, LSP)


“子型別必須可以替換他們的父型別。”

• 違反 LSP 時常導致以嚴重違反 OCP 的方式使用執行其型別資訊 (Run-Time Type Information, RTTI)

4/5
敏捷軟體開發:原則、樣式及實務 / Robert Cecil Martin

• 違反 LSP 就是潛在違反 OCP。


• 一個被隔離開來檢視的模組不可能被有意義地驗證。一個模組的有效性只能以用戶端的角度來表達。
• 如果試圖預測所有的假設,很可能讓系統充斥著“不必要的複雜度”的壞味,通常最佳的方法是除了很明顯違反
LSP 之外全部延緩設計。
• 契約式設計 (Design By Contract, DBC)
◦ 以每個函式所宣告的前置條件 (Precondition) 和後置條件 (Postcondition) 來指明。
◦ 衍生類別函式的重新宣告只能以相同或較弱的前置條件取代原先的前置條件,以相同或較強的後置條件取代原
先的後置條件。
◦ 契約也可以藉由編寫單元測試來加入詳述。

相依性反向原則 (The Dependency Inversion, DIP)


A. “高階模組不應該相依於低階模組,而兩者都應該相依於抽象概念。”
B. “抽象概念不應該相依於細節,而細節應該相依於抽象概念。”

• 高階模組獨立於低階模組,高階模組的重用就會相當簡單,這是框架 (Framework) 設計的核心。


• “所有具有良好結構的物件導向架構 (Architecture) 都有清楚定義的層級,每一層都透過定義良好和受控制的介面
來提供一組功能密切的服務。” ~ Booch
• 下層模組提供了介面的實作,這些介面需告於上層模組,並且被上層模組呼叫。
• “相依於抽象概念”─程式中所有的關係都應終止於抽象類別或介面上。
◦ 任何變數都不應持有指向具體類別的指標或址參器。
◦ 任何類別都不應衍生自具體類別。
◦ 任何函式都不應改寫其任何基礎類別中以實作的函式。
• 讓用戶類別宣告它們所需要之服務的介面,那麼介面改變唯一的時機就是當用戶端需要改變時,而改變實作出抽象
介面的類別就不會影響到用戶端。

介面切割原則 (The Interface Segregation Principle, ISP)


“用戶不應被迫相依於他們用不到的函式。”

• 具有臃腫介面的類別就是介面不具有內聚力的類別。
• 有些物件需要不具有內聚力的介面,然而用戶不應該知道這些介面位於單一類別中。相反地,用戶應該知道的是具
有內具性介面的抽象類別。
• 介面受到汙染常導致衍生類別提供退化的實作 (Degenerate Implemention) ─潛在違反了 LSP。
• 如果用戶被迫依賴於他們不使用的函數時,這會造成用戶之間意外的耦合。
• 解決 ISP 的作法:
◦ 以委託分割介面。
◦ 以多重繼承分割介面。
• 多元參數形式比單一參數形式更佳:
1. 將用戶分群
2. 改變介面
• 務必注意不要使用過當。

5/5

Você também pode gostar