【问题标题】:Rewriting a conditional statement in Java用Java重写条件语句
【发布时间】:2011-03-21 09:23:58
【问题描述】:

假设我有下面的代码,它基本上确定某些条件匹配,然后分配布尔值,然后运行一些代码。如果 booleanValue 为 false,则抛出异常。如果 booleanValue 为 false 而不运行其余代码,我希望它立即抛出异常怎么办?如果我只是将第二个条件语句放入第一个条件语句中,则会出现重复的代码。请告诉我一个聪明的方法来做到这一点(我已经修改了代码,使其看起来像我的实际代码)。

boolean booleanValue = false;
Permission value;

if (someCondition) {
   value = getPermission_1();
   booleanValue = someMethod(value);
   useValue_1(value);
}
else {
   value = getPermission_2();
   booleanValue = anotherMethod(value);

   useValue_2(value);
}

if (!booleanValue) {
   throw Exception();
}

【问题讨论】:

    标签: java design-patterns conditional


    【解决方案1】:

    消除布尔变量怎么样?你可以像这样重写你的代码:

    if (someCondition) {
       if (!someMethod()) {
         throw new Exception();
       }
       some codes...
    }
    else {
       if (!anotherMethod()) {
         throw new Exception();
       }
       some codes...
    }
    

    在我看来这看起来更容易,但这样的事情是一个品味问题......

    额外的好处:如果异常最终出现在堆栈跟踪中,您就会知道条件是什么,因为您有两个不同的抛出语句。这可能会加快调试速度。

    【讨论】:

      【解决方案2】:

      代替

       booleanValue = anotherMethod();
      

      你可以简单地写

      if( !someMethod() )
         throw new SomeException();
      

      在抛出一个通用异常时——不要。您抛出异常的原因是告诉调用者发生了异常情况。告诉他们什么几乎总是有用的,否则调用者和你都无能为力。

      【讨论】:

      • 你是对的,但我问的是一个不同的问题,这就是为什么我没有输入特定的 excpetion 名称。
      • 只是指出 if(!someMethod()) 与原始代码保持一致
      • 其实问题比这更复杂,请看我修改后的代码。
      • 不知道这如何使它更复杂......我的解决方案或@Nils 或这个仍然适用于您更新的方案。
      【解决方案3】:

      假设这两个some codes... 不同,您可能想要这样做:

      boolean booleanValue = someCondition ? someMethod() : anotherMethod();
      if(!booleanValue) {
          throw new Exception();
      }
      
      if(someCondition) {
          // some code
      } else {
          // some code
      }
      

      如果它们相同,则不需要if(someCondition)


      如果(假设)您有一个不允许三元表达式的静态分析工具,您可以将第一行替换为:

      boolean booleanValue;
      if(someCondition) {
          booleanValue = someMethod();
      } else {
          booleanValue = anotherMethod();
      }
      

      【讨论】:

      • 这对我来说是糟糕的代码风格。在 checkStyle 阶段会失败。
      • @newguy 那么,你将不得不定义你好的代码风格是什么;我对那个代码没有问题
      • 我的项目使用了一个检查样式插件,它不允许像第一行这样的任何代码,所以我必须遵守该规则。
      • @newguy 你的项目不允许三元表达式?这似乎......不好
      【解决方案4】:

      显而易见的解决方案是:

      boolean booleanValue = false;
      
      if (someCondition) {
         booleanValue = someMethod();
         if(booleanValue){
             //some codes...
         }
      }
      else {
         booleanValue = anotherMethod();
         some codes...
      }
      
      if (!booleanValue) {
         throw Exception();
      }
      

      ...但我不介意重复if(!booleanValue) throw Exception(); 位,因为您抛出异常可能是概念上不同的原因。 (例如,您可以在异常中提供更好的错误消息。)

      【讨论】:

      • 这不是解决方案。我想要的是在分配 booleanValue 后立即抛出异常,因为我不希望运行其余代码。
      • @newguy:请再看一遍。这就是它的作用。不过我的口味有点不清楚。我更喜欢 Joel 和 Nils 给出的答案。
      • @newguy:这个解决方案确实可以满足您的要求。我个人不喜欢这种风格,但它可能是编辑差异最小的解决方案。
      • 如果 anotherMethod() 给出一个错误的布尔值,它仍然会运行其余的代码,这不是我想要的。
      • @newguy:你是对的,可以假设你会在第一个块语句中看到模式,并推断出解决方案。
      【解决方案5】:

      这一切都非常主观,也许?

      boolean booleanValue = aBoolean;
      if (someCondition) {
         if (!someMethod()) {
             throw new SomeException();
         }
         some codes...
      } else {
         if (!anotherMethod()) {
           throw new AnotherException();
         }
         some other codes...
      }
      

      【讨论】:

        【解决方案6】:

        您最好的解决方案是......

        if (someCondition) {
           value = getPermission_1();
        
           if (!someMethod(value)) {
             throw new SomeException();
           }
        
           useValue_1(value);
        }
        else {
           value = getPermission_2();
        
           if (!anotherMethod(value)) {
             throw new AnotherException();
           }
        
           useValue_2(value);
        }
        

        而且您不应该将其视为重复代码,因为如果您想抛出异常,那么期望异常的原因在每种情况下都会有所不同,因此应该出现不同的异常或不同的消息在每种情况下都通过了。

        我假设您想知道哪个条件被执行并随后失败,因为您得到的只是来自您的 ...Method 调用的布尔值,在这种情况下,失败的原因可能不会很明显.

        【讨论】:

          【解决方案7】:

          这种气味……就像“代码气味”。正在将返回值转换为异常。似乎如果调用者编写了 someMethod 和 anotherMethod,那么解决方案是重写这些方法并从这些方法中抛出异常,而不是使用返回值。但这只有在程序员可以访问代码的情况下。如果是第 3 方 API 调用,我想可能必须进行翻译。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-02-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-06-16
            • 1970-01-01
            • 1970-01-01
            • 2015-03-22
            相关资源
            最近更新 更多