解bug的几种思路

不完美

人无完人,人写的程序天然免不了会产生各类各样的bug。
它就像空气同样,包围在咱们周围,解bug能够说是每一个程序员的屡见不鲜。css

解bug的过程

通常能够分为3步:前端

  1. 复现问题。若是问题能稳定重现,比较好说。对于很差复现的问题,笔者通常作法是在可疑代码里添加一些辅助日志,而后将这些辅助日志上线,等问题下次再次出现时,就能够经过这些新增的日志推测缘由。(若是日志太多,刷的太快,日志里面能够加上一些统一的关键字,这样能够经过grep查看本身关心的日志)
  2. 定位问题。定位bug问题过程当中,会像侦探同样,仔细寻找各类蛛丝马迹。这个过程很关键,若是能很快的找到缘由,那么解决问题就能驾轻就熟了。
  3. 解决问题。方法多种多样,能够本身寻找方案,能够网上查阅,或者找他人讨论等。

通常到这里,就算是解决了这个问题。不妨在这个时候总结一下,在定位和解决这个问题的过程是如何的?笔者最近开始留意所经历大大小小的bug,从中总结了一些通用的解决模式,这样之后若是一条路走不通,能够换下思路,以便可以更快的定位和解决问题。node

下面主要经过一些真实有趣的例子进行阐述,有些例子是开发过程当中遇到的问题或者需求,不必定是bug,但笔者认为能够做为一种解bug的思路做为参考。webpack

思路1-断点调试

之前端为例,能够在浏览器里设置断点调试,
node.js的项目能够在vscode里进行调试,
其余语言应该都有各自的调试方案。ios

断点调试或者添加辅助日志是最本能的一种方式了。git

思路2-缩小范围

删除法缩小范围

好几回遇到css样式有问题,可是不知道究竟是哪里的css产生的问题。程序员

举个例子:
咱们的页面使用了第三方ui库iview的table组件,这个组件给table自带了border样式,它的样子是这样的: github

使用这个table组件有个问题是,border自带的颜色和视觉稿的颜色不同,好比视觉稿的样子多是这样的:
因而但愿经过覆盖的方式改为视觉稿的样子,通常作法是先找到这个自带的border在哪设置的,而后修改旧的css样式去覆盖它。

一开始的作法是每层元素找啊找,是哪一个元素作了设置呢?因为border可能设置在不少元素上,好比div,table,thead,tbody,th,tr,td等等元素上,找了好久没找到设置的地方....web

后来换了种方法找,在元素上右键"Delete Element",依次对可疑元素进行删除。若是哪一个元素被删除以后,border没有了,那么就说明border设置确定是在这个元素上设置的。 经过这样排查后,最后发现这个border被设置在了2个地方。element-ui

border-top和border-left设置在table最外层的div上;
border-bottom和border-right设置在table某个外层的before和after伪类上。

找到了这些border设置的地方,就很好对其进行样式覆盖啦。

二分查找缩小范围

若是某个问题是最近有次代码提交引入的,但不知是哪次提交引入。好比,团队有人说,"这个问题,以前都没有的,最近才出现...",能够考虑这个办法。

  1. 假设有问题的最新提交是commit1,
  2. 找到最近一次没有问题的提交点,假设为commit2,
  3. 那么致使问题的应该是commit1和commit2之间的某次提交,能够用二分查找办法,查找这2个点之间的有问题的提交。
  4. 最后根据查看此次提交的内容,推测问题缘由

曾经尝试过一次,使用这个办法的前提是,须要肯定哪次commit是正常的,这个是关键。

思路3-对比法

前端有个特色,同一个功能,常常能够有多种方式去实现,这个特色就为咱们提供了一个很好解决问题的思路。
对比法是指,若是方法1有问题,那么使用方法2,若是方法2能够实现和方法1相同的功能,这样经过对比一下这2个方法的区别,从而找到方法1的问题所在。

举个例子:

先后端分离的项目,前端开发环境一般会经过webpack-dev-server,设置proxy和后端接口进行联通。

有次遇到个问题是,前端代码经过axios库发请求到proxy对应的后端接口,但是接口请求返回显示500,前端也没有报错信息。可是笔者经过postman直接调后端接口,返回正常的。
这说明接口是OK的,这就很诡异了,直接的办法固然找后端开发看下后台日志,查一下是什么致使的500,可当时后端开发不在,因而本身尝试换了js原生的fetch接口发请求,更诡异的是fetch发请求成功了!

发现这个结果后,就开始对比经过这2个方式发送的请求有什么不一样。在对比请求header时,发现2者的cookie不同。而后手动清除cookie以后,从新用axios请求就正常了。

思路4-搜索关键字

搜索工具是个咱们的好伙伴,如何搜索倒是一门学问。若是搜索关键字选的好,有些问题都能快速找到解决方案,也有些问题,须要反反复复修改关键字,才能找到解决方法。

我在使用hightcharts绘曲线图时,须要在series曲线点上hover时展现一个丰富数据的table和截图,以下图所示:

为了实现这个功能,我在series上除了曲线xy轴须要的数据,还额外加了hover须要展现的数据,这样hover时就能够经过fomatter方法拿到这个点points上额外的数据,从而绘制tooltip。 可是好景不长,在我扩大x轴观察范围时,hover展现的各项数据都是为undefined!!!

观察到的状况以下:

  • 当选择时间区间较短时,小于8分钟左右,大概400多个点,能获取到point数据全部数据,包括x,y以及这个点上其余自定义的数据
  • 当选择时间区间较长时,大于8分钟左右,能获取到point数据,但只能获取到x,y的值,没法获取到这个点上其余自定义的数据。

大于8分钟的效果以下:

因而开始搜索寻找问题所在和解决方案,尝试过如下各类关键字:

  • highcharts width limit tooltip formatter points
  • highcharts 宽度 数据拿不到
  • highcharts pointer undefined
  • highcharts large data pointer undefined
  • highcharts large number of points(data)

这些都没有办法,在这个过程当中,又观察到1个现象,若是把highcharts容器宽度width设大一些,就能够获取大于8分钟时的hover数据,因而曾一度冒出偷懒的想法,但愿能改下交互来解决这个问题,可是本着用户体验至上的想法,不能由于技术缘由让用户妥协,仍是继续查查吧。

皇天不负有心人,终于在官方issues里,经过下面这个搜索关键字下,总算找到了问题的答案!

  • highcharts points count less than data length

这个是highcharts官方issue里的一个问题 查看地址

根据highcharts开发人员的回答,Highstock(这是highcharts下的产品之一,笔者绘图也确实是使用的highstock,但若是用hightchats搜索应该更好)中有dataGrouping特性,默认是启用的,这个特性将指定数量的数据合并展示为一个点,显示的值根据不一样的图表类型有所不一样。因此多是由于不一样的点的数据被合并了,才致使hover时,展现的是undefined。

所以咱们对应的解决方案就很简单了,直接禁止这个特性就能够了,设置dataGrouping.enable = false,便可关闭这个特性,只须要一个简单的配置便可解决啦

在找到答案以前,也考虑过其余解决方案,好比hover时想要的points数据不直接从曲线的points,而是将时间轴的x值做为key,其它须要的数据做为value存入1个变量,hover须要数据时根据拿到x值,从变量中获取。(因为后面找到最直接的方案,这个方案就未验证了)

在这个例子中,笔者得到几个想法:

  • 去issues里搜索。这个适用于工程中使用了某些github上开源项目,若是遇到问题很差解决,优先考虑去github的issues里搜索答案,由于这里有来自开发者最直接的答案。这点在后好几回我使用其它开源工具时遇到问题时,都是经过搜索issues快速的成功解决了问题。
  • 如何优化关键字,应该有不少方法。笔者未作深刻研究,一点浅显理解是,英语要学好,多尝试修改问题描述,或者根据上次搜索结果,参考新的关键字,总能找到一些蛛丝马迹的。

思路5-查看源码

对于有些网上也很差搜到的问题,有的时候,顺着报错信息去查看源码,也不失为一种好的思路。

好比我在使用element-ui树组件时,使用了懒加载模式,其中有个问题就是,须要在最外层插入一个节点,天真的认为调用它的一些已有的insert/append相似API应该能够作到。好比在1个已有节点下加入了子节点,没啥毛病,而后指望用一样的想法实现最外层添加节点,尝试以下:

issues上有人提过这个问题,开发者的回答是无计划支持这个需求 地址

看着添加根节点时控制台的报错信息,要不就进去看看源码如何写的吧。因而找到报错入口,进入源码,大概研读源码,但愿能找到一些但愿。

从源码分析来看,报错的直接缘由是root节点的data为undefined致使。为了验证这个,再次在断点调试时,查看了节点data,和判断一致。

查看root信息,发现root下有2个childnodes,可是data却为空

因而笔者想到的解决办法是给root节点添加一个data,而后将须要新增的节点调用insertBefore加入,这样接口就不会报data undefined的错误了。

解决了这个问题,API就能顺利的在树的最外层添加了新节点。

想必不少人也经历过这些,若是源码比较多,能够看下关键的地方,另外边调试边看,效率会更高。

总结

以上即是我总结的几个思路,相信在从此的工做中,可能还有更多的更广阔的思路。 笔者水平有限,欢迎多多交流和指正,谢谢。

相关文章
相关标签/搜索