2

您有一个不可变对象,并在接受几个参数的构造函数中设置其内部变量。

问题
您是否发现在不可变对象的构造函数方法中验证构造函数参数有任何问题,ArgumentExceptions如果无效则抛出?

(对我来说这是有道理的,但我想问一下,如果有更好的方法或对此不满意 - 例如,将验证从构造函数转移到工厂是否是一个更好的设计)

或者,如果我通过改写问题来概括它

可以将业务规则逻辑放在构造函数方法中吗?或者构造函数应该总是只做设置对象的内部结构吗?

谢谢

4

5 回答 5

5

在某种程度上,在构造函数本身中进行验证是有意义的,因为您知道它的所有用法都将通过该单点,并且任何其他将使用您的代码的开发人员都将因为您的“低级“验证。

如果您将验证移到调用链的更高位置,则可以使类代码更干净,但会使代码暴露于“您使用错误”错误的可能性。

于 2012-12-19T10:10:03.447 回答
3

构造函数验证在数据无效的情况下有一个小问题:那你怎么办?如果您经常创建“无效”实例,则必须抛出异常,这可能会很尴尬并且还会影响性能。

为了摆脱try ... catch每次实例化对象,无论如何你都必须创建一个工厂。

我认为工厂是一个很好的方法,但方式略有不同——验证给工厂方法的参数,然后才创建一个(有效的)实例。

于 2012-12-19T10:10:40.060 回答
3

一个类应该尽其所能记录它所做的保证,并尽最大努力使自己始终处于有效状态。任何不适当或会使对象处于无效状态的传入调用都应生成异常。

这也适用于构造函数。不验证其输入的构造函数使得其他人可以创建您的类的无效实例。但是如果你总是验证,那么任何引用你的类的人都可以确信它是有效的。

于 2013-01-10T14:58:12.163 回答
1

如果是我,我会在将参数传递给构造函数之前验证它们。您永远不知道您的代码将如何发展,因此按照您的建议在工厂进行验证应该提供更多的可见性并感觉“更干净”。

于 2012-12-19T10:09:24.213 回答
0

如果您可以选择在哪里引发异常,只需选择您更可能记得用 包围它的地方try..catch,这也有助于考虑您的代码库的其他用户。这通常不取决于课程的目的,以及您如何看待它的使用方式。然而,一致性也很重要。

有时在两者中都不引发异常而是ValidateInstance()为不可变类型提供单独的函数很有用。您的其他选择是您所说的类创建(通过工厂或构造函数)或类使用(如果可以更快抛出错误,通常是一个坏主意......但有时是有道理的)。

将它们放在构造函数中的好处是,如果您选择稍后再制作,它们也会出现在 Factory 方法中。

高温高压

于 2012-12-19T10:16:50.797 回答