【问题标题】:Is it bad to do Inner assignments?做内部作业不好吗?
【发布时间】:2012-06-27 08:24:10
【问题描述】:

我们正在与我的同事讨论内部任务,例如:

return result = myObject.doSomething();

if ( null == (point = field.getPoint()) )

这些是可以接受的还是应该被以下替换?为什么?

int result = myObject.doSomething();
return result;

Point point = field.getPoint();
if ( null == point)

【问题讨论】:

  • 我猜result 在第一种情况下是类的成员而不是局部变量。否则,分配是多余的。
  • @nhahtdh 可能是多余的,但代码更清晰,这是我们讨论的更清晰或更简洁的代码?
  • 我知道,但既然你提出了替代品,我只好发表评论了。

标签: java coding-style


【解决方案1】:

内部作业更难阅读,也更容易错过。在复杂的情况下,它甚至可能被遗漏,并可能导致错误。

例如。如果条件评估阻止为变量赋值,这将是一个很难发现的错误:

if (i == 2 && null == (point = field.getPoint())) ...

如果i == 2 为假,点变量稍后将没有值。

【讨论】:

  • 附上示例,如果条件过早失败,点变量可能不包含值。
  • && 和 ||是短路评估,这意味着如果 i != 2,point=field.getPoint() 将不会被评估
  • 我不认为这是反对内部分配的有效论据......如果你写得不好,那不是它的错。在考虑 if 语句时,我同意它不好,但在 while 语句中,不使用内部赋值会导致两次编写相同的赋值,这也不是很好。
  • 同样代表goto。它可以正确使用,也可以错误使用,但通常被认为是一种不好的做法。在这种情况下并不是那么极端,但在使用时最好小心。我只是强调了危险。
【解决方案2】:

if ( null == (point = field.getPoint()) )

优点:

  • 少了一行代码

缺点:

  • 可读性较差。
  • 不将point 的范围限制为语句及其代码块。
  • 据我所知,没有提供任何性能改进
  • 可能并不总是被执行(当它前面有一个计算结果为假的条件时。

缺点大于优点 4 / 1,所以我会避免它。

【讨论】:

  • 不是说内部赋值很好,但是关于你的回答我必须说明以下几点:1.如果内部赋值是第一个操作数,它也提高了可读性if ( (point = field.getPoint()) == null )我想说那:您的示例进一步降低了可读性。 2.关于“不限制point的范围”-->这是内部分配应该做的,所以你也可以把它写成专业人士并将其从缺点中删除:)
【解决方案3】:

这主要与代码的可读性有关。避免内部赋值以使您的代码可读,因为内部赋值不会有任何改进

【讨论】:

    【解决方案4】:

    功能上 Not Necessarily. 为了便于阅读 Definitely Yes

    【讨论】:

      【解决方案5】:

      应该避免它们。减少每行标识符/操作的数量将增加可读性并提高内部代码质量。这是关于该主题的有趣研究:http://dl.acm.org/citation.cfm?id=1390647

      所以底线,分手

      return result = myObject.doSomething();
      

      进入

      result = myObject.doSomething();
      return result;
      

      将使其他人更容易理解和使用您的代码。同时,如果在您的代码库中散布一些内部分配,只要它们在其上下文中易于理解,就不会是世界末日。

      【讨论】:

      • 但是在这种情况下为什么不直接使用return myObject.doSomething();呢?
      • 是的,这通常会更好。在处理长/复杂的方法链时,我只会做中间分配。在这些情况下,变量名可以用作文档。
      • 我曾经喜欢过这种方式,但 Sonar 抱怨它——这就是我产生这个想法的地方。
      【解决方案6】:

      嗯,第一个不完全是内部分配,但在第二种情况下......它降低了可读性......但在某些情况下,如下所示,

      while ( null == (point = field.getPoint()) );
      

      这样写就好了

      【讨论】:

        【解决方案7】:

        在这两种情况下,第一种形式都更难阅读,并且当您想在调试器中检查值时,您会想要更改它。我不知道我在单步调试时诅咒“简洁”代码的频率。

        【讨论】:

          【解决方案8】:

          在极少数情况下,内部赋值会降低程序复杂性,例如在if (x != null && y != null && ((c = f(x, y)) > 0) {...} 中,您实际上只需要在复杂条件下执行的情况下进行赋值。

          但在大多数情况下,内部分配会降低可读性,并且很容易被遗漏。

          我认为内部赋值是 70 年代 C 编程语言的第一个版本的遗留物,当时编译器没有进行任何优化,优化代码的工作留给了程序员。在那个时候内部赋值更快,因为没有必要再次从变量中读取值,但是今天有了快速的计算机和优化的编译器,这一点不再重要了。然而,一些 C 程序员已经习惯了它们。我认为 Sun 将内部赋值引入 Java 只是因为他们希望与 C 类似,并让 C 程序员更容易转换到 Java。

          【讨论】:

            【解决方案9】:

            始终致力于代码可读性而不是可写性a > b ? x : y; 之类的东西也是如此 可能有很多开发人员在阅读您的第一个代码片段时没有问题,但他们中的大多数人已经习惯了第二个片段。

            【讨论】:

              【解决方案10】:

              更详细的形式也使得在 Eclipse 等调试器中更容易理解。我经常拆分单行赋值,以便更容易看到中间值。

              虽然 OP 没有直接要求,但类似的情况是函数调用,因为方法参数可以节省行数,但更难调试:

              myFunction(funcA(), funcB());
              

              不显示返回类型并且更难单步执行。如果两个值属于同一类型,也更容易出错。

              【讨论】:

                【解决方案11】:

                我发现使用内部分配没有任何害处。它节省了几行代码(尽管我确信它不会改善编译或执行时间或内存)。唯一的缺点是对其他人来说可能看起来很麻烦。

                【讨论】:

                  猜你喜欢
                  • 2015-04-10
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-09
                  • 1970-01-01
                  • 2011-08-13
                  • 2022-10-18
                  • 2012-03-02
                  • 2012-04-11
                  相关资源
                  最近更新 更多