验证参数性能与代码契约(Validating parameters properties with

2019-10-18 18:31发布

我有一个讨论,关于代码契约的使用情况进行检查的先决条件同事。

比方说,我们有下面的代码:

namespace Project
{
    using System;
    using System.Diagnostics.Contracts;

    public class Thing
    {
        public string Foo { get; set; }

        public int Bar { get; set; }
    }

    public class ThingsManipulator
    {
        public void AddThing(Thing thing)
        {
            Contract.Requires<ArgumentNullException>(thing != null);

            // Do something
        }
    }
}

如果// Do something ,我访问thing.Foothing.Bar做的事情,我应该验证他们也通过代码契约?

public void AddThing(Thing thing)
{
    Contract.Requires<ArgumentNullException>(thing != null);
    Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(thing.Foo));
    Contract.Requires<ArgumentException>(thing.Bar > 0);

    // Do something
}

我的同事说,只有参数作为一个整体,应检查(即我们应该只把第一份合同),我觉得方法应该检查他们使用什么不论它是整个参数或它的一个属性(即我们应该所有三个合同)。

请注意,我明白和同意这一点。如果一个参数的属性应始终满足一个要求,这个要求应该被放置在该对象的不变的检查。

什么我指的是价值观,其一般是有效的,但不是有效的特定方法(例如,在上面的例子中thing.Bar可以高高兴兴地抱负值,但AddThing不喜欢它们)。

我的同事在这些情况下说的方法签名应该明确所有项目它的使用,而不是一个单一的对象(如AddThing(string thingFoo, int thingBar)并在其上运行的检查。

所以:

  • 我们应该验证什么方法使用或只有参数作为一个整体,“爆炸”的参数?
  • 是否有一个技术理由这样做(无论什么“吧”的意思)或者是偏好的问题?

我一直没能找到这个准则的手册 ,也许我错过了什么?

Answer 1:

它有助于想不到的合同作为验证的东西,这么多的事实是语句,验证试图证明。 你在本质上说,“只要我输入的是正确的(Contract.Requires),那么下面的性质保持(Contract.Ensures,Contract.Assert,Contract.Invariant)”。

合同应声明,应始终对他们所使用的背景下真实的。在你的榜样,你说的事情的美孚要求非空, 只有当他们正在使用一个ThingsManipulator。

如果你能说的事情的富时总是要求非空,那么这总是对这些事情真与合同属于类的东西。

在这种情况下,你不能,所以我认为这将成为有关参数的面向对象的设计问题。 自言自语:

  1. 方法应该尽可能少的参数越好(见https://stackoverflow.com/a/175035/1554471 )。
  2. AddThing是一个公共方法,它可能应该处理更高层次的抽象,像框架值类型不是细节。
  3. AddThing是目前唯一有东西这些限制的唯一方法。
  4. 因此,保持类型的事情的一个参数,并检查其属性。

如果(3)不再是真实的,那么它可能是值得创建一种新型的装饰或以其他方式派生的东西,并把合同上出现,以避免问题重复自己 。 但此刻, YAGNI 。



文章来源: Validating parameters properties with Code Contracts