日志还是调试?

Published: 09 May 2014 Category: Others
调试太挫了,你应该使用日志。
如果你的代码是结构化的,根本不需要通过日志来进行调试。

这是两种截然相反的态度。一般来说,我都是持中庸的立场,下面我来说下原因。 首先使用日志还是调试没有本质的区别。这只不过是同一件事情的两种实现方式:以时间为维度来观察执行引擎的状态。

调试存在的问题

调试的时候你可以逐步前进,在任意一个暂停的执行点,你都可以观察到所有变量的值。它的缺点就是无法回退到前面的某个时间点。有的时候你突然意识到你想看下刚发生的某个方法调用 ,或者对象创建,又或者别的什么之前的某个变量的值 。这种情况下你只能重新运行代码了,还得期望它能正好走到刚才那个分支上,然后在前面的感兴趣的某个点拦截住。这也是调试的另一个缺点。如果你的代码的行为不确定的话,你很难进行调试。相信我:绝大多数BUG的行为都是不确定的。

日志存在的问题

日志的问题就不大一样了。时间这块不是问题,问题在于你要观察的状态和变量实在是太多了。你在代码中的某个执行点插入日志语句,把变量的值输出到日志文件中。当你检查日志文件的时候,可以随意地上下滚动。不过如果你没有在某个执行点打印出某个变量的值的话,日志文件对此就束手无策了。它的解决方案和调试一样:重新执行一遍,记得这次要加上一段新的日志语句。不过,如果你的日志文件中的信息足够详细的话,就算这个BUG是不确定的,你也有足够的信息来对它进行跟踪。不过,我们刚才说的是"如果"。

解决方案:记录所有变量的值?

理想的状态是在每次执行的时候都将所有变量的值输出到一个日志文件中,这样后面你就可以查看这个文件的内容了。这个查看过程有点像一个调试器,不同的是变量的变化是源自你记录的日志文件,而不是实时的运算。它就像在回放一段录制好的执行过程,你可以不停地回放它。我不知道JVM是不是也有类似的工具。

在多线程的执行环境下,就比如说像JVM这样,你根本没法定义什么是每一个状态,这是一个问题。还有一个问题是,如果每条指令你都dump一下JVM的内存(先不考虑多线程的事),这会消耗巨大的带宽及磁盘资源。 做白日梦是没有任何意义的。有什么实际能用的解决方案呢?

实际的方案

在合适的时候你可以使用调试。如果你一直都是用调试的话,那就继续吧。我个人倾向于使用日志,尽管有的时候环境允许我进行实时的调试。当我找到我在苦苦追寻的问题的原因后,我会检查一遍记录日志的语句,然后删掉它们。它们已经完成了自己调试的使命,现在已经不再需要它们了。不过后来我发现,我自己在写一些以前删掉过的日志记录的语句,至少我自己是有这样的经历。为什么呢?这是因为修复一个BUG并不意味着所有的BUG都修复了。BUG是永远也改不完的。但是散落在文件各处的日志记录给查找下一个BUG的相关信息增加了难度。换句话说,日志文件中的干扰信息太多了,这就是为什么我删掉它们的原因。那同样的,我们是不是可以把已经通过的单元测试也给删掉呢?这会节省掉很多编译的时间,不是吗?当然,我们不会这么做。

用一句话来总结下?选择日志还是调试,随你个人的喜好吧,也得看你在查找什么类型的问题。

译注: 文章已经结束了。但是文章后边有条评论非常有意思,注意,本文只有一条评论,而且署名是作者本人。 很感谢你指出了这个问题,在某些特殊的情况下,你或许可以对产品进行调试,但一般来说那都不是最佳的方式。 [我还没有蠢到自己回复自己的文章来感谢自己。这是在回复一条之前删除过的评论,很可能是评论者自己删除的,他当然有权利这么做。不过这让我的这条评论显得很傻。原来的那条评论是说,你无法在生产环境进行调试。] 译注:我强烈的感觉到,作者应该是个处女座。算了,不黑他了。

原创文章转载请注明出处:日志还是调试?

英文原文链接