剖析“持續交付”:五個核心實踐
原文發表于 InformIT
持續交付是一種軟件開發策略,用于優化軟件交付流程,以盡快得到高質量、有價值的軟件。這種方法讓你能更快地驗證業務想法,通過直接在用戶那里進行試驗,做到快速迭代。 盡管《持續交付》一書主要講的是工程實踐,但持續交付的概念對整個產品交付過程都有重大意義,包括對特性的”fuzzy front end”、設計和分析的意義。
持續交付的一般性原則如下:
與其設計一大堆特性,再策劃一個持續數月的版本發布,不如持續不斷地嘗試新想法,并獨立發布給用戶。通過充分思考,即便很大的特性或者大范圍的變更,也能夠通過一系列小步驟得到更快反饋,而且一旦你認為有必要停下來的話,可以隨時停下來。利用跨功能團隊在幾小時或幾天內交付這些小且增量式的功能,就能比競爭者有更多的創新,將投資回報最大化。
持續交付五個關鍵實踐,為你建立一個從猜測到持續反饋的最有效途徑,它們就是:
- 從最小可行產品(MVP)開始——Start with a minimum viable product.
- 衡量新特性的價值——Measure the value of your features.
- 做恰好充分的預先分析——Perform just enough analysis up front.
- 少做——Do less.
- 用戶故事中要包括特性開關——Include feature toggles in your stories.
Start with a Minimum Viable Product (MVP)
“假如你沒有因產品首發版本的寒酸而感到尷尬,就說明該產品的發布實在是太晚了。 ” Reid Hoffman, cofounder and chairman of LinkedIn (參見“建立大公司的十大創業原則”)
如果你的項目一啟動,就有一大堆需求文檔 放在項目經理的桌上,那你已經失敗了。精益創業運動的核心思想中,關鍵的一個就是最小可行性產品(minimum viable product, 縮寫為MVP), 即為驗證你的業務猜想而需做出的最小工作量。
當然,在制造業,MVP的概念已經有數十年的歷史——它們被稱作原型(prototypes)。在使用原型時,你不必把你的MVP展示給全世界的所有人,只要選擇其中一組測試(beta)用戶就行了。甚至用一個尚無法工作的軟件都行——你可以創建一個pretotype,來收集信息,一行代碼也不必寫。
假如對受眾來說,第一個版本至關重要,你也完全可以向全范圍的用戶展示經過精心打造的更完美的產品。例如,某個公司用別的商標品牌發布了它的iPhone應用的一個MVP版本。只是為了得到具有統計意義的重要反饋,即它的業務規劃是否能成功。而次要目標是驗證一下該軟件的交付流程。
找到MVP如何運作至關重要的一點是,需要一個由業務人員和技術人員組成的跨功能團隊(cross-functional team)。這個團隊中的角色包括用戶體驗設計(User Experience Designer,UX),分析、測試、開發、運營和基礎設施建設。當然,一個人可以承擔多個角色,所以也不是非要很多人,才能完成一件事。
由于一個小團隊在數周內(而不是一兩個月的時間里)就可以完成MVP,所以此時也不需要很多儀式,因為你不必象賭博一樣,押上整個公司,或一大筆錢。
Measure the Value of Your Features
“度量是產品的一部分” — John Allspaw, VP of Technical Operations, Etsy (參見“Building Resiliencein Web Development and Operations”).
精益創業中另一個核心概念是驗證性學習(validated learning),即通過收集產品被真正使用后的衡量指標,而不是通過對用戶的提問來驗證效果。正是電視劇《Dr. Gregory House》中,他喜歡說的那樣,人們會說慌的——盡管更文雅一些,我們可以說他們不知道他們想要什么。把你的用戶當做是試驗對象,而不是那些聰明的代言人(intelligent agents)。
你要能回答下面這樣的問題:
- 我們在產品上所做的這些修改是否讓更多的人注冊了,逗留時間增加了,還是增加了收入? Or is it time to pivot?
- 在做A/B測試時,該特性在哪個版本的效果更好?
- 所有的系統指標看上去都不錯,一個用戶說我們的網站不能用。難道是我們的網站壞了嗎?
- 我們產品中的哪些特性是收入的最大來源?
你不必在Apache的日志中搜羅信息,也不必試圖從那些輔助功能上回溯,或利用定制化查詢,就應該能夠回答這些問題。這些問題應該看一眼儀表盤(Dashboard)就能知道,而且,這些信息應該是完全可審計的。
在Eric Rie的《精益創業》The Lean Startup: How Today’s Entrepreneurs Use Continuous Innovation to Create Radically Successful Businesses(Crown Business, 2011)一書中,他提到了 Grockit 的故事:
遵循精益制造中的 kanban 原則, […]Grockit改變了產品優先級評估流程。在這個新流程中, 直到驗證性學習(validated learning)時,用戶故事才算完成。所以,一個用戶故事要經歷四個階段:在product backlog中,正在實現中,完成(從技術角度看特性是完成了),以及驗證中。驗證被定義為:“第一時間知道某個用戶故事是不是一個好主意” 。這種驗證通常是以某種隔離測試來展示客戶行為的變化,當然也包括客戶訪談或問卷調查。
只有當度量項被放在用戶故事中一起完成時,這種學習方式才有可能。
看上去,這一原則可能是針對web應用的,事實上,對于嵌入式系統和用戶自行安裝的產品也是同樣道理。為了遠程調試和失敗報警的目的,以及理解用戶的使用模式,所有類型的系統需要收集這些度量項。
Perform Just Enough Analysis Up Front
“你要知道,當團隊在編碼之前試圖完成規格說明的收集時,你就不是在做迭代開發。” Bas Vodde, “History of Nokia Test.”
一旦你想到了一個點子,是一個最小可行產品(minimum viable product),你就要開始交付軟件了。第一步是分析。但是backlog中所有的用戶故事不必被全面分析。因為那么做,這也是一種浪費。為了全面分析用戶故事,你要從客戶、開發人員、測試人員、用戶體驗設計和用戶那里得到信息。如果團隊在花大量時間去收集這些信息,那么他們的這些工作實際上還沒有交付有價值的功能,也無法從那些使用該系統的用戶中得到真正的反饋。
那么,需要做多少前置分析呢?在開始開發一個用戶故事之前,我們只關心三件事:
- 交付用戶故事的marginal value是什么?
- 交付用戶故事的marginal成本是什么?
- 我們是否有足夠的信息開始開發用戶故事?
前兩個問題是很重要的,這樣當有交付能力時,我們就可以決定我們應該做哪個用戶故事。為了做到這一點,需要找到哪個用戶故事會讓經濟產出最大化。而后兩個問題是緊密相關的,因為評估某個用戶故事的成本所需信息的數量通常要比你開始實現它所需的信息量多。但是,象我的同事Peter Gillard-Moss曾經和我說的:至少需要一個驗收條件。
“剛好夠用的分析”這個紀律需要在整個項目生命周期持續進行,并要強調創建小的、增量式的用戶故事。這會把我們帶到下一個實踐: doing less。
Do Less
“[如果]你發現自己沒有空間放卡片,就使用更小的卡片.” PhlIp (see “Re: [XP] Re: Token definition in User Stories”).
在敏捷分析中,也許最流行的短語就是Bill Wake的INVEST原則。Wake認為,好的用戶故事是獨立的(independent),可協商的(negotiable), 有價值的(valuable),可估計的(estimable),小的( small),和可測試的(testable)。我想說的是:“小的(small)”。
大家常常認為,特性 features 和 stories 是可以互換的。有時候人們認為一個特性就是需要花兩星期完成的工作。我記得在某個項目里,一個用戶故事就是一個幾頁長的word文檔。
XP讓人們把用戶故事寫在一個3 [ts] 5的索引卡片上,這是有原因的。用戶故事不應該幾天內還做不完。超過一個星期的工作就是太長了,應該被分成更小的工作。為什么呢?
- 為了確保我們可以從用戶那里得到對我們工作產出的瞬時反饋,以便我們可以發現我們做的事情是否有價值。
- 為了驗證我們是否做完了——不只是“開發完成”,而是可發布——以便我們可以展示我們真實的工作進度。
- 為了避免完成大塊工作后再集成、測試和發布帶來的痛苦。
- 為了確保我們不斷地測試并改進我們的交付過程
常見聽到的反對意見是,我們不能在幾天內就完成有價值的事兒。我認為,這說明了兩件事兒。一是缺乏想象力,二是沒有理解“哪些東西組成了價值”。正如我之前提到的,只有通過向用戶展示,一個用戶故事的價值才能被衡量。的確,你無法在一兩天之內就完成整個特性。是,你可以完成該特性的一個很小的部分,并得到反饋。比如說,你正在做一個網上訂酒店的網站,打算增加一個特性,讓人們能選擇他們是否需要早餐。你不必為所有的酒店或所有的合作方創建這個功能。相反,最開始的一個用戶故事只是為某個酒店增加這樣的特性,而且也不需要什么配置選項,然后在進行下一步時,為這種特性的可行性收集一些反饋。
無論你做什么,都不要把特性按照解決方案中的那些分層概念來劃分用戶故事,比如一個故事是實現持久層,另一個故事是實現業務邏輯,還有一個是實現UI。用戶故事應該總是很小的縱向切分。如果你不得不做一些集成工作,也要聚焦于讓這種切片盡可能薄。比如,假如作為功能的一部分,你要傳遞一系列信息的消息給另外一個系統,那么你第一個用戶故事應該是傳遞那個最簡單的消息,以便第一次實現就做到“端到端”的集成。
通過不斷對功能的分解,直到找到你可以向用戶展示的功能最小集,來強迫自己找到某個特性的真正價值(并從中學習)是一個很困難,但也極其有價值的學問。你可以使用得到的反饋來決定下一步(兩三天的工作)的工作是什么,或者是否不要再按當前的樣式開發這個特性,因為它并沒有象你想的那么有價值。
時刻牢記一點,即軟件開發中,最大的浪費就是無用的功能——超過50%的功能從來沒有或很少被使用(詳見這里)。
不要問下面這類問題:“我們還要加點什么放在這個特性里,才能確保大家喜歡它?”或者“我們還要在當前這個版本中增加哪些功能,才能算一個真正偉大的產品?”。相反,需要問這樣的問題:“我們現在就能交付我們手里的東西嗎?如果不能,那是為什么呢?”少做點兒,你就不再太關注你付出的努力,而是關注于從你的用戶那里學到了什么。
你可能想做一堆用戶故事之后才把某個特性展示給所有人。但總是要在發布和確保發布內容滿足質量要求(由用戶決定)之間做出平衡。所以你需要feature toggles。
Include Feature Toggles in Your Stories
“現在,在Facebook.com網站上的代碼中,已經包含了后六個月后將要發布的特性了。” Chuck Rossi (see TechCrunch discussion about Rossi’s May 26, 2011 “Facebook Tech Talk”).
如果你想提高發布的頻率,將應用的部署和特性的發布解耦是關鍵。特性開關是一種模式,用于控制誰可以使用哪個特性。這樣,即使軟件中包含一兩個故事,還不想公開的未完成特性,你也可以發布新版本。
Facebook的工具Gatekeeper讓它可以動態控制誰能看到哪個特性。比如,將某個特性僅開放給10%的Facebook用戶, 或者那些在Facebook工作的人,或者25歲以下的女性用戶,或者是英國居民,等等。(Gatekeeper甚至有這樣一個開關,可以讓除了TechCrunch員工以外的所有人使用某個特性)。這使得Facebook的開發人員可以僅在某類人群中試驗某個特性,并逐步向更多的人群擴展。
在將特性分解成多個用戶故事時,特性開關是一種非常重要的約束條件。對于使用開關來說,常見的反對意見是: ”有些用戶故事會涉及所有的用戶界面。如果對其使用特性開關的話,需要增加很多工作。” 答案是:以一種非常容易增加特性開關的方式將特性分解成用戶故事。
特性開關應該是用戶故事中的一等公民。Orbitz的一個團隊在其用戶故事中有特性開關,那么他們在實現這個用戶故事時的第一個任務就是加一個開關。特性開關是用戶故事價值的一部分,當然,由于增加開關所帶來的開發成本也在估算時考慮了。如果增加開關的成本太高了,這就是一個信號,你的用戶故事分解的不好。
除了能夠做增量式地功能交付以外,特性開關還有另一個重要的用途。萬一遇到未預期的負載過高,它們可以優雅地對在線服務進行降級(degrade),比如通過關閉資源密集型的特性,如推薦引擎。另外,當發布出了問題時,它們也可以讓你馬上關閉存在問題的特性,相當于做了一次回滾操作。
Conclusions
一種常見的軟件項目失敗模式是Don Reinertsen在他的書《The Principles of Product Development Flow: Second Generation Lean Product Development (Celeritas, 2009)》所說的“large batch death-spiral”,而product owners為了試圖確保產品的成功,在項目進行中,增加越來越多的范圍,從而導致成本顯著增加,工期明顯拖長。
持續交付讓團隊大幅度減少發布高質量軟件的transaction成本,所以你可以更頻繁地發布,產品團隊從而能夠從用戶那里得到更加豐富和迅速的反饋。但是,反過來,對于在整個軟件交付流程中如何管理工作流,你也需要改變一下思考方式。尤其強調的一點是,假如你正確地實施了持續交付,在用戶那里驗證新的主意時,技術人員就不再是一種約束了。使用傳統的交付流程,則你不得不等上數個星期或都是數月,才能看到你的想法變成軟件。通過增量式交付小的功能,并收集反饋,我們可以持續思考:“下一步我們應用做什么?”沒有哪個團隊達到這種轉變后,還想再回到原有的工作方式上。
使用傳統的交付方法,我們必須細心地挑選我們想實現哪些想法,因為軟件交付的過程成本太高了。當然,那種審查流程也并不是基于真實數據的。然而,通過持續交付,我們就有了我的同事Darius Kumana所說的一種 ”創新失敗的安全氣囊”。在系統 we can try crazily innovative ideas cheaply and safely at any stage in the evolution 演進的過程中,可以用廉價且安全的方式嘗試那些異想天開的創新想法,通過僅將其開放給少量用戶組,緩解可能失敗的風險。持續交付通過大幅度減少軟件發布的風險來解放我們,把分析師帶回他們本來的位置——全力創新。