11

我想知道在gettersetter或代码的其他地方进行验证是否是个好主意。

当涉及到优化加速代码时,这可能会让您感到惊讶,我认为您不应该在 getter 和 setter 中进行验证,而应该在更新文件或数据库的代码中进行验证。我错了吗?

4

8 回答 8

15

好吧,类通常包含具有公共 getter/setter 的私有成员的原因之一正是因为它们可以验证数据。

如果你的数字可以在 1 到 100 之间,我肯定会在 setter 中放入一些东西来验证它,然后可能会抛出一个被代码捕获的异常。原因很简单:如果在setter中不做,每次设置都要记住1到100的限制,导致代码重复或者忘记了导致状态无效。

至于性能,我在这里和 Knuth 在一起:

“我们应该忘记小的效率,比如大约 97% 的时间:过早的优化是万恶之源。”

于 2008-08-05T19:59:39.157 回答
4

@Terrapin,回复:

如果你只有一堆 [simple public set/get] 属性......它们也可能是字段

与字段相比,属性具有其他优势。它们是更明确的契约,它们是序列化的,它们可以稍后调试,它们是通过继承进行扩展的好地方。笨拙的语法是一种意外的复杂性——例如 .net 3.5 克服了这一点。

一种常见的(但有缺陷的)做法是从公共字段开始,然后在“根据需要”的基础上将它们转换为属性。这会破坏您与使用您的课程的任何人的合同,因此最好从属性开始。

于 2008-08-08T00:07:08.967 回答
3

从拥有最可维护代码的角度来看,我认为您应该在属性的设置器中进行尽可能多的验证。这样您就不会缓存或以其他方式处理无效数据。

毕竟,这就是属性的意义所在。如果您拥有的只是一堆属性,例如...

public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

...它们也可能是字段

于 2008-08-05T19:59:05.007 回答
3

这取决于。

一般来说,代码应该很快就会失败。如果该值可以由代码中的多个点设置,并且您仅在检索该值后才进行验证,则该错误似乎出现在执行更新的代码中。如果设置器验证输入,您就知道哪些代码试图设置无效值。

于 2008-08-05T19:59:13.010 回答
1

验证应该与验证方法中的 getter 或 setter 分开捕获。这样,如果需要跨多个组件重用验证,它是可用的。

当调用 setter 时,应该使用这样的验证服务来清理对象的输入。这样您就知道存储在对象中的所有信息在任何时候都是有效的。

您不需要对 getter 进行任何类型的验证,因为对象上的信息已经被认为是有效的。

在数据库更新之前不要保存您的验证!!最好快点失败

于 2008-08-05T19:55:52.127 回答
1

你可能想看看Eric Evans 的领域驱动设计。DDD 有这个规范的概念:

... 用于特定目的的显式谓词类 VALUE OBJECTS。SPECIFICATION 是一个谓词,用于确定一个对象是否满足某些标准。

我认为快速失败是一回事,另一件事是在哪里保留验证逻辑。域是保留逻辑的正确位置,我认为您的域对象上的规范对象或验证方法将是一个好地方。

于 2008-08-05T20:03:46.730 回答
1

我喜欢实现IDataErrorInfo并将我的验证逻辑放在它的 Error 和 this[columnName] 属性中。这样,如果您想以编程方式检查是否存在错误,您可以简单地在代码中测试这些属性中的任何一个,或者您可以将验证交给 Web 窗体、Windows 窗体或 WPF 中的数据绑定。

WPF 的“ValidatesOnDataError”绑定属性使这变得特别容易。

于 2008-08-07T22:24:01.610 回答
1

我尽量不让我的对象进入无效状态,所以 setter 肯定会有验证以及任何改变状态的方法。这样,我就不必担心我正在处理的对象是无效的。如果您将方法保留为验证边界,那么您永远不必担心验证框架和到处散布的 IsValid() 方法调用。

于 2008-09-23T19:44:28.420 回答