业务方法中的错误检查 a.k.a 进行防御性编程
Error checking in business methods a.k.a doing defensive programming
我开始向大型 java 代码库添加测试。我经常在我正在测试的会话 bean 中看到以下内容:
public OrderDTO getOrderDTO(Long id) {
Order o = (Order)entityManager.find(Order.class, id);
OrderDTO dto = new OrderDTO(o.getId(), o.getCurrency());
return dto;
}
编写单元测试来破解此代码(发送 null 或不存在的 ID)非常容易。当我这样做时,一半的团队开发人员说:
We are not error checking everything. If you parameter is rubbish you will know fast!
另一半说:
We must add ifs to the id and then to the o and if any of them are null the null is what we return.
单元测试的目的不就是为了准确地找到这些问题吗?
(是的,我是征求意见!)
是的,从 Long 切换到 Long 将删除一个 if。
虽然这在某种程度上是基于意见的,但如果给定 null
作为参数,很少有人会说 return null
是正确的。如果我要添加任何东西,它最多是一个IllegalArgumentException
(甚至NPE
)当传入null时。
可以创建一个测试来检查该方法是否以一致的方式失败,但它实际上是在测试 JPA 提供程序的行为,而不是您的代码。
应避免返回空值,它们是万恶之源。
您可以使用 Null Object Pattern.
或者抛出异常、非法参数或 entitynotexsits spring。
中
一如既往,这取决于 :)
如果您正在编写库代码(在其他地方或什至其他地方共享和使用的代码),那么您应该真正致力于以一致的方式处理所有可想到的输入值。使用记录良好的异常而不是 returning null 对于库代码来说当然更可取。
另一方面是本地代码。
我可以看到该方法是 public
,但这并不能排除它仅在代码库的一个孤立部分中使用的可能性。
在那种情况下,您不会使用关于参数的假设以及调用者在 return 中的期望。您使用定义的调用。您可以控制发送的内容以及调用方如何处理 return 值。因此,如果您知道调用者从不发送空值,则不进行空值检查是可以的。 return null 也可以,如果这样可以简化您的整体程序结构。
ps:如果 entityManager.find(..)
失败,该方法中最让我困扰的是未处理的 NPE :)
我开始向大型 java 代码库添加测试。我经常在我正在测试的会话 bean 中看到以下内容:
public OrderDTO getOrderDTO(Long id) {
Order o = (Order)entityManager.find(Order.class, id);
OrderDTO dto = new OrderDTO(o.getId(), o.getCurrency());
return dto;
}
编写单元测试来破解此代码(发送 null 或不存在的 ID)非常容易。当我这样做时,一半的团队开发人员说:
We are not error checking everything. If you parameter is rubbish you will know fast!
另一半说:
We must add ifs to the id and then to the o and if any of them are null the null is what we return.
单元测试的目的不就是为了准确地找到这些问题吗? (是的,我是征求意见!)
是的,从 Long 切换到 Long 将删除一个 if。
虽然这在某种程度上是基于意见的,但如果给定 null
作为参数,很少有人会说 return null
是正确的。如果我要添加任何东西,它最多是一个IllegalArgumentException
(甚至NPE
)当传入null时。
可以创建一个测试来检查该方法是否以一致的方式失败,但它实际上是在测试 JPA 提供程序的行为,而不是您的代码。
应避免返回空值,它们是万恶之源。
您可以使用 Null Object Pattern.
或者抛出异常、非法参数或 entitynotexsits spring。
中一如既往,这取决于 :)
如果您正在编写库代码(在其他地方或什至其他地方共享和使用的代码),那么您应该真正致力于以一致的方式处理所有可想到的输入值。使用记录良好的异常而不是 returning null 对于库代码来说当然更可取。
另一方面是本地代码。
我可以看到该方法是 public
,但这并不能排除它仅在代码库的一个孤立部分中使用的可能性。
在那种情况下,您不会使用关于参数的假设以及调用者在 return 中的期望。您使用定义的调用。您可以控制发送的内容以及调用方如何处理 return 值。因此,如果您知道调用者从不发送空值,则不进行空值检查是可以的。 return null 也可以,如果这样可以简化您的整体程序结构。
ps:如果 entityManager.find(..)
失败,该方法中最让我困扰的是未处理的 NPE :)