软件构造-失败原子性

打印 上一主题 下一主题

主题 507|帖子 507|积分 1521

  在研读《Effective Java》时发现其中提出了“努力使失败保持原子性”的概念,笔者认为十分重要且有用,这里将其归纳整理后贴出,也作为读书笔记自用。
概念

  当对象抛出异常之后,通常我们期望这个对象保持在一种定义良好的可用状态之中,基石失败是发生在执行某个操作的过程中间。对于受检异常(CheckException,必须捕获的异常)而言,这尤为重要,因为调用者期望能从这种异常中恢复。一般而言,失败的方法调用应该使对象保持在被调用之前的状态。具有这种属性的方法被称为具有失败原子性。
实现方法

使用immutable对象

  如果在发生异常时可能会创建新的对象,但是永远不会改变原有的对象,对象仍保持在被调用之前的状态。
对mutable对象在执行操作之前检查参数

  类似软件构造课程上所说的checkrep()函数,检查可变对象的有效性(rep),在对象的状态被修改之前,先抛出适当的异常。
调整计算处理过程

  调整计算处理过程的顺序,使得任何可能会失败的计算部分都在对象被修改之前发生。例如对于一个Map对象,它的元素被按照某种特定的顺序做了排序,为了向其中添加元素,该元素的类型就必须是可以在该规则下与其他元素进行比较的。如果企图添加类型不正确的元素,在Map被修改之前,首先会导致某种异常。
在拷贝的对象上操作

  当需要对一个对象进行修改时,现在它的一份临时拷贝上执行操作,当操作完成后再用其中的结果代替对象的内容。
编写一段恢复代码(不常用)

  编写一段恢复代码,用它来拦截操作过程中发生的失败,以及使对象回滚到操作开始之前的状态上。这种方法主要用于永久性的(基于磁盘的)数据结构。
其他

  虽然失败原子性通常是可取的,但它并不总是可以实现的。例如,如果两个线程试图在没有适当同步的情况下并发地修改同一个对象,那么该对象可能会处于不一致的状态。因此,如果假定在捕捉到ConcurrentModificationException之后对象仍然可用,那就错了。错误是不可恢复的,所以方法在抛出AssertionError时,甚至不需要尝试保存失败原子性。
  即使在可能存在实现失败原子性的情况下,也并非总是可取的。 对于某些操作,它会显着增加成本或复杂性。 也就是说,一旦你意识到这个问题,通常都可以自由而轻松地做到失败原子性。
  总之,作为规则,任何生成的异常都是方法规范的一部分,应该使对象处于方法调用之前的状态。 违反此规则的地方,API文档应清楚地指出该对象将保留在哪种状态。遗憾的是,许多现有的API文档无法实现这一理想。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

雁过留声

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表