你相信函数的返回类型么?

120 阅读2分钟

假设我们有一个函数用来返回整数的绝对值

public Integer abs(Integer value) {
    return Math.abs(value);
}

另外有一个函数用整数的绝对值作为索引取链表中对应的元素

public Integer getElement(Integer index, List<Integer> list) {

   Integer absIndex = abs(index);

   if(absIndex >= list.size()){
       return -1;
   }

   return list.get(absIndex);
}

问题来了,我们需要在getElement中检查absIndex >= 0么?

我们或许可以相信abs就是返回了一个非负整数,因为这就是它要实现的需求。但abs其实是和需求不一致的。需求是说abs应该返回整数的绝对值,也就是一个非负整数,但它返回的却是整数,是可以为负的。

考虑到abs非常简单,只是调用了Math.abs,我们也许有足够的信心相信,虽然它返回的类型是整数,但它返回的一定是非负整数。

但要是函数逻辑非常复杂怎么办?我们是很难通过一直记住这个复杂逻辑来得到正确的返回类型的。

我们可以通过添加测试来保证返回值是符合需求的,但我们很难覆盖所有场景,例如我们不可能测试所有的整数。如果将来有人修改了逻辑,测试依然是通过的,编译器也不会报错,我们只能在运行时发现错误。

所以函数的返回类型需要和需求相匹配,这样调用者就可以相信它。如果出现了不匹配的情况,我们就需要做一些额外的检查工作。

对于abs,最理想的方案是返回一个非负整数。但在Java里没有非负整数,我们不得不返回整数,那么我们最好对它的返回值做检查。

我知道这并不是我们的通常做法,例如我们不会检查Math.abs的返回值是否为负数。这是因为我们相信JVM的函数不会错。一切都和信心有关,如果我们团队有足够的信心,我们可以忽略这些检查,但团队必然需要付出其他的工作量,增加认知负担,添加更多测试或紧急修复线上bug。