帶團隊後的日常(三)

一、日常問題

1)BUG反饋

  參與制訂業務方的BUG規範,業務方最近投訴我們技術部,在飛書群中提出BUG後,技術部沒有人響應,認為我們的態度太冷漠。

  後面我就提出任何看到的人,只要知道是誰負責的,就@那個人,大家都不要客氣,這是第一步。

  第二步就是業務方建條BUG單,方便之後的追蹤和回溯,當然,如果條件不允許或者不會建,那就讓測試組的人創建單子。

  後面其他人補充了第三步,那就是測試組的人會檢查這條單子是否重複,若重複就直接關閉。

  我感覺這個流程中有個瓶頸,那就是測試組的人需要關注着BUG單,需要損耗一點他們組的人力。

2)量化效率

  經常會收到各類Web需求的優化,改完測試完後就上線,一套流水線,我們只是其中的一環。

  雖然我們知道這是用來提升他們效率的,但是無法直接量化提升的效率,這是我最近在思考的問題。

  量化後,就能知道自己為他們的工作帶來的多大的價值,其實也可以提升我們的工作積極性和參與度。

  經過驗證後,發現可以通過之前搭建的監控系統的通信和點擊日誌,來一步步地計算出耗時,而通過優化前後的兩個耗時,就能得出效率值。

  當然,並不是所有的效率提升都能計算出來,還有很多需要業務方的反饋才能得到。

3)協調人

  當需要多端聯合解決問題時,如果沒有協調人從中穿針引線,強力push的話,那麼問題解決將會異常緩慢、效率低下。當無人主動承擔時,可由自己擔任。

  這兩天客服反饋用戶充值後,虛擬幣沒有到賬,於是查看後台發現是很多是未支付狀態,聯繫財務進入第三方支付後台,導出已支付訂單。

  將兩邊導出的數據做Excel比對,篩選出了50多張有問題的訂單。發現訂單在特定的時間段內(0點~6點之間)出現了問題,根據之前畫的一張問題畫像大致可以推斷出是第三庫的問題。

  於是在日誌中搜索他們要回調的接口,發現在那段時間裏一條都沒有。馬上再去聯繫那邊的商務,將問題拋給他們。

  這裡必須得吐槽下他們的工作效率實在太低,12點50分反饋,一直到17點才說是總部系統問題,期間還得打電話給他們催促。

  那隻能我們自救了,聯繫客服諮詢補單流程,再去查看補單以及審核的代碼。並且查看回調接口的邏輯,以免二次補發。

  一切就緒後,和財務一起整理補單需要的數據,再聯繫當時的運營(他也充值了沒收到虛擬幣),測試一條,一切正常後,再讓客服和財務處理剩餘的問題訂單。

  這樣來來回回,也搞了大概一天的時間。

4)控制需求

  控制需求並不是為了逃避責任,恰恰是為了更好地盡責,好鋼用在刀刃上。

  最近接到一個需求,是在隱私條款更新後,要在APP中彈個框告訴用戶。那麼這裡就會涉及三端:客戶端、服務端和前端。業務方希望能在後台開放一個可視化頁面供他們操作,服務端希望由我們提供數據的寫入,他們直接讀取(我們組有操控數據庫的權限)。客戶端通過讀取服務端的接口來做相應地提示。

  理想情況下是做一張為此功能服務的新頁面,但情況並不理想。需要控制下需求,功能要做,但實現方式需要商量,而且要給出明確的解釋。

  1. 衡量後認為做新頁面的性價比太低,不僅功能太單一,而且還要做兩套(服務兩個APP)。在目前的管理後台中有很多這樣服務某個功能而已經廢棄的頁面,其實完全可以先預判一下,值不值得做或者有什麼更合適的替代方案。
  2. 目前的人力資源捉襟見肘,優先級很高的需求正在進行中,若做新頁面,時間成本我們無法負擔。
  3. 那些頁面被廢棄除了公司的客觀原因之外,還有人為原因,新來的運營都不知道有這些功能,久而久之就用其他方式替代了,他們的交接有嚴重的問題。
  4. 在後台為了應付這類動態配置,開發了一套通用配置系統,可以在此處配置參數,這是一段JSON格式的數據,對運營並不友好。因為更新不會頻繁,所以若要更新數據,可由測試、產品或我們組的人代勞。
  5. 服務端若不想讀取我們的數據庫,則可以提供內部接口,幫他們讀取。亦或者他們自己讀庫,緩存起來。

  由通用配置來實現該需求是一個折中的方案,既能維持我們自己的開發進度,也不會影響產品的發版。綜合考量後,決定採取此方案,當然在實際使用中還會碰到些問題,這些都好解決。

  在項目的開發中會碰到很多這樣的場景,而且我相信基本上開發時間人力資源都會很緊張。為了讓自己不被動,需要想辦法控制住需求,控制的方式有多種,例如提前未雨綢繆實現可復用的技術方案和系統,分析出需求存在的矛盾點引導產品順着自己的思路走,讓出現衝突的業務方自己PK先做勝的那方需求。

5)溝通細節

  在跨組聯調之前一定要溝通好細節,不能粗粗的一過。要細到數據庫表的一個字段都沒有歧義,否則很容易會在陰溝裡翻船。

  之前要做一個加密音頻的功能,客戶端播放加密的音頻文件,服務端將這些文件下發給客戶端,後台管理系統將原始音頻上傳到加密平台。

  在一開始的會議時討論的方案是從我們這邊拿到加密後的文件地址,然後再更新數據庫表的一個新字段,服務端讀取此字段,最後下發給客戶端。

  但是中途他們的實現方案發生了改變,沒有通知到我這邊(信息不對稱),導致在發生聯調時數據不匹配。

  我在中途也想當然的以為更新加密地址就行,沒有對清楚需求。好在,服務端需要的數據在我的代碼中已經讀取到,只要換個參數就能完成聯調。不過下次真的是要好好捋一捋了。

  經過這次事件後,團隊協作規範中也要補充一條確認細節,以免再次發生這類失誤。

二、工作優化

1)Node服務升級

  Node服務升級失敗,本來想從 v8升級到 v10,但出現一個時區問題,無法解決,只得回退,本來打算用代理轉發的方式,後來想想這樣太繞了,沒必要。

  於是新建一個項目,分配獨立域名,運用TS語言,依託框架 egg.js,它的優勢包括:

  • 基於KOA,定製上層框架的能力。
  • 按照約定進行開發,奉行『約定優於配置』,團隊協作成本低。
  • 穩定,功能完善,文檔齊全,適合多種場景。
  • 支持TypeScript,提供了應用層開發規範,有了強類型約束和靜態檢查,可以降低軟件腐化的速度。
  • 支持代碼的聲明索引,不用再通過項目搜索來查找變量或方法的聲明處了。
  • 讓成員使用新技術新語法的,開闢新的成長空間,並與當前主流接軌。

  具體遷移步驟包括:

  • 引入JWT(egg-jwt),自定義JWT驗證中間件。
  • MySQL,MongoDB,Redis的連接和配置,引入egg專用插件,egg-sequelizeegg-mongooseegg-redis
  • 日誌的配置,包括自定義的請求日誌,數據庫查詢語句日誌(包括MySQL和MongoDB),內部請求通信日誌。
  • 將config目錄中的文件全部上傳到配置服務器中,保留 config.default.ts、config.{env}.ts和plugin.ts文件。
  • 在服務器中部署時需要先將TS文件編譯成JS文件,再執行start命令,並且傳遞環境參數。
  • 當sequelize版本6以上時,要求MySQL最低版本得是5.7,但目前線上的版本都是5.6,因此無法更改,得想辦法將egg-sequelize降配。
  • 在部署Node性能監控平台的時候也遇到了點麻煩,搜集不到監控數據,主要是運維配置的問題,前前後後搞了好幾天。

2)問題畫像圖

  將問題和技術點通過一張圖聯繫起來,可快速而有序地定位到問題的出處。

  統計每周遇到的BUG,瀏覽公司的BUG單平台,再將BUG抽象成問題畫像圖,按照「問題 –> 平台 –> 技術點」的方式梳理。

  Web端的很多業務都是各類短期活動,並非階段性的,因此在提煉的時候比較難以抽象共性,很多問題不具代表性。

  下圖是經過整理後的問題畫像圖。

  

  例如遇到頁面空白,那有可能是JSON.parse()數據解析遇到了問題,也可能是語法編譯後瀏覽器不支持,亦或者是接口504了得不到渲染數據等等。

  最後推薦一款開源的辦公軟件:LibreOffice,支持PPT、Word、Draw,本次的圖就是用該軟件製作的,它也支持各個平台,包括mac、windows和linux。

3)疑難雜症

  為每個項目增加疑難雜症的wiki,記錄花費了很多時間修復或常見問題的排查過程。

  目的是在下次遇到時,不用再重頭開始,減少修復時間,提升工作效率。既能間接地補充文檔,也能梳理舊邏輯。

  像之前的那些充值問題,就可以記錄在案,下次遇到類似問題,都可以此為參考。

  在休息時間,線上遇到BUG,若找不到相關人員或相關人員不方便操作電腦,那麼就能讓其他人員按照記錄的排查步驟,一步步地修復,盡量做到一個問題可多人修復。

4)前後端分離

  這是我進公司後一直在推進的一件事,但是得不到服務端的支持,所以一直擱置着。最近遇到個站內信發送的問題,才將此問題又提上了日程。

  目前服務端與我們組分工的職責界線很模糊,很容易發生衝突,所以我才一直致力於前後端分離。

  我們組維護着一個比較龐大的管理後台,它連接的數據庫多達8個,但其中只有一個MySQL和MongoDB才是我們組維護的,其他都是與業務相關的數據庫。

  我的設想是除了自己維護的系統之外,其他邏輯都應通過調用接口的方式與後端交互(包括增刪改查),我們組需要與服務端的數據庫表以及緩存做隔離。

  前端監控系統,開發者工具,後台賬戶管理等是我們組的自有系統,仍然由我們來維護。

  討論後的方案:

  • 未來管理後台數據請求直接走服務端接口,服務端提供一個新的跨域域名。
  • 保留管理後台的鑒權和權限功能,在登錄時將用戶的權限傳輸給服務端。
  • 服務端的鑒權和權限驗證與當前保持一致。
  • 日誌保存在MongoDB中,需將其與服務端隔離,開放操作日誌接口,供服務端調用,統一日誌格式。

  H5活動會走一個Node.js提供的中間層服務,通過它再調用服務端接口。

  主流的前後端分離是前端只做頁面交互,數據處理全由服務端提供接口,目前在我們公司有很多現實問題使得難以這麼搞。

  折中的方案是我們自己維護Node中間層,業務數據從服務端讀取。但如果是一個大活動,會有很大並發量的,那麼就不走中間層,全部讀取服務端接口。

  討論後的方案:

  • 未來還是要走分離線路,但目前服務端對活動這塊還是空白,需要有個搭建過程。
  • 先從幾個小活動開始,嘗試着分離,穩步前進。

5)單元測試

  在公司的幾個項目中,其實早就將單元測試的環境搭建完成,但一直沒有啟用。

  不做的理由一大堆,諸如:接口就是簡單的增刪改查,讓測試組做功能測試就行了;工期太緊,來不及做;異步通信需要有後台接口等。

  後面讀了篇專欄才了解到,單元測試是不需要依賴外部服務的,也就是說不需要連接數據庫,調用內部接口、讀取本地文件等。

  藉助單元測試框架庫(例如sinon.js),能夠模擬出那部分外部服務,從而就能完成各個功能的單元測試。

  結合當前項目的實際情況,我並不要求組內成員覆蓋率達到一個數字,只需要對那些比較核心和複雜的業務邏輯加上單元測試即可。

  我在使用時,會修改源碼,讓源碼更容易測試,以函數或方法作為一個單元,在測試的過程中,發現了些潛在的問題,併當場修復,省得測試的時候出現而返工。

6)Code Review

  雖然每周都會開個周會,但Code Review還從未做過,根本原因還是因為沒有認識到Code Review的價值。

  最近有個比較重要的年中活動,所以在提測之前先做了簡單的Code Review。

  在這個過程中糾正了一些影響思路和視覺的寫法,例如 if 的一個判斷分支要一百多行,另一個分支就兩行,那可以將短的分支移到上面加個 return,長分支轉移到後面即可。

  還找到了幾個聯調錯誤,避免在測試階段才發現,造成不必要的返工,影響測試進度。

7)B計劃

  軟件的風險管理是必須要考慮的,在項目的開發階段,就要提前考慮線上出現狀況時的B計劃,未雨綢繆,防患於未來。

  例如定時任務中會計算榜單,當計算出現錯誤時,該如何快速恢復榜單數據?補救措施是提前備好腳本,在後台管理系統中留執行該腳本的入口。

  還例如會員充值從銀聯支付替換為微信公眾號支付,在試運行期間需要保留一個可以在兩者之間切換的開關,當出現問題時,可快速應對。