2008-08-22 42 views
9

我有一些代码给一个实用程序,然后发送电子邮件给该用户的用户ID。您是否为特定问题或一般例外编写例外情况?

emailUtil.sendEmail(userId, "foo"); 

public void sendEmail(String userId, String message) throws MailException { 
    /* ... logic that could throw a MailException */ 
} 

MailException可以抛出一些原因,与电子邮件地址的问题,与邮件模板的问题等

我的问题是:你创建的每一个新的异常类型这些异常,然后单独处理它们,或者您是否创建一个MailException,然后在异常(计算机可读,而不是描述文本)中存储一些东西,这些异常允许我们根据实际发生的事情做不同的事情。

编辑:作为一个澄清,例外不适用于日志和不是,这与代码如何对它们做出反应有关。为了保持与邮件例如去,让我们说,当我们发送邮件可能失败,因为你没有一个电子邮件地址,或者它可能是因为你没有有效的电子邮件地址,或者它可能会失败..等

我的代码会想不同的反应,每一个问题(主要是通过改变信息返回给客户端,但实际的逻辑也一样)。

难道是最好有这不得不给它一些内部的这些问题,每一个或一种把伞异常的异常实现(枚举说了),让代码区分什么样的问题,它是。

回答

8

我通常从一般的异常开始,并根据需要进行子类化。如果需要的话,我总是可以捕捉到一般的异常(以及它的所有子类异常),但也可以捕捉到具体的异常。

来自Java-API的示例是IOException,它具有FileNotFoundException或EOFException(以及更多)之类的子类。

这样,你得到两者的优点,你不必扔从句,如:

throws SpecificException1, SpecificException2, SpecificException3 ... 

一般

throws GeneralException 

就足够了。但是如果你想对特殊情况有一个特殊的反应,你总能找到特殊的例外。

1

这取决于你的应用程序在做什么。你可能想扔在案件个别例外像

  • 该应用程序是高可用性
  • 发送电子邮件尤为重要
  • 的应用范围小,发送电子邮件是一个很大一部分它
  • 该应用程序将被部署到一个网站,为远程和你只会得到日志调试
  • 您可以封装在mailException例外的某个子集恢复,但不是别人

在大多数情况下,我会说只要登录异常的文字,不要浪费你的时间已经相当granularizing颗粒例外。

10

在我的代码,我发现大多数例外渗透达到,他们是由我的异常处理程序简单地显示一个消息给用户(和写入日志)抓到一个UI层。毕竟,这是一个意外的例外。

有时候我也想赶上一个特定的异常(如你似乎想要做的)。但是,您可能会发现这种情况有点罕见,并且它指示使用异常来控制逻辑 - 效率低下(缓慢)并且经常被忽视。

因此,使用你的例子,如果你想运行一些特殊的逻辑没有配置邮件服务器时,您可能需要一个方法添加到emailUtil对象,如:

公共BOOL isEmailConfigured()

...先调用它,而不是寻找特定的异常。

当有异常情况真的发生,它的真正含义,这种情况是完全出乎意料和代码不能处理它 - 所以你能做的最好的是它报告给用户(或将其写入日志或重启)

作为具有异常层次VS例外与 - 误差码功能于他们,我通常做后者。如果你只需要定义一个新的错误常量而不是全新的类,那么添加新的异常就更容易了。但是,只要您尝试在整个项目中保持一致,则无关紧要。

+0

你还记录你的例外服务器端? – pjp 2009-08-07 10:39:42

+0

@php:是的,好点,如果它是一个服务器代码。对于真正的客户端应用程序(而不是web),我通常也可以选择在客户端登录异常以进行调试。 – 2009-08-08 17:21:54

1

我倾向于从可能执行有问题的方法返回一个状态对象列表,而不是使用异常。状态对象包含严重性枚举(信息,警告,错误,...)状态对象名称,如“电子邮件地址”和用户可读消息,如“格式不正确的电子邮件地址”

调用代码将决定过滤到用户界面以及自己处理的内容。

我个人认为,例外的是严格的,当你无法实现正常的代码解决方案。性能问题和处理限制对我来说有点太过分了。

另一个原因使用状态的对象的列表是标识多个错误(例如,在验证过程中)要容易得多。毕竟,你只能抛出一个例外,在继续之前必须处理。

想象一下,一个用户提交一个有畸形的目的地址,包含语言,你是阻止电子邮件。你会抛出畸形的电子邮件异常,然后,他们解决并重新提交后,抛出一个糟糕的语言异常?从用户体验角度来看,一次处理所有这些问题是更好的方法。

UPDATE:合并的答案

@Jonathan:我的观点是,我可以评估的动作,在这种情况下,发送电子邮件,并发送回多失败的原因。例如,“错误的电子邮件地址”,“空白邮件标题”等。

有一个例外,你只能渗透一个问题,然后要求用户重新提交,他们发现了关于第二个问题。这是非常糟糕的UI设计。

重新发明轮子..可能。但是,大多数应用程序应该分析整个事务,以便向用户提供最好的信息。想象一下,如果你的编译器在第一个错误时停下来。然后修复错误并再次编译,只是为了让它再次停止以发生不同的错误。屁股多么痛苦。对我来说,这就是抛出异常的问题,也就是我说的使用不同机制的原因。

+1

例外情况非常有用,如果正确使用,使代码更具可读性。随着每个现代虚拟机的发布,语言功能(例如异常)的性能都会发生变化,所以您必须每次都对照if-子句(您显然必须使用它来检查方法的结果)来衡量它。如果检查方法检查结果混乱你的代码,并使其难以维护。不要误解我的意思 - 有时候状态对象是一个很好的解决方案。特别是如果你处理多个错误(如你所提到的),它们比例外更有用。但是,这个决定应该是深思熟虑的。 – Mnementh 2009-08-14 11:01:38

2

@ Chris.Lively

你知道你可以在你的异常,甚至“状态码”传递的消息。你在这里重新发明轮子。

0

我倾向于有更少的异常类型,虽然它不是真正的OO方法。相反,我把一个枚举给我的自定义异常,它分类异常。大多数情况下,我有一个自定义的基本Exception,它可以保存到一些成员,这些成员可以在派生的Exception类型中被覆盖或自定义。

几个月前,我blogged关于如何国际化异常的想法。它包含了上面提到的一些想法。

-1

,我只想通过

throw new exception("WhatCausedIt") 
如果你想处理您的例外

去,你可以传递一个代码,而不是“WhatCausedIt”的反应,然后用switch语句不同的答案。

+0

而不是将异常中的代码作为参数传递,您可以继承异常并使用instanceof。 – Mnementh 2009-08-14 10:55:12

0

虽然可以differenciate代码执行寻找的异常,如果它是由“抓exceptionType层次模式”或做并不重要,“如果(...)...其他异常代码模式”

但是如果你正在开发将被其他人使用的软件,比如图书馆,我认为它是有用的创建你自己的异常类型,以通知其他人你的软件可以抛出比正常软件更多的异常,并且它们更好地捕捉并解决它们。

当我使用库和他们的方法简单地启动一个'例外'我总是想知道:什么会导致此异常?,我的程序如何反应?,如果有javadoc也许原因将被解释,但必须有没有一个javadoc或例外情况没有解释。使用WellChossenExceptionTypeName可以避免太多的开销女巫

0

这取决于捕获异常的代码是否需要区分异常或是否仅使用异常来出错到错误页面。如果您需要区分NullReference异常和调用堆栈中较高位置的自定义MailException,请花时间写出它。但是大多数时候程序员只是使用异常来捕捉网页上的错误。在这种情况下,你只是在努力编写一个新的例外。

1

我认为上述的组合会给你最好的结果。

根据问题,您可以抛出不同的异常。例如缺少电子邮件地址= ArgumentException。

但是,在UI层中,您可以检查异常类型,并在需要时检查消息,然后向用户显示相应的消息。我个人倾向于只向用户显示一条信息消息,如果抛出某种类型的异常(我的应用程序中出现UserException)。当然,您应该尽可能多地清理并验证用户输入,以确保任何异常都是由真正不太可能发生的情况生成的,而不是用于使用正则表达式可以轻松检查的畸形电子邮件的筛选器。

我也不会担心从用户输入中捕获异常的性能影响。唯一一次你会看到异常中的性能问题是当它们被抛出并陷入循环或类似情况时。

2

我发现如果您需要让CODE根据返回的异常决定要做什么,请创建一个名为异常的子类化常见基类型。通过的信息应该被认为是“仅限人眼”,并且太脆弱以至于无法作出决定。让编译器完成这项工作!

如果您需要通过一种不知道检查异常的机制将其传递给更高层,则可以将其包装在RuntimeException(MailDomainException)的适当命名子类中,该类可能会被捕获,并且原因会起作用根据。