1. 程式人生 > >敏捷(Agile)——“說三道四”

敏捷(Agile)——“說三道四”

概述

關於敏捷開發,Wiki給出如下解釋:

Agile software development describes a set of principles for software development under which requirements and solutions evolve through the collaborative effort of self-organizing cross-functional teams.

  可以這麼理解:一種以人為本、團隊合作、快速響應變化和可工作的軟體作為宗旨的開發方法。亦可理解為在一個高度協作的環境中,不斷地使用反饋進行自我調整和完善,持續交付使用者想要的軟體的過程。敏捷開發提倡通過多種工程實踐來提高交付質量,如自動化測試、持續整合、重構、結對程式設計、程式碼的集體所有權等,比傳統的設計-開發-測試-修改流程有更高的成效。

  前輩們“篳路藍縷”無私付出造就了敏捷開發,使軟體界不能承受之”重“變得輕盈,讓我們能夠站在巨人的肩膀上展望軟體界。現在我們就開始敏捷之旅吧。

  在介紹敏捷之前,先回顧一下傳統的開發流程。

瀑布式開發流程

  瀑布式開發流程(Winston Royce 1970)是最早得到廣泛承認的開發流程。這是一個線性的模式,只有完成了前一個步驟才能開始下一個步驟。比如說,在開始設計之前,必須先完成需求分析。如果發現了問題,就得返回上一個階段並進行適當的修改。

waterfall-model

  這種流程存在的不足之處:首先,即使需求會隨時間而變化是眾所周知的,但開發人員仍會努力在設計前完成文件,在編寫程式碼前完成設計,其中有大量工作被浪費。其次,將測試和整合延遲到專案開發結束時才執行,這就導致問題往往發現得太晚,如果要解決問題,則有可能導致錯過最後的交付期限。該流程既無法控制業務需求的變更,又抑制了反饋的週期閥值,伴之而來的是不可避免的延期和失敗。

對比瀑布式開發

  瀑布模型是最典型的預見性的開發方法,嚴格遵循預先計劃的需求、分析、設計、編碼、測試的步驟順序進行實施。步驟成果作為衡量進度的標準,例如需求規格,設計文件,測試計劃等。

  瀑布式開發流程的嚴格分級導致的自由度降低,專案早期即作出承諾導致對後期需求的變化難以調整,適應變化代價高昂。瀑布式方法在需求不明確並且在專案進行過程中可能變化的情況下基本是不可行的。而敏捷開發的一個核心理念便是:”Fix time, Flex Scope”——固定時間,彈性範圍。這就使團隊具有更高的靈活性去適應未來需求的變化。

60920267e95299539a96824736a63581_b

  敏捷方法在幾周或者幾個月的時間內完成相對較小的功能,強調的是能將盡早、儘量小的交付可用的功能,並在整個專案週期中持續優化。

迭代式開發流程

  是一種有別於傳統的瀑布式開發的軟體開發過程,它彌補了傳統開發方式中的一些不足,具有更高的生產率和成功率。其開發流程明顯比瀑布式開發流程更為靈活,其特徵如下:

  • 在進行開發之前就進行了風險評估。
  • 更早的獲取使用者反饋。
  • 對各個目標里程碑提供了短期的焦點。
  • 對過程的測量是通過對實現的評定來進行的。
  • 可以對區域性實現進行部署。

Iteration

迭代式開發的優點:

  • 降低專案風險。
  • 更早的得到使用者反饋。
  • 持續的測試和整合。
  • 使用變更。
  • 複用性增加。

      在迭代式開發流程中,整個開發工作被組織成一系列短小的、固定長度的小專案,被稱為一系列的迭代。每一次迭代都包括了需求分析、設計、實現與測試。實施這種開發流程,開發工作可以在需求被完整地確定之前啟動,在一次迭代中完成系統的一部分功能或業務邏輯的開發工作。再通過客戶的反饋來細化需求,並開始新一週期的迭代。快速迭代是為了使產品更加接近消費者的需求,使消費者的體驗變得更加完美。世界上沒有能一勞永逸的產品,更沒有所謂的正確產品,在網際網路的時代,服務和產品都是一個有機的生命體,需要不斷地發展變化。成功的產品就像一場蝶變,在蛻變中越顯完美。

對比迭代式開發流程

  迭代式開發流程是傳統的“階段一門限”工程實踐之一,而敏捷方法是一系列工程實踐的綜合體,兩者屬於一種包含與被包含關係。相比迭代式開發兩者都強調在較短的開發週期提交軟體,敏捷方法的週期可能更短,並且更加強調隊伍中的高度協作,這也是敏捷的核心理念之一“以人文字”。

敏捷實踐

Scrum

  像所有的敏捷過程一樣Scrum是一種迭代式和增量式的軟體開發方法。在Scrum專案中,測試人員需要知道測試也和符合使用者需求有關。程式設計師需要知道在編寫程式碼前並不一定需要有經過深思熟慮的設計。作為最受青睞的敏捷技術Scrum,我們有必要熟知它的機理,下面一步步介紹吧。

Scrum角色分配:

scrum rules

  1. Scrum Master (Scrum推動者): 是Scrum教練和團隊帶頭人,確保團隊合理的運作Scrum,並幫助團隊掃除實施過程中遇到的障礙。
  2. Owner (產品負責人):確定產品的方向和願景,定義產品釋出的內容、優先順序及交付時間,為產品投資回報率負責。
  3. Developer (開發者們):由開發者組成,人數5-9人,團隊擁有交付可用軟體需要的各種技能。

      在每一次衝刺(Sprint)或迭代當中,開發團隊建立可用的軟體的一個增量。每一次迭代所需要實現的功能來自產品需求。開發團隊決定在下一次迭代中他們能夠承諾完成多少需求項。

Scrum的四個會議

  • Sprint計劃會(Sprint Planing)
  • 每日站會(Daily Scrum)
  • Sprint評審會(Sprint Review)
  • Sprint回顧會(Sprint Retrospective)

以下逐一拆解

Sprint計劃會:

  1. 進行需求講解。
  2. 挑選PBI(product backlog item),也就是由客戶選出重要的PBI。
  3. 拆解PBI到SBI(sprint backlog item)。
  4. 討論每個SBI的工時。
  5. team挑選本次Sprint任務。

每日站會:

詢問自己三個問題

  • 從昨天Daily Scrum到這一刻,我完成了什麼工作?
  • 從這一刻到明天的Daily Scrum,我計劃完成什麼工作?
  • 是否有什麼困難阻礙了我的進展?

Sprint評審會:

在 Sprint 結束後,大家一起評審本次 Sprint 的產出。每個人都可以自由發表看法,協助產品負責人對未來工作做出最終決定。並根據實際情況,適度調整產品待辦事項列表。

Sprint回顧會:

在一次Sprint結束後,回顧一下團隊在流程和溝通等方面的成效。大家一起討論,哪些完成得好,哪些有待改進?

Scrum實施流程

Step1. 擬定 Vision
首先,我們需要有一個Vision ,就是我們所做的產品或者所做專案的需求。這個需要所有Team Members,包括Product Owner 一起確定,然後大家朝著同樣的目標前進。

Step2. 維護Backlog
它可以理解成我們從產品當中,從各個角度收集的需求。 Product Owner 要做的事情就是維護Product Backlog,將Backlog 一條一條的按照優先順序排好順序。Product Owner 是唯一有權利維護這個列表的人,並且可以給任務打標籤來標示優先順序。

Step3. 拆分Sprint
在開發週期中,將 Backlog 裡面的專案新增到Sprint 中去,成為Sprint Backlog。每一個Sprint 開始的時候,需要進行一個Sprint Plan。

Step4. 執行Sprint Plan
Sprint Plan 就是整個團隊在一起通過Backlog 從優先順序最高的這個item 開始分配,大家將Backlog 拆分成單個Task,團隊的成員領取Task,並負責完成Task。

Step5. 維護Daily Scrum
在 Daily Scrum 中,每個成員只需三件事情:我今天做了什麼,明天要做什麼,遇到什麼困難。Daily Scrum 一般來說會控制在15分鐘之內,而且所有的成員必須要站著開會。

Step6. Sprint Review
當Scrum 結束後都有有個產出物,這個產出物在Scrum 裡面,可以是一個可以執行的軟體,也可以是一個可展示的功能,我們要做的就是對它進行客觀的點評。

Step7. Retrospective
最後一步就是Retrospective。所有團隊成員一起參加討論,這個Sprint我們哪些做的不錯,哪些有待改善。

工具的作用

TeambitionWorktileTrello這三個工具對 Backlog 的管理和會議活動管理都非常方便,能更好地實現團隊協作、需求到研發的資訊關聯與共享。個人比較喜歡Trello

以下是一些Scrum的通用實踐:

  • 客戶成為開發團隊中的一部分。
  • 和所有其他形式的敏捷軟體過程一樣,Scrum有頻繁的包含可以工作的功能的中間可交付成果。這使得客戶可以更早的得到可以工作的軟體,同時使得專案可以變更專案需求以適應不斷變化的需求。
  • 開發團隊經常評估風險並制定緩解計劃。在每一個階段根據承諾進行風險緩解,監測和管理。
  • 計劃和模組開發要保持透明,讓每一個人知道誰負責什麼,以及什麼時候完成。
  • 參與者要經常開會以跟蹤專案進展 – 平衡的(釋出,客戶,員工,過程)儀表板更新 – 利益所有者更新。你必須擁有預警機制,例如在可能延期交付時提出警告。
  • 不要隱藏問題。認識到或說出任何沒有預見到的問題並不會受到懲罰。
  • 在工作場所和工作時間內必須全身心投入。– 完成更多的工作並不意味著需要工作更長時間。

在這裡我們需要明確一個問題,敏捷實際上就是一種理念,然後基於這個理念提供了一些方法和實踐,在我眼裡它意味著持續改進。

敏捷開發技術體系及原則

測試驅動開發(TDD)

  測試驅動開發始於20世紀90年代。測試驅動開發的目的是取得快速反饋並使用“illustrate the main line”方法來構建程式。一種軟體開發過程中的應用方法,由極限程式設計中倡導,以其倡導先寫測試程式,然後編碼實現其功能得名。測試驅動開發是戴兩頂帽子思考的開發方式:先戴上實現功能的帽子,在測試的輔助下,快速實現其功能;再戴上重構的帽子,在測試的保護下,通過去除冗餘的程式碼,提高程式碼質量。測試驅動著整個開發過程:首先,驅動程式碼的設計和功能的實現;其後,驅動程式碼的再設計和重構。

TDD

測試驅動開發可以有效的避免過度設計帶來的浪費,讓開發者在開發中擁有更全面的視角。

重構(Refactor)

按照《重構》書中的定義

第一個定義是名詞形式:

重構(名詞):對軟體內部結構的一種調整,目的是在不改變軟體可觀察行為的前提下,提高其可理解性,降低其修改成本。

“重構”的另一個用法是動詞形式:

重構(動詞):使用一系列重構手法,在不改變軟體可觀察行為的前提下,調整其結構。

以下內容出均自《重構》第2.2節

重構改進軟體設計

  如果沒有重構,程式的設計會逐漸腐敗變質。當人們只為短期目的,或是在完全理解整體設計之前,就貿然修改程式碼,程式將逐漸失去自己的結構,程式設計師愈來愈難通過閱讀原始碼而理解原本設計。重構很像是在整理程式碼,你所做的就是讓所有東西回到應該的位置上。程式碼結構的流失是累積性的。愈難看出程式碼所代表的設計意涵,就愈難保護其中設計,於是該設計就腐敗得愈快。經常性的重構可以幫助程式碼維持自己該有的形態

重構使軟體更容易理解

  所謂程式設計,很大程度上就是與計算機交談:你編寫程式碼告訴計算機做什麼事,它的響應則是精確按照你的指示行動。你得及時填補“想要它做什麼”和“告訴它做什麼”之間的縫隙。這種程式設計模式的核心就是“準確說出我所要的”。除了計算機外,你的原始碼還有其他讀者:幾個月之後可能會有 另一位程式設計師 嘗試讀懂你的程式碼並做一些修改。我們很容易忘記這第二位讀者,但他才是最重要的。計算機是否多花了幾個小時來編譯,又有什麼關係呢?如果一個程式設計師花費一週時間來修改某段程式碼,那才關係重大—如果他理解你的程式碼,這個修改原本只需一小時。

重構幫助找到bug

  對程式碼的理解,可以幫助我找到bug。我承認我不太擅長除錯。有些人只要盯著一大段程式碼就可以找出裡面的bug,我可不行。但我發現,如果對程式碼進行重構,我就可以深入理解程式碼的作為,並恰到好處地把新的理解反饋回去。搞清楚程式結構的同時,我也清楚了自己所做的一些假設,於是想不把bug揪出來都難。

重構提高程式設計速度

  我強烈相信:良好的設計是快速開發的根本──事實上,擁有良好設計才可能做到快速開發。如果沒有良好設計,或許某一段時間內你的進展迅速,但惡劣的設計很快就讓你的速度慢下來。你會把時間花在除錯上面,無法新增新功能。修改時間愈來愈長,因為你必須花愈來愈多的時間去理解系統、尋找重複程式碼。隨著你給最初程式打上一個又一個的補丁,新特性需要更多程式碼才能實現。真是個惡性迴圈。

一些常用的重構方法

  • 封裝成員變數(Encapsulate Field)—將僅限於本類使用的變數重寫成私有(private)成員變數,並提供訪問方法(accessor method)。這種重構方式可以將與外部呼叫者無關的變數隱藏起來,減少程式碼的耦合性,並減少意外出錯的概率。
  • 提取方法(Extract Method)—意思是將大段程式碼中的一部分提取後,構成一個新方法。這種重構可以使整段程式的結構變得更清晰,從而增加可讀性。這也對函式通用。
  • 一般化型別(Generalize Type)—將多個類/函式共用的型別抽象出可以公用的基類,然後利用多型性追加每個類/函式需要的特殊函式。這種重構可以讓結構更加清晰,同時可以增加程式碼的可維護性。
  • 函式歸父(Pull Up)—或譯函式上移,指的是方法從子類移動到父類。
  • 函式歸子(Push Down)—或譯函式下移,指的是方法從父類移動到子類。
  • 方法更名(Rename Method)—將方法名稱以更好的表達它的用途。

……

  重構在敏捷開發過程中重構是一個常用的和必要的實踐,它讓我們反思過去所為,掃除敏捷開發道路上的障礙。

持續整合

  大師Martin Fowler對持續整合是這樣定義的:持續整合是一種軟體開發實踐,即團隊開發成員經常整合他們的工作,通常每個成員每天至少整合一次,也就意味著每天可能會發生多次整合。每次整合都通過自動化的構建(包括編譯,釋出,自動化測試來驗證,從而儘快地發現整合錯誤。

  持續整合通常藉助於一個工具或者指令碼來實現,這些工具或指令碼會注意到有程式碼檢入版本控制系統。可以採用Cruise Control工具,它可以根據需要執行儘可能多的測試,並且可以自動傳送通知給破壞構建的開發人員或者整個團隊。

結對程式設計

  結對程式設計是指兩個開發人員一起寫程式碼。結對程式設計的想法來源自:如果偶爾的程式碼檢查會帶來好處,那麼持續進行程式碼檢查會更好。通過結對程式設計產出程式碼,會創造出集體所有權的感覺。其次如果有另外一個開發人員坐在你旁邊的時候,更容易讓程式碼比你在檢出修改前更乾淨。

敏捷的原則

關於敏捷開發以下原則我們必須知曉:

  • 對我們而言,最重要的是通過儘早和不斷交付有價值的軟體滿足客戶需要。
  • 我們歡迎需求的變化,即使在開發後期。敏捷過程能夠駕馭變化,保持客戶的競爭優勢。
  • 經常交付可以工作的軟體,從幾星期到幾個月,時間尺度越短越好。
  • 業務人員和開發者應該在整個專案過程中始終朝夕在一起工作。
  • 圍繞鬥志高昂的人進行軟體開發,給開發者提供適宜的環境,滿足他們的需要,並相信他們能夠完成任務。
  • 在開發小組中最有效率也最有效果的資訊傳達方式是面對面的交談。
  • 可以工作的軟體是進度的主要度量標準。
  • 敏捷過程提倡可持續開發。出資人、開發人員和使用者應該總是維持不變的節奏。
  • 對卓越技術與良好設計的不斷追求將有助於提高敏捷性。
  • 簡單——儘可能減少工作量的藝術至關重要。
  • 最好的架構、需求和設計都源自自我組織的團隊。
  • 每隔一定時間,團隊都要總結如何更有效率,然後相應地調整自己的行為。

敏捷團隊工具

所謂“工欲善其器,必先利其器”,優秀的工具有助於及早交付有價值的軟體使客戶滿意。

  • 站會:主要目的是給團隊討論每日的承諾和Sprint目標的進度的機會,每個團隊成員在會議中都必須回答以下三個問題:

    1. 過去24小時做了什麼?
    2. 接下來的24小時機會要做什麼?
    3. 有沒有什麼問題阻礙了進度?
  • 看板:被用來共享專案的狀態並將之視覺化

  • 演示:適合於小團隊的協作和優化反饋方式

  • 使用者故事:使用者故事是從使用者的角度來描述使用者渴望得到的功能。一個好的使用者故事包括三個要素:

    1. 角色:誰要使用這個功能。
    2. 活動:需要完成什麼樣的功能。
    3. 商業價值:為什麼需要這個功能,這個功能帶來什麼樣的價值。
  • 持續整合:隨時高質量交付的基礎,有利於應對變化劇烈的市場

      可以用它們來幫助規劃,跟蹤,分析和整合工作, 這些工具在敏捷開發中扮演著不可或缺的角色。

敏捷度量指標

  Ron Jeffries建議使用可工作的經過測試的特徵數量(Running Tested Features,簡寫為RTF,下同):

  1. 所需的軟體被分解為給定名稱的特徵(需求、故事等),它們組成了需要交付的整個系統。
  2. 對於每個給定名稱的特徵,至少有一個或者多個自動化驗收測試,(當它們都通過了),反映了特徵已經全部完成。
  3. RTF指標表示了專案在各個時刻有多少特徵通過了各自的全部驗收測試。

Scrum教練Peter Hundermark建議可工作的自動化測試數量(Running Automated Tests)也是度量指標。

敏捷方法的適用性

  在敏捷方法其獨特之處以外,它和其它的方法也有很多共同之處,比如迭代開發,關注互動溝通,減少溝通過程中無謂的資源消耗。通常可以在以下方面衡量敏捷方法的適用性:從產品角度看,敏捷方法適用於需求萌動並且快速改變的情況,如系統有比較高的關鍵性、可靠性、安全性方面的要求,則可能不完全適合;從組織結構的角度看,組織結構的文化、人員、溝通則決定了敏捷方法是否適用。跟這些相關聯的關鍵成功因素有:

  • 組織文化必須支援談判
  • 人員彼此信任
  • 人少但是精幹
  • 開發人員所作決定得到認可
  • 環境設施滿足成員間快速溝通之需要

      另外的問題是專案初期的大量假定或者快速收集需求可能導致專案走入誤區,特別是客戶對其自身需要毫無概念的情況下。與之類似,人之天性很容易造成某個人成為主導並將專案目標和設計引入錯誤方向的境況。開發者經常能把不恰當的方案授予客戶,並且直到最後發現問題前都能獲得客戶認同。雖然理論上快速互動的過程可以限制這些錯誤的發生,但前提是要有效的“負反饋”,否則錯誤會迅速膨脹,並在最終提交時造成極大返工。

寫在最後的話

  敏捷方法有時候被誤認為是無計劃性和紀律性的方法,實際上更確切的說法是敏捷方法強調適應性而非預見性。 敏捷開發不是一套一成不變的標準化流程,而更多的是一種自適應,自我優化的流程理念,不一樣的團隊有不一樣的流程,所以實施前一定要根據自己團隊當前狀態做調整。記住這一點:敏捷就是永遠只做對產品和專案有用的事情 。

附一

敏捷開發宣言

我們正通過親身實踐和幫助他人實踐,揭示了一些更好的軟體開發方法。通過這項工作,我們認為:

  • 個體和互動勝於流程和工具
  • 工作的軟體勝於詳盡的文件
  • 客戶合作勝於合同談判
  • 響應變化勝於遵循計劃

雖然右項也有價值,但我們認為左項具有更大的價值。

PS:圖片來源於網路,如有侵權請私信刪除。

參考書籍:

《敏捷軟體開發實踐》

《Scrum敏捷軟體開發》

《敏捷軟體開發實踐:估算與計劃》

《重構:改善既有程式碼的設計》