软件构造-失败原子性
作者:互联网
在研读《Effective Java》时发现其中提出了“努力使失败保持原子性”的概念,笔者认为十分重要且有用,这里将其归纳整理后贴出,也作为读书笔记自用。
概念
当对象抛出异常之后,通常我们期望这个对象保持在一种定义良好的可用状态之中,基石失败是发生在执行某个操作的过程中间。对于受检异常(CheckException,必须捕获的异常)而言,这尤为重要,因为调用者期望能从这种异常中恢复。一般而言,失败的方法调用应该使对象保持在被调用之前的状态。具有这种属性的方法被称为具有失败原子性。
实现方法
使用immutable对象
如果在发生异常时可能会创建新的对象,但是永远不会改变原有的对象,对象仍保持在被调用之前的状态。
对mutable对象在执行操作之前检查参数
类似软件构造课程上所说的checkrep()函数,检查可变对象的有效性(rep),在对象的状态被修改之前,先抛出适当的异常。
调整计算处理过程
调整计算处理过程的顺序,使得任何可能会失败的计算部分都在对象被修改之前发生。例如对于一个Map对象,它的元素被按照某种特定的顺序做了排序,为了向其中添加元素,该元素的类型就必须是可以在该规则下与其他元素进行比较的。如果企图添加类型不正确的元素,在Map被修改之前,首先会导致某种异常。
在拷贝的对象上操作
当需要对一个对象进行修改时,现在它的一份临时拷贝上执行操作,当操作完成后再用其中的结果代替对象的内容。
编写一段恢复代码(不常用)
编写一段恢复代码,用它来拦截操作过程中发生的失败,以及使对象回滚到操作开始之前的状态上。这种方法主要用于永久性的(基于磁盘的)数据结构。
其他
虽然失败原子性通常是可取的,但它并不总是可以实现的。例如,如果两个线程试图在没有适当同步的情况下并发地修改同一个对象,那么该对象可能会处于不一致的状态。因此,如果假定在捕捉到ConcurrentModificationException之后对象仍然可用,那就错了。错误是不可恢复的,所以方法在抛出AssertionError时,甚至不需要尝试保存失败原子性。
即使在可能存在实现失败原子性的情况下,也并非总是可取的。 对于某些操作,它会显着增加成本或复杂性。 也就是说,一旦你意识到这个问题,通常都可以自由而轻松地做到失败原子性。
总之,作为规则,任何生成的异常都是方法规范的一部分,应该使对象处于方法调用之前的状态。 违反此规则的地方,API文档应清楚地指出该对象将保留在哪种状态。遗憾的是,许多现有的API文档无法实现这一理想。
标签:状态,对象,构造,原子,失败,之前,软件,异常 来源: https://www.cnblogs.com/liwu7/p/16407304.html