我已经阅读了不同文章的主题,似乎在使用已检查或未检查异常方面存在巨大争议,这让我对我的最终设计产生怀疑。
我不会详细介绍批评或支持已检查/未检查异常的论点,因为它们可能都是众所周知的,而是为了寻求一些建议,以改进我的设计并使其(尽可能)类似于实际应用程序。
该系统负责使用JDBC在关系型数据库(比如MySQL)中执行基本的CRUD操作。我有以下内容:演示层、服务层和持久层。
根据 处理服务层中的Dao异常 的答案,不公开特定层实现并解耦层是有道理的。因此,我决定创建自定义异常,并将它们包装成每个层级的基本异常,以便我可以将特定层级的异常(即 SQLException)转换为一般层级的异常(即 PersistentException、BusinessException)。如果以后实现发生变化,我只需将新实现简单地包装在更高层级所期望的基本异常中即可。因此,我有以下异常:
com.user.persistent.exceptions
|_ PersistentException
|_ ExistingUserException
|_ Some more..
com.user.business.exceptions
|_ BusinessException
|_ somemore....
从Josh Bloch的书Effective Java中:“对于调用方可以合理地预期恢复的条件,请使用已检查异常。”我也不太确定,但我相信用户可以从SQLExeption中恢复(即用户错误提供现有ID,他可以重新输入正确的ID),因此我决定将先前的异常更改为已检查异常。以下是类的概述:
持久层。
public interface UserDAO
{
public void create(User team) throws PersistentException;
}
//Implementation in DefaultUserDAO.java
@Override
public void create(User team) throws PersistentException
{
try
{
System.out.println("Attempting to create an user - yikes the user already exists!");
throw new SQLIntegrityConstraintViolationException();
}
catch(SQLIntegrityConstraintViolationException e)
{
throw new ExistingUserException(e);
}
catch (SQLException e)
{
throw new PersistentException(e);
}
finally
{
//close connection
}
}
服务层:
public interface UserService
{
void create(User user) throws BusinessException;
}
//Implementation of UserService
@Override
public void create(User user) throws BusinessException
{
System.out.println("Doing some business logic before persisting the user..");
try
{
userDao.create(user);
}
catch (PersistentException e)
{
throw new BusinessException(e);
}
}
演示
try
{
userService.create(user);
} catch (BusinessException e)
{
e.printStackTrace();
}
现在有几点让我对这个设计感到不确定。
- 我喜欢编译器验证方法使用已声明异常时是否捕获/抛出的想法,但我同时认为这种方法会导致处理所有异常的混乱代码。不确定是因为我没有正确使用异常还是因为检查异常确实会导致混乱的代码。
- 我也喜欢通过将特定层的异常包装成通用异常来解耦层。但是,我可以看到会为每种可能的异常创建大量新类,而不是只抛出现有的Java异常。
- 我还可以看到,很多现有的代码都用于处理异常,只有一小部分用于系统的实际目标。