assert断言使用,调试

契约式编程和防御式编程

契约式编程契约作用于两方,每一方都会完成一些任务,从而促成契约的达成,但同时,每一方也会接受一些义务,作为制定契约的前提,有任意一方无视了必尽义的义务,则契约失败。函数调用者应该保证传入函数的参数是符合函数的要求,如果不符合函数要求,函数将拒绝继续执行。如果按照契约式编程的思想编写代码,就要求我们写函数时检查函数参数。有时候是简单的判断某个参数不能为空,或者数值不能小于0。如果在项目中全面应用契约式编程,则应该有一个“契约框架”帮我们来做这些事情,全部手动检查,代码就繁琐不堪了。在面向对象中,我们认为“接口”是唯一重要的东西,接口定义了组件,接口确定了系统,接口是我们唯一需要关心的东西,仅仅通过接口还不足以传达足够的信息,为了正确使用接口,必须考虑契约。只有考虑契约,才可能实现面向对象的目标:可靠性、可扩展性和可复用性。

防御式编程《代码大全》给我们提供了一个定义,人类都是不安全、不值得信任的,所有的人,都会犯错误,而你写的代码,应该考虑到所有可能发生的错误,让你的程序不会因为他人的错误而发生错误。 程序需要对可能的错误输入,做出兼容,例如一个除法的函数,你必须判断分母可能为0的情况,从而给调用者返回错误提示。另外,一般的高级编程语言,都提供了『断言』和『异常』两种方式来进行错误处理。断言断言是指在开发期间使用的、让程序在运行时进行自检的代码。断言为真,则表明程序运行正常,而断言为假,则意味着它已经在代码中发现了意料之外的错误。断言对于大型的复杂程序或可靠性要求极高的程序来说尤其有用。通过使用断言,程序员能更快速地排查出因修改代码或者别的原因,而弄进程序里的不匹配的接口假定和错误等。一个断言通常包含两个参数:一个描述假设为真时的情况的布尔表达式,和一个断言为假时需要显示的信息。

防御式编程就是持怀疑态度审视所有的代码,在游戏行业里,游戏服务端承担着游戏复杂业务逻辑实现,玩家数据持久化等重要作用,很多计算都是客户端发给服务器进行计算的,客户端很容易受到恶意用户的恶意修改,所以服务端会针对收到的数据进行严格的认证,在支付,金融行业更是如此。这些只是代码层面的,延伸了讲,个人认为用户行为日志,配置开关,一定的扩展涉及,等都是防御式编程思想的应用。

防御式编程和契约式编程都是一种理想化的,全面实现都是比较困难的。但必要的防御措施以及必要的契约还是要有的,让每个人都对自己写的代码负责,建立起良好的信任关系,服务模块之间保持必要的信任。常见的开发模式中,lib库或者rpc服务是server端,调用方式client端,个人觉得服务端需要做更多的防御式验证,不能因为非法调用而运行异常,但调用方要相信server端,不要在做二次验证,就拿那个争论来说,你给我返回了非null的Long对象,我就默认是正确的,我不去做额外的检查他是-1还是-2,在调用方看来只有成功和失败。

assert断言的使用

  1. 头文件
#include<cassert>//c++
#include<assert.h>//c
  1. 使用
assert(expr);//expr为假(0),输出信息并终止程序进行,为真,什么也不做
  1. 解除
    在DEBUG模式下才运行,用于调试
#define NDEBUG//assert不执行

或者编译时:

gcc -D NDEBUG main.c//相当于在文件开始加上上面的define