Skip to main content
14 of 17
added 98 characters in body
user avatar
user avatar

In my humble opinion, it's generally something to avoid largely for production code because you're generally not tempted to do it except in sporadic functions that perform disparate tasks. I tend to do it in some scrap code used to test things, but find no temptation to do it in production code where I've put some thought in advance as to what each function should do, since then the function will naturally have a very limited scope with respect to its local state.

I've never really seen examples of anonymous blocks being used like this (not involving conditionals, a try block for a transaction, etc) to reduce scope in a meaningful way in a function which didn't beg the question of why it couldn't be divided further into simpler functions with reduced scopes. It's usually eclectic code that's doing a bunch of loosely related or very unrelated things where we're most tempted to reach for this.

As an example, if you are trying to do this to reuse a variable named count, then it suggests you're counting two disparate things. If the variable name is going to be as short as count, then it makes sense to me to tie it to the context of the function, which could potentially just be counting one type of thing. Then you can instantly look at the function's name and/or documentation, see count, and instantly know what it means in the context of what the function is doing without analyzing all the code. I don't often find a good argument for a function to count two different things reusing the same variable name in ways that make anonymous scopes/blocks so appealing compared to the alternatives. That's not so suggest that all functions have to count only one thing. I'm saying I see little practical engineering benefit to a function reusing the same variable name to count two or more things and using anonymous blocks to limit scope of each individual count.

Not a Suggestion for Superfluous Methods

This is not to suggest you forcefully create methods either just to reduce scope. That's arguably just as bad or worse, and what I'm suggesting shouldn't call for a need for awkward private "helper" methods any more than a need for anonymous scopes. That's thinking too much about the code as it is now and how to reduce the scope of variables than thinking about how to conceptually solve the problem at the interface level in ways that yield clean, short visibility of local function states naturally without deep nesting of blocks and 6+ levels of indentation. I agree with Bruno that you can hinder code readability by forcefully shoving 3 lines of code into a function, but that's starting with the assumption that you are evolving the functions you create based on your existing implementation, rather than designing the functions without getting tangled up in implementations. If you do it the latter way, I have found little need for anonymous blocks that serve no purpose beyond reducing variable scope within a given method unless you're trying zealously to reduce the scope of a variable by just a few less lines of harmless code where the exotic introduction of these anonymous blocks arguably contributes as much intellectual overhead as they remove.

Trying to Reduce Minimum Scopes Even Further

If reducing local variable scopes to the absolute minimum was worthwhile, then there should be a wide acceptance of code like this:

ImageIO.write(new Robot("borg").createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())), "png", new File(Db.getUserId(User.handle()).toString()));

... as that causes the minimum visibility of state by not even creating variables to refer to them in the first place. I don't want to come off as dogmatic but I actually think the pragmatic solution is to avoid anonymous blocks when possible, and if they seem so absolutely necessary in a production context from the perspective of correctness and maintaining invariants within a function, then I definitely think how you are organizing your code into functions and designing your interfaces is worth re-examining. Naturally if your method is 400 lines long and a variable's scope is visible to 300 lines of code more than needed, that could be a problem, but it's not necessarily one to solve with anonymous blocks.

If nothing else, utilizing anonymous blocks all over the place is exotic, not idiomatic, and exotic code carries the risk of being hated by others, if not yourself, years later.

The Practical Usefulness of Reducing Scope

The ultimate usefulness of reducing the scope of variables is to allow you to get state management correct and keep it correct and allow you to easily reason about what any given portion of a codebase does -- to be able to maintain conceptual invariants. If a single function's local state management is so complex that you have to forcefully reduce scope with an anonymous block in code that's not meant to be finalized and good, then again, that's a sign to me that the function itself needs to be re-examined. If you have difficulty reasoning about the state management of variables in a local function scope, imagine the difficulty of reasoning about the private variables accessible to every method of an entire class. We can't use anonymous blocks to reduce their visibility. To me it helps to begin with the acceptance that variables will tend to have a slightly wider scope than they ideally need to have in many languages, provided it's not getting out of hand to the point where you'll have difficulty maintaining invariants. It's not something to solve so much with anonymous blocks as I see it as accept from a pragmatic standpoint.

user204677