Blocks for scope control

A

Arved Sandstrom

See
http://stackoverflow.com/questions/1563030/anonymous-code-blocks-in-java
for a general discussion.

I'm talking specifically about the block by itself: a pair of braces by
themselves, enclosing some code in a method. On occasion I do run across
situations where a judicious use of such a block inside a method, to
restrict variable visibility, is handy.

I almost never see anyone else using these things this way. A block in a
method always seems to be associated with a control construct or
exception handling. As any number of references point out, you wouldn't
expect to see many usages of local blocks, mainly because 99 times out
of 100 that situation is probably handled best by a new method. But in
my years of looking at Java it occurs to me that I barely see any use of
this at all...even where it wouldn't be a bad idea.

Any thoughts?

AHS
 
R

Robert Klemme

See
http://stackoverflow.com/questions/1563030/anonymous-code-blocks-in-java
for a general discussion.

I'm talking specifically about the block by itself: a pair of braces by
themselves, enclosing some code in a method. On occasion I do run across
situations where a judicious use of such a block inside a method, to
restrict variable visibility, is handy.

I almost never see anyone else using these things this way. A block in a
method always seems to be associated with a control construct or
exception handling. As any number of references point out, you wouldn't
expect to see many usages of local blocks, mainly because 99 times out
of 100 that situation is probably handled best by a new method. But in
my years of looking at Java it occurs to me that I barely see any use of
this at all...even where it wouldn't be a bad idea.

Any thoughts?

I can't remember ever having used a block without flow control inside a
method for other purposes than experimenting with scoping rules. And I
am not missing anything. I believe the fact that variables can be
declared in a for loop header as well as that all loops and if-else open
a new scope (as well as methods, of course) is responsible for me never
using blocks inside methods. IMHO chances are that if you need one or
more blocks inside methods that these things are pretty independent and
better handled by a method call which has the added benefit of providing
documentation via the method name, if chosen wisely.

Kind regards

robert
 
S

Stefan Ram

Arved Sandstrom said:
Any thoughts?

Im using this whenever it makes sense. For example,
say you wanted to add a button:

{ final Button button = new Button(); frame.add( button ); }

We now have clearly documented that »button« is just a
temporary name, used only in this line (better readability).
Moreover, when we want to add two buttons in this way, we
can copy the line

{ final Button button = new Button(); frame.add( button ); }
{ final Button button = new Button(); frame.add( button ); }

with no need to find an artificial new name for »button«
(although one could argue against such redundant coding)
or add a loop

for( int i = 0; i < 2; ++i )
{ final Button button = new Button(); frame.add( button ); }

or apply the refactor »extract method«:

void m( final Frame frame )
{ final Button button = new Button(); frame.add( button ); }

without ever needing to open the block and change something
inside of it (open-closed principle).
 
R

Robert Klemme

Im using this whenever it makes sense. For example,
say you wanted to add a button:

{ final Button button = new Button(); frame.add( button ); }

Why do you think it makes sense to replace this

frame.add( new Button() );

with the block above? If initialization is more complex, I'd rather do this

frame.add( createButton() );

than
or apply the refactor »extract method«:

void m( final Frame frame )
{ final Button button = new Button(); frame.add( button ); }

Cheers

robert
 
S

Stefan Ram

Robert Klemme said:
Why do you think it makes sense to replace this
frame.add( new Button() );
with the block above?

This code (comments removed by me):

for (ThumbnailAction thumbAction : chunks) {
JButton thumbButton = new JButton(thumbAction);
buttonBar.add(thumbButton, buttonBar.getComponentCount() - 1);
}

can be found in the renowned Java Tutorial at

http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html

. So such temporary names for one-time use are not
against common teachings.
 
M

markspace

I almost never see anyone else using these things this way.


IMO, I dislike spurious and overused indentation in code, so that's
likely why I shy away from "extra" use of braces.

for( ...some code )
{
do some init
{
do a little work
{
declare a temporary variable
}
{
declare another temporary variable
}
{
declare yet another temporary variable
}
{
declare still yet another temporary variable
{
declare a temporary variable inside
an anonymous block
}
}
}
}

vs. just one level of indentation, I believe I'd greatly prefer the
latter, especially in the long run. And the above is with 3-4 spaces
for indenting, imagine what it would look like with 8.
 
L

Lew

Arved said:
See
http://stackoverflow.com/questions/1563030/anonymous-code-blocks-in-java
for a general discussion.

I'm talking specifically about the block by itself: a pair of braces by
themselves, enclosing some code in a method. On occasion I do run across
situations where a judicious use of such a block inside a method, to
restrict variable visibility, is handy.

I almost never see anyone else using these things this way. A block in a
method always seems to be associated with a control construct or
exception handling. As any number of references point out, you wouldn't
expect to see many usages of local blocks, mainly because 99 times out
of 100 that situation is probably handled best by a new method. But in
my years of looking at Java it occurs to me that I barely see any use of
this at all...even where it wouldn't be a bad idea.

Any thoughts?

You see it standardly in initialization blocks, especially static, though I
often (more often than not) find myself refactoring static initialization
blocks to private static methods. For instance initialization they're
extremely useful for blocks that multiple constructors must share.

Within methods I use them as well, to enforce temporariness of variables.
This is very handy to prevent re-use of a variable whose usefulness has
expired. The need is rare, but like the legendary left-handed stembolt, if
you don't have it when you need it, that's a worry.

This idiom is also valid in other languages (e.g., C).

Calling such code blocks "anonymous" doesn't make sense. Code blocks aren't
named in the first place.

There are many, many idioms in Java that are woefully underused. 'assert' is
the prime example. People don't understand it, even excoriate it (strange as
that seems), and it's been around about a decade, since Java 1.4. Lack of use
does not equate to lack of value.
 
L

Lew

Stefan said:
This code (comments removed by me):

for (ThumbnailAction thumbAction : chunks) {
JButton thumbButton = new JButton(thumbAction);
buttonBar.add(thumbButton, buttonBar.getComponentCount() - 1);
}

can be found in the renowned Java Tutorial at

http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html

. So such temporary names for one-time use are not
against common teachings.

Some argue, and there's merit in the position, that the one-time name idiom
enhances code readability over the constructor-in-the-method-argument idiom.

(I also find merit in the "you ought to know Java well enough to read a
friggin' construction in an argument, for God's sake" argument, for anyone
claiming remuneration for their Java skills. Lacking such knowledge and
charging for your Java skills is fraud if the ignorance is not disclosed up
front.)
 
L

Lew

IMO, I dislike spurious and overused indentation in code, so that's likely why
I shy away from "extra" use of braces.

for( ...some code )
{
do some init
{
do a little work
{
declare a temporary variable
}
{
declare another temporary variable
}
{
declare yet another temporary variable
}
{
declare still yet another temporary variable
{
declare a temporary variable inside
an anonymous block
}
}
}
}

vs. just one level of indentation, I believe I'd greatly prefer the latter,
especially in the long run. And the above is with 3-4 spaces for indenting,
imagine what it would look like with 8.

Since eight-space indentation violates the Java coding conventions it doesn't
deserve consideration. Code that indents eight spaces should be rejected in
code review and brought into compliance.

<http://www.oracle.com/technetwork/java/codeconventions-136091.html#262>

But your larger point is valid, and you can just do this:

for( ...some code )
{
do some init
do a little work
declare a temporary variable
declare another temporary variable
declare yet another temporary variable
declare still yet another temporary variable
declare a temporary variable inside
}

The reason to go with the supposedly "extra" braces is to guarantee that a
temporary variable is not re-used, but if a method is so long that that's a
risk there's a good chance that it's too long.

And again I say, "anonymous block" makes no sense because blocks aren't named
in the first place.
 
A

Arved Sandstrom

You see it standardly in initialization blocks, especially static,
though I often (more often than not) find myself refactoring static
initialization blocks to private static methods. For instance
initialization they're extremely useful for blocks that multiple
constructors must share.

At the instance and class levels, it's true, these blocks operate
similarly to "local" blocks.
Within methods I use them as well, to enforce temporariness of
variables. This is very handy to prevent re-use of a variable whose
usefulness has expired. The need is rare, but like the legendary
left-handed stembolt, if you don't have it when you need it, that's a
worry.

This is exactly the use I was calling out. After visibility modifiers we
then have a number of levels of scope - class, instance, method and
block. We already use restrictive variable scoping in blocks; everyone
who re-uses for-loop index names benefits from this.

My point is simply that on some occasions, as you point out yourself,
you do want to "enforce temporariness" of a variable in a scope narrower
than that of its enclosing method. The answer here, on those infrequent
occasions where it makes sense to use a block, is not to blindly create
a new method simply to get variable scoping. That reflexive practice can
lead to unreadable fragmented code.
This idiom is also valid in other languages (e.g., C).

Calling such code blocks "anonymous" doesn't make sense. Code blocks
aren't named in the first place.

Well, to be fair, *I* didn't call them "anonymous", the original poster
at StackOverflow did. :) Strictly speaking they are blocks, and nothing
but blocks; in order to specify more exactly what type of block I meant
I referred to them as "local blocks".
There are many, many idioms in Java that are woefully underused.
'assert' is the prime example. People don't understand it, even
excoriate it (strange as that seems), and it's been around about a
decade, since Java 1.4. Lack of use does not equate to lack of value.
Quite apart from (lack of) understanding as to how to apply assertions
effectively and correctly, I believe that there are other reasons why
they are not more widely used. Some are good, some not so good, some are
neutral.

I'm with you on this one, though. I like assertions and use them.

AHS
 
L

Lew

Okay, not all that many, but some.
Quite apart from (lack of) understanding as to how to apply assertions
effectively and correctly, I believe that there are other reasons why
they are not more widely used. Some are good, some not so good, some are
neutral.

I'm with you on this one, though. I like assertions and use them.

I am curious as to the "good" reasons why they're not more widely used. I can
think of none I'd categorize as "good".

There are good reasons not to use them in certain scenarios, e.g., they are
not intended nor should be used for checking arguments to public methods, but
that doesn't speak to why 'assert' isn't more widely used for the intended use
cases.
 
R

Robert Klemme

At the instance and class levels, it's true, these blocks operate
similarly to "local" blocks.

That's also a feature I use from time to time. But I thought this
discussion was more about blocks inside methods since initializer blocks
are a quite different beast (you can view them as anonymous methods
without arguments and return type).
This is exactly the use I was calling out. After visibility modifiers we
then have a number of levels of scope - class, instance, method and
block. We already use restrictive variable scoping in blocks; everyone
who re-uses for-loop index names benefits from this.

My point is simply that on some occasions, as you point out yourself,
you do want to "enforce temporariness" of a variable in a scope narrower
than that of its enclosing method. The answer here, on those infrequent
occasions where it makes sense to use a block, is not to blindly create
a new method simply to get variable scoping. That reflexive practice can
lead to unreadable fragmented code.

But there are other blocks which also restrict scope (i.e. flow
control). So more often than not I find myself using those. Plus, I
now have made it a habit to make variables final as often as possible
(mostly for documentation reasons) and thusly also prevent accidental reuse.

Regarding the method refactoring argument: if there is so much code and
hence so many local variables that you want to use blocks to introduce
smaller scopes chances are that the logic within that blocks is also
largely independent from the code around so it is a good candidate for
refactoring anyway. The reason for refactoring into methods isn't the
scope but the independent logic.

Kind regards

robert
 
R

Robert Klemme

This code (comments removed by me):

for (ThumbnailAction thumbAction : chunks) {
JButton thumbButton = new JButton(thumbAction);
buttonBar.add(thumbButton, buttonBar.getComponentCount() - 1);
}

can be found in the renowned Java Tutorial at

http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html

. So such temporary names for one-time use are not
against common teachings.

OK, but here there are more arguments to add() and the line is longer.
That makes more sense than the original example to me.

Cheers

robert
 
R

Roedy Green

Any thoughts?

I use them fairly often for this construct:
{
FastCat sb = new FastCat( 2);
sb.append( "xxx");
sb.append( "yyyy");
thing = sb.toString();
}

{
FastCat sb = new FastCat( 2);
sb.append( "zzz");
if ( q )
{
sb.append( "aaa");
}
another = sb.toString();
}
 
H

Henk van Voorthuijsen

I use them fairly often for this construct:
  {
  FastCat sb = new FastCat( 2);
  sb.append( "xxx");
  sb.append( "yyyy");
  thing = sb.toString();
  }

  {
  FastCat sb = new FastCat( 2);
  sb.append( "zzz");
  if ( q )
    {
    sb.append( "aaa");
    }
  another = sb.toString();
  }

Interesting cae, but even here I would be inclined to use a variation
of "extract method":

thing = cat("xxx", "yyyy");

String cat(String... strings) {
FastCat sb = new FastCat( 2);
for (String str: strings) {
sb.append(str);
}
}

....
 
A

Arne Vajhøj

See
http://stackoverflow.com/questions/1563030/anonymous-code-blocks-in-java
for a general discussion.

I'm talking specifically about the block by itself: a pair of braces by
themselves, enclosing some code in a method. On occasion I do run across
situations where a judicious use of such a block inside a method, to
restrict variable visibility, is handy.

I almost never see anyone else using these things this way. A block in a
method always seems to be associated with a control construct or
exception handling. As any number of references point out, you wouldn't
expect to see many usages of local blocks, mainly because 99 times out
of 100 that situation is probably handled best by a new method. But in
my years of looking at Java it occurs to me that I barely see any use of
this at all...even where it wouldn't be a bad idea.

Any thoughts?

I can see couple of reasons why it is not used much:

1) The average Java developer is not aware of the possibility.

2) If a method is so complex that this trick has a significant effect
for avoiding mistakes, then the method should be broken up in
multiple smaller methods.

Arne
 
A

Arved Sandstrom

On 15.01.2012 22:49, Arved Sandstrom wrote:
[ SNIP ]
But there are other blocks which also restrict scope (i.e. flow
control). So more often than not I find myself using those. Plus, I
now have made it a habit to make variables final as often as possible
(mostly for documentation reasons) and thusly also prevent accidental
reuse.

Also a good practice. There is some irony in you mentioning this,
insofar as most programmers don't do this either...usually because they
don't see anyone else doing it. Which leads to a situation where one
needs to justify using "final" as often as possible, rather than the
burden of justification being the other way around.

I know there's the perennial debate about final classes, but final
variables are a different ball of wax. I rather wish folks thought the
way you did, and maybe then a coder would have to justify *not* making a
variable final.
Regarding the method refactoring argument: if there is so much code and
hence so many local variables that you want to use blocks to introduce
smaller scopes chances are that the logic within that blocks is also
largely independent from the code around so it is a good candidate for
refactoring anyway. The reason for refactoring into methods isn't the
scope but the independent logic.

Kind regards

robert
To focus on your points above, you _would_ refactor into
methods...*except* for those few cases where the methods end up being
trivial, and because the method body is located elsewhere you lose some
perspective on your code, and the replacement of the potential local
blocks with methods obscures the calling code.

Let me give you an example. Some days prior to writing my post I had to
write some code that processed a number of items in a similar fashion.
Each item was a matter of 2 or 3 lines of code. In theory each process
could have been collapsed into one very long line with multiple
duplicated and chained method calls, rather than use temporary local
variables, but I abhor this practice. So for clarity I kept the
operations on each item as 2 or 3 lines of code with at least one
temporary local variable.

Although the type of the local variable was the same, the operations
that produced it were not - they depended on the item. So any method
that would have replaced all these individually simple simple groups of
operations would have been either a moderately complex switch or a
moderately complex if-else if-else structure, less easy to understand,
and more error-prone. Furthermore, a flag would have been necessary to
the method to indicate which branch to take.

As you may have guessed this logic had to do with post-processing
various String and Boolean command-line options delivered by a
command-line processor. Quite frankly there is nothing pretty about
this, and there never has been in any language I've ever used - all you
can hope for is to keep the code clear, as error-free as possible, as
change-proof as possible (one of the main reasons for me using local
blocks actually), and just tolerate the boilerplate processing otherwise.

So this is one example, and I think a decent one. I don't think I
actually need to defend it, because a block is a legitimate language
construct, and you may wish to use them sometimes rather than end up
with mini-methods.

However, the intent of the thread was to get some feedback, and I thank
you all for it.

AHS
 
A

Arved Sandstrom

Okay, not all that many, but some.


I am curious as to the "good" reasons why they're not more widely used.
I can think of none I'd categorize as "good".

There are good reasons not to use them in certain scenarios, e.g., they
are not intended nor should be used for checking arguments to public
methods, but that doesn't speak to why 'assert' isn't more widely used
for the intended use cases.
Lew, I had side-effects of assertions in mind when I wrote that, for
one. I know, and you know, that Java docs on assertions clearly point
out that assertions should not have side-effects, that you should be
able to omit their execution and not affect the remaining code. However,
good intentions and all, a widespread use of assertions by developers
who haven't thoroughly checked the assertion logic to ensure its purity
may lead to testing anomalies.

As an example, what if the condition you wish to assert at a specific
point has no immediately available variables to work with? It might be a
temptation for a programmer to call some getters to obtain the values.
As we know, many getters are not side-effect free, even ones that ought
to be, and unless a coder religiously checks this out there may be a
problem. A novice coder might not notice that a getter is synchronized,
as an example, and simply note the fact that the getter itself does
nothing but return a value.

Perhaps not a "good" reason, but I'd call it a realistic one.

Yes, the Java assertion documentation happens to use an example where a
local variable is conveniently produced by a previous necessary piece of
logic, and the following assertion can happily use that value. Not
always so easy.

Another decent reason, in my opinion, is if the management of them is
not disciplined. An organization that doesn't even wonder whether they
are disciplined enough to manage assertions in code isn't, and others
that do ask the question may decide that they are not.

What I mean by this is, assertions are easy to put in. They are not
always correct when put in, and they have to be maintained in any case
as code changes (or at least removed if necessary). Existing obsolete
assertions need to be taken into account when adding new ones in the
same class or package, because if you enable one then you may enable
more. Or you remove old ones you don't understand, if you trust yourself
to understand the business rules from 4 years ago well enough to
classify the assertions as being defunct.

Let me put it this way: I would feel good about looking at code that had
assertions in it if I saw that they were also commented where necessary,
including traceability notes where that makes sense, *and* were
supported by unit tests that exercised the assertions.

Again, you may wish to not think of this as a "good" reason. It's not
really. It's another realistic reason. I've worked with a number of
development teams that, if they were ever to read about assertions and
get a wild hair about trying them, would either be useless with them or
be obstructive with them. It may not be a "good" thing that they don't
use assertions, but it's not a bad thing either.

AHS
 
R

Robert Klemme

Another decent reason, in my opinion, is if the management of them is
not disciplined. An organization that doesn't even wonder whether they
are disciplined enough to manage assertions in code isn't, and others
that do ask the question may decide that they are not.

I think this does not necessarily need to be handled on organization
level. Why make it so big? Every developer can help himself and their
colleagues by using them in a reasonable way.
What I mean by this is, assertions are easy to put in. They are not
always correct when put in, and they have to be maintained in any case
as code changes (or at least removed if necessary). Existing obsolete
assertions need to be taken into account when adding new ones in the
same class or package, because if you enable one then you may enable
more. Or you remove old ones you don't understand, if you trust yourself
to understand the business rules from 4 years ago well enough to
classify the assertions as being defunct.

Assertions also have the effect that they force you to think about
certain - possibly not obvious - properties of the code / class at hand
when you change the code. So while an assertion may look tricky it
actually helps you when modifying code to not forget important aspects.
This may be more tedious but it certainly helps code robustness in the
long run.
Let me put it this way: I would feel good about looking at code that had
assertions in it if I saw that they were also commented where necessary,
including traceability notes where that makes sense, *and* were
supported by unit tests that exercised the assertions.

I view assertions in part also as documentation. Often no additional
commenting is needed. I frequently have a private boolean method
"classInvariant" or with other (hopefully telling) name with checks and
has documentation of its own. In these cases you have the name of the
method plus documentation on the method.

Kind regards

robert
 
S

Stefan Ram

{ final Button button = new Button(); frame.add( button ); }

I also use blocks to clarify the scope of a comment
(when extracting a method is no better solution):

alpha();
{ /* add a button to the frame */
final Button button = new Button();
frame.add( button ); }
beta();

I teach both the use of omitable »final« keywords and the
use of omitable blocks (which both serve only to enhance
readability) in my classes right from the beginnig. In fact,
I start to teach /all/ variable declaration and parameter
declarations with »final« and later explain when »final« can
be removed.

(Many English dictionaries do not have an entry »omitable«.
This word is intended to mean the following above: An omitable
part of the source code often [but not necessarily always]
can be removed without changing the behavior of the program.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top