我們知道Git協(xié)作中最重要的一個步驟是Pull Requests(簡稱PR,Gitlab中也叫Merge requests,MR,本文中統(tǒng)一叫PR),在之前的文章"理清基本的git(github)"流程中,蟲蟲介紹過基于Fork-PR的開發(fā)協(xié)作流程。擁有有效的git協(xié)作流程,編寫良好的PR可以極大的提高團隊的工作效率,最大限度地減少挫敗感。本文中蟲蟲給大家介紹良好協(xié)作的PR實踐,雖然PR傳統(tǒng)上被認為是開發(fā)人員工作流程的最后一點,但這些最佳實踐涵蓋整個開發(fā)過程。
本文主要涵蓋良好的用戶故事,代碼測試,代碼的可讀性,編寫良好的修訂控制commits以及編寫良好的pull請求消息的。
良好Pull Requests的重要性
在團隊中編寫好的PR的流程可以大大提高開發(fā)生產(chǎn)力。如果一個協(xié)作團隊中提交的PR小而精悍、頻繁迭代、易于查看和測試,則能加速PR、加速版本合并,快速實現(xiàn)開發(fā)迭代和版本上線。
如果在開發(fā)人員,審閱者,測試人員和PM之間來回反復發(fā)送的不常見的大PR可能會顯著影響進度,開發(fā)人員需要浪費大量時間處理沖突和合并。繁瑣的PR也大大增加了引入大bug的風險,由于變化太大,很難仔細檢查所有變化并且回歸測試。
所以,項目PR的質(zhì)量是團隊開發(fā)實踐效率的一個很好的宏觀指標。如果一個團隊已經(jīng)在編寫快速合并的PR,則說明他們的協(xié)作流程比較健康優(yōu)良。
用戶故事
用戶故事(User Story)是對需要完成的工作單元的簡短描述,描述對用戶有價值的功能。它通常從用戶的角度來完成解釋,因此得名。用戶故事通常的格式為:作為一個<角色>, 我想要<功能>, 以便于<商業(yè)價值>。
一個良好的PR應(yīng)該從編寫精良的用戶故事開始。
細化用戶故事
用戶故事通常從一個通用的用例開始,隨著項目的進展被分解為更小,更具體的故事。例如:
"作為客戶,我需要登錄管理系統(tǒng)。"
雖然這看起來像是一個合理的用戶故事,但應(yīng)該進一步細分,因為太范。開發(fā)人員可能需要一天多才能創(chuàng)建一個完全可操作的登錄系統(tǒng)。它的細分程度取決于團隊,但理想情況下,用戶故事應(yīng)該需要一天或更少的開發(fā)工作。以下是該故事的一部分可能如下所示的示例:
"作為客戶,我打開表單頁面,輸入我的用戶名和密碼,然后點擊提交。"
從這個跟蹤的其他故事可以涵蓋當用戶提供無效輸入時發(fā)生的事情(異常處理),或者點擊提交后發(fā)生的事情(登陸跳轉(zhuǎn))。許多團隊在sprint規(guī)劃時候提出并細分用戶故事,因此團隊中的每個人都可以了解即將開展的工作。
垂直劃分
還有一件事值得一提的是分解許多團隊細化用戶故事時候常犯的錯誤。在細分時,應(yīng)該垂直劃分,而不是水平劃分。
垂直劃分故事通常需要在整個工作流程上:從視圖到服務(wù)/類,再到數(shù)據(jù)庫。水平劃分的故事通常只涉及其中一個。引用上面的例子,一個水平細分:
"作為用戶,我可以將我的詳細信息存儲到數(shù)據(jù)庫中"
這首先作為一個用戶故事,很不合規(guī),但團隊通常基于流程構(gòu)建任務(wù),而不是某些操作。因此,需要一次構(gòu)建很多個故事的用例,然后查看其面向客戶的價值。
通過創(chuàng)建垂直劃分的故事,團隊可以清楚地了解需要完成哪些特定任務(wù)才能為最終用戶增加價值,并且任務(wù)更加離散且更容易跟蹤。
用戶故事依賴
理想情況下,用戶故事應(yīng)該不依賴于其他另一個正在完成用戶故事。這樣,所有工作都可以并行完成。但實際上,用戶故事經(jīng)常相互依賴。搞清故事依賴非常重要。
當處理一系列相互依賴的故事時,最常見的構(gòu)成一系列PR"塔"型請求,劃分到時,最終會得到一系列嵌套的功能分支。最簡單的解決方案是在完成其他故事之前合并上一依賴的故事。
我們考慮一個具有三級嵌套的示例分支。
master <分支1 <分支2 <分支3
如果在創(chuàng)建分支3之后,對分支1中進行了更改,則必須在分支2上rebase 分支1,然后分支2 rebase 分支2。萬一分支1 rebase了master分支則分支沖突和合并災難也會發(fā)生。
理想情況下,要從底部到頂部來解決這個問題。將分支3合并到分支2中,然后將分支2合并到分支1中,最后合并到master中。但是,通常的合并是從舊到新來的,其中分支1將首先會被合并,然后分支2 rebase到master。
為了避免出現(xiàn)這種情況,盡可能避免依賴關(guān)系,但是無法避免時,就要快速合并PR,然后在進一步工作。如果團隊會立即處理PR,這樣是OK的。但如果不是這的話,最好通知團隊優(yōu)先處理依賴性的額PR。
為GitHub/Gitlab活動設(shè)置一個特殊Slack通道會很有幫助,可以通過使用GitHub的Slack的集成來實現(xiàn)。該通道將會非常有用,可以突出顯示團隊中有關(guān)不能等待的PR。
準確評估故事
許多企業(yè)都在努力解決這個問題,但這對規(guī)劃至關(guān)重要。上面我們提到了改善這個問題的一個關(guān)鍵因素,將故事分解為可在一天或更短時間內(nèi)完成的事情。但帶來一個問題:如何知道故事是否需要一天或更短的時間?
有一個值得推廣的好方法是做"計劃撲克"。在sprint計劃之前或期間,讓每個開發(fā)人員獨立的投票決定一個故事需要多長時間。投票結(jié)果的中位數(shù)應(yīng)該能夠合理準確地估計故事的持續(xù)時間。如果故事超過一天,劃分該故事,重新投票。
要熟練使用這方法,需要一些反復試驗和實踐。可以讓開發(fā)人員使用時間跟蹤來詳細說明每個故事所花費的時間,這也是衡量每個故事所花費的實際時間和驗證估算的好方法。進行一次計劃撲克之前,可以查看之前估算的值,并將其用作調(diào)整未來估算的參考。一些項目管理軟件,如Jira,內(nèi)置時間跟蹤功能,可以用來做評估和參考。
良好的測試
編寫好的測試用例有很有幫助。一方面可以用這些用例確保代碼實現(xiàn)它應(yīng)該做的事情。如果有好的測試結(jié)果,則很可能代碼有效。但是,在將代碼提交給PR之前,不能用它作為線上運行的版本。在QA環(huán)境和運維試運行環(huán)境中運行驗證代碼可以發(fā)現(xiàn)由環(huán)境不同或未經(jīng)測試的錯誤導致的錯誤。
測試即文檔
經(jīng)驗豐富的開發(fā)人員會首先查看用戶故事,并為其編寫驗收測試,用來作為開發(fā)的開始。這也是倡導良好用戶故事的原因,因此開發(fā)人員可以編寫好的測試并最終產(chǎn)生良好的PR。
當另一位開發(fā)人員開始審查某人編寫的代碼時,如果他們可以查看測試,查看此PR涵蓋的內(nèi)容,會很有幫助。許多測試框架,例如RSpec,也允許測試打印出預期的期望,以說明正在發(fā)生的事情。下面是一個RSpec驗收測試示例。
審查代碼的開發(fā)人員將立即看到此PR包含允許用戶創(chuàng)建窗口小部件的變化。運行此測試的輸出如下所示。失敗的測試將顯示為紅色。
當審查該PR時,這也允許開發(fā)人員審查代碼以仔細檢查是否已滿足和測試用戶故事的所有需求,或者此PR的范圍是否超出原始用戶故事。
高可讀性代碼
編寫高可讀性的代碼將產(chǎn)生更好的PR。如果代碼易于閱讀,則意味著它也很容易查看。高可讀的代碼可縮短審查時間,并降低審查人員和開發(fā)人反復溝通的可能性。
代碼注釋
通常代碼需要額外的幫助來解釋我們?yōu)槭裁催@樣寫??梢酝ㄟ^編寫描述性方法/函數(shù)和變量名來解決,以使代碼更口語化。另一種流行的解決方案是使用代碼注釋來解釋代碼正在做什么。
代碼注釋有拆分視圖。有些團隊鼓勵自由使用代碼注釋,而其他團隊則倡導純代碼,消除過多的注釋。當考慮是否要添加注釋來時,可以考慮使代碼更人性化,自具說明。必要的情況下,再添加評論可,以幫助其他閱讀代碼的人。
比如上圖中g(shù)olang序列化的示例代碼,去掉注釋,函數(shù)功能也是一目了然的。
代碼注釋標簽
使用代碼注釋標記(如TODO或FIXME)來解釋注釋的性質(zhì)以及為什么將它放在首位可能更具描述性,如果使用注釋來解釋代碼,則在注釋前加上TODO來改進代碼,可以審閱人及其他提供改進的人來解釋意圖。
良好的commits
編寫好的git commit消息允許其他人瀏覽分支的歷史記錄并了解所執(zhí)行的操作。做到這點,需要小而頻繁的提交。理想情況下,提交應(yīng)包含完整的,獨立的更改。開發(fā)人員可以按需cherry pick或回滾commits。對于大型提交或許多"開發(fā)進行時" 的不完全commits,很難實現(xiàn)此類操作。
在編寫commit消息時,一定要堅持團隊的約定高于其他任何內(nèi)容。要編寫有意義的commit消息,好的實踐是,在消息前添加動詞,例如"增加","刪除"或"修復",然后是所做的內(nèi)容。力求簡潔和簡單,不要害怕在信息中提供更多信息。下面是一些好的實例:
添加管理面板的登錄頁面
更改路由以指向新的登錄頁面
刪除舊的登錄頁面
有些團隊喜歡在合并之前將分支squash為單個提交。關(guān)于這一點的好處是沖突的合并會更容易處理,并且commit歷史更加簡潔。但是這樣一來,會丟失掉大量的commit信息。如果一個團隊擅長做一些小的,頻繁的PR,這是良好的實踐。
Pull request流程
大多數(shù)團隊都有某種PR標準流程來組織PR并確保記錄所有內(nèi)容。一個實踐流程如下:
1.手動測試運行代碼以確保其無錯有效。
2.確保測試所有變化。
3.給PR添加標簽。
4.更新用戶故事的狀態(tài)并鏈接到PR。
5.在PR中添加對用戶故事的鏈接。
6.如果不能自動實現(xiàn),手動更新變化日志。
7.提交PR,請求審閱者進行審查。
根據(jù)團隊的工作流程,該步驟可能會很長。一些也可以實現(xiàn)自動化,加快流程完成。對于必須手動的執(zhí)行的,提供參考流程清單會很有幫助。
GitHub/Gitlab 的PR描述支持交互式清單和模板,這次以前的文章中蟲蟲寫過,關(guān)注蟲蟲,可以瀏覽。還可以在團隊的項目管理軟件中該流程建模,這樣可以和其他項目/開發(fā)管理(比如JIRA,禪道等)的審批、消息流程集成。