在一個技術群里,遇到一個網友提了一個問題,這種場景我曾經遇到過,提供一種解法,這需要去構建,但是如果需要的是【立即有效】的解法,可能不存在。這個方式,最小的情況下3人的迷你小team就可以實施,所以可以說是一個面向小企業的團隊的介紹。麻雀雖小,五臟俱全,要用好的調度、原則、自動化工具帶來效率和自由。
一個網友的問題:
為了趕時間,dev和pub並行,我一天發五六版,不是在發版就是在發版的路上,就是發版太頻繁 導致我沒時間開發。
問題其實在於業務方,業務為了給領導看,我軟件沒做好,他們就用,我現在一邊開發一邊維護一個線上版本,他們還在往里錄入數據,導致的結果就是,問題要馬上解決,解決后要發版本然后我還在開發。
怎么辦?
首先,源代碼的分支,和部署的環境需要隔離。
- 源代碼要有不同分支,發布的分支上,只修復BUG。開發的分支是新功能。
- 部署的環境要有三套,一套是開發的,一套是測試的,一套是正式的。
- 請使用好的git版本線查看工具,例如sublimemerge
你在Git的開發分支上開發新功能,部署的時候只能部署到開發環境。
你在Git的發布分支上修復BUG,部署的時候先部署到測試環境測試,測試驗證通過了再發布到正式環境。
其次,工具鏈要做成自動化:
- 配置不同環境的部署信息,例如用JSON配置好某個環境的所有依賴的配置信息+賬號密碼,這個配置文件不提交到git倉庫。
- 編寫部署的腳本,一鍵部署某個Git分支的當前代碼到某個部署環境上去。
- 如果進一步,可以將自動化部署配置到內部的持續集成(CI)工具上,但是,這要仔細考慮密碼的存儲問題。確保安全。此處可以進一步考慮。
接着,問題應該有issue管理軟件整理
- 應該用一個issue管理軟件管理客戶提交的問題。例如,redmine、jira、teambition等。
- 在issue管理軟件上創建不同的分支標記,例如1.1.1表示發布的了版本,1.1.2表示正在開發新功能的內部版本。
- 客戶反饋的問題,應該添加到1.1.1版本的issue列表下。內部新開發功能的問題應該放在1.1.2版本上。
然后,人員上調整下。
- 配置一個專門的人負責和對方對接,開發不要直接和對方對接,讓那個人匯總客戶的問題,再提交到issue管理器軟件里的1.1.1上。
- 開發如果對某些issue有問題,應該直接給這個專門負責對接的人反饋,由他/她統一跟對方協商。
- 開發人員處於「開發密集型」,無法同時應付和對方的對接和反饋問題上,這樣是沒法開發的。
還有,如何修復issue
- 測試需要在內部的測試環境上按照對方提交的操作步驟重現(reproduct)問題。因此,對接人需要與對方確認清楚問題出現的必要環境,是否是必現的,還是偶發的。
- 因此,需要內部搭建和對方盡量一致的測試環境,測試環境應該與開發環境能並行工作,避免開發人員占用資源時,測試無法進行測試。
- issue重現后,開發介入診斷問題,分析問題,找到原因,在issue管理軟件里應該寫下原因,如果原因不明,就不是【修復】,而只是【猜測】。
- 修復后,應該更改issue的狀態,測試介入回歸測試。
- 測試通過后,與對方溝通,確認發布到測試環境。對方在測試環境下驗證通過確認后,可以發布到正式環境。
- issue列表多的時候,要標記不同的【優先級】,如果一個問題處理在一半中,如果估計時間不是阻塞的,要處理完再處理其他問題,如果是阻塞的,就要在Git上創建一個分支去處理它,這樣如果不能立刻修復,可以暫時切出去修復其他更容易修復的問題。
- 如果issue很多,開發人員應該不只一個,在能力允許的范圍內,盡可能的把issue分發給對應的人修復,讓開發並行起來。
最后,控制周期
- 很多issue提交后,對接人員整理的issue列表,要根據2周為單位能處理多少issue,根據優先級分類,整理出2周為周期的里程碑節點,確認2周內主要解決這些issue,其他的必須延后。
- 這個分類和划分可能一開始不准確,但是要堅持這么做,多個里程碑后就會獲得足夠的經驗來支撐作出更合理的控制。
- 盡量控制開發周期,不能用掉所有時間,例如在2/4-3/4時間內完成開發,預留內部測試的時間。
如果,項目的某些部分有嚴重的技術債務。技術債務一般是指:
- 設計上的某些錯誤,導致問題不斷;
- 或者構架上的不合理,導致某些功能的增加非常費勁,成了瓶頸;
- 或者代碼實現質量上出現嚴重的意大利面條,不論是BUG的追蹤分析還是功能的增加都異常困難,或者會拆東牆補西牆
- 那么此時應該申請一個2-3周的【重構里程碑】,償還技術債務。
- 償還技術債務不是客戶提的需求,但是在必要的時候,它就是必要的,軟件最終要有質量才能提供穩定的現有功能,以及可維護的狀態。
考慮小工具。
- 項目中,應該提供一組便利的工具,這些工具,每個用來獨立的診斷一個特定的問題是否能正常工作。這在排除問題的過程中有用,並且能節省你的時間。
- 這些工具應該能方便的運行,例如做成windows下的bat運行,*nix上的sh腳本運行。
- 提供切換到【調試模式】和【非調試模式】的便捷工具、菜單等。在【調試模式】里,應該可以方便的查看日志。如果是UI程序,調試模式下,應該可以在UI上展示一些關鍵的診斷信息。注意這里說的不是在IDE里的【調試】,而是發布后運行時可切換。
編寫良好的日志。
- 程序代碼的日志應該根據不同模塊,提編寫同Tag標記的日志行。例如[module1][module2]…,這樣便於你在查看日志時通過Tag來搜索。
- 如果某個模塊A【向下】調用了模塊B,那么A的日志里應該包含
[tagb][taga]
,這樣B模塊可以看到自己內部的日志以及自己被A調用的日志。A模塊可以看到自己的日志,以及自己調用B的日志。如果A同時調用了C,[tagc][taga]
將只會看到A和C之間有關系的日志。諸如此類。 - 嚴格區分日志級別,一般來說,WARN、INFO、ERROR、三種是重要的區分。更簡化的,INFO和ERROR兩種區分就能覆蓋大部分問題。
- 程序的內部充滿了不同的控制邏輯,一般來說if-else及其嵌套,應該在所有重要的分支里都加好日志。漏掉的那個沒寫日志的分支很可能實際出現問題,但是你的日志丟失了,無法確認問題。
- 如果是一個循環,或者一個反復執行的定時器,此類日志要小心控制。同樣的日志太多可能影響性能,也可能不利於診斷。
- 日志庫應該支持日志寫文件,以及日志文件個數的控制,超出配置的大小后,要循環覆蓋。
- 應該提供【上傳日志】的能力,當現場出現問題時,能上傳日志到日志服務器。應該提供開發工具【下載日志】,下載日志去分析問題。
- 請使用合適的工具分析日志。例如,合理使用*nix下的cat/grep等命令過濾日志。如果是使用編輯器,一種方式是用cat把所有日志寫入到一個日志文件,用sublime text打開,裝一個它的擴展,使得你可以方便的在[ctrl+k][ctrl+s]后,輸入關鍵字,sublime text將自動將過濾的日志在一個新的臨時文件標簽頁里打開,這很方便做各種過濾和分析。可以說是grep的便利ui版。
項目是可以迭代的,這是基於:
- 如果我們知道一些已知【事實數據】,在這些【事實數據】支撐下,我們能做出假設,編寫程序。
- 如果程序不能良好運行,那么它可能是我們對【事實數據】的分析不周密,漏掉了分支,這種是可以修復的。修復之后,這個程序處於【比之前更正確】的狀態,有序的做這個過程,可以讓程序對已知的【事實數據】的分支覆蓋率達到足夠的程度,例如98%。
- 如果出現新的【事實數據】,那么原來的覆蓋率就降低了,新數據會對原來的假設有交叉,交叉的那些地方要重新考慮。這需要一個過程去再次達到平衡。
- 在這個過程中,程序運行所依賴環境的事實數據,以及基於此所作出的分支,達到了一定程度后,測試覆蓋率足夠后,例如98%,程序就應該處於98%情況下可以確定能正確運行。如果出現了意外的不在考慮內的新事實數據,程序有很小的概率會不正確工作。
- 在這種對數據足夠的理解、分支的足夠的分析、測試的足夠覆蓋率下。程序可以被【有信心】的發布。
這個過程,本身就是一個程序,如果要讓整個過程有效率、有序收斂,越是issue來的猛烈,越要遵守原則,守住底線。
—end—