Question:
什么被认为是“最佳实践” -and why- 处理构造函数中的错误?
“最佳实践”可以引用 Schwartz 的话,或者 50% 的 CPAN 模块使用它,等等……;但我对任何人提出的合理意见感到满意,即使它解释了为什么常见的最佳实践并不是真正的最佳方法。
就我自己对该主题的看法(多年来通过 Perl 软件开发了解),我在 Perl 模块中看到了三种主要的错误处理方法(在我看来从最好到最差列出):
-
构造一个对象,设置一个无效标志(通常是“is_valid
“方法)。通常通过类的错误处理来设置错误消息。
Pros:
允许标准(与其他方法调用相比)错误处理,因为它允许使用$obj->errors()
在错误的构造函数之后进行类型调用,就像在任何其他方法调用之后一样。
允许传递附加信息(例如 >1 错误、警告等...)
允许轻量级的“redo”/“fixme”功能,换句话说,如果构造的对象非常重,具有许多复杂的属性,那么100%总是可以的,并且它无效的唯一原因是因为有人输入了日期不正确,您只需执行“$obj->setDate()
“而不是再次重新执行整个构造函数的开销。这种模式并不总是需要的,但在正确的设计中可能非常有用。
Cons: 据我所知没有。
-
Return "undef
".
Cons:无法实现第一个解决方案的任何优点(全局变量之外的每个对象错误消息和针对重对象的轻量级“fixme”功能)。
死在构造函数内。除了一些非常狭窄的边缘情况之外,我个人认为这是一个糟糕的选择,因为有太多原因无法在这个问题的边缘列出。
更新:为了清楚起见,我认为(否则非常有价值且出色的设计)解决方案具有非常简单的构造函数,根本不会失败,并且有一个繁重的初始化方法,其中所有错误检查都只是其中一个的子集出于本问题的目的,情况#1(如果初始化器设置错误标志)或情况#3(如果初始化器死亡)。显然,选择这样的设计,您会自动拒绝选项#2。
这取决于您希望构造函数如何表现。
这个回应的其余部分属于我个人的观察,但与 Perl 的大多数事情一样,最佳实践实际上可以归结为“这是一种实现方法,您可以根据自己的需要采用或保留它”。您所描述的偏好是完全有效且一致的,没有人应该告诉您其他情况。
其实我prefer如果构造失败就会死,因为我们将其设置为在对象构造期间可能发生的唯一类型的错误实际上是应该停止执行的大的、明显的错误。
另一方面,如果您不希望这种情况发生,我想我更喜欢 2 而不是 1,因为检查未定义的对象与检查某些标志变量一样容易。这不是 C,所以我们没有强类型约束告诉我们构造函数必须返回这种类型的对象。所以回来了undef
,并检查它以确定成功或失败,是一个不错的选择。
构造失败的“开销”是某些边缘情况下的一个考虑因素(在这种情况下,在产生开销之前你不能很快失败),因此对于那些你可能更喜欢方法 1 的人。同样,这取决于你为对象定义的语义建造。例如,我更喜欢在构造之外进行重量级初始化。至于标准化,我认为检查构造函数是否返回已定义的对象与检查标志变量一样是一个很好的标准。
EDIT:为了响应您关于初始化程序拒绝案例 #2 的编辑,我不明白为什么初始化程序不能简单地返回一个指示成功或失败的值,而不是设置一个标志变量。实际上,您可能想同时使用两者,具体取决于您想要了解所发生错误的详细信息。但初始化程序在成功时返回 true 是完全有效的,并且undef
失败时。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)