0%

防御使编程和契约式编程

问题

Api返回的数据合适和约定的不一致时,调用方能不能崩溃?

编程原则

兼容异常,不兼容错误,要解决错误。

好的代码应当核心是处理正确的事情,而不是一堆错误检查。

为什么

Api不按约定返回,那么属于错误,解决这个错误即可。所以当遇到返回不一致时可以崩溃,这会促使我们及时发现并解决错误,让程序越来越正确,健壮。

不要害怕崩溃,及时解决崩溃就行了,通过try catch,或者出现什么错误就添加一个检查兼容的方法处理,那是隐藏错误和崩溃,是在挖坑的行为,会让程序越来越难维护。

参数检查

参数分为内部输入外部输入

内部输入,我们是可以完全相信的,我们不需要进行过多的检查,函数内部只需要专心于做正确的事情

public function void test() {
File file = getFile();
if (null == file) {
return;
} else {
readFile(file);
}
}
private function String readFile(File file){
// 一个内部使用的函数,这个检查就完全没必要
// 如果传进入了null,那就让他及早的崩溃,发现问题,修复内部传参错误的代码
if (null == file) {
return;
}
//读取文件....
}

注意:每一个内部参数的检查必须能给出合理的业务场景,不能仅仅只是通过代码判断可能崩溃,就添加一个检查。 内部参数的检查时属于业务逻辑的一部分,不需要有和业务逻辑无关的检查

外部输入,我们是不能相信的,是不可控的,我们需要进行参数检查

可以把我们自己的服务端Api当作是内部输入,从这个角度理解,也不需要对api的返回格式进行检查。

程序健壮性理解的误区

并不是程序不崩溃,就是程序健壮,程序健壮是程序执行正确的业务,包括输入非法的参数时,能得到正确的反馈。

参数非法和参数错误是两个概念,参数非法是程序需要处理的业务,参数错误是bug,是程序本身就没写对。

如果输入了错误的参数,但程序也不崩溃,也没有任何反馈提示,那么这样的程序是最糟糕的,掩耳盗铃,给后人挖坑,埋雷。

防御式编程

防御式编程防御的是不可控的三方输入,例如readFile()是一个提供给外界使用的对外接口

public function String readFile(File file){
// 对外的接口,那么不能相信别人的输入,需要检查
if (null == file) {
return;
}
//读取文件....
}

契约式编程

契约式编程中,在开发阶段使用断言来检查契约,对于不遵循契约的行为直接报错,其实和崩溃的行为是一样的。服务端Api属于契约,所以解析api数据时只需要按契约解析,不需要添加契约外的兼容代码。

参考资料

https://blog.csdn.net/qq_38022403/article/details/84029066