作者:颯然Hang
原文:http://www.rowkey.me/blog/2016/08/17/dev-manage/
作者已授權運維幫發布
早在讀研究生的時候,自己負責著實驗室的項目,就一直在思索如何建立一套簡單又高效的研發管理體系,能夠在保證項目高質量順利進行的同時還能夠提升團隊成員的技術level。後來在自己在校的幾次小的創業中,也做過一些嘗試。直到畢業後進入前東家,在幾個項目的參與過程中,見到了大公司的研發管理是如何進行的。直至加入目前的公司,將研發體系梳理一遍,且學且抄且實踐,對這一套東西算是有了一定的實踐感悟。
對於一個研發管理體系,其核心是圍繞著產品的整個生命周期來進行的。因此,根據一個產品的生命周期,可以把研發體系劃分為幾個關鍵的環節,如圖所示:
可知,即時溝通和技術提升雖然不屬於研發流程中的某一個環節,但它們是貫穿整個研發體系不可或缺的一部分,有著不可替代的作用。此外,任務管理需要對任務做整個研發生命周期的管理,除了作為其中的一個關鍵環節,也是貫穿整個研發流程的。
任務管理任務管理是產品整個生命周期首要的環節,其對研發體系也是至關重要的。項目生命周期模型,傳統的有五種:瀑布模型、原型模型、螺旋模型、增量模型、V模型,而現在最為流行的是迭代開發模型,敏捷開發則是採用迭代模型的一種典型項目管理方法集合。Scrum是目前敏捷開發中最為大家熟知的開發模式(XP極限編程也是一種比較常見的敏捷開發模式),其開發流程的概覽如下圖所示:
簡單來說,Scrum是依賴於三種角色、四種會議的自組織、信息透明化、成員平等的一種敏捷開發流程。更為詳細的描述,可參見此篇文章:http://blog.devtang.com/2014/09/13/scrum-introduction/。
除了Scrum之外,看板是最近興起的另一種開發模式,在最近很火的美劇《矽谷》裡面「魔笛手」就是採用的這種方式。看板將工作流程形象化,首先把工作細分成任務並根據需要將任務分為Pending、Analysis、Development、Test、Deploy等狀態,然後根據任務的進行,在幾種狀態之間進行轉換。對比Scrum,看板使用開發周期作為計劃和過程改進的度量數據,不強調迭代的概念,也沒有很強的時間期間概念,也不需要制定任何團隊角色。對於看板方法論的詳細介紹可見此篇文章:http://kanbanblog.com/explained/,http://www.jianshu.com/p/e44b1038c9cf這篇則做了比較形象具體的說明。這裡有一點需要注意,Scrum和看板並非是對立的,它們是可以結合起來使用的。使用看板來管理每一次迭代的任務是一種可取也是很常見的精益實踐。
依賴於任務管理方法論,市面上很多軟體都做了相應的支撐,自己曾經使用過的任務管理軟體如下:
Redmine: 這個是自己最開始接觸的任務管理軟體,使用也比較廣泛。比較遺憾的是,redmine安裝有點繁瑣,而且基於ROR,如果需要二次開發,需要重新學習ROR。
Tower.im: 這是一個任務管理雲服務,界面設計的簡單優雅,一目了然。很多小的私有項目,我都會用這個進行任務管理。類似的還有teambeation等。
Jira: 這款軟體是商業版的任務管理軟體,對於這一塊做的是非常專業的,很多大公司都在使用。但是,它是收費的。所以,如果你要用,要麼付錢,要麼去破解。。。
禪道:這款軟體最早是叫做bugfree, 是開源且主要針對Bug管理的,後面慢慢發展成現在的集任務管理、bug管理、團隊管理等的項目管理軟體,並開啟了收費策略。總體來說,功能很全,也比較專業,但是ui上有種傳統it系統的感覺,流程上也不具有現在敏捷開發的一些優勢。
Kanboard: 是實現了Kanban方法論的任務管理軟體。
對於個人的項目,其實依賴於tower.im這種第三方雲服務完全足夠了。如果擔心數據安全的話,那麼推薦在內網搭建Kanboard進行看板任務管理。
文檔協作研發中首當其衝的就是文檔撰寫,這個很多情況下都決定了項目的可維護、可管理性。有人會說現在流行的是敏捷開發,根本不需要寫文檔,但其實這是對敏捷的誤解。敏捷開發強調的是快速試錯、快速迭代,而非簡單粗暴,對比傳統開發模型雖然並不強調文檔,但並不代表不需要。對於一個項目,從開始就需要需求文檔、產品原型文檔、項目進度文檔等等,而到了研發這一步,在系統實現、寫代碼之前最好的就是先「想」再做,而「想」的一種比較好的輸出形式就是文檔。對於一個軟體系統,一般來說需要寫的文檔有以下幾種:
系統業務流程文檔:描述系統業務邏輯的文檔,能清晰的說明真箇業務的流程。
系統架構設計文檔:對整個系統的架構的描述,需要包含系統的各個關鍵組成模塊以及相關的各個關鍵技術點等。
系統功能模塊概要設計/詳細設計文檔:對於某一個模塊的流程、邏輯的描述。
數據DDL/DML文檔: 與系統相關的資料庫的DDL和DML文檔,對於前者,是需要包含所有的操作的,而對於後者,必不可少的是查詢語句,用來提供給DBA,來做查詢sql的review,以保證索引的正確建立等。
系統部署文檔:描述系統關鍵部分部署在哪裡,需要做哪些配置。
尤其對於一些相對複雜的功能來說,整理思路形成文檔,不僅可以讓自己邏輯清晰,也能讓後續維護的人更快的接手下去。
而對於文檔撰寫協作的方式,我自己經歷過的有以下幾種:
使用word撰寫各種文檔,提交到svn等版本管理工具上
使用google doc進行協作
使用word撰寫文檔,然後提交到項目管理軟體中進行管理
使用markdown撰寫文檔,提交到版本管理工具上
我自己比較推崇的是使用markdown撰寫文檔,然後使用git、svn版本管理工具或者是其他團隊協作工具做版本管理。之所以使用markdown, 能夠極大地節省使用word時調各種格式、樣式耗費的時間。對於程式設計師來說真的是如虎添翼。如果是對文檔多人協同編輯有剛需的團隊,可以選擇使用google doc或者國內的石墨(http://shimo.im)。
此外,在移動app開發中,還有一個非常關鍵的文檔就是api文檔,是服務端提供給客戶端調用接口的說明文檔。比較簡單直接的方法就是定製一套api文檔模板,然後在寫接口代碼之前或者之後,按照模板編寫接口文檔。此外,可以實現一套根據源碼自動生成文檔的機制,在代碼編寫的同時就能自動生成相應的接口說明文檔。在使用Spring MVC開發的後端應用中,個人推薦SpringFox,使用此項目能夠通過在Controller中加入相應的註解信息從而自動生成Api接口文檔,同時也提供了在線調試的功能,極大減少了api文檔的工作量。
對於一個技術團隊,最最關鍵的肯定是寫代碼。一個人單打獨鬥那倒好說,但是這就像籃球場上,一對一靠個人硬實力,但是5對5,那就不僅僅是一個人實力強就贏得了的了。因此對於技術團隊來說,代碼協作是至關重要的一個部分。
代碼版本管理:Git + SVN
幾年前最流行的代碼版本管理工具是svn(當然此前,更加古老的還有cvs之流),的確為程式設計師們的代碼管理帶來了很多便捷。但到了現在,相比起這種集中式代碼管理,目前最為火熱的當屬git這種分布式代碼管理工具,在Linux上直接搭建git伺服器來構建項目的git系統的。而這幾年隨著Github以及類似系統的湧現,對於很多私人項目我都是採用oschina或者gitcafe提供的git私有代碼管理來做代碼版本管理的。當然,對於公司來說,有很多開源類github系統可以搭建在企業內網。詳細的可以參見:搭建自己的github。當然,對比svn,git也是有缺點的。無法天然的支持對於目錄級別的權限管理和基於目錄的版本管理操作是目前不得不結合svn和git一起使用的重要原因。通常情況下,可以使用git做版本管理,輔以svn做基於目錄級別的發布包管理。
代碼分支/Tag管理: Git Flow
其實分支/Tag管理是代碼版本管理包含的內容,之所以單獨出來,是因為對於分支的使用其實還是有一定的原則和技巧的。並非如很多人一樣,所有項目就一個master分支,所有修改都往這裡塞。目前,最為流行的一種基於分支的工作方式就是:Git flow。介紹可以見: 基於git的原始碼管理模型——git flow。簡單概括就是:
用於開發新功能時所使用的feature分支;
用於輔助版本發布的release分支;
用於修正生產代碼中的缺陷的hotfix分支。 對於此種開發模型,這裡也提供了一個命令行工具:https://github.com/nvie/gitflow
master和develop作為主分支。主分支是所有開發活動的核心分支。所有的開發活動產生的輸出物最終都會反映到主分支的代碼中。master是可以隨時發布的分支,而develop則時刻保持最新的開發代碼。
輔助分支是用於組織解決特定問題的各種軟體開發活動的分支。輔助分支主要用於組織軟體新功能的並行開發、簡化新功能開發代碼的跟蹤、輔助完成版本發布工作以及對生產代碼的缺陷進行緊急修復工作。這些分支與主分支不同,通常只會在有限的時間範圍內存在。包括:
代碼質量保證:結對編程 + 定期review + PR目前一種比較好的方式。結對編程這個是一個老生常談的方式,兩個人共同承擔某一開發任務,互相保證對方的代碼質量,在很大程度上能夠提高代碼質量。而定期review則是讓團隊所有的成員都能夠參與到這個過程中,不僅僅能夠保證被review者的代碼質量,也能夠讓團隊成員學習到好的代碼是怎樣的而差的代碼又是怎樣的。PR是Pull Request的簡寫,當開發完成的代碼提交到主分支時,需要發起pull request,此時團隊負責人需要review相關代碼,確保沒有問題之後,才能accept此次pr。當然,上面講述的是如何通過人來保證代碼質量。除此之外,還可以通過技術上的手段在一定程度上保障代碼的質量,這一部分在後續的自動化測試機制會講述。
此外,在移動app項目中,一個很普遍的問題就是:在定義好Api文檔之後,客戶端如何在後端並沒有完成接口開發的情況下開發或者調試程序?這裡有兩種方案:
關於客戶端和後端的接口代碼協作,還有一個Chrome插件POSTMAN可以使用。後端可以使用此插件在編寫完接口後進行自我功能測試,測試無誤後可以將接口以文件或者url的形式分享給客戶端供客戶端參考和調試。
質量保證當代碼開發完成之後,需要質量保證機制的介入來保證功能的正常運行,從而保證代碼是可發布的。一般來說,質量保證的手段就是測試,分為:
代碼質量測試一般是在編譯打包代碼之前進行,通常是自動化進行的。針對Java項目,自動化代碼質量測試可以分為以下幾步:
原始碼規範檢查:對於Java來說,代碼規範的檢查一般使用checkstyle來檢查。默認的規範非常嚴格,這裡大家可以根據需要放寬一些規範。
原始碼靜態質量檢查: 常用的工具是pmd, 可以檢查Java源文件中的潛在問題, 比如空try/catch/finally/switch語句塊等。
字節碼bug檢查:常用工具是findbugs,基於Bug Patterns概念,查找javabytecode(.class文件)中的潛在bug。如NullPoint空指針檢查、沒有合理關閉資源、字符串相同判斷錯(==,而不是equals)。
單元測試:使用junit即可,當然在這裡當使用mvn時,其test phrase會默認生成測試報告到${project.build.directory}/surefile-reports文件夾中。這裡建議使用coverage生成單元測試報告,其中一個關鍵的單元測試覆蓋率指標達到98%以上才為合格(根據需要自己調整即可)。
以上提到的工具,都是有maven插件的。通常情況下,也推薦使用這些工具的maven插件來調用。目前流行的自動化ci工具jenkins、QuickBuild等結合各種豐富的插件可以提供這些功能,將他們集成到一個測試流程並形成最終的測試結果報表。
在代碼發布到線上環境之前,一個關鍵的步驟就是功能測試,通常都是工程師來進行的。需要測試工程師根據產品需求,形成測試用例,然後根據這些用例做相應的測試。測試用例的一個模板如下:
用例ID功能名稱用例名稱測試數據前置條件操作步驟預期結果測試結果備註review說明需要測試工程師根據需求創建並經過研發人員reivew確定測試用例,待到發布前進行測試以及反饋,直到所有測試用例都通過。
對於移動app功能的測試,目前市場上有類似bugtags這種所見即所得提交測試工具,可以很方便的提交bug。
功能測試通過之後,對於一些對性能有要求的項目,還需要進行性能測試。對於這種測試來說,通常有以下幾種方式:
當然,所有這些測試都是在項目發布上線之前進行的,通常是在項目的測試、預發布環境中進行的。
此外,對於測試任務的管理工作一般在任務管理軟體中都做了集成。也有類似Mantis這種事專門做缺陷管理的。
自動化部署對於Java項目的發布流程,如下圖所示:
使用ci軟體可將以上步驟自動化的。
如上圖所示,對於一個項目,我們是劃分為三種或者四種環境的。
測試環境: 這個環境是一個相對來說比較寬鬆的環境,所有代碼的提交都會觸發jenkins的自動代碼質量檢查和部署。測試工程師也是首先在這個環境下進行功能、性能測試的。只有通過了,才能部署到後續的下一個環境。
集成環境:這個環境不是必須的,只有當項目出現了兩個大的分支並行開發,發布前需要集成兩部分代碼時才需要這樣一個環境。一般來說只使用jenkins進行部署前的打包流程,部署流程由相關人員進行。這個環境也是需要測試工程師進行測試的。
預發布環境:這個環境和線上環境是一模一樣的,不同的是此環境下的伺服器是不在線上伺服器集群中的,並不為用戶提供服務。此環境下的項目發布也是需要人工參與的,也必須由測試保證功能和性能的正常。
線上環境:這個環境是比較嚴格的一個環境。在發布前,一般來說會進行發布確認等一系列上線評審工作後,由項目負責人或者運維人員部署發布。
其中,上線確認書的一個例子如下:
–xx項目上線確認書–需求方驗證結果意見:確認人:[由各個負責人籤字]開發確認意見:確認人:測試確認意見:確認人:伺服器是否需要重啟[是否需要自動更新那些App?]確認人:伺服器配置影響[是否需要增加新的伺服器ip,是否需要修改nginx/tomcat,是否新裝軟體,是否新建域名?]確認人:資料庫更改[是否需要修改線上資料庫?是否有初始化語句]確認人:數據初始化[是否有初始化數據?如價格,默認分類等]確認人:上線評審結論[ ]通過後續任務計劃,示例如下:
由於各種客觀原因如帶寬、主機配置、流量異常或者程序邏輯不夠嚴謹等原因,線上服務並非100%可用的。研發體系中最後把關的就是這一道故障應急機制。也就是說,一旦發生線上故障,如何快速反應並修復問題,如何避免下一次犯同樣的錯誤。
對故障的快速反應需要依賴於運維的監控機制,包括基礎設施層面的監控以及業務層面的監控,一旦發生故障應該立刻發出告警到相關人員。這裡可以使用nagios、cacti或者第三方服務(如:監控寶)實現,當然,如果你使用的是雲服務,一般也會有相應的雲監控服務提供給你的。後續的故障問題定位很多情況下則是取決於你的應用日誌打的是否合理,是否有足夠的覆蓋面的,是否有足夠的信息。ELK和請求鏈路監測系統(同染色日誌系統)是目前比較流行的基於日誌的故障定位解決方案。問題一旦定位到了,那麼修復就是水到渠成的事情了。
這裡需要說明的一點是,上面講述的是後端的故障快速反應和修復。針對客戶端的故障,一般情況下都是由用戶發現的。但是由於客戶端發布流程的繁瑣,很難及時修復一次發布版本的故障,只能等到下次解決。但是,目前一些客戶端使用混合開發,其中的h5頁面是可以在線修復的,另外,很多安卓app熱更新方案也都能在線修復一些代碼故障,如Nuwa、HotFix、dexposed。
故障解決完並非最終的結果,之後的故障總結也是故障管理尤為關鍵的一點。大公司會根據故障產生的影響不同定義不同的故障級別,從而追責到個人,再進一步影響個人的職級評定或者績效考核、獎金之類的。但這一套卻並不適用於小公司,畢竟大多數小公司沒有那麼完善或者說根本就沒有職級和績效這麼一說。其實,追責並不是主要目的,最主要的是如何避免再次出現問題。因此,對於小的創業公司來說,最需要做的就是如何對已經發生的故障做總結,吸取教訓。構建一套故障總結wiki則是一種很好的方式。下面是一次故障總結模板;
–2016.08.01xxx故障總結–故障等級[故障等級]顯而易見,即時溝通是任何團隊都必不可少的一個機制,同樣也是研發團隊必不可缺的。常用的就是QQ、釘釘或者企業內部的im軟體。那麼對於小公司或者創業公司,不想用第三方服務的該怎麼辦呢?之前蘑菇街開源過一個teamtalk的軟體,不過後來由於某些原因已經下線。目前,有一款開源的web im軟體可以供大家選擇:Rocket.Chat,能夠搭建出內網的slack服務(將分散的溝通方式聚集到一個地方,融入到一個信息流中)。
此外,我自己還嘗試過使用intellij自帶的IDE TALK來進行研發團隊的在線交流。使用這個比較好的一點是可以直接做基於代碼的即時交流,比如能夠發送一個代碼片段給同事,他那邊接收到之後是直接能在他的項目裡相關代碼處進行操作的。
技術提升一個研發團隊,很重要的一點是如何提高團隊的戰鬥力。對於個人來說,在平時的工作中,提高技術的熟練度和深度,在業餘補充學習專業知識,提升技術廣度,這些都無須多言。那麼如何在整體層面或者說是管理上促進團隊成員的技術提升呢?可以採取的方式有以下幾種:
構建內部的技術wiki並建立技術分享機制,鼓勵大家以演講或者技術博客的方式分享自己的技術經驗或者教訓,既可以對自己進行review又可以給其他成員以啟示。這一點,很多公司都是納入績效中的。
將一些項目開源,讓團隊成員能夠享受到開源項目帶來的各種好處,比如提升個人在業界的知名度、提高編碼的水準(畢竟不好的代碼,你也不好意思放出去)。
定期舉辦類似黑客馬拉松的比賽,提高團隊成員的凝聚力,也能夠提升成員解決實際問題的技術能力。
自己比較推崇的是第一種方式,但是開始的時候往往會發現很多人是不會主動去分享的。要麼是覺得自己的東西技術含量都很低,要麼就覺得自己的知識為何要分享給別人。可以採取的辦法就是從最初的周期性安排人員進行技術分享,然後慢慢形成一種氛圍和習慣,再到後續鼓勵大家主動分享。當然,輔以獎品激勵或者績效獎勵也是一種不錯的方式,但切忌不要忽視一些業務能力很強但不愛或者不善於分享的工程師。
至於項目開源,前提一定是團隊的項目真的是高質量並且會對開源社區有貢獻的,不能為了開源而開源。尤其是對於一個公司來說,一個開源的項目直接體現了公司技術水準的高低,會對公司的pr、招聘等都帶來一定程度的影響。
而黑客馬拉松比賽這種方式,尤為關鍵的一點是要選擇合適的主題。一般來說,圍繞現實的業務場景來出題不僅能夠提升大家解決問題的能力,也能順便解決實際問題。比如」根據用戶已有行為日誌預測用戶未來的行為」、「怎樣構建合適的用戶質量模型」都是比較合適的主題。此外,借鑑黑客馬拉松的這種形式,可以採取類似「每周一題」的做法:在每周例會上給出一道和線上業務相關的問題,如「如何提高信息流的點擊轉化率」,然後每個人發散思維給出自己的解決方案,最終形成文章發布在內部的技術wiki上。對於每次主題,都會在下周的例會上針對每個人的解決方案進行討論。
此外,在安排團隊成員去調研一種將要使用的新技術的時候,務必要深入到源碼層面,這個觀念是需要灌輸到團隊每一個人的意識中去的。去使用一個沒有看過源碼或者沒有掌握其運行原理的開源軟體是一件風險非常大的事情,極有可能造成巨大的線上故障。
以上,是自己對於研發體系的一些實踐和感悟,很多地方仍然有所欠缺或者並非最佳實踐,也一直在探索更好的方案。