背景:
项目使用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 也许也能发现问题
记:
即便是大公司 较成熟的协议 使用起来也可能存在隐患
掉过越多坑的程序员 越有价值
早为未来做打算
闲暇时间多翻翻之前的(无论是谁写的)代码 即便是互相挑刺 对项目来讲 是好事情