3

我们通常在业务逻辑中进行不必要的检查以避免失败。

例如。

1. public ObjectABC funcABC(){

      ObjectABC obj = new ObjectABC;
     ..........
     ..........
     //its never set to null here.
     ..........
     return obj; 
} 

ObjectABC o = funABC();

if(o!=null){
//do something
}

如果我们确定它永远不会为空,为什么我们需要这个空检查?这是一个好习惯吗?

2. int pplReached = funA(..,..,..);
   int totalPpl   = funB(..,..,..);

   funA() just puts a few more restriction over result of funB().


    Double percentage = (totalPpl==0||totalPpl<pplReached) ? 0.0 : pplReached/totalPpl;

我们需要'totalPpl<pplReached'检查吗?

问题是:通过这样的检查,我们不是吞下了一些基本问题吗?通过进行这些检查可以避免理想情况下应该显示的问题。

推荐的方法是什么?

4

1 回答 1

8

想想你的听众。支票是值得的

  1. 帮助你,程序员,检测错误,
  2. 帮助其他程序员检测他们的代码遇到的错误,
  3. 允许程序从错误输入或无效状态中恢复,或
  4. 帮助维护人员避免以后引入错误。

如果您null上面的检查不属于这些,或者有一个更简单的机制可以做同样的事情,那么就把它排除在外。

更简单的机制通常包括,

  1. 单元测试。
  2. 向读者传达意图并且可以通过findbugs或类似工具检查的注释
  3. asserts 导致代码提前失败,并传达意图,而无需您放入永远不应到达的错误处理代码,也不会混淆代码覆盖工具
  4. 文档或内联注释

在这种情况下,我建议添加注释

public @Nonnull ObjectABC funcABC(){

将 findbugs 集成到您的构建过程中,并可能替换

if(o!=null){
//do something
}

assert o != null: "funcABC() should have allocated a new instance or failed."

通过这样的检查,我们不是吞下了一些基本问题吗?

根据经验,

  1. 单元测试适用于检查一小段代码的行为。如果您不能为重要功能编写单元测试,那么根本问题是您没有编写可测试的代码
  2. 注释有助于向代码审查者、维护者和自动化工具传达意图。如果您没有将这些工具集成到您的流程中,那么根本问题是您没有利用可用的代码质量工具。
  3. asserts 有利于仔细检查您的假设。如果您不能在代码中加入断言并快速判断哪些被违反,那么您的根本问题是您没有快速的方法来针对代表性数据运行代码以解决问题。
  4. 文档和内联注释(包括源代码控制注释)有助于在团队中传播有关系统的知识——确保团队中不止一个人可以解决代码中任何部分的问题。如果它们经常丢失或不同步,那么潜在的问题是您在编写代码时没有考虑到维护者。

最后,契约式设计是一种编程方法,许多人发现它对业务逻辑代码很有用。即使您无法说服您的团队采用特定的工具和实践,阅读 DbC 仍可能有助于您推理和解释如何在代码库中强制执行重要的不变量。

于 2012-03-27T17:26:51.187 回答