本博客为笔者阅读《程序员修炼之道:从小工到专家》的读书笔记十月第二篇,也是整个过程的第二篇,值得一提的是,每月两篇正好八篇,而本书正好八章,因此每一篇博客都将是对于对应章节的记录和感受描写
本篇仅包含对于本书第四章内容的感触
在生活中检查每一个可能的问题似乎是一种病态,然而编码时对输入数据、接口的误用以及自己的可能问题保持警惕十分必要。
这一章介绍了许多工具,用来对代码进行约束、检查,以免出现问题而带来更大的问题。
按合约设计:Designed by Contract,俗称DBC。
合约:合约约定了进入一个函数/方法/模块的前条件,即进入模块必须满足的条件,常常指满足模块运行的情景或变量取值范围等等;后条件,即模块需要达成的结果,模块运行之后所能达到的状态;不变量,是对于模块的约束,在调用模块前后始终为真的一些描述。
合约可以是动态的,由“合约代理”在不同模块之间协商出一套合约,但我不知道相应技术。
这是一个很好的想法,其优点在于让代码早崩溃,此时问题更小更单纯。但是在常用的c、cpp中这个想法并没有那么可行。可以通过断言实现一部分功能。
不过通过良好的文档,可以对前条件、后条件、不变量进行描述,从而达到合约的想法,一定程度上获得其优点。
死程序不说谎:一个出现问题的程序可能会因为异常操作造成很大的破坏,所以运行出现问题时,崩溃好于破坏。要利用异常机制。
断言式编程:对于“不可能发生”的情况进行断言,以保证系统的健壮与安全,以免因错误数据或恶意攻击出问题。
然而断言时要避免加入执行代码及其他有副作用的代码,避免“海森堡bug”:不当调试改变了被调试系统的行为。
异常:检查每一个可能的错误,尤其是意料之中的错误是有必要的。
要将异常用于真正异常情况的处理而非模块逻辑的一部分。检查这一点的方式是去掉异常,观察模块能否正常运作。
怎样配平资源:谁申请的资源谁解除该资源,降低代码耦合度。
对于嵌套分配,以与资源分配相反的顺序解除资源分配以免资源的遗弃,在代码不同地方申请资源时以相同顺序申请以免死锁。
在异常处理机制中,一个模块可以通过捕捉异常再抛出从而退出和正常退出两条退出途径。为了遵守对资源利用有始有终并减少重复的原则,有以下思路:对于c++,使用类封装而非指针以保证析构函数会解除相应的资源;对于java,可以使用finally语句解除资源。在更多复杂的情况下,比如树状结构中一个资源指向更多资源,可以用类封装等方式减少出错率。
练习中指出了两个小技巧:c/c++中为了避免释放后的指针被错误地引用,修改不该修改的内存,可以将指针值改为null;java为惰性内存管理,所以使用完某个变量后可以将变量值改为null,从而解除引用,使变量更快被回收。
1、注重实效的程序员会不信任自己,所以他们针对自己的错误行为进行防卫性编码。
2、按合约设计(Design By Contract,简写DBC)是 Bertrand Meyer 为 Eiffel 语言发展的概念。它的核心是用文档记载模块的权利与责任,并进行校验。它的目的是对函数做一些前置检查和后置保证,结合编译器的支持,我们能够尽早的发现代码问题。
3、DBC 有三个概念。
前条件:为了调用例程必须为真的条件。
后条件:例程保证会做的事情,其完成时的状态。
类不变项:其确保从调用者的视角来看,该条件总是为真。
4、Java 中的 iContract 框架是专为 DBC 设计的,它通过注释里的 @pre、@post、@invariant 声明这三个概念。它会读取注释并生成包含断言逻辑的源文件。Eiffel 则是通过 require、ensure、is 三个值表示对应概念。但是支持 DBC 的语言真的很少。
1、对待程序我们通常会有“它不会发生”的心理状态,这会导致我们忽视一些问题。对于注重实效的程序员来说,如果我们忽略了一个错误,将是非常糟糕的事情。
2、我们一些异常情况,我们应该及早崩溃,用于强调问题的存在。
3、引起崩溃的时候不要造成破坏,比如申请的资源还没有释放等情况。
4、死程序带来的额危害通常比有隐患的程序要小得多。
第23节 断言式编程
1、如果它不可能发生,用断言确保它不会发生。
assert(string != NULL)
1.
断言里写的为真的条件,当不为真时触发断言,程序退出。
2、断言检查的是决不应该发生的事情,而不是错误处理。
3、断言应该一直开着,不要在线上环境关掉它。
断言对应的是一种强提示,它迫使我们必须遵守。像是单元测试,我们通常都使用断言的形式进行检查。
第24节 何时使用异常
1、异常很少应作为程序的正常流程的一部分使用,异常应该保留给意外情况。如果移除了所有的异常处理器,代码就无法运行,那说明异常正在被用于非异常情况中。
2、是否应该使用异常取决于实际情况。比如打开文件,文件不存在,是否应该发生异常?如果文件应该在那里,那么异常就有正当理由。如果不确定文件是否在那里,返回错误就可以了。
第25节 怎样配平资源
1、对于资源(内存、事务、现成、文件、定时器等)的管理要有始有终,你分配了对应的资源,就需要考虑对应的解除逻辑。要有始有终。
2、嵌套的资源分配,应该使用与分配次序相反的顺序进行解除。
3、异常的配平需要避免违反 DRY 原则。例如文件打开的异常情况,会导致 try..catch 有两条路径,那如何避免在正常流程和 catch 流程都处理 error 情况呢?C++ 可以依赖对象自动析构的特性,Java 可以依赖 finally子句。
4、当无法配平资源时,需要设定一个规则,决定谁为某个聚集数据结构中的数据负责,以及如何负责。这里有点类似引用计数方案,无引用时释放。
5、自动化检查资源配平状态,可以依赖一些三方工具。
标签:断言,第二篇,小工,程序员,模块,配平,异常,DBC,资源 From: https://www.cnblogs.com/Arkiya/p/16817154.html