OOP设计问题 - 验证属性

时间:2009-10-30 19:55:19

标签: oop

我习惯总是针对不良数据验证属性设置器,即使我的程序中没有合理输入错误数据的地方也是如此。我的QA人不希望我抛出异常,除非我能解释它们会发生在哪里。我应该验证所有房产吗?我可以指出这个标准吗?

示例:

public void setName(String newName){
   if (newName == null){
      throw new IllegalArgumentException("Name cannot be null");
   }
   name = newName;
}

...

//Only call to setName(String)
t.setName("Jim");

8 个答案:

答案 0 :(得分:4)

您正在执行方法的前提条件,这是其合同的重要组成部分。这样做是没有错的,它也可以作为自我记录的代码(如果我读了你的方法的代码,我会立即看到我不应该传递给它的代码),尽管assert可能更适合。

答案 1 :(得分:2)

就我个人而言,我更喜欢在这些极不可能的情况下使用Asserts,以避免难以阅读的代码,但要明确假设在函数的算法中做出了假设。

但是,当然,这是一个必须根据具体情况进行的判断。你可以看到它(而且我已经看到它)完全失控 - 直到一个简单的函数变成一个if语句的纠结,几乎从未评估为真。

答案 2 :(得分:1)

你做得好! 无论是setter还是函数 - 总是验证并抛出有意义的异常。你永远不知道什么时候你需要它,你会...

答案 3 :(得分:1)

总的来说,我不赞成这种做法。并不是说执行验证是坏的,而是在简单的setter之类的东西上,它往往会产生比保护bug更加混乱的价值。我更喜欢使用单元测试来确保没有错误。

答案 4 :(得分:1)

嗯,自这个问题发布以来已经有一段时间了,但我想就这一主题提出不同的观点。

使用您发布的具体示例,恕我直言,您应该进行验证,但方式不同。

实现验证的关键在于问题本身。想一想:你要处理的是名字,而不是字符串。 字符串是非空的名称。我们还可以考虑使字符串成为名称的其他特征:不能为空也不能包含空格。

假设您需要添加这些验证规则:如果您坚持使用自己的方法,那么最终会让您的setter变得混乱,因为@SingleShot说。

此外,如果多个域对象具有setName setter,您会怎么做? 即使你像@dave一样使用辅助类,代码仍然会重复:调用辅助实例。

现在,想一想:如果你在setName方法中获得的所有参数都有效,该怎么办?肯定不需要验证。 我可能听起来过于乐观,但可以做到。

记住你正在处理名字,为什么不对名字的概念进行建模? 这是一个显示这个想法的香草,虚拟实现:

public class Name

  public static Name From(String value) {
    if (string.IsNullOrEmpty(value)) throw new ...
    if (value.contains(' ')) throw new ...  

    return new Name(value);
  }

  private Name(string value) {
    this.value = value;
  }

  // other Name stuff goes here...  
}

由于验证是在创建时进行的,因此您只能获得有效的Name实例。无法从“无效”字符串创建Name实例。 不仅验证代码已经集中化,而且在对它们有意义的上下文中抛出异常(创建Name实例)。

你可以在Hernan Wilkinson的“巴塔哥尼亚背后的设计原则”中阅读有关伟大设计原则的内容(名称示例取自它)。请务必查看ESUG 2010 Videopresentation slides

最后,我想你可能会发现Jim Shore的"Fail Fast"文章很有趣。

答案 5 :(得分:0)

这是一个权衡。编写,审查和维护的代码更多,但如果以某种方式获得空名称,您可能会更快地发现问题。

我倾向于拥有它,因为最终你发现你确实需要它。

我曾经有实用程序类来保持代码最小化。而不是

if (name == null) { throw new ...

你可以

Util.assertNotNull(name)

然后Java在语言中添加了断言,你可以直接更新。如果你愿意,可以把它关掉。

答案 6 :(得分:0)

在我看来这很好。对于null值,抛出IllegalArgumentException。对于其他类型的验证,您应该考虑使用与域对象相关的自定义例外层次结构。

答案 7 :(得分:0)

我不知道任何有关“验证所有用户输入”的文档标准,但这是一个非常好的主意。在当前版本的程序中,可能无法使用无效数据访问此特定属性,但这不会阻止它在将来发生。在维护期间发生各种有趣的事情。嘿,你永远都不知道有人会在传递它之前在另一个不验证数据的应用程序中重用该类。