[英]Alerting Library Users to an Inconsistent State
在本机库上的托管包装器中,我必须完成某些操作,这些操作对于高级对象的用户应该被认为是原子的和一致的。 但是,本机代码中的基础操作是原子的并且是单独一致的,但不是整体的。
// Simplistic look at the AddRange operation
void AddRange(IEnumerable<ChildType> range)
{
foreach (var value in range)
{
this.NativeAdd(value);
}
}
// Simplistic look at the Delete operation
void Delete(ParentType value)
{
foreach (var child in value.Children)
{
this.NativeDelete(child);
}
this.NativeDelete(value);
}
如果Native代码存在错误,则所有Native操作都会失败并显示常见的异常类型:
void NativeDelete(ChildType child)
{
StatusCode status = StatusCode.NoError;
NativeMethods.DeleteChild(this.id, child.Id, out status);
if (status != StatusCode.NoError)
{
throw new LibraryException(this, child, status);
}
}
在高级AddRange和Delete例程中,我遇到了一些本机Add或Delete调用已完成的情况,但其中一个调用发生错误,其余调用未完成。
更新:对于用户来说,如果他们添加了7个项目并且在第7个项目上失败了,或者如果他们成功添加了6个项目,则磁盘上的实际文件看起来不会有任何不同。 记录错误的唯一时间是在运行时。 因此,如果用户未意识到状态不一致的可能性,则他们可能无法确定基础文件是否有效。
我是不是该:
没有真正的两阶段提交支持(即事务管理器),就不可能实现3。 如果发生错误,手动回滚只会导致更多的不一致状态。
我认为2是多余的。 如果在父类型上调用方法(这是这些方法公开的方法),并且在抛出该异常时发生异常,则假设对象上的状态已损坏(除少数例外) 。 通常,当发生这种情况时,您不能对该对象做很多事情,除非将其抛弃并使用具有一致状态的新对象。
留下1,记录它。 虽然您可能会在2中提供大量结构化信息,但如果对象处于不一致状态,您实际上并不想尝试修复该状态,因为您冒更大的风险。
我喜欢你的第二个选择 -
这将提供一个更有意义的例外,您可以控制它。 没有理由强迫你的最终用户理解一些奇怪的状态代码等。至少这样,很明显发生了什么以及为什么。
如果我正确理解您的更新,则调用者可以做的就是将信息传递给最终用户,最终用户必须决定是接受状态还是回滚。
在这种情况下,(2):提供所有信息,以便调用者可以将信息传递给用户,或日志文件,或一些统计数据,而无需大量工作。
(1)如果(2)没有信息差异,则可以,例如,知道哪个项目失败是无关紧要的。
(3)如果你不能指望在大部分时间里修复它是没有意义的,如果你有一点机会让它变得更糟,那就很危险了。
根据文件大小,您可以通过处理副本来进行准原子更改。 至少,用户可能期望一种简单的方法来回滚到上一次保存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.