设计问题:我应该在多大程度上依赖控制流程的例外?

我正在研究一个java Web应用程序,我有一些关于设计的问题。

基本上在其当前版本中,它在很大程度上依赖于捕获exception以确定控制流

例如,在我的一个Spring服务类中,我有以下方法来检查数据库中是否存在作为参数提供的电子邮件。

@Override public boolean validateEmailAddressDoesNotExist(String accountEmailAddress) { try { return !dao.checkIfEmailAddressAlreadyExists(accountEmailAddress); } catch (NoResultException re) { log.error("NoResultException", re); } catch (RuntimeException re) { log.error("RuntimeException", re); } return true; } //from "dao" class public boolean checkIfEmailAddressAlreadyExists(String accountEmailAddress) { return (loadAccountFromAccountEmailAddress(accountEmailAddress) == null ? false : true); } //also from "dao" class public Account loadAccountFromAccountEmailAddress(String accountEmailAddress) { return entityManager.createNamedQuery("Account.findByEmailAddress", Account.class).setParameter("accountEmailAddress", accountEmailAddress).getSingleResult(); } 

我怀疑我目前的设计可能是错的,但我很高兴看到你对它的评论和意见,以及你认为它有多大程度上存在缺陷。

服务模型中的validation方法不应该捕获exception。 由于以下几个原因,这很糟糕:

  • 这不是特例。 “没有结果”是一种常见的情况。

  • 间接地将您的validation与框架的数据检索方法的实现相结合。 要想知道为什么这不好,想象一下你的框架是否会发生变化,现在它会引发一个EmptyResultSetException 。 您必须更新所有validation方法。 哎呀!

如果您的底层框架引发exception以指示“无结果”,则您无法提供帮助,但您当然可以控制checkIfEmailAddressAlreadyExists执行的操作。

更改此方法,以便在地址存在时返回true ,如果不存在或者未找到结果则返回false

一般的经验法则是例外是针对“特殊”条件。

因此,如果数据项可能存在,或者可能合理地缺席,那么返回布尔值将更为正常。 它通常也会产生更简单,更清晰的代码。

然后,您可以将exception保存为真正特殊的条件,例如网络故障等。

在某些情况下,第三方库可能不会给你任何选择 – 如果它们抛出exception,那么你必须处理它们!

我更喜欢从checkIfEmailAddressAlreadyExists等方法返回一个布尔值,并根据返回值简单地控制流,并将Exceptions保留为真正exception的条件,例如,无法连接到数据库。

我不是Java程序员,实际上从未使用它。

但我确实知道在C#世界中提高和捕获exception是非常昂贵的。 因此,控制流量与它们相比是非常低效的,而不是自己检查事物,而是为DNA所说的事情留下例外。