【问题标题】:Returning Null vs Exception vs Contract返回 Null vs Exception vs Contract
【发布时间】:2018-10-25 08:07:56
【问题描述】:

从数据库返回记录的可接受的处理方式有以下 3 种潜在结果:

  1. Db 连接有效,找到用户并返回填充的用户对象
  2. Db 连接有效,未找到用户,返回新用户对象
  3. 数据库连接/查询失败...

我的主要目标是按合同设计:

class Scratch {
        public User getUser(int id) {
            try {
                // Prepare SQL Query
                PreparedStatement s = this.connection.prepareStatement(
                        "select * from get_user(?)"
                );

                // Provide SQL Parameters
                s.setInt(1, id);

                // Run our SQL
                ResultSet rs = s.executeQuery();
                rs.next();

                // Extract data into Entity
                User user = User.createFromDatabase(rs);
                rs.close();

                return user;

            } catch(Exception e) {
                e.printStackTrace();
            }

            return new User();
        }
}

在数据库连接或查询失败的情况下,我应该做什么不太明显,我有几个选择:

  • 返回一个新的用户对象,因为我们的方法已经同意返回一个用户
    • 专业人士:坚持按合同设计
    • 缺点:这使它看起来用户不存在。
  • 返回 null,因为它实际上并没有获得用户。
    • 专业人士:很明显,找不到用户
    • 缺点:需要空检查
  • 抛出异常进一步向上链。
    • 专业版:明确说明未完成操作
    • 缺点:不会尝试纠正发生的问题

我倾向于处理异常,因为它避免了数十亿美元的错误,并且在正常情况下也保持了合同设计。

但是,我想知道是否存在任何明显的缺陷,或者这是否是一种熟悉的情况,并且有一个成熟的模式来解决它。

【问题讨论】:

  • getUser 应该只做一件事,就是获取用户。如果它不能,它应该抛出一个异常。对我来说,返回 null 给人的印象是用户不存在。相关:stackoverflow.com/questions/77127/when-to-throw-an-exception
  • @Ivar 谢谢我现在更新了,我在 IntelliJ 中打开了一个新的暂存文件并粘贴了一些代码。

标签: java exception-handling null design-by-contract


【解决方案1】:

我会抛出异常并让用户知道连接失败。返回 NULL 是我永远不会做的事情,因为你不会知道问题出在哪里。

如果您没有与数据库的连接,我不知道您为什么会返回“新用户对象”。您将无法保存该用户。

我的选择是抛出异常

【讨论】:

  • 我认为这是最合适的解决方案,从 ivar 的附加阅读来看,它看起来一致。我现在也重构了我的应用程序,这个解决方案最适合。
【解决方案2】:

使用可选(请)。这明确表明无法在数据库中找到用户并避免 NullPointerException。

  • 如果在数据库中找到用户,则可选(用户)
  • 如果找不到用户则为空
  • 如果出现错误,您有两种选择:
    • 通知客户端,以便它可以获取反馈并对失败做出反应。在这种情况下,抛出一个异常并在适当的层处理它。这应该是大多数应用程序的默认行为。
    • 向客户隐藏它,这种情况不太常见,但有时客户并不关心,或者您不想公布您的失败。在这种情况下,只需返回一个 Empty。

【讨论】:

  • 我不同意你的最后一点。我不确定“客户端”是什么意思,但如果那是最终用户,那么你总是可以在应用程序的其他地方捕获你的异常。像什么都没发生一样继续下去很容易出现错误/数据损坏。
  • @Ivar 这正是它在我的用例中不起作用的原因,我是批处理用户,所以假装一切正常会导致批处理更新程序进一步处理记录而不是暂停 &正在重试当前批次。
  • 我想我应该得到负面评价,不知道我在想什么-_-!。顺便说一句,我真的鼓励你使用 Optional 来避免在空结果请求上返回 null。
猜你喜欢
  • 2012-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 2011-10-27
相关资源
最近更新 更多