最近我对我的一些java类一直很偏执,我一直在各处插入异常,以确保我没有将值设置为null或者如果它们没有正确初始化则获取值。起初,这似乎是遵循标准验证模式的好主意:
public method doSomething(arg1)
{
if(!isValidArg1(arg1))
{
throw new IllegalArgumentException;
}
...
}
但这已经达到了我的每一个吸气剂/孵化器看起来像这样的程度:
public String getLogicalName()
{
if (logicalName == null)
{
throw new UninitializedAttributeException("attribute: logical name.");
}
return logicalName;
}
public void setLogicalName(String logicalName)
{
if (StringUtils.isBlank(logicalName))
{
throw new IllegalArgumentException("attribute: logical name, illegal value: null, empty or whitespace.");
}
this.logicalName = logicalName;
}
除了在编写这些琐碎的方法上花费太多时间之外,我觉得我在过度设计。当然,调试变得更加困难,但它不像普通的nullpointerexpection那样没有告诉你问题是什么。
我抛出所有这些异常的主要原因是因为我想在前端向最终用户显示出错的明确信息。我对一些只是catch(Exception e)
包裹所有代码的程序感到失望,如果某个地方出现问题,所有用户看到的都是“某些地方出了问题,但我无法告诉你什么和哪里。”。但是,大多数情况下,用户无法对这些异常做任何事情,因为这是一个开发问题(尽管用户可以告诉开发人员究竟出了什么问题,这很好)。那么这个过度设计了吗?
我对此表示怀疑。你们其他开发者如何应对这种情况?在哪些情况下,明确检查方法的输入/输出值是一种良好的做法,以及哪些情况下冗余并使源代码混乱?可以绘制一条线吗?
答案 0 :(得分:1)
输入验证总是一个好主意 - 越早完成,越好。我建议为所有非私有方法执行此操作。有些人甚至提倡对私人方法这样做,以防万一在任何时候可见性发生变化。其他人相信他们自己的包,只验证公共和受保护的方法。
不需要在getter中执行验证。您可以完全控制类的内容,因此您的字段不应进入错误状态。输入验证可确保您永远不会设置您以后未在getter中批准的状态值。记住从getter返回可变对象时的防御性复制。
关于用户的错误消息 - 只需专注于抛出对您的方法有意义的异常。稍后如何呈现给用户取决于表示层。您所能做的就是准确描述您班级背景下出了什么问题。
“第61项 - 抛出适用于抽象的例外”,( Effective Java,Second Edition )。
答案 1 :(得分:0)
如果您对这些检查的设计方面感兴趣,Microsoft有一个有趣的C#系统,它允许您定义方法的输入要求以及您可以期望作为输出的内容。它比运行时检查更进一步,因为它可以与静态分析工具结合使用。
代码合约
http://msdn.microsoft.com/en-us/library/dd264808(v=vs.110).aspx
我尝试在Java中寻找类似的东西。如果您想立即使用某些东西,这可能会引起您的兴趣:
guava-libraries:PreconditionsExplained
https://code.google.com/p/guava-libraries/wiki/PreconditionsExplained