Wiki: http://en.wikipedia.org/wiki/Agile_software_development
在按照我的了解方式審查了軟體開發的生命周期後,我得出一個結論:實際上滿足工程設計标準的惟一軟體文檔,就是源代碼清單。
-- Jack Reeves
簡介
2001年,為了解決許多公司的軟體團隊陷入不斷增長的過程泥潭,一批業界專家一起概括出了一些可以讓軟體開發團隊具有快速工作 、響應變化能力的價值觀和原則,他們稱自己為靈活聯盟。靈活開發過程的方法很多,主要有:SCRUM,Crystal,特征驅動軟體開發(Feature Driven Development,簡稱FDD),自适應軟體開發(Adaptive Software Development,簡稱ASD),以及最重要的極限程式設計(eXtreme Programming,簡稱XP)。極限程式設計(XP)是于1998年由Smalltalk社群中的大師級人物Kent Beck首先倡導的。
極限程式設計
設計和程式設計都是人的活動。忘記這一點,将會失去一切。
-- Bjarne Stroustrup
極限程式設計(XP)是靈活方法中最著名的一個。它是由一系列簡單卻互相依賴的實踐組成。這些實踐結合在一起形成了一個勝于部分結合的整體。
下面是極限程式設計的有效實踐:
- 完整團隊 XP項目的所有參與者(開發人員、客戶、測試 人員等)一起工作在一個開放的場所中,他們是同一個團隊的成員。這個場所的牆壁上随意懸挂着大幅的、顯著的圖表以及其他 一些顯示他們進度的東西。
- 計劃遊戲計劃是持續的、循序漸進的。每2周,開發人員就為下2周估算候選特性的成本,而客戶則根據成本和商務價值來選擇要實作的特性。
- 客戶測試作為選擇每個所期望的特性的一部分,客戶可以根據腳本語言來定義出自動驗收測試來表明該特性可以工作。
- 簡單設計團隊保持設計恰好和目前的系統功能相比對。它通過了所有的測試,不包含任何重複,表達出了編寫者想表達的所有東西,并且包含盡可能少的代碼。
- 結對程式設計所有的産品軟體都是由兩個程式員、并排坐在一起在同一台機器上建構的。
- 測試驅動開發編寫單元測試 是一個驗證行為,更是一個設計行為。同樣,它更是一種編寫文檔的行為。編寫單元測試避免了相當數量的回報循環,尤其是功功能能驗證方面的回報循環。程式員以非常短的循環周期工作,他們先增加一個失敗的測試,然後使之通過。
- 改進設計随時利用重構方法改進已經腐化的代碼,保持代碼盡可能的幹淨、具有表達力。
- 持續內建團隊總是使系統完整地被內建。一個人拆入(Check in)後,其它 所有人責任代碼內建。
- 集體代碼所有權任何結對的程式員都可以在任何時候改進任何代碼。沒有程式員對任何一個特定的子產品或技術 單獨負責,每個人都可以參與任何其它方面的開發。
- 編碼标準 系統中所有的代碼看起來就好像是被單獨一人編寫的。
- 隐喻 将整個系統聯系在一起的全局視圖;它是系統的未來影像,是它使得所有單獨子產品的位置和外觀變得明顯直覺。如果子產品的外觀與整個隐喻不符,那麼你就知道該子產品是錯誤的。
- 可持續的速度 團隊隻有持久才有獲勝的希望。他們以能夠長期維持的速度努力工作,他們儲存精力,他們把項目看作是馬拉松長跑,而不是全速短跑。 極限程式設計是一組簡單、具體的實踐,這些實踐結合在形成了一個靈活開發過程。極限程式設計是一種優良的、通用的軟體開發方法,項目團隊可以拿來直接采用,也可以增加一些實踐,或者對其中的一些實踐進行修改後再采用。
靈活開發
人與人之間的互動是複雜的,并且其效果從來都是難以預期的,但卻是工作中最重要的方面。
-- Tom DeMacro和Timothy Lister
靈活軟體開發宣言:
- 個體和互動 勝過 過程和工具
- 可以工作的軟體 勝過 面面俱到的文檔
- 客戶合作 勝過 合同談判
- 響應變化 勝過 遵循計劃
雖然右項也有價值,但是我們認為左項具有更大的價值。
- 我們最優先要做的是通過盡早的、持續的傳遞有價值的軟體來使客戶滿意。
- 即使到了開發的後期,也歡迎改變需求。靈活過程利用變化來為客戶創造競争優勢。
- 經常性地傳遞可以工作的軟體,傳遞的間隔可以從幾個星期到幾個月,傳遞的時間間隔越短越好。
- 在整個項目開發期間,業務人員和開發人員必須天天都在一起工作。
- 圍繞被激勵起來的個體來建構項目。給他們提供所需的環境和支援,并且信任他們能夠完成工作。
- 在團隊内部,最具有效果并富有效率的傳遞資訊的方法,就是面對面的交談。
- 工作的軟體是首要的進度度量标準。
- 靈活過程提倡可持續的開發速度。責任人、開發者和使用者應該能夠保持一個長期的、恒定的開發速度。
- 不斷地關注優秀的技能和好的設計會增強靈活能力。
- 簡單是最根本的。
- 最好的構架、需求和設計出于自組織團隊。
- 每隔一定時間,團隊會在如何才能更有效地工作方面進行檢討,然後相應地對自己的行為進行調整。
當軟體開發需求的變化而變化時,軟體設計會出現壞味道,當軟體中出現下面任何一種氣味時,表明軟體正在腐化。
- 僵化性: 很難對系統進行改動,因為每個改動都會迫使許多對系統其他部分的其它改動。
- 脆弱性: 對系統的改動會導緻系統中和改動的地方在概念上無關的許多地方出現問題。
- 牢固性: 很難解開系統的糾結,使之成為一些可在其他系統中重用的元件。
- 粘滞性: 做正确的事情比做錯誤的事情要困難。
- 不必要的複雜性: 設計中包含有不具任何直接好處的基礎結構。
- 不必要的重複性: 設計中包含有重複的結構,而該重複的結構本可以使用單一的抽象進行統一。
- 晦澀性: 很難閱讀、了解。沒有很好地表現出意圖。
靈活團隊依靠變化來擷取活力。團隊幾乎不進行預先設計,是以,不需要一個成熟的初始設計。他們更願意保持設計盡可能的幹淨、簡單,并使用許多單元測試和驗收測試作為支援。這保持了設計的靈活性、易于了解性。團隊利用這種靈活性,持續地改進設計,以便于每次疊代結束生成的系統都具有最适合于那次疊代中需求的設計。為了改變上面軟體設計中的腐化味,靈活開發采取了以下面向對象的設計原則來加以避免,這些原則如下:
-
單一職責原則(SRP)
就一個類而言,應該僅有一個引起它變化的原因。
-
開放-封閉原則(OCP)
軟體實體應該是可以擴充的,但是不可修改。
-
Liskov替換原則(LSP)
子類型必須能夠替換掉它們的基類型。
-
依賴倒置原則(DIP)
抽象不應該依賴于細節。細節應該依賴于抽象。
-
接口隔離原則(ISP)
不應該強迫客戶依賴于它們不用的方法。接口屬于客戶,不屬于它所在的類層次結構。
-
重用釋出等價原則(REP)
重用的粒度就是釋出的粒度。
-
共同封閉原則(CCP)
包中的所有類對于同一類性質的變化應該是共同封閉的。一個變化若對一個包産生影響,則将對該包中的所有類産生影響,而對于其他的包不造成任何影響。
-
共同重用原則(CRP)
一個包中的所有類應該是共同重用的。如果重用了包中的一個類,那麼就要重用包中的所有類。
-
無環依賴原則(ADP)
在包的依賴關系圖中不允許存在環。
-
穩定依賴原則(SDP)
朝着穩定的方向進行依賴。
-
穩定抽象原則(SAP)
包的抽象程度應該和其穩定程度一緻。
上述中的包的概念是:包可以用作包容一組類的容器,通過把類組織成包,我們可以在更高層次的抽象上來了解設計,我們也可以通過包來管理軟體的開發和釋出。目的就是根據一些原則對應用程式中的類進行劃分,然後把那些劃分後的類配置設定到包中。
下面舉一個簡單的設計問題方面的模式與原則應用的示例:
問題:
選擇設計運作在簡易台燈中的軟體,台燈由一個開關和一盞燈組成。你可以詢問開關開着還是關着,也可以讓燈打開或關閉。
解決方案一:
下面圖1是一種最簡單的解決方案,Switch對象可以輪詢真實開關的狀态,并且可以發送相應的turnOn和turnOff消息給Light。
解決方案二:
上面這個設計違反了兩個設計原則:依賴倒置原則(DIP)和開放封閉原則(OCP),DIP原則告訴我們要優先依賴于抽象類,而Switch依賴了具體類Light,對OCP的違反是在任何需要Switch的地方都要帶上Light,這樣就不能容易擴充Switch去管理除Light外的其他對象。為了解決這個方案,可以采用ABSTRACT SERVER模式,在Switch和Light之間引入一個接口,這樣就使得Switch能夠控制任何實作了這個接口的東西,這也就滿足了DIP和OCP原則。如下面圖2所示:
解決方案三:
上面圖2所示解決方案,違返了單一職責原則(SRP),它把Switch和Light綁定在一起,而它們可能會因為不同的原因而改變。這種問題可以采用ADAPTER模式來解決,擴充卡從Switchable 派生并委托給Light,問題就被優美的解決了,現在,Switch就可以控制任何能夠被打開或者關閉的對象。但是這也需要會出時間和空間上的代價來換取。如下面圖3所示:
靈活設計是一個過程,不是一個事件。它是一個持續的應用原則、模式以及實踐來改進軟體的結構和可讀性的過程。它緻力于保持系統設計在任何時間都盡可能得簡單、幹淨和富有表現力。
靈活開發實踐疊代實施流程
從4月中旬開始,我們部門進行了破天荒有史以來第一次靈活項目實踐,兩周的時間雖然 不長,但是整個團隊感覺無論從技術上,還是溝通與合
作上,都有很大收獲。當然,還有很多我們事先沒有想到的纰漏和問題,經過與團隊每個成員的面談,我為後續的疊代整理出了下列的優化流程。
說明:
◇在下面的流程中着重疊代開始的規劃和疊代中,開發團隊與測試團隊的協作過程,對PO的review會議和回顧會議沒有做詳細闡述
◇本流程僅針對我們目前特有的項目,有些特征不具有一般性。
◇其中使用到的一些縮略用語
PM: 項目經理/項目負責人/項目協調人
US/us: user story
PB: product backlog
PO: Product Owner
1. PM根據上個疊代的結果,對已有的PB做修正,添加需要修正的BUG,未完成的us等,并送出給PO作為參考
2. PO根據PB和自己的業務需求,并根據優先級 順序,提出本次疊代希望完成的us和PB; 并對這些us和PB的細節部分進行整理
3. PO将整理後的us和PB送出給PM
4. PM提前一天将po送出的文檔作為planning meeting會議提綱的一部分,分發給項目團隊
5. 項目團隊成員仔細研究PO的需求,并記錄自己針對業務需求和邏輯的想法或疑問
6. PRODUCT PLANNING會議
a) 參與者:PO,PM,開發團隊、測試團隊
b) 過程
i. 項目團隊對PO提出的需求進行讨論, 并由會議記錄人記錄每個us的細節
ii. 涉及到某個業務細節,讨論的時間不超過5分鐘, 并且最終拍闆權在PO手中
c) 會後
i. 由會議記錄人負責,将本次疊代涉及到的us 其描述和相關細節,直接建立在部門内部的 wiki中
記錄形式:所有的us按照疊代的周期不同 放在不同的page中,每個us以 panel相包裹
7. ITERATION PLANNING會議
a) 參與者:PO(可選),PM,開發團隊、測試團隊
b) 過程
i. 根據us和記錄的PB,對本次疊代的任務進行 拆分和估算
ii. 要考慮各個任務之間的前後邏輯關系, 以确定優先順序
注意:估算時,應該把DEBUG的時間也要考慮在内
iii. 如果估算的時間超過了本次疊代的可用時間,那麼PM找PO進行協調,請求放棄不能完成的US和PB
c) 會後
i. 會議記錄人負責将會議中最後确定的任務配置設定情況送出給PM
ii. PM在jira中建立任務并配置設定到人
使用us作為jira中的COMPONENT
同時使用us作為一個task的名稱,将與該us相關的任務作為subtask作為us task的子問題
8. DBA 可以開始考慮在資料庫中進行建表等操作了
9. ITERATION DESIGN會議
a) 參與者:PM,開發團隊、測試團隊
b) 過程
i. 根據本次疊代要完成的任務,開發團隊與測試團隊确定每個us和PB 要驗收測試所涉及到的代碼接口
ii. 開發團隊使用類圖、順序圖等uml工具,對 代碼中的一些接口和調用方法進行名稱的定義
iii. 可以使用照相手機等工具,把白闆上繪制的簡要圖表拍攝下來,并上傳至部門的wiki中
10. PM準備一個項目變更日志,用來記錄疊代中,某時間點發生的變化,包括下列内容
a) 資料庫字段的變化
b) us的細節的補充
c) ......
注意:對該日志的通路必須友善和直覺
下面進入開發階段
11. 開發團隊
a) 采用tdd的方式,完成各自的任務
b) 每當一個任務中的細小任務完成,并确認在 本地編譯無錯誤,而且單元測試都可以通過後, 才允許上傳到ci伺服器
c) 上傳完成後,開發人員要注意即時監控ci伺服器的反應, 如果有問題,馬上進行解決
d) 當開發人員确認自己的任務完成後,對應的sub task可以解決, 并且記錄工作實際完成時間
e) 每個任務的完成,都有可能觸發一次CODE REVIEW的過程
i. 如果發現問題,或者需要對代碼進行重構, 在完成後,負責人要修正任務的實際工作完成時間
f) 團隊針對一項任務的CODE REVIEW結束,并且負責人修改完成後,該負責人可以針對自己剩餘商未開始的任務,調整估算的時間,
12. 測試團隊
a) 負責維護測試庫
b) 并且要根據與開發團隊定義好接口, 撰寫針對每個us的自動化測試腳本, 準備自動化測試的TEST SUITE
13. PM
a) 當一個us相關的任務都完成後,PM修改jira中的us task的狀态,變更為"等待內建測試",并通知相關的開發人員和測試組 馬上對
該us進行內建測試,并在測試完成 後,馬上進入修正階段
14. 在這個過程中,如果任何人發現US有任何不完整的地方, 都應馬上與PM和PO進行協調和溝通,如果需要馬上補漏的, 發現者應該對wiki中
的相關us進行補充。如果不需要在本次 疊代中進行考慮,那麼PM應該記錄到項目變更日志中
15. 開發人員仍然要堅持每日立會,每日立會後,PM更新BURNDOWN CHART
16. 項目中用到的一些特殊的技術,可以考慮在某日立會之後, 用半個小時左右的時間,該技術的掌握者向整個團隊分享該知識
進入疊代收尾階段
17. 所有的us都已經完成(測試團隊完成驗收測試,開發團隊修正完畢并且無誤)
18. PO REVIEW 會議
19. 團隊回顧會議
上面的任務分析過程中,每個分拆出來的任務,我認為都應該有對應的us,理由如下:
◇ 如果沒有,那麼這個任務對于PO的業務價值在哪裡展現呢?
◇在任務分析時,發現了某些隐藏的而又是必須完成的任務,那就說明,還有隐藏的us沒有發現。這就需要找PO進行溝通,看這些隐藏的任務是否對其有價
值,如果有的話,那麼就分析隐藏的us,并根據目前疊代的任務完成和配置設定情況,進行本疊代應完成的任務和us的調整
◇沒有對應的us,沒有與PO讨論,PO可能在将來經過缜密的思考後,提出的要求,目前的解決方案可能不能夠滿足,就增大了返工的幾率
◇沒有對應的us,測試組沒有參與,那麼一些驗收測試的細節就很難得到充分的發掘;
◇除此之外,還有可能造成系統切分的粒度過粗,進而增加了這些沒有us的功能代碼和與其相關的功能代碼之間的耦合度,由此可能帶來的一系列後果:
◆針對這些無us的代碼,沒有自動化驗收測試的腳本;測試組需要等到與這些代碼相關的us的功能代碼送出後再進行測試,從進度上講,會延遲測試組
和開發人員的協同合作的時間,并延遲一些問題的暴露時機(我們都知道:問題暴露的時機越早,解決起來成本越低)。
◆針對這些無us的代碼,大家的關注度和思維的缜密性可能不如有us的代碼,那麼在這對這些代碼做tdd和debug的時候,投入相對較小,出現
纰漏的幾率就變大了。當我們在開發或調試與其相關的代碼的時候,對于發生的問題的定位,這些代碼就會造成一定的困擾
Agile
靈活開發
Backlog
一項工作
Build
值軟體編譯建構好的一個可運作的版本
Burndown chart :
用來顯示目前還剩下多少工作未完成的圖形化工具。通常以時間為橫軸,本次疊代要完成的工作為縱軸。
Code Review
代碼稽核,通常由非代碼編寫者完成。
Daily Scrum Meeting :
每日 Scrum 會議。每天 15 分鐘的每日例會 , 每個人回答三個問題:上次例會到現在我完成了哪些工作;在下次例會前我将完成哪些工作;有沒有什麼事情阻礙了我的工作。
In Progress :
進行中
Product Backlog :
産品功能特性清單,主要由産品責任人負責維護并定義優先級。
Product Backlog Item :
産品功能特性清單中的條目,每個條目就是一個工作單元,大小必須限制在團隊可以在一個疊代内完成,同時一個工作單元可以被分解成許多任務。
Product Owner :
産品責任人。負責确定 Backlog 中各條目的優先級,同時解決所有關于需求的問題。
Safari
蘋果作業系統上的浏覽器
Scrum
Scrum 一詞來自英式橄榄球,它把軟體開發團隊比作橄榄球隊。 Scrum 是當今流行的靈活開發方法之一。
Scrum Master
負責管理每日 Scrum 流程的人,是 Product Owner 和 Team 之間的橋梁,推動雙方的合作,負責為 Team 成員解決障礙和問題,保證他們工作的進行。相當于傳統項目的項目經理或主管。
代表 Scrum 的一次疊代,周期通常是 30 天。期間不能給 Team 增加額外的需求,確定疊代結束時能夠獲得預期的結果。
Sprint Planning Meeting :疊代開始之前的計劃會議,由 Team 與 Product Owner 之間商讨本次疊代的目标,決定本次疊代要完成哪些工作。
Sprint Review Meeting :
Sprint 評審會議。在疊代結束時召開, Team 展示這個疊代中完成的功能,一般是以 Demo 本疊代中完成的功能的形式來展示。
Sprint Retrospective Meeting :
Sprint 回顧會議。在一個疊代的評審會議之後召開,由 Team 與 ScrumMaster 共同讨論這個疊代中哪些地方做得比較好,哪些地方需要改進。使團隊持續成長。
Stakeholders :
利益相關者。項目成敗對他們影響不大的一類人,參與提出産品的需求,積極提出回報意見。
Sprint :
Task
任務
Team :
跨功能的 Scrum 團隊,人數限制在 5-9 人,可能包括的角色有開發人員、架構師、測試人員、 UI 設計師等。是一個自組織的團隊,他們自己決定如何最好地滿足使用者需求,并承擔責任。
User Story :
使用者故事 ( 情景 ) ,從使用者的角度,對系統的某個功能子產品所做的簡短描述。
wiki:
維基百科,是一種開放和共享的線上文檔編輯系統,任何人都可以在系統中編輯修改文檔。最早的應用是線上開放式的百科全書,現在廣泛應用于各種文檔系統。