前言
作為創業公司很重要的一個環節就是在有限的時間和資源下把產品需求落地為產品,也就是研發和專案管理,毫無疑問,這個階段的主角是開發人員,那作為一個PM,把做專案管理的過程也當成做產品的過程的話,是不是應該多思考下怎麼面向開發人員來優化整個研發過程和專案管理流程。本文就是我們如何通過優化開發環境搭建,程式碼管理,需求生命週期管理,開發任務分配和追蹤,專案整體進度管理來提高研發過程中開發人員效率,通過持續整合和交付讓開發中的問題更早暴露,通過合理的測試反饋工具讓開發人員最快定位和解決問題。
一點前提條件和背景
印象中很多關於產品和開發為了進度撕逼的段子,其實作為一個開發轉的產品,對這兩塊都有所瞭解,就我的看法是研發效率不止是研發人員本身的技術能力和工作效率,而是整個研發過程和專案管理流程的效率,但我自己理解的高效的研發和專案管理有兩個前提:
- 公司內各團隊有個大家認同的溝通協作方式:因為所有的流程和工具都是為人所用的,只有團隊有主動性去溝通協作才能提高效率,這也是我這個系列第一篇寫“異地創業團隊如何做團隊溝通協作”的原因。
- 儘量清晰的需求定義:產品經理的任務就是讓研發團隊開發正確的任務,我所碰到的開發延期或者交付失敗很多時候就是由於自己對需求的認識不夠,開發中過多需求的變更造成的,一個表達清楚,考慮完善的需求定義才能保證下面的研發和管理是不是在做無用功,所以本系列的第二篇是“聊聊針對異地團隊的需求協作和原型、設計的評審”
說到創業團隊的研發和專案管理的實踐,就逃不開先要說一下我們研發和專案管理中的工具作為背景:
- 即時交流和協作:Slack,這個我在“異地創業團隊如何做團隊溝通協作”裡重點談到過,鑑於它的開放性,已經基本連線了我們用到的檔案管理,設計評審,持續整合,測試分發,Bug Report等一系列工具。
- 程式碼管理:Git+Gitlab,在VPN環境內自己搭建Git和Gitlab一定程度上保證了程式碼的安全性,不過維護和備份都是個會耗費精力的問題,對沒有專業運維的創業團隊推薦直接Github託管。
- 專案管理:Redmine,老實說Redmine一直都不是專案管理上的最佳方案,專業級的有JIRA,輕量的有Asana、Tower等很多,我們就是已經習慣了,有一套Githooks在上面,並沒有什麼動力去換。
- 持續整合:Jenkins,雖然Java的坑也很大,維護起來也不時被坑,不過功能和外掛確實齊全,搭起來也不易,有興趣的可以嘗試Travis CI或者Gitlab CI。
最後切入正題了,本篇涵蓋的是我們在研發過程和專案管理流程,以及當中在DevOps上做的一些努力去優化開發人員的體驗,就試著從各個環節總結一下,因為不同團隊的研發流程和專案管理都不一樣,各位看官可以挑有興趣的來看:
- 研發環境的搭建:包括如何kick off新開發者,如何搭建日常開發環境
- 程式碼的管理:包括原始碼管理,Code Review和組織公共庫
- 需求在研發中的生命週期管理:包括功能需求清單,功能需求定義和其中的開發任務項分配和狀態管理
- 專案進度的管理:包括如何通過Redmine有效的執行敏捷開發
- 研發階段的產品測試和反饋:包括在產品測試和反饋中的一些經驗和工具分享
- 持續整合和持續釋出:包括如何針對Web, Android和iOS分別搭建持續整合和釋出
一、研發環境的搭建
如何讓團隊新的開發者儘快上手
對新的開發人員,一般都會有開賬號,裝系統,配環境,跑程式碼這些過程,我自己發現每次都低估這些工作的耗時,以前就發現有時候不小心就一兩天過去了還沒跑起來程式碼,一兩週還沒搞清楚目前產品的功能,我總結了兩點加快這個進度的方法:
1.加快能讓程式碼跑起來的速度
有很多可以加速的環節,一個比較重要的就是自動構建程式碼,就是指開發人員checkout程式碼後通過簡單的構建指令碼就能完成程式碼依賴安裝,程式碼編譯,單元測試執行,也就是我們常說的跑起來。以Web為例,可以通過npm的指令碼完成npm依賴的安裝,然後用gulp完成程式碼的構建和執行,這也是持續整合的基礎。
2.對產品功能需求和目前進度的瞭解
在背景的裡說的保持一個儘量清晰的需求定義的一個用途就在這,新的開發人員可以通過瀏覽產品的需求文件來了解產品功能,我們的做法是在Redmine上把“系統功能彙總(含已排期未完成功能)”作為一個Custom Query,將所有功能的PRD列出來,有兩種檢視可以選擇,一個就是下圖這樣按照產品線,能看到每個產品線的功能:
另一個檢視就是按照功能完成的時間來歸類,可以知道以前每個版本都做了什麼功能,未來有什麼功能正在排期中:
如何方便開發人員進行日常開發除錯
目前對於Web開發來說,一般構建的過程中程式碼都會進行混淆、合併、CDN地址替換、CSS Sprite生成等等操作,造成在Dev伺服器上除錯很不方便,我們採取的解決方法是在web的Gulp構建流程中分不同的Build Target,本地除錯使用未混淆的程式碼加本地搭建的Python環境,連線Dev資料庫,方便Web開發人員本地除錯。
二、程式碼管理
首先最重要的就是程式碼必須用原始碼管理工具,我們一直用的Git。程式碼的檢視和管理都在Gitlab上,可以檢視程式碼,code review,合併分支,打版本tag之類的,不過Gitlab對開發者不是必須要用的,所有這些操作都能用git command解決的事情,有兩點我覺得需要關注的:
1.怎麼讓開發人員高效的使用第三方庫
專案開發的過程中去抽象公共元件,使用第三方庫或開發工具都可以提高開發效率,但需要做好模組和版本管理,有時候碰到一個開發人員引入了一個不合理的依賴,或者學習成本陡峭的元件,每個參與開發人員都要增加學習成本。這個一般都是根據不同的技術棧有相應的一套工具可以使用,我們自己在Web、Python、iOS、Android上面都有自己習慣的選擇,需要加新的元件或者替換正在使用的都可以一起討論之後加入,以免發生重複或者後期的分歧。我們主要考慮的點有下面這些。
2.如何做新功能開發的程式碼管理
只要多人開發,而且多功能並行開發都避免不了要考慮如何管理程式碼,一般有Feature Toggle和Git Branching兩種,目前我們根據自己的需求定義了一個Git brancing model,對於複雜的新功能建立feature branch來開發:
雖然我個人更喜歡Feature Toggle的方式,不過實踐起來需要的模板開發和構建方式上的配合,不如Git Branching對開發來說上手更簡單一些,暫時就沒有更換,建議看一下Baidu FEX的Feature Flag 功能釋出控制>>去考慮自己適合哪一種。
三、需求在研發中的生命週期管理
對於開發人員來說,開發工作一般是圍繞著具體的功能需求進行的,而背景中提到過的“清晰的需求定義”就是研發的主要輸入,由負責的PM來主導需求(User Story)的狀態更新,本節以一個功能需求(User Story)為例,先上一個時序圖來說明單個功能在研發中的生命週期是什麼樣的:
從功能需求(User Story)的時間線上可以看出來其分為下面幾個狀態:
1 |
PM建立後協作編寫需求文件(New) -> 需求確認(Confirmed) -> 開發中(In Progress) -> 待測試(Wait for test) -> 已完成,可以上線(Finished) -> 完成,可以關閉(Closed) |
可以劃分為需求確認,需求開發,需求測試和上線三個階段:
1. 需求確認
對於需求文件的編寫和確認,不同團隊方式不一樣,我在前一篇“聊聊針對異地團隊的需求協作和原型、設計的評審”>>聊瞭如何通過怎麼協作完成清晰的需求定義,我的理解是包括功能需求的前置條件和後置條件,使用者流程和規則,完整的產品互動原型,評審確認的設計稿。下圖為在Redmine上定義的一個功能需求(User Story)
2. 需求開發
在需求定義清晰後,開發前需要整個開發團隊的參與確認任務的分配。任務分配的原則就是將功能需求對應的任務按樹形結構分解,敏捷開發裡的學名就是“Work Breakdown Structure (WBS)”,保證其中每個任務都是可以開發,並且是可以測試的。下圖就是一個功能需求對應的任務的例項:
具體到其中一個單獨的任務項(Task),裡面會有它所屬的功能需求(User Story),當前的狀態,優先順序,任務指派的開發者,任務所屬的產品線(Web, iOS, android…),一個簡單的任務描述的,所屬的milestone,預計開發時間和結束時間,任務當前的狀態和進度等等。如下圖所給的就是一個Task的例項:
從上文中“需求在研發中的生命週期”的時序圖上可以看出其對應的任務的生命週期是如何管理的,包括前端和後臺之間的任務協作是如何完成的,簡單來總結的話Task有下面幾種狀態:
1 |
新建 -> 開發中 -> 待程式碼複查(目前僅junior developer需要被code review) -> 待測試 -> 反饋 -> 完成(可以上線) -> 關閉(上線以後可以關閉) |
開發人員主要負責的就是開發的同時更新自己任務的狀態,看起來狀態蠻多,如果開發需要每次登入redmine來改也確實蠻累,在實踐的過程中我們引入了一下優化的方法:
- 為Redmine自定義一些Git hooks來更新狀態。通過自定義git提交語法,讓Git提交能自動更新在Redmine相應的issue上,既節省了更新狀態的時間,又能保持一個乾淨的git logs。下面是我們定義的Git提交語法:
1[component] Abc: (Issue #Id) + Message (Issue Status)
[component] 就是任務所屬的模組,比如[ios], [android], [backend], [web],這和Jenkins的Build Job繫結,當有相應模組的程式碼提交就會觸發相應部分的持續整合和交付。 Abc 就是操作的Action是什麼,比如Add, Mod(ify), Ref(actoring), Fix, Rem(ove) and Rea(dability),用來讓程式碼提交資訊的目的看起來比較清晰。 (Issue #Id) 就是對應的Task的Id是什麼,為了將changelog和task繫結在一起。提交以後就會自動更新Redmine的Task: - Server端介面文件自動生成。在需求定義裡可以將規則和邏輯寫的很清楚,但在前端和服務端協作開發的過程中,如果服務端沒有文件可能會經常被前端打斷,詢問介面具體引數的名稱或引數型別,也是比較煩的事情,可以考慮用Documentation Generator在程式碼中新增註釋來自動生成文件,我們使用的“Sphinx”作為Python的文件生成工具,用Python的推薦使用。
- 開發中的持續整合和交付。這個後面會專門來講如何操作,具體的意義就是開發人員提交程式碼之後在Dev伺服器上進行自動構建和釋出,這樣一方面每次提交都做Lint檢查,有單元測試的做單元測試,降低程式碼最後整合的時候出現問題的風險,另一方面讓PM可以儘早的接觸到成品,儘早進行反饋。
2. 需求測試和上線
當單個功能需求下面對應的所有任務都開發完成後,由PM進行測試和反饋,在確認與PRD一致後可以由PM更新為“待測試(Wait for test)”。這裡“待測試(Wait for test)”的意義就是該功能需求可以在釋出到測試伺服器(Test Server),由業務團隊及測試使用者參與測試。當測試沒有問題後,如果是Web功能則根據上線計劃上線到Production Server;如果是Native App,則按照版本計劃,可能需要固定時間釋出或者等待幾個功能完成後一起釋出。
由於這裡講的是單個功能需求的研發週期,而測試和上線更多是在整個專案這個Scope上來討論,所以針對測試和上線的部分在後面持續整合和釋出的部分會來細說。
四、專案進度的管理
順著上面的思路,當你有單個需求研發的流程後,整個專案的管理就是管理所有的需求,安排優先順序和迭代計劃,然後對所有需求進行同樣的研發流程管理。敏捷開發裡把一個迭代週期稱為一個Sprint,每個Sprint做一次產品釋出,然後回顧Sprint內的問題,規劃下一個Sprint的開發任務,如下圖:
我們的實踐不完全是Scrum,但比較接近,我們的迭代週期為一週,保證每週至少都往Production上做一次同步。專案的進度管理在Scrum的實踐裡其實就是在它的三個Meeting時完成的:
- Sprint Planning Meeting:從整個產品的Product Backlogs裡一起規劃出下一個Sprint要完成的功能,可能對應著很多團隊的需求評審會
- Daily Standup Meeting:在一個Sprint裡每天和開發人員一起回顧昨天的開發進度,討論碰到的問題和確認當天的工作計劃,其實對應著為開發人員詬病的專案日報
- Sprint Review Meeting:在一個Sprint結束回顧專案進度,問題和下一個Sprint的計劃,一般對應著PM要做的專案週報
在產品體驗的優化中有個理論就是在所有直接接觸使用者的‘Touchpoint’上進行體驗優化,其實我個人覺得這三個Meeting就是專案進度管理裡的Touchpoint,在這三個Meeting上PM會和開發人員或者Product Owner進行接觸,如果這裡體驗不好就會影響專案的管理。其實我們總結的優化方案也比較簡單,就是通過專案管理工具Redmine去實現的功能需求和開發任務的“看板”:
Sprint Planning Meeting
平時積累下的需求我會建立一個Future Milstone來存放,這樣在Planning Meeting上可以直接以這些作為Product Backlogs,作為產品以後可以去做的內容,這些需求可以按照功能模組來組織,然後在Sprint Planning Meeting上一起規劃出下一個Sprint要完成的功能:
Daily Standup Meeting
每日的站立會議是粒度最細的會議了,就是追蹤每個人每天的任務情況,在這裡我們在Redmine上建立一個叫“本週需要完成的任務(開發人員)”的Custom Query,將這個Sprint裡的任務按照不同類別( 網站,後臺管理,iOS或者Android)來歸類,作為我們的看板:
對於開發人員,只需要按照前面提到的提交程式碼來更新任務狀態,完全不需要額外的工作就可以彙報自己每天的進度。每天早上一上班,所有的開發人員聚在一起,按照不同的類別一個個過任務項,同步昨天完成的任務,確定今天的任務,有疑問的就在早會解決。
Sprint Review Meeting
對於專案進度Review來說,Scrum的看板管理是將任務項按照狀態來分類,這樣能更清晰的看出來哪些已經完成,哪些還沒有開始,可以通過變換Custom Query來實現:
不過Sprint Review Meeting一般就不只是研發團隊參與,為了輔助相關的業務人員和測試使用者一起來Review,我們通過在Redmine上建立一個叫“本週已經完成的任務(業務人員)”的Custom Query準備上線的功能,裡面是這個Sprint已經完成的功能,將已經完成功能的按照來歸類,PM可以按照這個來測試已經完成的功能,全部完成測試提交到測試伺服器以後,相關的業務人員和測試使用者也可以按照這些任務來試用,節省一下每次都要介紹更新了什麼的時間:
五、研發階段的產品測試和反饋
產品釋出到測試渠道後的反饋
當產品釋出到測試渠道就是希望在正式釋出前得到業務團隊或內測使用者的反饋,對比開發人員的測試反饋,業務人員和測試使用者的反饋一般都比較抽象,就是問題描述不具體,環境上下文不清晰,沒有復現流程,解決這些問題最好藉助反饋輔助工具:
- 移動端的Bug反饋工具目前我們使用BugTags,目前只用在Test版本上,可以讓測試人員通過截圖示記的方式描述反饋內容,傳送時候也會附上環境和App日誌,能節省不少對於反饋的處理時間。不過這個是顯式的反饋收集工具,需要測試使用者主動提交,如果需要隱式的反饋收集可以考慮AppSee,我自己沒有試用過,但一些測評都表示可以記錄使用者行為的視訊,統計介面點選熱圖和漏斗分析,不過收費比較高,有機會可以嘗試下。
- 移動端的錄屏工具的話可以選Lookback,其實是個用研的工具,功能就是語言錄屏+面部攝像,目前還在Beta期間,免費試用,可以Mac直接連線錄屏後傳送到它的網站,也可以在它的本地目錄裡找到。
- Web端的Bug反饋工具可以也使用BugTags,之前沒發現它也提供了Web版,後來有網友提醒,我就試了下,確實可以截圖示註反饋。另外的話,曾經在《How Google Test Software》裡面看到Google曾經開源的Chrome外掛工具BITE,有各種web上bug記錄和復現的黑科技,不過在Google Code上一副年久失修的樣子,我沒有勇氣去嘗試,如果有知道其他類似合適的可以推薦一下。
- Web的線上使用者追蹤的話,我們目前使用了Mouseflow,它可以記錄使用者的行為,然後在它的網站上通過iframe你的網站幫你復現出來,雖然不是100%精準,但可以觀察一些使用者的行為。
產品釋出前的測試用例表
我自己的經驗是每次釋出前的測試都需要產品經理親自來做,一方面確認釋出功能的正確性,另一方面重新走一遍使用者流程,確認產品目標可以達到。測試的方法比較笨,暫時就是通過Google Sheet維護一張測試用例的表,如果是移動端就每個版本維護一個測試用例表,開發版測試時會把表格分享給所有開發人員,每個人都可以遍歷測試用例提交自己發現的問題。測試用例表的結構為:
1 |
一級目錄,二級目錄,三級目錄,用例名稱,優先順序,前置條件,執行方式,操作步驟,預期結果,測試狀態,測試備註,是否自動測試覆蓋 |
六、持續整合和持續釋出
前幾年有一段為海外客戶做移動產品設計開發和諮詢的經歷,這裡面一個重要的痛點就是不停發測試版給客戶,徵求意見和反饋,但對於移動app來講之前每次打包都需要打斷開發人員,等待編譯,改檔名加版本號,上傳等一系列繁瑣的過程,然後還經常因為客戶沒有裝最新版而造成溝通時間的浪費,所以早期我們就開始著手建立持續整合和持續釋出體系來避免這些問題。
我理解的一個完善的持續整合應該包括程式碼提交後的構建->部署->測試->釋出幾個階段,可以看‘The Product Managers’ Guide to Continuous Delivery and DevOps’上這個圖來理解:
自動構建
在上文Redmine的Git hooks提到過githooks在持續整合中的作用,其實就是當Git Commit Message出現相應的模組,就會在程式碼提交成功後能在持續整合服務端(CI Server)觸發相應的Server,Web,iOS或android端的自動構建,這是持續整合的基礎。
這裡面有個針對開發這邊的優化就是儘量縮短自動構建的時間消耗,我們的Web編譯就是個反例,優化前有10來分鐘的時間,現在穩定在3分鐘,還有優化空間:
持續部署
部署分為客戶端部署和服務端部署兩種,就是構建以後要把可執行的程式碼釋出到相應的伺服器和手機端。
持續測試
這部分在服務端和每種客戶端都分為單元測試和整合測試,理論上來說能在持續整合的過程中執行測試,是對產品質量極大的提升,不過對團隊的規模和時間要求比較高,一般還是按自己的實際情況來。
自我檢討來說我們客戶端的單元測試這塊做的比較少,自動化整合測試的話每個專案都只對主要流程做一下覆蓋,這也是個從Linkedin早期開發流程裡看到的經驗,可以通過分析使用者行為得到主要使用者流程,然後先自動化測試這些流程。早期在Android開發的時候實踐過,通過Jenkins+Spoon+Robotium可以在CI上跑多種不同的Android裝置來對主要流程截圖,實現多裝置的測試,在CI的效果是這樣的:
雖然效果確實不錯,可以在持續整合階段發現在什麼版本或者解析度下出現問題,但用Robotium測試寫起來還比較麻煩,後來我在Github上fork過一些優化測試的方法進行優化,但如果不是非常長期維護的產品還是慎用吧。
持續交付
持續整合後的持續釋出是我們主要需要解決的痛點,釋出的物件分別是給開發和測試人員的Dev版,給內測使用者的Test版和給最終線上使用者的Production版,釋出的渠道又分為Web端和Mobile端,需要分別來考慮,一個涵蓋上面所有的情況專案的Jenkins大概是這樣的:
在之前Gitflow的圖上有展示到,我們將釋出的dev,test和production分為三個不同的伺服器:
- 對於Dev伺服器就是由Git hooks來觸發,每次程式碼提交都會更新Redmine對應的Task,然後Redmine發郵件給這個Task的Watchers,同時觸發CI整合新版本到Dev上。
- 對於Test伺服器就是當有新功能測試完成,準備上線的時候,就先同步到Test伺服器上,通知內測使用者下載測試,相當於Staging伺服器。
- 對於Production的正常的流程就是當Sprint Review Meeting之後,按照確認要上線的功能進行釋出。這裡我有個習慣就是釋出的時候在CI上檢查一下發布對應的redmine tasks,避免有不該被同步的內容。
需要注意的就是,Web的持續交付相對來講比較簡單和成熟,但Android端和iOS端處理起來都比較麻煩,首先就是對於Production版本,都不能直接釋出到AppStore或者國內的一堆Android市場,能在CI上做的就是build好production以後自動在Git上打版本tag。然後對於Test版本的分發,可以考慮使用Testflight或者國內的蒲公英,繫結到CI上,可以整合好以後直接釋出上去,然後通過Slack建立測試使用者Channel,自動傳送通知訊息,收到通知可以直接點選下載安裝。
後記
關於團隊溝通,需求協作和專案管理三塊的總結終於寫完了,很久沒碼文字了,寫出來感覺蠻生硬,很多地方沒有說清楚,不過水平確實也就這樣了。寫的過程中還是想到不少現在的方法裡面有缺陷的地方,正好給自己一個ToDo List,以後去優化。