没有代码合同的先决条件

时间:2013-11-05 07:32:01

标签: c# asp.net .net-4.0 refactoring

在ASP.net MVC中(不一定仅限于MVC,只是一个例子),我们的动作方法总是有类似下面的前提条件:

[HttpPost]
public ActionResult Edit(FooModel viewModel)
{
    if (viewModel == null)
    {
        throw new ArugmentNullException("viewModel");
    }

    if (viewModel.Foo < 1)
    {
        throw new InvalidOperationException();
    }

    // Perform real tasks on viewModel (e.g. map it to model, persist to database)

}

现在我知道我们可以将检查重构为存储库类中的静态方法:

[HttpPost]
public ActionResult Edit(FooModel viewModel)
{
    if (FooModelRepostory.IsValid(viewModel)
    {
    }

    // Perform real tasks
}

FooModelRepository.cs

public static bool IsValid(FooModel viewModel)
{
    if (viewModel == null)
    {
        throw new ArgumentNullException("viewModel");
    }

    if (viewModel.Foo < 1)
    {
        throw new InvalidOperationException();
    }

    // ...many more checks and throw exceptions accordingly

    // if we reach up to here, we are good, return true
    return true;
}

我的问题是,我们是否有更好的方法来重构代码而不会使用这样的支票来混淆存储库?

2 个答案:

答案 0 :(得分:0)

我没有看到任何更明确的事情已经提供给你。 Code Contracts,是的,允许您向程序添加声明性行为,但也隐藏了明确的逻辑。所以,无论如何,它有两个方面:好的和坏的。

我个人会选择你选择的解决方案,所以采用简单的控制方法。 我唯一想引起你注意的是:

public static bool IsValid(FooModel viewModel)
{
 ...
}

转发bool,因此如果出现失败/否定回复,我希望返回false / true值而不会引发异常。这是程序的控制流程,因此简单的return truereturn false就足够了,并且期望来自您方法的使用者。

答案 1 :(得分:0)

另一种选择是创建验证类。您只需将这些类的对象添加到列表中,并询问列表是否每个验证都有效。只是一些优点:

  • 同样的验证可以重复用于其他控制器。
  • 如果添加了验证,则现有代码不会受到影响(打开关闭/原则)
  • 单元测试验证更容易,因为您不必调用控制器来查看它是否有效
  • 如果您在验证中“找到所有参考”,您可以看到使用验证的控制者
  • 您可以稍后选择是否只需要一个bool例外而不更改验证。

更多信息和示例: enter link description here