我们知道,代码是不可能没有问题的,
从编写第一行代码开始,它就有问题 —— 未完成所有的需求。
在编写代码的过程中,它也一直有问题,
新代码的业务逻辑有问题,或者新老代码的衔接上有问题。
所以,排查问题是开发者的家常便饭,
但谁都不愿意排查问题,尤其是排查那些缺少线索的问题。
因此,写出易于排错的代码,是一项重要的编码技巧,
会给自己省出大量的时间,少掉几根头发。
状态
一个系统无缘无故的出问题了,但重启之后又好了。
换言之,系统是否出现故障,取决于它的 “心情”。
这就很难排查,因为我们不知道它当时是什么 “心情”。
上文所谓的 “心情”,指的是程序的运行状态,它是变动的,
同一段代码,在不同的程序状态下,可能会有不同的结果。
考虑一段依赖外部数据库状态来执行不同任务的代码,
假如有人在程序执行时,通过其他手段改动了数据库,
程序的执行结果就变了,我们根本不知道发生了什么。
所以,要想写出易于排错的代码,必须对程序状态有所警觉,
程序大部分的反常行为,正是由意料之外的程序状态所导致的,
因此我们得想个办法让状态一目了然。
日志
如上文所述,“让代码易于排错” 是我们对代码附加的额外要求,
因此,秉持这一信念的开发者,总是会从一开始就考虑到它。
一个例子是大多数系统都具有的日志模块,
通常是在系统的设计之初,人们就已经考虑了日志问题。
所谓日志,其实是保存了程序执行之关键节点的重要信息,
这些信息为事后排查问题,留下了线索,
让我们可以按图索骥,清晰的找到问题发生的第一现场。
虽说日志是一条重要的线索,但也并非多多益善,
过多无效日志,反而会让重要信息变得难以寻到,
所以写日志时还是要回到初心,是不是做到了 “让代码易于排错”。
调试
现在很多程序的开发过程,都是离不开调试的,
调试使得我们可以跟进代码的执行过程中,
与上文的观点类似,为了 “让代码易于排错”,调试也要从一开始就得考虑。
具体而言,从编写第一行代码开始,我们就得搭好调试配置,
让第一行代码就是可调试的。
以后增加越来越多的功能,可能会破坏调试的可用性,
这时,我们应时刻保证它可用,甚至不惜在代码中写入调试变量。
让代码始终可调试,会加速从发现问题到解决问题的反馈循环,
不可调试的代码,我们自己开发起来都会很麻烦。
开发者接口
有时候给开发者,提供一些额外的接口,是有必要的,
虽然这会违反 “最小接口” 原则。
这是因为代码其实并非只为功能服务的,
前几篇文章,我们介绍的每一个编程技巧,
其实都是在不改变代码功能的前提下,对代码做出了调整。
这其实是对代码编写者提出了更高的要求,
即,如何在满足功能需求的前提下,写出具有更多优秀特征的代码。
所以,面向开发者的接口,也是这一思路的体现,
开发者接口可以获取程序中更多信息,或者实现一些特殊功能,
为我们增加了与系统交互的一种新途径。
Roslyn was thus born out of an openness mindset: sharing the inner workings of C# for the world to programmatically consume. 共享 C# 的内部工作机制,让世界以编程的方式消费。
结语
排查错误是开发者习以为常的事情,
为了让写出来的代码易于排错,通常在编写之初就得有所考虑。
本文介绍了几个常用编码技巧,
包括写日志、保证代码可调试,提供开发者接口。
总而言之,就是给代码添加额外的属性,让它具有 “易于排错” 的特征。
很多事情是类似的,等出了问题之后再考虑办法,就来不及了,
因此,我们会提前留下线索,帮助未来的自己。