在知乎上看到这个讨论话题,贴上原始链接:
在函数的入口处对参数的合法性进行检查是一个值得提倡的好习惯吗?
摘录其中比较有意思的观点:
观点一:参数的有效性应该由函数的调用者来保证,在函数内部进行检查会降低函数的性能。
观点二:持有观点一的人会死的很惨。。。
一些论据:
- 健壮性比那点微不足道的性能重要太多了
- 如果真的是性能极其敏感,应该增加十几甚至几十倍的单元测试代码来换取这点儿性能
- 说到底是个信任的问题。默认情况下所有人都是不可信的,除非:
1、内部接口可以省略部分入口检查。因为内部接口只有自己或者自己人调用,信任程度高
2、一定要提升性能的时候需要增加单元测试代码来换取放弃入口检查,为了彻底检查任何情况下都不会产生违法调用- 最外层接口添加检查代码,可以明确提醒模块使用者问题在哪里,减少沟通成本
- 所有函数都添加检查代码,能有效减少错误调用栈,减少调试成本
- 靠人自觉是行不通的。如果传进来的是一个字典或者类似json的object,不检查就是作死
- 先检查是一个低成本的好习惯。
1、在代码层面,规定了什么样的数据是可以接受的,
2、有了前面的检查,可以放心写后面的业务逻辑- 大多数时候,这样的检查是和业务无关的。理论上说一个系统和业务无关的代码越少越好。
- 系统对外接口,如用户输入,读文件,其它系统接口,一定要做严格校验,提高边界识别效率
- 系统内部接口,可以不写,或者写Asser系统边界离出错现场最近,在这里发现问题,纠错方䅁最简明。
- 接口参数检查是在 debug 阶段检查开发者自身的问题。而异常抛出,返回错误代码是检查 runtime 的问题
- 推荐是加断言,方便排查。
- 用assert检查pre condition和post condition,这样你可以去掉一部分单元测试。
- 我认为接口参数检查合理:
1、assert 可以由宏 “NDEBUG” 控制。正式 release 的时候关闭掉,不存在性能问题。
2、 assert 是为保证 “程序员保证正确的接口调用” 提供一种工具和手段。
3.、assert 可以为实现上述目的提供方便的机制,比如 core dump。
4、 assert 的退出方式非常简单粗暴。不过因为面向的是开发者而不是用户,这样有利于提前暴露问题
个人比较受用的结论:
1、对外接口,一定要加检查,便于尽早拦截异常,杜绝错误传递,便于编写更加优雅的业务代码,而不是关注错误处理
2、内部接口,使用assert,在最靠近错误的地方,粗暴一点退出,提高纠错效率
3、性能敏感的代码,通过加强单元测试来保障