1. 程式人生 > >我在ThoughtWorks中的敏捷實踐

我在ThoughtWorks中的敏捷實踐

為了更好的閱讀體驗,歡迎訪問 部落格原文
此文章已發表於InfoQ,閱讀InfoQ文章

專案回顧

專案背景

E專案是一個線上的物資跟蹤監控系統。由ThoughtWorks團隊為客戶提供的一套完善的軟體交付服務。

該系統為資助物資的跟蹤與監控提供了完整的網路解決方案。整個流程涵蓋了客戶對物資來源的管控、庫存管理、物資下發與跟蹤、客戶與IP(Implementing Partner,合作伙伴)的協作溝通、IP對運輸結果的反饋(生成報告,警告通知,簡訊互動,郵件通知),以及IP對物資的二次分發後的記錄跟蹤與監控。

該專案屬於海外獨立交付專案,整個開發過程由ThoughtWorks

團隊負責管理。好了,專案資訊只能透漏這麼多了,不然客戶要找我打官司了。

成員背景

ThoughtWorks提供完整的交付團隊(PM, BA, TL, QA, DEV, UX),團隊為頗具代表性的敏捷團隊,規模10人左右。客戶團隊主要介面人3位。

ThoughtWorks團隊成員,猶如一架生猛的戰鬥機:PM英文一流,敏捷開發管理相當到位,因為看了上萬本腦殘小說,時不時就用到了生活中來。TL擁有7年以上的開發經驗,7年之癢,什麼,不用說都懂的。TL還富有學習激情和被黑精神,黑歷史牆列滿了他的關輝血淚史。QA被譽為IT界的福爾摩斯,DEV都休想逃過她敏銳的鼻子(怎麼是鼻子呢?太陶醉了吧,這是境界!),最後,就是'苦逼'

的DEV,也就是以程式設計師自居的我們。

我們每個人特點各不相同,但有一點神似:專業,責任心,追求卓越

我們團隊還有一個workout的文化特色,向⬇️看:

PS:我們的workout自開始之日到專案交付之期,不曾落下過一天,且收到良好的反饋。即便團隊成員分開了,每個人都能將運動精神傳播下去,乃至源遠流長……

技術背景

我們是一個全功能團隊,人人身懷敏捷開發領域的知識和技能,且有一定的經驗積累,所以可以說我們天生敏捷,在開發過程中大家都能高效地分工合作。

再說技術棧,專案使用的主要技術棧是Python, Django, AngularJs, PostgresSQL

, Docker。而我們DEV在進入這個專案之前,擅長的技術棧是Java, Springboot, C#, Android, jQuery

敏捷實踐

專案之所以成功交付,核心在於人,而良好的敏捷流程與實踐也是不容忽視的。

早在2001年,17位追求卓越的志願者聚集在美國猶他州雪鳥獨家聖地,討論一個新的軟體開發趨勢,它被稱作輕量型軟體開發過程,後來他們將它定義為敏捷,並且釋出了敏捷開發宣言:一種把以人為本、團隊合作、快速響應變化和可工作的軟體作為宗旨的開發方法。敏捷宣言可以總結為四句話:

個體與互動    優於  流程與工具
客戶協作     優於  合同談判
響應變化     優於  遵循計劃
可工作的軟體  優於  面面俱到的文件

也就是說,儘管右項有其價值,我們更重視左項的價值。

敏捷開發的核心就是在一個高度協作的環境下,不斷的通過反饋來進行自我調整和完善。重點強調的是協作反饋,協作體現在團隊與客戶之間的協作,團隊成員之間的協作。反饋則是在開發中的任何環節,包括程式碼質量、自動化測試、部署、專案進度、需求變更、客戶驗收等,而且反饋越快越好。有句土耳其諺語這麼講的:"不管你走了多遠,錯了就要重新返回",所以我們越快得到反饋,就能越早確認自己有沒有走錯路。如果沒有錯,我們會更加充滿信心。反之,及時做出調整,讓浪費最小化。

專案中所涉及的敏捷實踐主要圍繞迭代進行,用一張圖概括:

可以總結出以下幾點:

  • Iteration通常始於IPM ,止於Showcase。
  • 每天都會發生事件有Standup 。
  • Pair、TDD、Code Review穿插在日常Coding中。
  • Story kick-off之後,該Story就進入了開發環節。
  • CI屬於基礎設施,通常在一個名為Iteration0的迭代完成,也就是正是開發開始之前就應該完成CI的搭建。
  • Retro較長一段時間才進行的活動,根據實際情況,1個月或兩個月舉行一次。
  • Regular catch up with client也會因專案而異,Daily或者Weekly,甚至某些專案可以省略該項活動。

敏捷的宗旨是減少浪費,所有的敏捷實踐也都是圍繞著高效協作快速反饋這兩個核心理念展開。

IPM

IPM(Iteration Plan Meeting),迭代計劃會議主要是跟客戶保持溝通與資訊更新的一個會議。

敏捷宣言裡面有一條:客戶協作優於合同談判。在Scrum團隊中有一個角色叫做產品負責人,Ta的核心職責是確保業務需求的清晰和透明,保證開發團隊對業務有足夠的瞭解,並將這些待完成的業務需求(Story)按照優先順序排列出來,按照任務卡的方式來驅動團隊的開發。並在客戶需求有變更後能夠第一時間告知團隊以做出調整。

在我們團隊中,這個角色就是一開始提到的BA。她是IPM主要參與人,另外還有Tech Lead會一起參與討論(團隊中每一個人成員都是可以參與進來的)。IPM按照團隊指定的迭代的週期,通常是兩週,每隔兩週跟客戶介面人一起約一個時間,主要討論以下幾個方面的內容:

  • 下一個迭代的Story。
  • 對下一個迭代的期望。
  • 團隊的人員可用性。
  • 風險的評估總結。

通過這種會議,能夠讓客戶對我們團隊狀況有一個清晰的瞭解,而且客戶對我們下一個迭代要做的功能有了整體的把控,一起設定好期望,這樣也會大大降低風險。

IPM的主要產出是下一個迭代中完成的Story,這些Story即為下一個Story要完成的目標,我們通過敏捷看板工具來管理它們,例如下圖mingle上位於Backlog欄中的Story:

Regular catch up with client

跟客戶建立信任關係是合作的基礎,而讓客戶保持愉悅,也是專案成功交付的助推劑。

Regular catch up with client,即 定期跟客戶進行溝通,雙方共同商議一個時間(工作時間最佳),一起開個短暫的小會,時間上的成本較低。

Catch up的主要參與人員是BA(PM)和TL,通過於客戶方Face2Face會議或者online會議進行一個短暫的溝通,溝通內容主要涉及:

  • 我們團隊昨天的更新.
  • 客戶昨天的更新
  • 確認Story。如果有變更,能及時作出調整。
  • 提醒客戶使用我們開發出來的功能,以便我們儘早得到反饋。
  • 一些節日的問候,噓寒問暖,表達我們團隊的關懷。

因專案而異,Catch up實踐可以大體分為兩種:

  • 針對Onsite專案Face2Face形式。因為跟客戶在一起工作,就可以較為高效地組織Face2Face的會議,實踐證明,Face2Face是效率最高的一種形式。
  • 針對獨立交付專案的Online形式。因為地點、時差等原因,適當調整Catch up的頻率,另外選擇一個便捷可靠地工具(例如:Fuze, GTM, Skype等),提前設定好環境並分享給客戶相關人員。

通過與客戶進行定期的溝通,產生的價值主要體現在客戶信任和客戶關係方面:

  • 首先,讓客戶有非常強烈的參與感,以及讓他們對專案整個進展的把控(他們會覺得自己才是專案的主導者),增強他們的信心以及對我們的信任。
  • 其次,讓客自己決定功能實現以及及時驗收功能,降低了需求變更和打回的風險。
  • 最後,則是潤滑劑了,能夠在客戶良好的信任的基礎上,保持合作關係的輕鬆愉快,這會為專案的成功交付使上勁。

並不是每一個專案都會有這個實踐,有些獨立交付的專案,他們每日站會的時候客戶也會參與進來,就不需要額外單獨的時間去做這件事情了,而有些專案,因為特殊性,客戶可能不希望這麼頻繁的Catch up,這時候需要團隊靈活變通,與客戶一起商討出一個合適的時間週期,做出一些權衡,讓客戶自身覺得舒服。總之,Keep住的一點是:保持跟客戶的資訊溝通,儘可能早的得到客戶的反饋,保持良好的客戶關係

Standup

Standup是一項成本小收益大的活動,做好它是敏捷的第一步。

Standup,就是每日站會。我聽過一個有趣的事情:在敏捷開發方法興起的時候,很多傳統開發模式的團隊躍躍欲試,他們選擇從Standup切入。然後每天早上上班後,大家聚在一起開個會(站著、坐著都有),然後該怎麼做還是怎麼做。他們會對別人說,我們在搞敏捷開發…

沒錯,Standup就是團隊在一起快速地開一個會,大家挨個的更新一下自己的狀態,更新包含以下幾個方面:

  • 昨天完成的工作。
  • 今天計劃做什麼。
  • 面臨什麼阻礙。
  • 自己手頭Story的進展。
  • 是否存在技術風險。

既然是快速的會議,Standup的時間就不宜過長,建議5~15分鐘。最好是站著開會,因為研究表明,當人們坐著開會的時候,會議的時間會被無形中拉長。Standup的時間安排在工作時間開始後的半個小時最佳(比如9:00上班,9:30開始),這樣大家就不用一到公司就急急忙忙的參加Standup,大家有個緩衝的時間,比如說設定電腦,泡咖啡,沏茶,整理今天的todo list等。

沒有什麼特殊原因的情況下,確保團隊成員都要參加,如果一些人因為特殊原因經常不按時到,適當調整Standup的時間,但也不宜太晚。

而對於規模很小的團隊(3~5人),也強烈建議執行Standup,因為它的成本真的很低。

或許有人會覺得:大家天天都在一起工作,溝通如此方便,何必要這項活動? 這有點深處酒巷中不覺酒香的味道了。站會能夠給團隊帶來的價值不容忽視:

  • 讓大家進入一天的工作狀態。
  • 清楚自己的Story的進展,提醒自己把握好時間,或者激勵其他成員的開發進度。
  • 讓團隊成員知道專案其他地方的進展。
  • 如果誰遇到不好解決的問題,可以將問題丟擲來,大家一起積極討論解決方案,也能尋求其他人員的技術支援。
  • 避免在重複造輪子而耗費時間,讓大家知道目前團隊中可供複用的解決方案。
  • 幫助Team Leader瞭解哪些領域需要更多的幫助,從而更好地分配資源。

下面是我們團隊的Standup:

PS: Standup的時候,選一實物作為Token,發言時拿著Token。上圖中我們選擇了瑜伽球作為Token,逗比們說:健身無處不在~

Story kick-off

在一個Story開始前,確保BA, QA, DEV對Story的理解達成一致,並嚴格按照AC來驗收。當然,前提是Story本身是不容置疑的。

Story kick off,指的是對某一個Story進行開卡,也就是啟動該Stroy,從而使其進入開發階段。Story kick off的時候,通常需要三個角色一起參與:BA、QA以及要開發該Story的DEV。

Story由BA預先寫好,並通過專業的敏捷管理工具進行管理。DEV在kick off的時候,BA會給DEV講解這個Story要完成的功能,以及它的AC。DEV如果對其中的描述有任何疑惑,需要及時提出來,當場弄明白才可以正確的去完成這些功能。在後續的開發過程中,如果碰到任何疑惑,隨時找BA或者QA瞭解清楚,不應該自己猜測著開發,更不可跟著心走。

Story kick off 的核心目的是確保DEV開發出的功能都是符合客戶期望的。而Story本身存在錯誤並不在討論範圍之內。實際上在開發過程中,也未發生過這種情況,因為一旦客戶的需求變更後,Story卡也會及時變更過來。Story kick off 可以follow以下實踐:

  • DEV自己先完整地過一遍Story的描述。
  • DEV給BA和QA去講這個Story的功能以及AC。
  • 要能夠清晰的講出來,並且三者達成一致,如果有疑惑,需要當場得到解決。
  • DEV開始開發Story,並自行將Story參照AC拆分成很多個子任務列表,然後逐一干掉它們。

最後一個實踐嚴格上講不是kick off環節裡面的,它發生在kick off後,DEV自行決定怎麼去完成功能。我比較推薦DEV在kick off後將Story劃分成子任務列表,按照依賴關係和優先順序排序,逐個幹掉他們。一些敏捷管理工具(Trello, mingle, Pivotal Tracker, teambition)都支援這種任務拆分,你還可以很容易的記錄與跟蹤。

Story kick off也是一項短時間高收益的活動,因為在我們DEV界中,有一句邪門的定律:

猜出來的需求往往是不靠譜的,最終需要打回重做!

所以kick off能夠有效的避免Dev自行臆測業務需求而產生的浪費。除此之外,能夠彌補BA在編寫Story的時候技術視角的一些遺漏

一些專案會引入好的開發實踐,比如說BDD。它能按照人類自然語言去描述一個功能的實現。我們的Story描述通常會參照這種方式: as...when...then...when...then。這個時候,DEV、QA、BA可以在Story kick off的時候利用一些測試工具(Cucumber)一起來編寫Story驗收測試用例(主要由QA來編寫),DEV負責編寫程式碼來通過這些測試。理想情況下,驗收測試用例如果正確完整,當所有測試都通過後,意味著Story功能已經完成。而且這種TDD的方式,程式碼出現bug的機率也會大幅度降低。

下面是一對Pair做Story kick off:

Pair

結對程式設計的開發速度通常小於簡單地將一個人的開發速度乘以2,但它依然能創造價值:知識的共享,程式碼質量的提高,缺陷率的降低。

XP裡面提到了結對程式設計,經過事實證明,它是一項利大於弊的實踐。

通俗地講,Pair就是兩個人同時工作在同一個Story上,一起討論Story的解決方案,並編寫程式碼實現功能,一個人敲鍵盤,一個人看螢幕,穿插著進行。Pair的小夥伴在快速敲擊鍵盤的時候會伴隨一些交流,並時不時停下來討論說笑片刻,亦或是在欣賞一下自己漂亮的程式碼。

兩個人一起寫程式碼即為Pair,那麼如何進行高效的Pair呢,也有一些良好的實踐:

  • 搭檔的選擇上,兩個人的技能和經驗最好是相當的,這樣就不至於一個人成為被教育的物件,而另一個人成為鍵霸。
  • 有新人加入時,需要一個經驗較豐富的老人Pair,最好是有良好Coach技能的老人,老人儘量只提供思路啟發,並讓新人多思考和動手實現。
  • 經驗相當的Pair時,可以一起討論解決方案,並達成一致,然後一個人寫測試,另一個人編寫程式碼通過測試,兩人同時保持focus。
  • 定期更換Pair,粒度可以控制在以一個Story完成為節點。大一點的Story可以keep住一個人不動,另一個人進行更換。
  • 遇到技術阻礙時,分頭並行尋找解決方案,並最終一起決定採取什麼方案。
  • 當兩個人對實現細節的優劣拿捏不定時,邀請團隊經驗豐富的老人做出建議參考。
  • 在一些很簡單的defect上,可以不採用Pair。

Pair將本來可以並行工作的兩個人聚焦在一件事情上,表面上是在降低生產力,實際上它確實是有一定的成本的。而這種付出並不會打水漂,最明顯的好處是能夠最大化知識的共享(尤其是更換pair的場景下),包括業務知識的共享、技術方案共享、解決問題思路的共享,這一點尤其體現在團隊有新人融入的時候,通過Pair能夠快速帶領新人成長起來,提高整個團隊的戰鬥力。另一方面可以提高程式碼質量,Pair實際上是兩個人一直在不停的做Code Review,兩個人的思維碰撞能夠避免很多程式碼小聰明和不好的編碼習慣。

有些時候,因為專案進度的緊張,Pair並不會這麼理想的被落實,團隊可以進行靈活的調整。如果Pair的時間減少了,可以通過加長Code Review的時間來做一些彌補。

下圖是我跟TL Pair的剪影:

TDD

TDD,測試驅動開發,這項人人都稱讚、卻很少有人真的去做的活動,不應該只是一個被供奉起來的神。接地氣,再接地氣一點。

TDD,即測試驅動開發,強調的是測試先行。TDD是一個存在爭議的主題,因為在一個連測試的沒有的程式碼庫中(多數客戶也不關心測試程式碼,他們通常只想要看得到的功能),它的立身之本就不復存在了。我經歷過只有純手工黑盒測試的專案,沒有單元測試、沒有整合測試、沒有E2E測試(測試金字塔, Martin Folower),所以TDD無從談起。我也經歷過客戶要求測試覆蓋率的專案,有專門的測試覆蓋率工具(coveralls)來檢測程式碼庫,有的甚至整合在CI上作為一個硬性指標。

所以,TDD必須在一個有測試的專案中去講。它跟我們先實現功能程式碼後新增測試的過程恰恰相反。我們根據對業務理解,先寫一些測試(E2E,Integration, Unit),此時得到執行結果為紅色(測試執行失敗),然後編寫業務程式碼讓其變綠(測試執行成功)。

當然,TDD實踐存在一定的門檻,TDD更多地考察一個人的設計能力,所以需要有一定經驗的開發人員,而新人往往是很難做到這一點,但這不應該是新人不去嘗試TDD的藉口。

在實際專案中,可以根據團隊自身的條件,靈活採取TDD去編碼。就我個人的經驗而言,TDD編碼的時候剛一開始的時候並不是那麼順手(因為TDD更偏重設計),心裡會覺得比較耗費時間,最終Story的完成時間相差無幾,而TDD除了有效地降低缺陷率,還有以下三個方面的好處。

  • 從巨集觀把握Scope,開發人員不會在開發的過程中擴大或偏離Scope。舉個例子,開始一個功能點時,一上來新增一個E2E測試,整個Scope在此時就被框定,然後再細分到內部實現,最終以通過這個測試來完成這個功能。
  • 提高程式碼的設計。當我們先寫測試的時候,就會考慮到被測試的物件要儘可能被方便的測試,此時我們會盡可能的改良我的的API設計,以便利於測試,這樣一來,我們寫出的程式碼更具有可測試性,這樣的程式碼往往具備較高的質量。
  • 確保功能不會被遺漏。我們一開始更多關注的是業務,而不是程式碼的實現細節,此時寫出來的測試會更全面的涵蓋不同的Case。

Code Review

不可否認的一個事實:人人都愛整潔的程式碼。而一個人單獨編碼難免會耍一些小聰明,或引入一些自身習慣難以察覺的不良程式碼。Code Review能讓你提高警惕,並改善程式碼的質量。

Code review,檢查程式碼,也叫程式碼審查,就是開發人員湊在一起來檢閱彼此所產出的程式碼。看看有沒有新的程式碼壞味道,看看有什麼不合理的設計甚至是錯誤的設計,等等。

既然是開發人員湊在一起審查程式碼,那麼Code Review會產生一定的時間成本(根據團隊的規模1~2小時 = 5~10個開發人員),所以需要一些良好的實踐來確保Code review的高效產出:

  • 團隊一起擬定一個開始時間和時長,並落實到位,保證團隊成員的參與度和Focus。
  • 短時間的描述自己的Story業務,主要Focus在程式碼上。
  • 持續跟蹤記錄,並獲取反饋。這需要有一個人記錄問題(可以按天輪流),結束後交給Owner執行更改,並且下一次Code Review的時候先過上一次的更改。
  • 必要的時候拉長時間,條件允許下建議在一個有大顯示器的會議室中進行。

另外,從團隊規模和時間安排上,可以遵循以下兩個原則

  • 對於規模很小的團隊,可以適當減少Code Review的時間和頻率,如果團隊經常Switch Pair,也可以適當減少Code Review的時間。
  • 安排在下班前進行。一方面,大家經過一天的高強度的思考與編碼,適當停下來,看看其他人寫的程式碼,同時將自己程式碼講解出來,還能意外的獲得一些靈感,或許能解決自己面臨的阻礙(你所面臨的問題可能已經被其他人解決了)。另一方面,如果這個時候發現程式碼的壞味道,需要改進的地方,下班後可以花少量時間作出更改。

長期的實踐證明,Code Review能帶來的好處有:

  • 讓每一個人提高警惕:自己寫的程式碼並不是只有自己看的,所以要督促自己做好。比如規避不想寫測試,程式碼耍酷等。
  • 共同找出程式碼的壞味道(命名規範,程式碼整潔,API內聚性,面向物件設計),及時做出改正,提高程式碼庫的質量,有助於後期擴充套件和維護。
  • 讓團隊成員知道他人在做什麼以及怎麼做,分享好的編碼習慣和技術實現,有助於團隊整體進步。

下面是某個時刻,我們Team四個人正在專注地討論為一個函式取個更好的名字(猜猜誰是表情帝??):

Showcase

不管客戶有多忙,也要定期讓客戶確認自己的期望是否得到滿足。在簽訂合同前,要跟客戶達成一致:Showcase的地位不可動搖。

Showcase就是給客戶演示我們上一個迭代已經完成的功能,它的宗旨是及時得到客戶的反饋,確認團隊的產出是否滿足客戶的期望,降低需求變更返工的風險。

Showcase從專案開始時週期性地進行,並直到專案交付。這個時間間隔是基於團隊設定的迭代週期,我們團隊是兩週一次。團隊跟客戶安排一個遠端會議(如果是在客戶現場,一些參與討論效果更好),主要涵蓋了以下內容:

  • 跟客戶確認上一個迭代的Story列表。
  • 專案目前的交付狀態。是否正常進度,會不會延期。
  • 演示上一個迭代完成功能。線上系統演示,需要一個staging環境。
  • 客戶對功能確認,對達到期望的story簽字,反之。我們記錄下問題,並修改,再次確認簽字。

Showcase的目標是客戶,需要針對不同的客戶有不同的策略。如若客戶覺得每兩週一次過於頻繁,團隊可以變通調整迭代週期,通常建議的是1~4周,不宜太長,太短也沒什麼效果,至於如何權衡這個時間,有兩點可以參考:

  • 在探索中找到適合團隊的迭代週期,如果發現每個迭代時間不夠用,要麼是story劃分太大,要麼是迭代週期太短,這時需要根據幾次的平均結果做出調整,適當擴大迭代週期,或者更合理的拆分Story。
  • 如果Showcase的時候功能背離了客戶的期望,通常是因為迭代週期太長。因為使用者的需求以及團隊對需求的理解都在隨著時間的推移而變化,導致釋出時的產出並不是客戶需要的。這個時候,可以考慮適當縮短迭代週期,讓反饋來的更快更舒緩一些,而不是更慢更猛烈。

試想一下傳統瀑布開發模式下,一個功能的演示通常安排在在某個里程碑節點,此時專案或許開展了半年或一年甚至更久,客戶這個時候見到自己的系統,簡直會驚叫起來,原來這壓根不是他們想要的東西(因為客戶一開始都不知道自己要什麼),即便開發團隊嚴格按照預先的設計文件。這是一種時常發生的災難,它導致大量的浪費,且很難挽救。

敏捷開發可以規避這種災難性事件的發生。而Showcase在敏捷開發中是一個不容忽視的環節,它契合了敏捷宣言中的擁抱變化優於遵循計劃。Showcase能夠讓團隊在每個迭代完成後及時從客戶那得到反饋,對變化做出快速的響應,避免了勞動成果的浪費以及方向的偏離,也能最大化讓客戶的期望得到滿足。

為了達到更好的Presentation效果,Showcase通常提前準備一個總結性的Slide來引導整個過程的推進,結束後該Slide即為產出的一部分,另外也會有一封總結性的郵件來跟蹤記錄Showcase的結果。

CI

沒有CI的專案開發是在耍流氓。CI在Agile中是一項最基礎的設施,它通過自動化來提供有效的反饋機制以及高效的部署,大大降低代了碼整合和專案交付的風險。

CI,持續整合。在敏捷開發中,它是一個專案開始前必須搭建起來的基礎設施。當代的軟體開發專案中,幾乎沒有專案是隻有一個人在開發的。超過一個人就形成了團隊,每個人同時並行開發不同模組的功能,這就涉及到程式碼的整合,所以程式碼整合是幾乎所有開發團隊都要面臨的問題(一個人的開發專案不在本文範疇中)。

持續整合跟團隊開發人員獨立開發沒有衝突,相反,藉助一些工具(Jenkins, GoCD(ThougthWorks開發), Travis CI),它能快速的對我們開發人員提交到程式碼庫的程式碼作出反饋。開發人員每天都在程式碼庫提交程式碼,版本控制工具(比如Git)在提交前必須更新程式碼庫最新的程式碼(解決衝突,程式碼合併,應用更改),然後將程式碼提交到程式碼庫中。這個過程是程式碼整合的第一步,最重要的是如何確保這些整合是可靠的,以下是一些關於CI的良好實踐:

  • 開發人員對自己編寫的程式碼新增足夠的測試覆蓋率。這是基本,基本最無敵:一來驗證程式碼的正確性,二來防止被誤更改。
  • 每個人提交程式碼到程式碼庫之前在自己的機器上保證單元測試都能通過,很耗時整合測試和E2E測試可以更多的交給CI去跑。
  • 藉助一些CI工具(見上文),將程式碼整合的結果反饋展示在團隊所有人都能看到的Dashboard上,一定要大家都可以看到。
  • CI定期檢查程式碼庫的更新,只要有更新,就要執行所有的測試。這裡有個權衡:不耗時的單元測試每次全部執行,整合測試也要頻繁的執行,耗時的E2E測試可以稍微執行少一點(比如設定夜間執行)。我們這個專案,是每次檢查到更新就會執行所有的測試(單元測試+整合測試6分鐘,E2E測試30分鐘)
  • CI如果沒有通過,所有人都應該停止向程式碼庫中提交程式碼,直到CI被修復,所以如果CI掛了,能夠及時通知相關開發人員,要第一時間修復。
  • 所有測試通過之後,CI負責自動化部署到不同的環境(Test,開發團隊測試環境;Staging,客戶ShowCase環境;UAT和Production,使用者驗收測試環境和生產環境,通常開發團隊沒有許可權),並正常啟動所有的服務。

通過這些實踐,CI能帶來的價值也是相當可觀的,主要體現在五個方面:

  • 減少重複的過程。CI通過自動化,將一些需要重複執行的操作(程式碼審查、編譯、測試、構建、部署)自動化管理起來,大大減少了重複的過程,節省了大量的時間。
  • 降低風險。開發過程中,每天進行多次整合,並且添加了足夠相應的測試,每次整合CI都會快速檢查程式碼中的缺陷並提供及時的反饋,降低了未知的風險。
  • 視覺化。CI提供了大量真實且最新的資料,能夠讓我們關注當前整合的趨勢(例如構建時間、構建失敗比例、測試覆蓋率等),有利於有效決策。
  • 增強團隊的信心。每次構建的結果都是公開透明的,所有人清楚地知道自己的每次提交改動對軟體所造成的影響。
  • 隨時隨地可以生成可部署的軟體(CD)。對於客戶來說,可以部署的軟體產品是最實際的資產,而CI讓我們可以在任何時間釋出可以部署的軟體。

可以藉助一些工具,比如Chrome外掛BuildReactor可以將CI的多個Pipeline集中展示出來。

下面是我們CI的Dashboard,使用了一個Chrome外掛BuildReactor(如果載入不了就說明需要翻牆)將Go的多個Pipeline集中展示出來。

Retro

團隊專注於交付目標,埋頭幹活的同時,也要懂得停下來總結過去,並更好地擡頭看路。

Retro是Retrospective的簡寫,即回顧。團隊通常以回顧會議的形式進行,大家坐在一起,對過去的這段時間裡,我們Team的工作狀態(團隊合作,技術實踐,團隊氛圍等)做一個總結,它有一點基本思想:對事不對人,大家思想自由Open。如何做到這一點,下面是我們Team的實踐:

  • 確認構建安全的環境。什麼意思呢?就是每個人都是覺得當前的會議是可以自由發表意見的,而不是因為某些人(比如說不友善的Leader)而不敢發表意見。開始前每個人對安全係數打分,1~10分,如果平均分數偏低(比如低於6分),需要將Leader從會議中”驅趕出去”,直到大家覺得安全了才好。
  • 建立幾項總結指標(Well, Less Well,Suggestion,Action),大家分別對前三項提出自己的看法。第四項是綜合所有前三項的結果總結出來後面要做的事情。
  • 使用Sticker紙片,最好是用馬克筆寫(這樣一張Sticker就不能泛泛無邊的寫),一張Sticke寫上一個點的內容即可。
  • 編寫Sticker內容的時間控制在5分鐘以內,每個人自己將Sticker按照分欄貼好,然後Facilitator(通常是PM或BA)開始帶著大家過每一欄的Sticker,對Less Well欄中,將同一類的問題歸納起來,總結出相應的解決措施。
  • 將Action欄中的Sticker指派Owner,並落實。
  • 如果跟客戶關係融洽且相對容易參與進來,可以將客戶Involve進來,然後一起構建一個安全的環境(有可能因為大家的打分較低,客戶不得不“出場”,所以客戶參與不是必須的)。

說得天花亂墜,沒有行動,猶如竹籃打水。Retro這個環節最核心的產出物是Action,團隊共同一致商量出來的措施,有沒有效果就在於行動了,所以Action分配了Owner之後,一定要跟蹤這些Action有沒有落實執行。一方面,需要Owner擁有高度的責任心和執行力,盡職將這些Action落實執行。

Retro的細節因團隊而有些差異,而它的理念是一致的:總結過去,做的好的方面繼續保持及加強,做的欠佳的方面一起討論改進措施,並盡全力落實。Retro讓團隊在實踐中摸索出適合團隊的最佳實踐,引導團隊和個人不斷自我完善,追求卓越。

我們Team的一次Retro

總結

這是我參加的一個關於敏捷實踐很完善的專案,個人親身經歷了這些,深深體會到這些敏捷實踐帶來的益處以及個人的成長是非常大的。敏捷很好,但不只在於這些流程形式,在形式背後,我們應該深入思考這些實踐是否真的讓團隊變得高效?讓交付變得更加順利?每個團隊都是不同的,不必拘泥於這些流程形式,而是要追求這些流程產生的真正價值與意義。

PS:文章中提供的連結在有網路的情況下如果不能訪問,確認自己是否可以翻牆,如不可以,切勿較真。

術語註釋

  • PM:Project Manager,專案經理
  • BA:Business Analyst,業務分析師
  • TL:Technical Leader,技術領導
  • QA:Quality Assurance,測試人員
  • DEV:Developer,開發人員
  • UX:User Experience,使用者體檢設計師
  • AC:Acceptance Criteria,驗收條件
  • UAT:User Acceptance Test,使用者驗收測試
  • Retro:Retrospective,回顧會議
  • TB: Team building,團隊建設