我和我的朋友有争执。
他告诉我这段代码:method SetBalance(balance) {
if (balance > 0) {
this.balance = balance;
return true;
}
return false;
}
比这更好:
method SetBalance(balance) {
if (balance < 0) {
throw new InvalidArgumentException("Balance couldn't be negative")
}
this.balance = balance;
}
我的问题是:“哪种方法更适合验证?”为什么?
谢谢。
答案 0 :(得分:6)
阿。返回状态与异常。
我更喜欢抛出异常,因为你无法真正忽略异常。该程序要么崩溃,要么必须明确地捕获并处理它。
您可以忽略退货状态。
此外,这不是现代节目中存在例外的原因吗?处理好......异常(余额&lt; = 0,不应该发生的事情)。
答案 1 :(得分:1)
对于setter,开发人员永远不会期望这些方法的返回值,因为他们认为无论如何都将负责设置值。
万一,如果有异常,那么这将有助于理解某些事情确实是错误的,并再次照看代码。
而不是runtime exception
,您最好定义自己的异常,如InvalidBalanceException
,并指定此方法将在签名本身中抛出此异常。这避免了测试阶段的意外情况,并决定了开发阶段的业务逻辑。
答案 2 :(得分:1)
很容易忽略返回值。在这里你有明确的编码错误,所以大声崩溃。我甚至会停止/段错/停止程序 - 异常可能仍然被捕获。我们生活在“理想世界”中,但想象一下我们不那么幸运的同事 - 他们很可能会因为错误的信号设施无法处理根本原因(这里插入更复杂的错误情景)。当你不给客户做错事的方法时,编码会变得容易得多。
答案 3 :(得分:0)
除了已经给出的答案之外,在名为&#34; setFoo&#34;的函数中返回一个布尔值。是非常误导。如果你翻译一个布尔值,你会想出是/否。因此,在oop中返回布尔值的函数应该是可读的,作为回答是/否的问题,例如isBalanceSet。
在与同事的讨论中,我们认为普通setter的唯一有效返回值是fluent接口的类本身。
关于你的问题,如果类实际验证其属性本身,则抛出异常是更好的解决方案;)
答案 4 :(得分:0)
我的个人观点:这两种方法都有其用途。这取决于出现这种情况的原因,是否可以防止,客户可以做些什么来阻止它。
服务器强>
method SetBalance(int balance)
{
// do something only if balance >= 0
}
<强>客户端:强>
myServer.SetBalance(balance);
案例1: 出现这种情况只是因为某处(服务器或客户端)存在错误。抛出异常。让责任方修改其代码。
案例2: 从某些外部依赖项收到错误输入。客户可以轻松检查前提条件。抛出异常,如果客户对此代码不满意,请让客户修改代码。
if(balance>0)
myServer.SetBalance(balance);
else
//take appropriate action.
案例3: 从某些外部依赖项收到错误输入。客户端无法轻易检查前提条件。示例:它将要求客户端解析字符串,这是服务器的工作。在这里,服务器应该返回成功是有道理的:
bool succeeded = myServer.SetBalance(balance);
if(!succeeded)
//take appropriate action.
在写下我的答案之后,我注意到这一切归结为:客户端不应该使用try-catch来调用方法SetBalance。(要么它是一个bug,所以不要捕捉异常,或自己检查前提条件,或检查返回值)
以下是对相关主题的精彩解读:http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx
修改强> 乔乔提出了一个很好的观点。如果有可能失败,请重命名方法 TrySetBalance()。
答案 5 :(得分:0)
异常处理是处理OOP中的错误的选择方法,无论是运行时错误还是逻辑错误。证明异常处理的一个论据是,如果使用错误代码,函数的客户端可能忘记检查错误代码,从而导致可能不容易找到的潜在错误。然而,如果使用异常处理,即使它没有被捕获,它也会传播直到它被处理。因此,OOP纯粹主义者总是建议使用异常处理。