当我使用JUnit测试检查我的编码过程时,我发现有一些问题困扰我。 例如:
List<User> list = userDao.findBy("id",id);
list.get(0).getName();
存在问题。我没有使用任何断言来检查列表在使用之前是否为空,这可能导致NullPointException。但请查看业务逻辑。
当我像这样创建一个新用户时。
if(user!=null){
userDao.save(user)
}
它应该不为null。因为我在添加一个用户时检查用户不是null,所以我肯定知道用户在数据库中是成功的。
如果我在收到用户时添加了很多内容:
if(list!=null||list.size()>0){...};
在使代码陷入混乱的类似地方。
我应该添加还是不添加?如何做出选择? 无论如何。不过。
答案 0 :(得分:0)
我认为您要找的是方法preconditions,或者更常见的是contracts。
让我们假设你的代码被分成许多小方法,应该是这样。然后为每个方法定义前置条件和后置条件。这些都需要得到满足,否则就会出现失败。如果你一直这样做,那么把这些检查放在哪里的问题将以非常直观的方式回答自己。
作为一个例子,让我们考虑两种方法来编写一个用User
做某事的方法:
private void doSomethingWithUser(User u) {
if (u == null) {
/* take appropriate steps */
}
/* perform some action on the user object */
}
上面,该方法负责空值检查。因此,调用代码不需要这样做。
/*
* Does this and that with the User.
* Precondition: the User `u` may not be null!
*/
private void doSomethingWithUser(User u) {
/* perform some action on the user object */
}
此处,该方法不会检查u
null
,但是阅读评论后,我们可以看到这就是该方法的设计方式。调用代码负责提交非null对象,否则行为将是未定义的。
当然,现在你面临着何时决定采用哪种方式的决定。显然,您可以为方法设置前提条件和让它们仍然执行适当的检查。然后,他们可以返回一个指示错误或抛出异常的值,这很常见。
修改强>
但如果在使用之前需要检查很多对象?我应该检查它们吗?
考虑一下:
public class SimpleClass {
public static void main (String[] args) {
User sware = new User("sware");
User domdom = new User("domdom");
doSomethingWithUser(sware);
doSomethingWithUser(domdom);
}
}
在这里,我们声明和在main
方法中初始化两个对象。我们知道它们不是空的。然后我们马上使用它们。无论该方法是否检查null
,我都不会在外面执行此类检查 - 这些对象无法null
。
现在,想象一下我们有一个更复杂的代码:
public class VeryComplexClass extends ComplexClass implements ComplexInterface {
/* ... */
@Override
private boolean doSomethingWithUser(User u) {
if (u == null) {
return false;
}
/* ... */
}
}
假设我们需要实现doSomethingWithUser()
方法来满足接口。或者该方法来自父类,我们覆盖它。我们不知道u
将来自哪里。谁有可能称之为这种方法?来自课外的用户?或者这个方法是否被类本身使用?会被传递成员吗?在这一点上很难说清楚。因此,我建议将null
检查到位。
答案 1 :(得分:0)
由于您已经检查过用户是否为空,我不认为您需要担心NullPointerException。只需继续使用该代码