今天要讨论的这个问题是一个很小的点,但是个很开放的问题,没有标准,在工作中是否要求到这个程度也全看各自的要求。
举一个场景,不以真实业务代入,只是说明问题。例如我们有一系列处理任务,都是接收一个 List,然后根据一些业务规则来处理,可能返回结果,也可能不返回,我们讨论的这个小问题集中在边界条件的判定上。因为传入的是 List,要进行如下的业务逻辑,仅在 List 有元素的情况下才有处理意义,所以每个函数开头都有对空的判断,类似如下:
public List<ResultOne> dealOne(List<One> ones) {
if (ones == null || ones.isEmpty()) {
return new ArrayList<>();
}
return new ArrayList<>() {{
new ResultOne();
}};
}
public List<ResultTwo> dealTwo(List<Two> twos) {
if (twos == null || twos.isEmpty()) {
return new ArrayList<>();
}
return new ArrayList<>() {{
new ResultTwo();
}};
}
public List<ResultThree> dealThree(List<Three> threes) {
if (threes == null || threes.isEmpty()) {
return new ArrayList<>();
}
return new ArrayList<>() {{
new ResultThree();
}};
}
复制代码
我们不管函数中的其他部分,只看开头的判断部分,也就是我们要讨论的问题。这句判断长得都一模一样,只是 List 的元素类型不同,这个判断如果要抽可以怎么抽呢,可以看如下抽取后的函数:
private boolean isEmptyList(List list) {
return list == null || list.isEmpty();
}
复制代码
相应的函数中就可以用 isEmptyList(xxx)来代替判断语句。从利用的角度讲这样做是有意义,但实际我们是比较少这么做。如果考虑到针对 List 的操作对 empty 的情况其实自身都有保护,如果最终只是判断一个 null,就更显得不是很必要。
进一步考虑,如果除了判断 List 外,很多地方都有对容器的空判断,像 Set、Map 等,那这个函数进一步改造一下就可以支持,如下:
private boolean isEmptyCollection(Collection collection) {
return collection == null || collection.isEmpty();
}
复制代码
这样对于 Collection 的所有实现都可以统一判空,似乎就多了些意义。但对其必要性我仍然是不确定的。
对这个简单的示例,考虑第二部分,比如触发了鞋类业务条件需要返回一个默认的含有一个指定元素的集合,如上面示例中每个函数返回了一个不同 Result 的 List,如果也要进一步抽象的话,用泛型实现如下:
private <T> List<T> getDefaultList(T t) {
List<T> results = new ArrayList<>();
results.add(t)
return results;
}
复制代码
经过这么抽象之后拿一个之前的函数来看效果,就变成了如下这样:
public List<ResultThree> dealThree(List<Three> threes) {
if (isEmptyCollection(threes)) {
return new ArrayList<>();
}
return getDefaultList(new ResultThree());
}
复制代码
对于这一篇中讨论的复用场景,是那种不是非常必要的场景,那么做不做也就看团队自己的要求和综合考虑吧。
评论