您应该检查构造函数中的参数值是否错误?
您是否在每个构造函数中检查数据有效性,还是只是假设数据正确并在参数有问题的特定函数中抛出异常?
Do you check for data validity in every constructor, or do you just assume the data is correct and throw exceptions in the specific function that has a problem with the parameter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我同意一般情况下的 Sharptooth,但有时有些对象可能具有某些功能有效而某些功能无效的状态。 在这些情况下,最好推迟检查具有这些特定依赖项的函数。
通常您需要在构造函数中进行验证,因为这意味着您的对象将始终处于有效状态。 但某些类型的对象需要特定于功能的检查,这也没关系。
I agree with sharptooth in the general case, but there are sometimes objects that can have states in which some functions are valid and some are not. In these situations it's better to defer checks to the functions with these particular dependencies.
Usually you'll want to validate in a constructor, if only because that means your objects will always be in a valid state. But some kinds of objects need function-specific checks, and that's OK too.
这是一个很难的问题。 在过去的几年里,我多次改变了与这个问题相关的习惯,所以我想到了一些想法:
我认为这实际上取决于情况...我最终的结果是仅当我知道参数确实来自外部系统(例如用户输入、数据库、Web 服务或类似的东西...)时才编写参数检查。 如果数据来自我自己的系统,我大多数时候不会编写测试。
This is a difficult question. I have changed my habit related to this question several times in the last years, so here are some thoughts coming to my mind :
I think this really depends on the situation... what I ended up is to only write parameter checks when I know that the parameters do come from an external system (like user input, databases, web services, or something like that...). If data comes from my own system, I don't write tests most of the time.
我总是尝试尽早失败。 所以我最终检查了构造函数中的参数。
I always try to fail as early as possible. So I definitively check the parameters in the constructor.
理论上,在调用函数之前,调用代码应始终确保满足先决条件。 构造函数也是如此。
在实践中,程序员很懒,为了确保最好还是检查前提条件。 断言在那里派上用场。
例子。 请原谅我的非大括号语法:
或者,您可以随时更改前提条件。 对于构造函数来说,这并不是很方便。
In theory, the calling code should always ensure that preconditions are met, before calling a function. The same goes for constructors.
In practice, programmers are lazy, and to be sure it's best to still check preconditions. Asserts come in handy there.
Example. Excuse my non-curly brace syntax:
Alternatively, you can always change the preconditions. In case of a constructor this is not really handy.
总是尽快失败。 运行时展示了这种实践的一个很好的例子..
* 如果您尝试对数组使用无效索引,则会出现异常。
* 尝试铸造时会立即失败,而不是在稍后的某个阶段。
想象一下,如果引用中保留了错误的转换,并且每次您尝试使用它时都会遇到异常,那将是一场灾难代码。 唯一明智的方法是尽快失败并尝试尽快避免不良/无效状态。
Always fail as soon as possible. A good example of this practice is exhibited by the runtime ..
* if you try and use an invalid index for an array you get an exception.
* casting fails immediately when attempted not at some later stage.
Imagine what a disaster code be if a bad cast remained in a reference and everytime you tried to use that you got an exception. The only sensible approach is to fail as soon as possible and try and avoid bad / invalid state asap.
构造函数也是一个函数 - 为什么要区分?
创建对象意味着所有完整性检查都已完成。 检查构造函数中的参数并在检测到非法值后抛出异常是完全合理的。
其中,这简化了调试。 当您的程序在构造函数中引发异常时,您可以观察堆栈跟踪,并且通常可以立即找到原因。 如果您延迟检查,则必须进行更多调查以检测哪些早期事件导致当前错误。
A constructor is a function too - why differentiate?
Creating an object implies that all the integrity checks have been done. It's perfectly reasonable to check parameters in a constructor and throw an exception once an illegal value has been detected.
Among all this simplifies debugging. When your program throws exception in a constructor you can observe a stack trace and often immediately see the cause. If you delay the check you'll then have to do more investigation to detect what earlier event causes the current error.
拥有一个完全构造的对象,并且从一开始就“满足”所有不变量总是更好。 但是,请注意非托管语言中的构造函数抛出异常,因为这可能会导致内存泄漏。
It's always better to have a fully-constructed object with all the invariants "satisfied" from the very beginning. Beware, however, of throwing exceptions from constructor in non-managed languages since that may result in a memory leak.
我总是在构造函数中强制值。 如果用户懒得遵守规则,我只是默默地执行它们而不告诉他们。
因此,如果他们传递的值为 107%,我会将其设置为 100%。 我只是在文档中明确说明这就是发生的情况。
只有当没有明显的逻辑强制时,我才会向他们抛出异常。 我喜欢称其为“那些懒惰或愚蠢而无法阅读文档的人最惊讶的原则”。
I always coerce values in constructors. If the users can't be bothered to follow the rules, I just silently enforce them without telling them.
So, if they pass a value of 107%, I'll set it to 100%. I just make it clear in the documentation that that's what happens.
Only if there's no obvious logical coercion do I throw an exception back to them. I like to call this the "principal of most astonishment to those too lazy or stupid to read the documentation".
如果您放入构造函数,堆栈跟踪更有可能显示错误值的来源。
If you throw in the constructor, the stack trace is more likely to show where the wrong values are coming from.