关于代码调试de那些事
原文出处:http://www.wklken.me/posts/2014/11/23/how-to-debug.html
- 关于代码调试de那些事
- 1.你得明白你在做什么, 保持清醒
- 2.想清楚了再写代码
- 3.关于脚手架代码
- 4.写完一段代码第一时间自己review一下
- 5.review中注意, 代码是抠过来的么?
- 6.搞明白问题的表现是什么(症状)
- 7.调试过程中, 需要时刻注意
- 8.环境/数据一致性
- 9.先不要动代码, 假设代码是正确的
- 10.首先要怀疑自己
- 11.对于莫名其妙的问题, 多试几种情况
- 12.先回到正确的代码
- 13.如果一段代码是没动过的代码
- 14.bug总是倾向于集中出现在一起
- 15.对于很长很长, 上二分法
- 16.print or debug?
- 17.十分十分诡异的问题
- 18.当一个问题超过半小时
- 19.关于google
- 20.关于求助
- 21.吃一堑长一智
写代码最完美的就是, 想清楚, 码, 运行, perfect, DONE, 下班.
当然, 那是完美的状态. 大多数时候只存在于理想中.
现实是, 我们会被各种坑, 被环境坑, 被语言坑, 被依赖坑, 被第三方库坑, 被编辑器坑, 被自己坑(三个月前的自己/昨天的自己/几分钟前的自己), 被数据库坑, 被缓存坑, 被队友坑(这个比较惨), 被需求变更坑(这个也是)......
所以, 总是避免不了代码调试.
今天顺带过了下<<想计算机科学家一样思考Python>>, 里面每一章最后都有关于调试的一些观点, 例如阅读 - 深思 - 修改/运行/回退
, 所以决定来写写关于代码调试的一些东西.
其实, 代码调试是论如何排查问题
的一个过程, 根据一切蛛丝马迹, 推断出问题所在, 并消灭之.(破案的即视感)
下面是一些关于一些自己在写代码和调试的总结
1.你得明白你在做什么, 保持清醒
代码调试有时候会让你陷入无尽的自我怀疑/迷茫/愤怒/沮丧/窘迫/挫败(无限负能量), 很容易被这些情绪左右, 不清醒, 陷入怀疑自我(一定是我调用的方式不对), 或者怀疑一切(一定是数据库问题, 不对, 缓存问题, 不对, 接口问题, 好像不对, 数据问题), 或者胡乱改代码(改-跑-错了-再改-跑-又错-再改, 传说中的随机行走编程), 或者......(挣扎吧......)
此刻, 保持清醒的自我是非常重要的, 要明确: 我在做什么
, 问题是什么症状
, 原来逻辑是什么
, 最有可能出问题的是哪里
?
2.想清楚了再写代码
如果连需求是什么, 想要做什么都没整明白, 就吭哧吭哧开写, 意图在实践中摸索通向胜利的道路, 是很愚蠢的行为.
需要去理解需求, 自己要做什么, 然后, 在大脑中构造, 现在有什么, 为了完成需求需要做什么, 完成大体的组成结构/步骤流程的思考后, 再着手去做.
大到整体设计, 小到一个函数, 都可以这么处理
例如, 遇到复杂问题, 可以先写注释, 完整所有函数整体设计, 然后再填充细节
def dosomething():
“””
“””
# step1: call func test() # step2: parse url to # step3: judge # step4: convert and return
3.关于脚手架
代码
在逻辑的关键位置, print/assert关键信息, 用于在调试中迅速确认问题. (一些中间值/状态/条件判断结果)
当然, 信息除了关键
这个特性, 还需要足够丰富
和显眼
, 一遍一次性定位问题. (既要好看又要有用)
你需要确定下如何用顺手的编辑器快速输入这些代码, 可以用各类语言的snippets
例如, 在写python时候, 我很喜欢prt(k-vim自动补全), 快速插入一些需要的信息
print "TRACK ================= result", type(result), result, result == "test"
4.写完一段代码第一时间自己review一下
事实证明, review的效果比写完直接跑再来调, 效率高多了.
刚写完一段代码, 思路还很清晰, 跳到开始, review过程中注意各类变量, 条件判断, 函数调用, 上下文, 一致性, 错误处理等, 花不了多少时间, 却能发现一些显而易见
的问题, 省下很多无谓的调试时间(没问题不需要调试!).
5.review中注意, 代码是抠
过来的么?
很多时候从其他地方copy代码过来(一行或几行, 有时候只是一个函数调用或一个判断), 但是很容易忘了根据当前情况修改一些必要的值, 导致问题
例如函数调用, 这个地方调用参数可能跟你copy这行代码需要参数不一样, 但是放在这里并不会报错(一切运作正常), 最终结果并不对.....
好了, 开始调试
6.搞明白问题的表现是什么(症状)
运行代码, 报错了, 有些人会瞬切回编辑器, 开始改代码(作高效状)......>_<#
问题是: 报错提示你看了么, 看明白了么?
现在大部分语言, 其报错提示已经很明显了, 精确到行/变量, 虽然整个异常栈信息可能很长(非常长), 但是都有其特征(在最前或在最后,或在中间靠后, 有关键字), 仔细看下报错信息, 精确制导才是王道.
所以, 你需要从错误信息中先确认
错误类型
发生错误的地方
很多语法问题可以根据这个信息直接定位
7.调试过程中, 需要时刻注意
改的是不是正确的目录下正确的文件?(大坑)
保存了么(编译了么)?(又一个坑)
服务重启了么?
跟数据库有没有关系/跟缓存有没有关系, 要不要清?
……
以上问题, 随便碰上一个你都可能发现, 自己书写的代码和当前运行来调试的代码不一样.(会浪费你巨量的时间)
自己调试半天怎么还是一样的结果
我一直在修改, 但是没有什么区别(出现这种情况要自问一下了)
可以显示在代码头部打印或者故意出错, 确认是同一套代码
8.环境/数据一致性
当你发现在本地无法复现别人报过来的问题(在我电脑上是正常的), 这时候, 需要考虑是否是环境和数据的问题.
9.先不要动代码, 假设代码是正确的
遇到问题, 不要急着修改代码, 需要假设, 代码是正确的, 然后去复现, 复现之后定位.
10.首先要怀疑自己
你不能一旦代码跑不动就怀疑是别人的问题, 然后抛给别人, 这样做同样是很不负责任而且很愚蠢的.
首先, 你需要怀疑自己, 排查问题, 当确定不是自己的问题之后, 将问题定位, 输入, 预期结果, 现在的异常结果都处理好, 生成一个问题, 抛给对应负责人. (一切没有价值的怀疑都是无意义的)
程序员都是好人, 每次都在想: 一定是我的问题
11.对于莫名其妙的问题, 多试几种情况
有时候碰上一些诡异的问题, 例如有一种情况的输入会报错, 这时候, 再跳过去修改代码前, 可以多尝试几种输入, 涉及边界/异常/正常等情况, 排除法, 精确制导.
例如, 可以变换输入值的范围(扩大或缩小, 可能用二分法), 变换输入类型和格式
12.先回到正确的代码
如果这段代码是由于修改导致的, 可以注掉此次变更代码, 同样的输入再次验证定位
13.如果一段代码是没动过
的代码
如果你确保确实没动过
, 此时, 先不要怀疑自己, 更大的可能是别人的问题
.
可能情况: 依赖出了问题(调用函数返回数据不对/异常? 依赖请求挂了? ……), 数据出了问题(表结构变更/服务返回数据变更), 环境问题(数据库/缓存)
14.bug总是倾向于集中出现在一起
很多时候, bug是扎堆的, 可以回忆下之前修改的地方, 确认问题.
15.对于很长很长, 上二分法
可能函数很长, 或者调用链很长, 不易调试.(光打调试信息就得打得手疼)
找到关键变量, 上二分法
, 无上利器.
16.print or debug?
个人偏好简单粗暴的print
, 主要是用的vim+sinppet, 快速高效.
当然, 如果用IDE, 用 debug
吧
17.十分十分诡异的问题
上debug
, 打断点, 一点点调试吧, 只能这样了.
18.当一个问题超过半小时
歇一歇, 走动走动, 打个水, 呼吸下新鲜空气.
这时候有利于脱出情境, 去掉挫败感/愤怒/迷信等
很多时候突然灵感一到, 瞬间明了(这种感觉很奇妙)
19.关于google
有些错误信息, 如果觉得比较独特诡异, 可以google下, 你会找到更多的一些信息的.
20.关于求助
实在搞不定, google大神也搞不定, 此时可能需要求助了.
前提, 你自己能把问题想清楚, 并且逻辑清晰地描述出来.(什么业务什么位置的什么逻辑, 报错类型和报错信息, 输入输出, 迄今做了哪些尝试等等) 要学会聪明地问问题, 高效, 尊重自己也尊重别人.
如果你自己都没整明白怎么问, 别人也无能为力.
遇到很多人, 直接上来就一句xxx出问题了
, 没有前置条件后置结果中间症状......
不过, 如果你会聪明地问, 那就放心大胆地问吧, 不用磨磨唧唧的, 程序员大都是善良的孩子.
21.吃一堑长一智
被坑了就要总结总结, 有个记录, 不被同一个问题坑两次.
如果被坑了就忘, 还需要去反复求助, 那这属于坑队友的行为(鄙视下)
好了, 就这些:)
关于代码调试de那些事的更多相关文章
- javascript代码 调试方法
你的代码可能包含语法错误,逻辑错误,如果没有调试工具,这些错误比较难于发现. 通常,如果 JavaScript 出现错误,是不会有提示信息,这样你就无法找到代码错误的位置. 在程序代码中寻找错误叫做代 ...
- Web开发者的六个代码调试平台
代码调试平台是Web开发者进行开发.测试.分享.协作和交流的网络应用,它们支持实时的编辑.预览HTML.CSS和JavaScript的客户端代码.这些代码调试平台最值得称道的地方在于,它们中的大多数都 ...
- GDB代码调试与使用
GDB代码调试与使用 Linux下GDB调试代码 源代码 编译生成执行文件 gcc -g test.c -o test 使用GDB调试 启动GDB:gdb test 从第一行列出源代码:list 直接 ...
- OI中的代码调试
作为一位OIer,代码调试的能力必不可少. 今天梳理一下自己进行代码调试的方法,下面只是一些个人的总结. 代码的评价有三部分: 正确性 强健性 高效性 检查也应该从这三部分出发. [正确性] 打完代码 ...
- 初识 Javascript.02 -- Date日期、Math对象、数据类型转换、字符串、布尔Boolean、逻辑运算符、if else 、三元表达式、代码调试方法、
Date()对象: Date对象用于处理日期和时间. 1.1 Math对象 ◆Math.ceil() 天花板函数 向上取整 只取整数,不足则进1 ◆Math.floor() 地板函数 ...
- .NET Core快速入门教程 5、使用VS Code进行C#代码调试的技巧
一.前言 为什么要调试代码?通过调试可以让我们了解代码运行过程中的代码执行信息,比如变量的值等等.通常调试代码是为了方便我们发现代码中的bug.ken.io觉得熟练代码调试技巧是成为合格程序员的基本要 ...
- Node.js系列文章:如何进行代码调试
使用任何一门编程语言,都少不了代码调试这一功能.我们在使用JavaScript编写浏览器端代码时,Chrome提供了强大的调试工具Dev Tools,但是在编写Node.js代码时,大多数人最开始都使 ...
- #7 Python代码调试
前言 Python已经学了这么久了,你现在已经长大了,该学会自己调试代码了!相信大家在编写程序过程中会遇到大量的错误信息,我也不例外的啦-遇到这些问题该怎么解决呢?使用最多的方法就是使用print打印 ...
- CodeBlocks(17.12) 代码调试基础方法&快捷方式
转载:CodeBlocks(17.12) 代码调试基础方法&快捷方式: https://www.cnblogs.com/DCD112358/p/8998053.html
随机推荐
- mac上使用命令行显示隐藏文件
终端中输入命令 打开<终端> - 粘贴下面的两行命令执行 defaults write com.apple.finder AppleShowAllFiles TRUEkillall Fin ...
- 工程化---cnpm不是内部命令的解决
(1)问题描述 安装完,执行cnpm -v发现报出不是内部命令. 安装成功如下图: (2)解决方案: 之前配置过默认安装都会在D:\\nodejs\node_global中,所有我们cd 到 这个路径 ...
- python之dic {字典}(重要指数*****)
1. 什么是字典 {'name': '汪峰', 'age': 18} '键':'值' 别的语言键值对数据 键: 必须是可哈希(不可变的数据类型),并且是唯一的 值: 任意 可以保存任意类型的数据 字典 ...
- SSH中的jar包讲解
我们在搭建SSH框架的时候,需要引入各自的一些jar包 首先,先来看一下我们使用的SSH的各自版本及引入的jar包. struts2.3.1.2: struts2-core-2.3.1.jar j ...
- shell脚本,awk实现每个数字加1.
[root@localhost add]# cat file [root@localhost add]# cat file|awk '{for(i=1;i<=NF;i++){$i+=1}}1' ...
- [转载] Python数据类型知识点全解
[转载] Python数据类型知识点全解 1.字符串 字符串常用功能 name = 'derek' print(name.capitalize()) #首字母大写 Derek print(name.c ...
- int main(int argc,char *argv[])的具体含义
int main(int argc,char * argv[]) argv为指针的指针 argc为整数 char **argv or: char *argv[] or: char argv[][] m ...
- LeetCode(1)Two Sum
题目: Given an array of integers, find two numbers such that they add up to a specific target number. ...
- Debian 修改时间时区
http://blog.51cto.com/zhujiangtao/1554976 第一种图形化方面推荐使用 第二种修改文件的形式 只是在当前的terminal生效 笔者使用的是: debian9.3
- Absolute(绝对定位)与relative(相对定位)的图文讲解
Position的属性值有:1. Absolute:绝对定位,是相对于最近的且不是static定位的父元素来定位 2. Fixed:绝对定位,是相对于浏览器窗口来定位的,是固定的,不会 ...