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

2022-09-01 00:04:23

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

我认为,在我自己的代码中,我已经很好地利用了这一点。但是由于它不是惯用语,以至于优秀的程序员在看到它时会不信任它,我真的有两条路要走:

  1. 避免这样做,或
  2. 推广它,希望它能成为一个成语。

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

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

在这里,我使用公历日历只是为了初始化日期,我想确保我不会意外地重用它。

有些人评论说,你实际上并不需要命名块。虽然这是真的,但原始块看起来更像一个错误,因为意图尚不清楚。此外,命名某些内容会鼓励您思考块的意图。这里的目标是标识代码的不同部分,而不是为每个临时变量指定自己的作用域。

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

  • 甚至要考虑命名块,代码应该是简短的一次性代码,永远不会在其他地方调用。
  • 命名块是一种快速组织超大方法的方法,无需创建具有十几个参数的一次性方法。当一个类处于变化中,并且输入可能会因版本而异时,尤其如此。
  • 创建新方法会鼓励其重用,如果用例尚未建立,这可能是不明智的。命名块更容易(至少在心理上)扔掉。
  • 特别是对于单元测试,您可能需要为一次性断言定义十几个不同的对象,并且它们只是足够不同,以至于您无法(尚未)找到将它们合并到少量方法中的方法,也无法想出一种方法来区分它们与一英里长的名称。

使用命名作用域的优点:

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

弊:

不是惯用语:没有见过这种命名块使用的程序员(即除了我以外的所有人)都认为这是错误的,因为他们找不到对块名称的引用。(就像Eclipse一样。让某些东西成为惯用语是一场艰苦的战斗。

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

  • 制作巨大的,整体的方法,其中几个小方法将更清晰。
  • 层缩进太深,不容易阅读。

注意:我根据一些深思熟虑的回答,对这个问题进行了广泛的编辑。谢谢!


答案 1

我只是直接重构成更小的方法。如果一种方法足够大,需要像这样分解,如果可能的话,它确实需要分解成多种方法。

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


答案 2

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

我经常编写与您示例中完全相同的代码。当你想初始化一个变量时,需要做一些计算来弄清楚它应该是什么,这涉及到几个变量......那么你不希望这些变量在整个函数范围内徘徊,那么一个小范围来包含初始化效果很好。

迷你作用域是将代码分解为“段落”的一种简单方法。如果拆分为多个方法,则可以使代码更难导航,因为这些方法不会从其他任何地方调用,并且具有需要执行它们的串行顺序。

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

没有硬性规定。我有时有点厌倦了同事,他们过度地将所有内容都放入自己的方法,类或文件中,这成为导航的噩梦。在某个地方有一个很好的平衡!