调试的第一原则

      程序难免会出现各种各样的问题,对于一般的问题,只要借助于调试器、日志,很快也可以解决,对于一些特殊的情况,比方非必现问题,问题现象多变,或者出现问题所在的模块庞大而且我们对其只是一知半解,要定位到问题往往要耗费大量的时间。

      笔者在前几日,遇到一问题,问题现象如此:在客户端每进行一次文件分享操作,文件的分享记录数会变为原来的两倍。

      笔者在接到该问题后,觉得该问题应该很好排查,毕竟只是一个必现的问题,当排查了文件的分享接口后,发现接口的每个数据项都没有问题,才意识到该问题并没有那么简单。而后,笔者意识到可能并不是分享接口的问题,可能是流程上的问题(因为笔者是后端开发,该问题是帮客户端人员修改,对客户端流程并不熟悉)。于是,笔者在后端thrift接口的分发函数中加入日志,这样前端每次调用后端的接口就可以获取到一条日志,可以清晰看到前端的控制逻辑。果不其然,对比客户端在正常的情况,出现该问题的时候,没有调用一个取消分享的接口,笔者甚是欣喜,以为已经找到根因,把没有调用取消分享的接口解决后,笔者再次测试,发现问题还是没有解决,多次分享后,分享的记录数还是会出现不断递增的情况,有时是正常的,有时会突然增加多个。笔者在前端和后端都进行了调试,使用vs的调试器在客户端获取取消分享接口和分享接口,两个接口参数是正常的。笔者怀疑会不会是编码的问题,于是乎又在后端打了接口传的数据(十六进制数据)的日志,但是发现也没有问题,问题一下子就进入了死胡同,没有任何头绪。

       查到这里,笔者一直纠结是:对比正常的情况,数据没有任何变化,为什么会出现不一样的现象?在纠结中,不知不觉已经到了晚上九点多,疲劳夹杂排查不出问题苦恼愈感疲惫,于是就放弃继续排查,把问题留到明天解决。

       到了第二天,由于前一天一直在客户端排查无果,只能转变方向,从后端开始排查起。于是笔者在插入分享记录的操作中,加入日志,发现后端确实会存在插入多条分享记录的情况,顺着这条线索,很快就排查到是客户端在thrift接口中的文件记录参数传递了多个文件,正常这里只能是一个文件记录;很快,笔者又排查到是原先编码客户端的开发人员,使用了一个全局对象的成员变量传递给了文件分享接口,而该成员变量的值在调用接口前没有清除,导致每做一次操作,都会增加一个新的文件数据,所以第N次操作,就会增加N个分享记录。而此时,由于笔者已经修改了流程上要先取消分享记录的问题,所以问题就表现为第N次操作,会增加N-1个记录,再加上原先流程上的问题,每次操作会增加的记录数就是(N-1) + 1 = N,至此问题才彻底解决。

        事后,反思该问题,一个必现的问题,为何沦落到要处理一天多,在客户端调试的时候,应该早可以发现是客户端传递的参数文件数不正确才对,笔者这才意识到,是笔者在调试客户端的过程中,一直都只调试第一次操作,而第一次操作传递的文件个数就是1,恰好这个参数就是没有问题的,那再看多少次参数,都还是没能发现任何问题,而笔者自己为什么每次都只看第一次操作的参数呢?调试了那么多次,怎么没有去看第二次操作的参数,第三次操作的参数,不就一下子解决问题了?因为第二次,第三次操作的调试要比第一次操作的调试要麻烦,潜意识中也默认第一次和后面的调试都是一样的,所以才犯了该错误。我们要做的是在对问题调试之前,就要在意识中建立对该问题的逻辑认识,才能避免自己再犯同样的错误。

         比方在这个问题中,我们要清楚的意识到,该问题的现象是什么?和什么因素有关?一开始我们是可以知道的,第一次操作是增加一个分享记录,第二次是两个,第三次是三个,那么我们要清楚的把操作次数列入到调试的范畴中,我们必须考虑操作次数对问题的影响,才可以避免笔者在前面只调试第一次的致命错误,第一次操作的数据是看不出任何问题的。而对于其他的情况,比方问题出现的时间,顺序等等,也都应该被列入到考察的因素。这才是调试问题的第一原则!

Guess you like

Origin blog.csdn.net/lyj22/article/details/106760182
Recommended