代码之家  ›  专栏  ›  技术社区  ›  sharptooth

如何调用这种编写代码的方式?

  •  1
  • sharptooth  · 技术社区  · 15 年前

    我正在回顾一个相当老的项目,并且已经第二次看到像这样的代码(C++类伪代码):

    if( conditionA && conditionB ) {
       actionA();
       actionB();
    } else {
       if( conditionA ) {
          actionA();
       }
       if( conditionB ) {
          actionB();
       }
    }
    

    在这个代码中 conditionA 对两个计算的结果都相同,对 conditionB .所以代码相当于:

    if( conditionA ) {
       actionA();
    }
    if( conditionB ) {
       actionB();
    }
    

    因此,对于相同的效果,前一种变体的代码只增加了两倍。如何才能调用这种编写代码的方式(我的意思是前一种变体)?

    12 回复  |  直到 15 年前
        1
  •  1
  •   manji    15 年前

    我会称之为“两次更好”。这样做是为了确保运行时真正理解问题;)。

    (尽管在多线程、不安全的环境中,这两种变体的结果可能不同。)

        2
  •  13
  •   Nikolai Fetissov    15 年前

    这确实是一种糟糕的编码实践,但请注意,如果条件A和条件B的评估有任何副作用(var增量等),那么这两个片段是不等价的。

        3
  •  6
  •   chotchki    15 年前

    我会称之为坏代码。尽管我倾向于在项目中发现类似的构造,它们在没有进行任何代码审查的情况下增长。(或其他松散的开发实践)。

        4
  •  4
  •   Wim ten Brink    15 年前

    伙计们?看这部分:(条件A && 条件B) 基本上,如果条件A恰好是假的,那么它不会计算条件B。

    现在,这将是一种糟糕的编码风格,但是如果条件A和条件B不仅仅是评估数据,而且如果这些条件后面还有一些代码可以更改数据,那么这两个符号之间可能存在巨大的差异!

    如果ConditionA为false,则ConditionA被计算两次,ConditionB只被计算一次。 如果ConditionA为true,ConditionB为false,则对这两个条件进行两次计算。 如果两个条件都为真,则两个条件只执行一次。

    在第二个建议中,这两个条件只执行一次…因此,只有当两个方法的值都为真时,这些方法才是等效的。

    为了使事情更复杂,如果ConditionB为false,那么Actiona可以更改将更改此验证的内容!因此,else分支也将执行actionb。但是,如果两个条件的值都为true,而actiona会将conditionb的值更改为false,那么它仍然会执行actionb。

    我倾向于将这种代码称为:“当你可以用一种困难的方式做事情时,为什么要让事情变得容易?”把这当作一种设计模式。实际上,它是” Mortgage-Driven development “如果代码变得更复杂,那么主要的开发人员将是唯一能够理解它的人,而其他开发人员将变得困惑,希望放弃重新设计整个代码。因此,最初的开发人员需要留下来仅仅是为了维护这个代码,这被称为“工作保障”,从而能够支付他的抵押贷款多年。


    我想知道为什么会使用这样的东西,然后意识到我在自己的代码中使用了类似的结构。类似,但不相同:
    if (A&&B){
      action1;
    } elseif(A){
      action2;
    } elseif(B){
      action3;
    } else{action4}
    

    在这种情况下,每个操作都将显示不同的消息。无法通过连接两个字符串生成的消息。比如说,它是游戏的一部分,A检查你是否有足够的能量,B检查你是否有足够的质量。你没有足够的质量和能量,你不能再建造任何东西,需要显示一个严重的警告。如果你只有能量,警告你必须找到更多的质量就足够了。只有能量,你的建设者就需要充电。两者都可以继续构建。四种不同的动作,所以这个奇怪的结构。 然而,Q中的样本显示出完全不同的东西。基本上,你会得到一个信息,你失去了质量,另一个信息,你失去了能量。这两条消息没有合并成一条消息。

    现在,在这个例子中,如果条件A可以检测到能级,条件B可以检测到质量能级,那么这两个解都可以正常工作。现在,如果actiona告诉你的建设者们降低他们的质量并开始充电,你会突然在游戏中再次获得一点质量。但是如果条件性B表明你的质量耗尽了,那就不再是真的了!仅仅是因为Actiona再次发布了大量内容。如果行动B是命令建筑商尽快开始收集质量,那么第一个解决方案将给所有建筑商这个命令,他们将首先开始收集质量,然后继续他们的其他行动。在第二个解决方案中,不会给出这样的命令。建筑商再次充电,开始使用刚刚释放的小质量。如果每5分钟进行一次检查,那么这些建筑商将在一分钟内重新充电,以使其闲置4分钟,因为它们的质量耗尽。在第一种解决方案中,它们会立即开始收集质量。

    是的,这是一个愚蠢的例子。再次扮演最高指挥官。:-)只是想想出一个可能的方案,但是它可以改进很多!…

        5
  •  3
  •   Michael Kristofik    15 年前

    它是由不知道如何使用 Karnaugh Map .

        6
  •  3
  •   Michael Burr    15 年前

    这与“Fizzbuzz”设计模式非常接近:

    if( fizz && buzz ) {
       printFizz();
       printBuzz();
    } else {
       if( fizz ) {
          printFizz();
       }
       else if( buzz ) {
          printBuzz();
       }
       else {
          printValue();
       }
    }
    

    也许代码是作为fizzbuzz的一个实例开始的(可能是复制的n粘贴的),然后由于稍微不同的要求而被稍微重构成您今天看到的内容,但是重构并没有达到它应该达到的程度(布尔逻辑有时可能比人们想象的要复杂一些-因此fizzbuzz作为一个面试排除了TE技术。

        7
  •  2
  •   Clement Herreman    15 年前

    我也会称之为坏代码。

    缩进没有最好的方法,但有一条金科玉律:选择一条并坚持下去。

        8
  •  2
  •   PaulMcG    15 年前

    这是“冗余”代码,是的,它是坏的。如果必须在对actiona的调用中添加一些前提条件(假设前提条件本身不能放入actiona中),那么我们现在必须在两个位置修改代码,因此会有忽略其中一个的风险。

    在这种情况下,删除一些代码行比编写新的代码行感觉更好。

        9
  •  2
  •   Rodrigo    15 年前

    效率低下的代码?
    也可以称为 每行付费

        10
  •  1
  •   heijp06    15 年前

    我可能会称之为“上个月我在匆忙中写的代码/不专注/疲惫”。它发生了,我们都犯过或曾经犯过这种错误。改变它。如果你想,你可以试着找出是谁做的,希望不是你,并给他/她的反馈。

        11
  •  1
  •   sbi    15 年前

    既然你说你已经看过不止一次了,这似乎不止是因为疲劳造成的一次错误。我看到有人反复提出这种代码的几个原因:

    1. 代码最初是不同的,被重构了,但不管是谁做的,都会发现这是多余的。
    2. 做这件事的人对布尔逻辑没有很好的理解。

    (此外,还有一点可能性,这可能比您简化的截图显示的更多。)

        12
  •  1
  •   Patrick    15 年前

    正如pgast在注释中所说,如果action a影响conditionb,则此代码没有任何错误(请注意,这不是一个有副作用的条件,而是一个有副作用的操作(您可能希望如此))。