背景:
項目使用protobuf作為socket傳輸數據的序列化協議 數據對象的定義時 使用了很多枚舉類型
人物:
這部分代碼經手應該超過3位以上程序員
起因:
為了豐富聊天內容形態 增加了新的消息類型(嫌原單圖展示死板 增加了多圖合並展示的消息類型)
經過:
正常的開發、提測, dang!!發現老版本在進入聊天界面時會必先崩潰 排查發現原因
protobuf 對象生成的java對應的代碼中 舊版本不認識新版本數據 導致枚舉類型的值為 UNRECOGNIZED(-1)
舊代碼中通過getNumber()獲取對應值的時候直接拋出異常(方法定義中並沒有聲明) IllegalArgumentException("Can't get the number of an unknown enum value.");
結果:
很明顯 舊版本不能兼容新加的類型
解決:
其實很多方法可以解決這個問題
其中比較理想的是
如果項目之前引入熱修復的話 這里打個補丁 改一下代碼(可惜沒如果)
服務器端增加客戶端版本判定 將新類型轉成舊類型處理 不過 如果處理不當可能造成丟圖(沒辦法對我們來說這是最好的結果了)
還有相對不理想的
比如先給舊版本來一個小升級 解決這個問題(要等用戶大量升級小版本之后才能上最新版本 周期比較長)
舊版本強制升級(會造成一定量的用戶流失)
思考:
其實這個問題很好排查也很好解決 但是卻能留給我一些思考
1 如果protobuf生成的代碼 能將拋出的異常寫在方法聲明里 其實就可以提醒調用者注意這個部分的問題
2 如果當初寫這個對象轉換邏輯的人 在獲取枚舉對應值的時候發現生成代碼的問題 使用get*Value()而不是get*().getNumber()
3 早點引入熱修復也是
4 如果項目組定期組織代碼review 也許也能發現問題
記:
即便是大公司 較成熟的協議 使用起來也可能存在隱患
掉過越多坑的程序員 越有價值
早為未來做打算
閑暇時間多翻翻之前的(無論是誰寫的)代碼 即便是互相挑刺 對項目來講 是好事情