今天测试同学为了赶进度,加班去测试我的功能。

因为我的代码都写完了,也没有陪测的必要,所以就没去了~

下午第一个问题提过来,根据经验,这个应该是测试的逻辑问题,最后他自己也发现了。

过了一会,提了第二个问题,说是本该命中条件进入某个等级的,没有进入,跳到下个等级了。

拥有几年开发经验的我,此时当然不会说“我的代码没有bug,你再试一遍”。说出这句话的成本近乎为0,但是脸要是打起来,那是真的疼啊~~~

脑海中快速思考下,发现不是靠脑海中演练就能给出答案的,于是乖乖的,掀开电脑盖,指纹解锁,连接VPN,查看日志,一气呵成。

因为这个需求指标巨多,流程相对较长,所以我已经在代码的关键节点打印了数据日志。

所以,想要的信息,日志都是有的。只是,仔细看了下日志的数据,又认真的比对了测试同学给出的测试数据。讲道理,这确实应该命中。

可是事实就是没有命中,于是开始排查。

查看配置中心

因为指标多,每个指标都有阈值,首先第一反应当时是别人的锅,所以我不放心的看了看是不是测试同学调整的参数阈值有问题,看完后,我有点愧疚,这不是测试同学的问题,指标都对上了。

但是还是不死心,是不是没有按照我给他说的要点选热加载选项,导致指标没生效。想到这里,我有点小激动,没错,我又可以表面轻描淡写,实则内心激动的告诉他真相:你这个是配置忘记勾选了吧(怎么回事,又是你的问题)

想归想,想要趾高气昂就要有底气,要底气就得拿证据。

我们的配置中心做的就是这么贴心,每一次操作都可以查看历史记录。赶紧点一下,然后截个图,甩给他。

等等,这个,没想到啊,测试同学居然这么严谨,选项勾选了。

emmm

调整策略

从日志来看,测试的数据没有问题。

从配置中心来看,配置也勾上了。

测试排除嫌疑,真相只有一个,是我的问题(自己打自己脸,下手可以轻点)。

虽然家里连上了VPN,也可以看日志、发布项目,但是本地启动服务不好使,UT也跑不通。

那只能看代码了,要知道,近朱者赤近墨者黑,找别人缺点,那是章口就莱,一莱一个准。

找自己的问题?首先得否定自己,知道自己原来也是有瑕疵的,这是多么难的事儿,但是我做到了!

为了给测试同学一个交代,我开始老老实实的研读自己的代码,企图一眼就发现自己的不足~(太南了

失策了

涉及测试点的代码逻辑也不复杂。大概过程是这样的

上游并发调用获取各个指标的当前值 -> 在规则层过滤 -> 如果命中两个规则条件则视为命中,否则未命中

于是,按照测试同学提供的两个指标以及提供的测试数据比对两个规则的阈值。

从日志来看,上游的数据是没有问题的,从数据比对来说,应该是比对通过了,但是没有命中。

于是开始仔细检查这两个规则相关的代码,以防出现,手抖把"!="写成"=="的情况。

很遗憾,在我认为比较关键的地方查看后,发现我的代码就是这么严谨,找不出任何破绽。

为了不让测试同学hang在我这个线程上划水、摸鱼,我得先释放锁:“代码看着没啥问题,你先测试其他逻辑,我再看看。”

小黄鸭救了我

我心里清楚,虽然我有一点散光,但是眼睛还没瞎。

所以即使再比对十遍八遍,肯定也还是找不到bug。

是时候换一种思路了。

上面说了,上游代码排除嫌疑,涉事代码本身排除嫌疑,当然,测试同学也排除嫌疑,更别说下游代码,下游完全不知情啊。

仔细想想,两个规则之前还有有其他代码的,虽然也是一个规则。我决定擦亮双眼,人肉找bug。

把自己当做一台没有感情的机器,一遍读这我写的工整简洁的代码,一遍计算代码的结果,再到排除嫌疑。

上游赋值没有问题!
变量初始化和结果返回没有问题!
第一个规则没有问题!

  

第一个规则没有问题!

其他初始变量赋值和返回没有问题!

然后开始过第一个规则和第二个规则之间的中间规则代码。

在方法返回的时候好像没有返回期望的值啊?!

没错,我把本来应该不管命中与否都要返回的一个变量值,只在命中的条件里赋值返回了。如果没有命中这个规则,则没有赋值,那实际上返回的是这个变量的类型默认值,也就是0,归零了!

趾高气昂只会迟到,但永远都不会缺席。

我告知测试同学,我应该知道原因了,我修复下,一会再试下,后面的“英雄事迹”就不多介绍了。

总结盘点

虽然不是什么大问题,也不是什么线上大事故。

只是想表达,几乎没有人敢说自己写的代码0bug,写完就可以上线。曾经有跟我这么承诺和标榜的人,最终都是难逃翻车和打脸的命运。

有问题,理性分析最重要,从涉及bug的方方面面,包括经手的人和代码本身,都有可能出问题。

有时候,如果发现是自己的问题,但是又迟迟找不到原因,不要一个人闷着头苦苦思索,找个同事来帮你一起找。有时候就在你准备让别人一起来看看,你开始描述问题的诡异之处,还没说完,你就突然知道了原因。不知道你遇到过没有,反正我有。

今天回过头想想,哪些被我叫来的人其实就是工具人,他们和小黄鸭无异。

什么是小黄鸭和小黄鸭调试法呢,参见百度词条

此概念是参照于一个来自《程序员修炼之道》书中的一个故事。传说中程序大师随身携带一只小黄鸭,在调试代码的时候会在桌上放上这只小黄鸭,然后详细地向鸭子解释每行代码  。
  许多程序员都有过向别人(甚至可能向完全不会编程的人)提问及解释编程问题,就在解释的过程中击中了问题的解决方案。一边阐述代码的意图一边观察它实际上的意图并做调试,这两者之间的任何不协调会变得很明显,并且更容易发现自己的错误。如果没有玩具小鸭子也可以考虑向其它东西倾诉,比如桌上的花花草草,键盘鼠标。

  

类似这样

或者这样

找不到鸭子,找同事也一样~

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

我的代码真的没有bug,稍等,先试试小黄鸭调试法的更多相关文章

  1. 转:Eric Lippert:阅读代码真的很难

    转自:http://blog.jobbole.com/438/ 相关文章 微软资深软件工程师:阅读代码真的很难(第2篇) 阅读优秀代码是提高开发人员修为的一种捷径 学会阅读源代码 如何阅读大型代码库? ...

  2. 来试试这个来自静态代码分析工具PVS Studio提供C++的小测验吧

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:来试试这个来自静态代码分析工具PVS Studio提供C++的小测验吧.

  3. [置顶] 几行代码实现ofo首页小黄人眼睛加速感应转动

    最新版的ofo 小黄车的首页小黄人眼睛随重力而转动,感觉有点炫酷,学习一下吧,以下代码是在xamarin android下实现 ofo首页效果图: xamarin android实现效果: 实现思路: ...

  4. Bug中的中的小问题编程需要注意

    Bug中的中的小问题编程需要注意 1. 关于局部变量与全局变量是否同名问题 如果参数传递的是一个数组,且全局变量与参数数据同名,则局部变量作用域中,这两个同名的数据可能会引起冲突. 如下:如果一开始是 ...

  5. 音频算法之小黄人变声 附完整C代码

    前面提及到<大话音频变声原理 附简单示例代码>与<声音变调算法PitchShift(模拟汤姆猫) 附完整C++算法实现代码> 都稍微讲过变声的原理和具体实现. 大家都知道,算法 ...

  6. FindBugs 入门——帮你减少代码中的bug数

    FindBugs 入门 FindBugs 作用 开发人员在开发了一部分代码后,可以使用FindBugs进行代码缺陷的检查.提高代码的质量,同时也可以减少测试人员给你报的bug数. 代码缺陷分类 根据缺 ...

  7. 程序员怎样在复杂代码中找 bug?(简单)

    分享下我的debug的经验 1. 优先解决那些可重现的,可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间. 2. 对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经 ...

  8. 程序员新人怎样在复杂代码中找 bug?

    分享下我的debug的经验 1. 优先解决那些可重现的,可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间. 2. 对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经 ...

  9. Eclipse插件 - FindBugs 检查代码隐藏的 Bug

    简介         FindBugs 是一个在 Java 程序中查找 bug 的程序,它可以查找可能出错的代码,注意 FindBugs 是检查 Java 字节码,也就是*.class文件.其实准确的 ...

随机推荐

  1. 2、asp.net core 部署到服务器之后外网访问不了

    解决问题 把自定义端口的http://localhost:5001改成http://*:5001. 什么都没有改也不行的小伙伴试试在Program的Main方法中的.UseKestrel()后面添加. ...

  2. 2013-4-3 C#中alt键不是Keys.Alt 而是 Keys.LMenu

    2013-4-3 C#中alt键不是Keys.Alt而是Keys.LMenu

  3. CODE FESTIVAL 2017 qual A C Palindromic Matrix(补题)

    彩笔看到题目后,除了懵逼,没有啥反应了,唯一想的就是 这是不是dp啊?看了题解才发现,原来是这样啊. 画几个矩阵看看就能看出来规律. 思路:先假设这是个M * N的矩阵 如果M和N都是偶数,则每个出现 ...

  4. LRJ 3-7

    #define _CRT_SECURE_NO_WARNINGS #include <cstdio> int main() { int T; int m, n; ][]; // 4 < ...

  5. Linux下yum安装Redis

    检验是否有yum源: [root@localhost ~]# yum install redis 显示没有软件包Redis,安装epel仓库(提供一些RHEL/CentOS默认不提供的软件包). [r ...

  6. Codeforces Round #178 (Div. 2)

    A. Shaass and Oskols 模拟. B. Shaass and Bookshelf 二分厚度. 对于厚度相同的书本,宽度竖着放显然更优. 宽度只有两种,所以枚举其中一种的个数,另一种的个 ...

  7. 安装node-sass时出现的错误解决方案(Mac自用,也可以借鉴)

    安装node-sass时出现一下错误: gyp ERR! configure error gyp ERR! stack Error: EACCES: permission denied, mkdir ...

  8. P1025 最大完美度

    题目描述 定义一个字符串的完美度为字符串中所有字符的完美度的和. 现在给你一个只含字母的字符串s, 每一个字母的完美度由你进行分配, 可以分配给一个字母[1,26]中的一个数字作为完美度, 但每个字母 ...

  9. jQuery 工具类函数-检测浏览器是否属于W3C盒子模型

    浏览器的盒子模型分为两类,一类为标准的w3c盒子模型,另一类为IE盒子模型,两者区别为在Width和Height这两个属性值中是否包含padding和border的值,w3c盒子模型不包含,IE盒子模 ...

  10. C# 多线程的等待所有线程结束

      //前台线程和后台线程唯一区别就是:应用程序必须运行完所有的前台线程才可以退出://而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,//所有的后台线程在应用程序退出时都会自动结束 ...