命名块来限制变量范围:好主意?

Dav*_*pik 46 java coding-style

多年来,我一直在使用命名块来限制临时变量的范围.我从未在其他任何地方看到过这种情况,这让我想知道这是不是一个坏主意.特别是因为Eclipse IDE默认将这些标记为警告.

我认为,在我自己的代码中,我已经使用了这个效果.但是,既然好的程序员在看到它时会不信任它,这是非惯用的,我真的有两种方法可以从这里开始:

  1. 避免这样做,或
  2. 促进它,希望它将成为一个成语.

示例(在更大的方法中):

final Date nextTuesday;
initNextTuesday: {
    GregorianCalendar cal = new GregorianCalendar();
    ... // About 5-10 lines of setting the calendar fields
    nextTuesday = cal.getTime();
}
Run Code Online (Sandbox Code Playgroud)

这里我使用GregorianCalendar来初始化日期,我想确保我不会意外地重复使用它.

有些人评论说你实际上不需要命名块.虽然这是真的,但原始块看起来更像是一个bug,因为意图不明确.此外,命名的东西鼓励你思考块的意图.这里的目标是识别代码的不同部分,而不是为每个临时变量赋予自己的范围.

很多人评论说最好直接采用小方法.我同意这应该是你的第一直觉.但是,可能有几个缓解因素:

  • 为了考虑一个命名块,代码应该是简短的一次性代码,永远不会在其他地方调用.
  • 命名块是一种快速组织超大方法的方法,无需使用十几个参数创建一次性方法.当一个类不稳定时,尤其如此,输入可能会随版本而变化.
  • 创建一种新方法可以促进其重用,如果用例不完善,这可能是不明智的.一个命名的块更容易(在心理上,至少)丢弃.
  • 特别是对于单元测试,你可能需要为一次性断言定义十几个不同的对象,它们只是不同,你不能(还)找到一种方法将它们合并为少量的方法,你也不能想办法用一英里长的名字来区分它们.

使用命名范围的优点:

  1. 不能无意中重用临时变量
  2. 有限范围为垃圾收集器和JIT编译器提供了有关程序员意图的更多信息
  3. 块名称提供了对代码块的注释,我发现它比开放式注释更具可读性
  4. 使得将大型方法中的代码重构为小方法更容易,反之亦然,因为命名块比非结构化代码更容易分离.

缺点:

不是惯用的:没有看到使用命名块的程序员(即除了我之外的所有人)都认为它有问题,因为他们无法找到对块名称的引用.(就像Eclipse一样.)让事情成为惯用语是一场艰苦的战斗.

它可以作为不良编程习惯的借口,例如:

  • 制作庞大的,单一的方法,其中几种小方法更易读.
  • 压痕层太深,无法轻易阅读.

注意:基于一些深思熟虑的回答,我已经广泛地编辑了这个问题.谢谢!

Jon*_*eet 26

我只是直接重构为更小的方法.如果一个方法是足够大,它需要打破这样的,它真正需要分解成多个方法,如果在所有可能的.

虽然限制范围很好,但这并不是命名块的用途.它是单一的,很少是一件好事.

  • 这里"命名块"是指带有标签的块.您可以在任何语句上添加标签,但它(当前)仅对块或控制语句有意义.可以将标签附加到break和continue语句,以指定它们应用于哪个(间接)封闭语句. (2认同)

Sco*_*ham 14

如果这很糟糕,那为什么这是该语言的一个功能!它有一个目的,你找到了它.

我经常编写与您的示例完全相同的代码.当你想要初始化一个变量时,需要做一些计算来计算应该是什么,并且这涉及到几个变量...那么你不希望这些变量在你的整个范围内闲逛函数,然后一个小范围包含初始化工作很棒.

迷你范围是将代码分解为"段落"的简单方法.如果您拆分为方法,那么当这些方法无法从其他任何地方调用时,您可以使代码更难导航,并且具有需要执行的序列式顺序.

它始终是一种平衡,但如果您认为它最容易维护,并且它实际上为未来的代码读者增加了价值,如果它全部内联,那就去吧.

没有严格的规则.有时候我会让同事过度地把所有东西都放在自己的方法或类或文件中,这让我感到有点厌倦,这成了导航的噩梦.某处有一个很好的平衡!


Joh*_*son 10

有时我使用未命名的块来隔离准备一些不可变的东西所需的可变事物.我没有使用标签,而是将块放在不可变变量声明下.

final String example;
{
   final StringBuilder sb = new StringBuilder();
   for(int i = 0; i < 100; i++)
     sb.append(i);
   example = sb.toString();

}
Run Code Online (Sandbox Code Playgroud)

当我找到块的其他用途,或者只是认为它在阻碍时,我把它变成了一个方法.


小智 9

在我的书中使用块来限制范围是一种很好的技术.

但是,既然你正在使用标签来做评论工作,为什么不只是使用实际的评论呢?这将消除对未引用标签的混淆.


anj*_*anb 5

这是我第一次看到其他人使用积木.噢!我以为我是唯一一个.我知道我没有发明它 - 记得在某处读它 - 可能来自我以前的C++世界.

我不使用标签,只是评论我在做什么.

我不同意所有要求你将其提取到方法中的人.我们在这些块中提供的大部分内容都不是真正可重用的块.它在大型初始化中是有意义的并且是的,我使用了块来防止COPY/PASTE错误.

BR,
~A