美文网首页
Android客户端如何规避服务端数据格式错误导致的crash问

Android客户端如何规避服务端数据格式错误导致的crash问

作者: yoyo_zyx | 来源:发表于2016-09-03 17:05 被阅读435次

    一、背景

    场景如下:
    应用新增了一个功能,升级了版本,客户端静默升级后,从桌面打开应用竟然出现了直接闪退、奔溃的现象!

    测试:不能忍,无论如何,这是不允许存在的现象,怎么可以出现如此严重的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

    阅读原文

    相关文章

      网友评论

          本文标题:Android客户端如何规避服务端数据格式错误导致的crash问

          本文链接:https://www.haomeiwen.com/subject/vvokettx.html