如何使用代码契约定义外在状态的前提条件



如何在以下接口中的Invoke方法上放置一个前提条件,声明由ObjectId表示的对象必须存在

interface IDeleteObjectCommand {
   Guid ObjectId { get; }
   void Invoke();
}

尝试#1

我已经有一个名为IObjectExistsCommand的命令,可以用来确定对象是否存在。这些命令可以通过CCD_ 4来实例化。我曾考虑过做以下事情,但这给命令的接口(IMO)增加了不希望的噪音:

interface IDeleteObjectCommand {
   IObjectExistsCommandFactory ObjectExistsCommandFactory { get; }
   Guid ObjectId { get; }
   // Contract.Requires(ObjectExistsCommandFactory.Create(ObjectId).Invoke());
   void Invoke();
}

尝试#2

与上面类似,只是使用ServiceLocator。由于明显的原因不受欢迎,但更清洁:

interface IDeleteObjectCommand {
   Guid ObjectId { get; }
   // Contract.Requires(ServiceLocator.Get<ObjectExistsCommandFactory>().Create(ObjectId).Invoke());
   void Invoke();
}

编辑:同样,您将如何定义外部状态的发布条件?也就是说,这种方法导致了一个新文件的存在。

我认为这是个坏主意。这是一个受竞争条件约束的契约,我不喜欢这些(两个调用方验证契约是否满足,然后其中一个赢得了删除对象的竞争,然后第二个在尝试删除对象时获得了违反契约的异常)。

如果要删除的对象不存在,则引发异常。

我决定创建一个定义外部先决条件的"先决条件"enum。然后,我在接口上定义了一个单独的方法,它返回enum,从而暗示哪些外部状态的位无效:

interface IDeleteObjectCommand {
   Guid ObjectId { get; }
   DeleteObjectPreconditions? GetImpediments();
   // Contract.Requires(!this.GetImpediments().HasValue);
   void Invoke();
}
enum DeleteObjectPreconditions { ObjectExists, ObjectUnlocked };

我这样做完全疯了吗?当然,唯一的缺点是用户没有可证明的方法来满足先决条件。。。

编辑:我实际上更喜欢服务定位方法而不是这种方法。至少通过这种方法,用户能够通过签订合同(尽管位于服务位置)的接口证明先决条件得到了满足。

第2版:这提出了一个有趣的问题。。。你将如何定义外在状态的后条件?

最新更新