12

我想减少大型遗留 Java 代码库中声纳违规的数量,似乎“速赢”是将所有这些条件语句更新为带有大括号。这似乎是一件容易的事,我不明白为什么它不容易自动化。

有人知道可以执行这样的批量操作的工具吗?或者为什么在我花时间自己写东西之前做这样的事情可能是个坏主意?如果我自己写一个,最好的工具是什么?理想情况下是 Java 语言感知的东西,这样我就不必处理格式化极端情况等。

顺便说一句,这条规则是不可协商的,所以这确实是最好的方法。

4

8 回答 8

13

Control flow statement without braces首先在检查设置中启用。

IntelliJ Idea -> 运行代码检查 -> 快速修复(至少在商业版中有效)

于 2012-11-11T22:55:16.950 回答
7

最简单的方法是使用Eclipse并单击Clean-up整个项目。在Clean-up配置文件配置中选择Code style选项卡。在那里你可以选择Use blocks in if/while/for/do statementsAlways

于 2012-11-11T22:50:35.320 回答
6

虽然建议对遗留代码保持谨慎,但检测遗留代码中的错误也是一件好事……或者至少使错误更容易被发现。

让我们考虑一下 Brian Agnew 的困难案例:

// Case #1
if (x) doMethodA(); doMethodB();

事实上,就 JLS 和 Java 编译器而言,这意味着

if (x) doMethodA();
doMethodB();

所以当转换器将代码重写为:

if (x) { 
    doMethodA();
}
doMethodB();

它不会改变代码的含义,而是纠正可能导致某人误读代码的问题,并错过代码中已经存在的潜在错误;即如果第二次调用应该是有条件的......

// Case #2
if (x) 
    // doMethodA();
    doMethodB();

再一次,当它被重写时,你应该得到:

 if (x) {
    // doMethodA();
    doMethodB();
 }

这和原来的意思是一样的。此外,这很可能反映了程序员的意图……如果要相信缩进的话。但是考虑一下:

// Case #2a
if (x) 
    // doMethodA();
doMethodB();

当我们将其重写为

if (x) {
    // doMethodA();
    doMethodB();
}

代码的实际含义没有改变,不正确的缩进不再会误导。如果程序员决定取消第一次调用的注释,他可能没有意识到之前的注释已经产生了意想不到的后果。(证据在我们已经“修复”的原始缩进中。)但是有一个潜在的解决方案;见下文。


如果我们假设代码转换工具在正确理解 Java 的语法和语义的情况下运行,那么它不会破坏任何尚未破坏的东西,并且它会(在一定程度上)使任何现有的破坏对某人来说更加明显阅读代码。对我来说,这是一个零风险的胜利,即使对于遗留代码也是如此。

现在,如果我们让转换器更智能,它可以检测到原始缩进指示可能存在错误的一些情况(如上面的情况 #1 和 #2a),并标记它们以进行更仔细的代码检查。

于 2012-11-12T00:04:01.490 回答
3

这让我觉得可能非常危险。你有全面的单元测试覆盖率吗?

我可以看到一些直接困难的案例,例如

if (x) doMethodA(); doMethodB();

if (x) 
  // doMethodA();
  doMethodB();

有两个会浮现在脑海中并且不能天真地处理(您应该具有语言意识来解决这些问题)。除非你有语言感知和可靠的工具,否则我不会尝试自动化这样的任务,而是强制执行一个策略,当你出于其他原因更改代码时修改代码,并且可以在那个阶段通过单元测试断言代码覆盖率在更改代码之前。

于 2012-11-11T22:51:00.120 回答
2

罗伯特在评论中说:“@ira 我也有兴趣听到这个真正的语言感知工具!”

对不起,戏弄。对于取笑的原因,请查看我的简历。

Untease:参见http://www.semanticdesigns/Products/DMS/DMSToolkit.html作为基础引擎,以及http://www.semanticdesigns.com/Products/FrontEnds/JavaFrontEnd.html。这对创建了一个完全语言感知的源到源程序转换系统。

可以使用具有两个源到源转换规则的 DMS 完成此任务:

  rule curlies_for_then_statement:(c:expression, s: statement}: 
             statement->statement
       " if (\c) \s " -> "if (\c) { \s } ";


  rule curlies_for_else_statement:(c:expression, b: block, s: statement}:
              statement->statement
       " if (\c) \b else \s " -> "if (\c) \b else { \s } ";

这很可靠,因为 DMS 完全由形式语法驱动(在本例中为 Java),并且不是在原始文本上操作,而是在抽象语法树上操作;这也使得独立于布局。(理解“块”、“表达式”和“语句”是语法非终结符的规则可能很有用。

于 2012-11-12T13:56:06.663 回答
2

如果您首先在编辑器设置中设置正确的编码样式, Intellij 2017 通过Reformat Code支持此功能。

File -> Settings -> Editor -> Code Style -> Java -> Wrapping and Braces

编辑器设置 Intellij

于 2017-08-04T13:45:05.627 回答
1

虽然这可能是一个快速的声纳胜利,但你正在做一些危险的事情。推荐的方法是仅在必须重新访问该代码时才修复遗留代码。这些一揽子方法可能会导致非常微妙的错误。因为政策已经改变了你的管理团队需要明白这是一项艰巨的任务,并且应该保证所有未来的代码都按照标准开发。

于 2012-11-11T22:53:40.463 回答
-1

顺便说一句,这条规则是不可协商的,所以这确实是最好的方法。

有趣的。

您有一个充满样式错误的遗留代码库,并且必须修复样式错误是不可协商的。

这个练习的价值主张(至少可以说)是可疑的。“遗留代码库”通常是一种礼貌的说法,即代码应该被丢弃并重写......但你负担不起。但是,显然,您可以负担得起纠正丢失的大括号的费用,这不太可能对可维护性产生任何真正的影响。

正如之前的答案所指出的那样。如果您正确地自动执行此样式校正:

  • 它实际上不会修复任何错误,但也不会引入任何新错误。

  • 它可能会删除作为现有错误标志的“线索”(例如,可疑的缩进)。

但是,如果您手动进行样式更正:

  • 您有可能会注意到一些错误。这些可以添加到您的问题跟踪器中,以进行进一步的诊断和修复。

  • 您也有可能引入新的错误。如果我们假设现有的单元/系统不存在或质量低下(这是一个遗留代码库),那么这些新错误很有可能未被发现。

现在概括 Sonar 检测到的与样式相关的错误。

总而言之,修复遗留代码库中所有样式错误的整个过程(IMO)如果自动化则很大程度上是浪费时间,如果手动则可能存在风险。

应该是可以商量的。您应该能够告诉管理层这些问题......

于 2019-01-19T02:48:56.807 回答