一、背景
场景如下:
应用新增了一个功能,升级了版本,客户端静默升级后,从桌面打开应用竟然出现了直接闪退、奔溃的现象!
测试:不能忍,无论如何,这是不允许存在的现象,怎么可以出现如此严重的bug!
服务端开发:这是由于新增的数据字段,没有被赋予正确格式的原因导致,测试只要在服务端推送数据时修改为正确的格式即可解决。
测试:服务端并没有约定说一定要填入那种格式的数据,我填入“非法数据”时,并没有被拒绝。我不管你们是怎么实现的,总之,不应该在引入新功能的时候发生如此严重的必现bug。
服务端开发:那在客户端那边加个try catch,规避这种crash的严重问题。
客户端开发:客户端不像服务端,不是所有的问题都是用try catch来解决就可以了,加try catch严重影响了效率问题。就不能在服务端那边控制一下,只传特定格式的数据吗?
二、分析
服务端发送给客户端的数据,由于不是指定格式的数据,导致客户端解析时出现问题,导致应用奔溃。
测试认为服务端传入的数据应该可以是任意的,而客户端必须要有容错机制,一定不能出现这种严重的crash问题。
而服务端为什么不控制一下,数据只能设置为指定格式数据,否则弹出非法数据警告提示呢?对服务端理解尚浅,不理解其中的原理,暂且就认为这是有一定道理的吧。
那么,我们就来探讨一下,如何从客户端出发,添加数据的容错机制吧。
前面开发建议,添加try catch,若接收到的数据为非法数据,则返回默认值。的确,这是解决问题的一种方案,至少,它能确保,不会因为数据格式问题导致crash的不能忍问题。
然而,try catch却要付出时间的代价。若代码中大量使用try catch来解决问题,一是代码不够简洁,二是若数据格式确实是非法的,则增加时间消耗。
为什么不考虑在做数据格式转换之前,先做一个数据格式检查,若为指定格式才对数据进行转换呢?这样一来,至少在代码简洁度上是更加有保障的。
为了对比以上两种方法的效率问题,我们用数据说话!
三、论证
1. 目的:
对比try catch机制与先检查格式再转换的执行效率
2. 准备:
A. 利用junit单元测试来测试代码块的执行时间,由于代码的执行都是闪速的,而junit测试也包含了一些初始化的准备时间,为了更加精确地统计代码的执行时间,采用循环100次取平均值及纳秒级别的时间差来做测试。
B. 从所在项目的情况来看,最主要问题存在于转化为long型时出错上,下一步的案例均基于long型数据的转化来设计,且基本上为项目中常用到的一些情况进行对比。
3. 测试案例编写:
A. 直接得到的非法字符串转化为long型
非法字符串强制转换
B. 从SharedPrefrence中获取字段非long型强制转化为long型
获取字段后强制转换
C. 直接得到的纯数字String转化为long型
纯数字转换
4. 结果对比:
将上步中的案例执行多次,进行耗时对比,为避免偶然性,进行了多次比较,以下随机截取了5次执行结果:从结果可以看出,虽然每次的执行耗时都略有不同,但相同的是:不管是在正确格式情况下还是非法数据强制转化,tryCatch的耗时都比通过正则表达式先判断数据格式再转换,平均多耗时1ms左右(执行100次的情况下),即执行1次约多耗时0.01ms 。
结果1 结果2 结果3 结果4 结果5四、结论
从第三部分的论证过程可以看出,先通过正则表达式判断后再做数据处理稍微比tryCatch方式高效率,虽然0.01ms是一个几乎可以忽略不计的时间,但编码是一种习惯、优秀也是一种习惯,不只是简单地用tryCatch来规避crash问题,而是找到问题的本质,并择优采取更合适的方式解决问题,这样不是更好吗?同时,尽可能避免tryCatch的使用,在一定程度上也能够提高代码的简洁度。
五、代码
文中涉及代码链接:GitHub
网友评论