契约、断言、异常、门及其他

来源:百度文库 编辑:神马文学网 时间:2024/04/27 15:44:30
以前一直搞不清楚为何在应用程序发布时把断言去除掉。今天突然想通了。
在一个系统内部,各部分是相互“信任”的,因此可以去除契约检查。
但对于不信任的外部调用者,需要保留契约。(一个类库发布时,需要保留)
契约的建立是为了防范不信任的交互者。
对于一个独立的应用程序,或说是一个系统,和人交互时,系统的契约无法保证,因此要采取防范措施。相当于建立一个防火墙,墙内是可信任的。
契约可以看作是墙、门、或者检查通道。你不能携带炸药上飞机。
正确的程序保证内部是“可”信任的,绝对安全的,没有逻辑错误,也就是无论何时任何契约都不被违反。
程序发布前,程序被看作是不正确的。因此,要设置门。设置门是为了不让违反契约的错误四处蔓延,将其拒绝在第一道防线之外,方便除错。
发布时,程序被“认为”是正确的。于是门成了多余的,应该拆掉。
系统为防范不信任的用户,需要建一个门。但这个防范措施和契约有些不一样。契约在不被满足时,函数拒绝执行,并抛出错误,直接导致程序终止。但对于一个和人交互或和第三方交互的系统,这种方式显然不够友善,需要换个方式来应对错误的输入。比如,显示出错信息,让用户重新尝试。如果是和程序打交道,可能需要返回详细的出错信息,让另一方进行后续处理。
被检查的异常和未被检查的异常
Java里有这两种异常
//也许Unchecked应该翻译成不被检查的
Checked UnChecked
文件找不到 除零
主机不可达 参数不合法
网络断了
很显然,Checked异常是由于和不可信任的外界打交道所造成的。而Unchecked纯粹是逻辑错误。
对于Checked异常,问题发生在函数和程序外部世界的交互之中。不仅是前提条件可能不满足了,甚至在处理的过程中,也可能出错。这种条件是函数在运行的全过程都应该确保的,不过很可惜,外部世界如此易变,根本无法确保。
对于这种外界环境不满足函数执行条件的情况,需要有别于契约的方式。契约针对的是程序内部的环境,这种环境是我们可以控制的。而外部环境我们是无法控制的。如何防范呢?使用Checked异常。这个函数是程序和外部世界的接口(嗯,也可以说是桥梁)。接口通过Checked异常来报告错误的外界环境。和契约一样,函数在错误的环境下执行是没有意义的。
其实,程序和用户的角色可以互换。我们把程序看作是外部世界,而我们自己看作程序。两者的接口是UI。当程序出错时,UI应该汇报一个错误,以方便用户作相应的处理。一个和外部世界打交道的函数抛出Checked异常是同样的道理,是对它的调用者——应用程序负责。
Unchecked异常意味着程序本身的错误,我们应当“修改”程序了,而不是让它运行下去。
契约的违反代表Unchecked异常。
为什么还要PostConditions?出去的门。
他来源于函数对被调用者(函数使用的函数)的不信任和对自身的不信任。
被调用者和自己可能暗中破坏(环境)或者逻辑不对。PostConditions队这种错误设卡,防止其蔓延出去,不仅仅是到调用者那儿。Class invariants是相同的目的。
Preconditions、Postconditions和Class invariants都是为了方便将程序改变到正确的状态。正确的状态就是起码要符合这些契约。
也许,不仅仅是门。门仅对函数负责。而Contract是对整个程序负责。也许应该叫作程序的门,程序从这个状态通向下一个状态的门。
当程序是正确的或者被认为是正确的后,门就可以拆了。因为门的存在仅仅是用于促进错误更正的工具。继续存在下去是多余,而这种多余往往会浪费大量的CPU时间。
和外部世界打交道的门应当保留,因为外界是不可信任的。
拒绝毒药!!!
拒绝北极!!!