views:

580

answers:

11

For years, I've been using named blocks to limit the scope of temporary variables. I've never seen this done anywhere else, which makes me wonder if this is a bad idea. Especially since the Eclipse IDE flags these as warnings by default.

I've used this to good effect, I think, in my own code. But since it is un-idiomatic to the point where good programmers will distrust it when they see it, I really have two ways to go from here:

  1. avoid doing it, or
  2. promote it, with the hope that it will become an idiom.

Example (within a larger method):

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

Here I'm using a GregorianCalendar just to initialize a date, and I want to make sure that I don't accidentally reuse it.

Some people have commented that you don't actually need to name the block. While that's true, a raw block looks even more like a bug, as the intent is unclear. Furthermore, naming something encourages you to think about the intention of the block. The goal here is to identify distinct sections of code, not to give every temporary variable its own scope.

Many people have commented that it's best to go straight to small methods. I agree that this should be your first instinct. However, there may be several mitigating factors:

  • To even consider a named block, the code should be short, one-off code that will never be called elsewhere.
  • A named block is a quick way to organize an oversized method without creating a one-off method with a dozen parameters. This is especially true when a class is in flux, and the inputs are likely to change from version to version.
  • Creating a new method encourages its reuse, which may be ill-advised if the use cases aren't well-established. A named block is easier (psychologically, at least) to throw away.
  • Especially for unit tests, you may need to define a dozen different objects for one-off assertions, and they are just different enough that you can't (yet) find a way to consolidate them into a small number of methods, nor can you think of a way to distinguish them with names that aren't a mile long.

Advantages of using the named scope:

  1. Can't accidentally reuse temporary variables
  2. Limited scope gives garbage collector and JIT compiler more information about programmer intent
  3. Block name provides a comment on a block of code, which I find more readable than open-ended comments
  4. Makes it easier to refactor code out of a big method into little methods, or vice versa, since the named block is easier to separate than unstructured code.

Disadvantages:

Not idiomatic: programmers who haven't seen this use of named blocks (i.e. everyone but me) assume it's buggy, since they can't find references to the block name. (Just like Eclipse does.) And getting something to become idiomatic is an uphill battle.

It can be used as an excuse for bad programming habits, such as:

  • Making huge, monolithic methods where several small methods would be more legible.
  • Layers of indentation too deep to read easily.

Note: I've edited this question extensively, based on some thoughtful responses. Thanks!

+13  A: 

I'd just go straight for refactoring into smaller methods. If a method is big enough that it needs breaking up like this, it really needs breaking up into multiple methods if at all possible.

While limiting scope is nice, this isn't really what named blocks are for. It's unidiomatic, which is very rarely a good thing.

Jon Skeet
What are named blocks for specifically?
Jeremy
I've only ever seen them used for break/continue in loops.
Jon Skeet
Here "named blocks" refers to a block with a label. You can put a label on any statement, however it (currently) only makes sense for a block or control statement. Labels can be appended to break and continue statements to specify which (indirectly) enclosing statement they apply to.
Tom Hawtin - tackline
+3  A: 

If you have 5-10 lines of code that can safely be put into a block like that, the same code could just as well be extracted into a method.

This might seem like it's only a semantic difference, but at least with extracting into a method then you would gain the benefit of the ability of re-use.

matt b
+2  A: 

If this was bad, then why is this a feature in the language! It's got a purpose, and you've found it.

I often write code exactly as in your example. When you want to initialize a variable, and there's a little calculation that needs doing to work out what that should be, and that involves a couple of variables... then you don't want those variables hanging around for the entire scope of your function, then a little scope to contain the initialization works great.

Mini scopes work an easy way to break code into 'paragraphs'. If you split into methods you can make the code harder to navigate when they don't get called from anywhere else and have a serial kind of order in which they need to be executed.

It's always a balance, but if you think it's going to be easiest to maintain and it actually adds value to a future reader of your code if its all inline, then go for it.

There are no hard and fast rules. I get a little fed up sometimes with co-workers who excessively put everything into its own method or class or file, and this becomes a nightmare to navigate. There's a nice balance somewhere!

Scott Langham
A: 

I have done this in some of my c#. I didn't know you could name the blocks though, I'll have to try that see if it works in c# too.

I think the scope block can be a nice idea, because you can encapsulate code specific to something within a block of code, where you might not want to split it out into its own function.

As for the disadvantage of nesting them, I see that as more of a fault of a programmer not of scope blocks themselves.

Jeremy
+1  A: 

Using blocks to limit scope is a good technique in my book.

But since you're using the label to do the work of a comment, why not just use an actual comment instead? This would remove the confusion about the unreferenced label.

+3  A: 

I sometimes use unnamed blocks to isolate mutable things needed to perpare som immutable thing I'll need later on. So instead of having a label i put the plock under the immutable variable declaration.

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

}

Then when I find som other use for the block, or just think it's in the way I just move it to a method;

John Nilsson
+1  A: 
anjanb
A: 

Just because they exist doesn't mean they should be used. Most of the advantages gained from using named blocks are better gained by using a new private method.

  1. You won't be able to use the temporary variables declared in the new method
  2. The GC and JIT Compiler will glean the same info by using a new method
  3. Using a descriptive name for the new method (using "private Date initNextTuesday()" in your case) will allow for the self commenting code advantage
  4. No need to refactor code when you have already "pre-factored" it

In addition to these benefits, you also get code reuse benefits and it will shorten your long methods.

Haphazard
A: 

Named scopes are technically ok here, it's just they aren't used in this way very often. Therefore, when someone else comes to maintain your code in the future it may not be immediately obvious why they are there. IMHO a private helper method would be a better choice...

johnstok
A: 

It's a good technique in my book. Managing large numbers of throwaway methods is evil and the reasons you're providing for naming the blocks are good.

What does the generated bytecode look like? That'd be my only hesitation. I suspect it strips away the block name and might even benefit from greater optimizations. But you'd have to check.

Allain Lalonde
+1  A: 

I'd use a block with a comment rather adding a label there.

When I see a label, I can't assume that nothing else is referencing the block.

If I change the behavior of the block, then the label name may not be appropriate any more. But I can't just reach out and change it: I'll have to look through the rest of the method to determine what label is calling out to the block. At which point I'll figure out that it's an unreferenced label.

Using a comment is clearer in this instance, because it describes the behavior of the block without imposing any extra work on the part of the maintainer.

Will Sargent