Blocks for scope control

S

Stefan Ram

declarations with »final« and later explain when »final« can

The keyword »final« also can help to detect errors, and if
there really are people who refuse to use it in the cases
where it would serve this purpose, then these people should
also refuse to use »java.lang.Override«, which also can be
omitted without a change of behavior and also serves to
detect errors of the programmer. But omission of
»java.lang.Override« when it would be appropriate is
largely accepted as a sign of low-quality code.
 
L

Lew

{ 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 [sic] »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« [sic].
This word is intended to mean the following above: An omitable [sic]
part of the source code often [but not necessarily always]
can be removed without changing the behavior of the program.)

Dictionaries frequently do not list all possible inflections of a word. In
this case they undoubtedly leave it to the normal rules of English to produce
"omittable" (note the double "t") without a separate entry.
 
S

Stefan Ram

Robert Klemme said:
commenting is needed. I frequently have a private boolean method
"classInvariant" or with other (hopefully telling) name with checks and

private static boolean classInvariant(){ ... }
private boolean objectInvariant(){ ... }

However, since it's boolean, I prefer »is«- or »has«-names:

boolean isValid(){ ... }

. One can compare the readability of:

if( this.classInvariant() )...

and

if( this.isValid() )...
 
G

Gene Wirchenko

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 dislike block ends at the end of a line.

I use blank lines myself and comment headers with bigger, oh,
call them "wings".

*
*
* This is a high-level comment.
*
*

code
code

*
* This is a less high-level comment.
*

code
code

* This is a fairly tactical comment.

code
code

* This a block comment.
code
code && and this is a line comment.
&& Sometimes continued.
code

I usually do not use wings and rarely use two line wings. If I
add a lesser comment to a winged comment, I put it after the
after-wing, as in:

*
* This is a less high-level comment.
*
* If you modify this code, check over OtherCode() as well.
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.)

It was surprising to me that there was apparently no such word of
capable of being omitted. It turns out that it is irregular. The
word you want is "omissible":
http://dictionary.reference.com/browse/omissible

Sincerelyk,

Gene Wirchenko
 
S

Stefan Ram

Gene Wirchenko said:
*
*
* This is a high-level comment.
*
*

This would be a comment in a language, where asterisk
alone can start a comment.
code && and this is a line comment.

This would be a comment in a language, where ampersands
start a comment.

Thank you, I later also became aware of this.
I dislike block ends at the end of a line.

One Way to Format Parentheses

There are several different ways to format texts with braces
and parentheses. One of them is being described here.

Indentation within Braces

An indentation of just one space often is too small to be seen
clearly, because the natural width and form of characters
often varies by an amount that is not very much smaller than a
space. Therefore, the indentation should amount to at least
two positions. In order not to waste horizontal spaces, an
indentation of exactly two positions is chosen. This means,
that the left position of the next level is two larger than
the position of the directly enclosing level.

Indentation by two positions within a block

{ ++x;
++x; }
^ ^
0 2

Bad: A small indentation by one position is not always visible
clearly

{++x;
++x; }

Good: The indentation by two positions is visible clearly

{ ++x;
++x; }

Bad: A large indentation by more than two positions wastes
horizontal space with no additional benefit

{ ++x;
++x; }

Spaces within braces

In mathematics, there are often no spaces at the inner side of
parentheses or braces in expressions, but spaces are used
indeed at the inner side of braces in set notation, when the
braces contain a description (not when they contain a list).

Spaces in set notation

{ x | x > 2 }

This style is adopted here: One space is written at the inner
side of braces.

Spaces at the inner side of parentheses within a block

{ ++x; }

This style is consistent with the indentation by two
positions, because only using this style, corresponding parts
of two lines have the same position.

Bad: No space after the first brace, the two statements are
misaligned

{++x;
++x; }

Good: One space after the first brace, the two statements are
properly aligned

{ ++x;
++x; }

Bad: Two spaces after the first brace, the two statements are
misaligned

{ ++x;
++x; }

There are some exceptions to this rule: No spaces are used
within empty braces "{}" and between two or more closing
braces of the same direction "}}", except, when the first one
of them is part of an empty pair "{} }" (an empty pair of
braces if treated like a single non-braces character).

Unified rules for all Brackets

For simplicity and uniformity, the rules from above apply to
all kinds of brackets, including parentheses, braces (curly
brackets), square brackets, and angle brackets.

Spaces within parentheses and square brackets

{ y = f( x )+ g() + a[ 2 ]; }

Binary operators are sorrounded by a space, but the space is
omitted, when there already is a space on the other side of a
sequence of brackets directly beside the operator: By this rule,
" )+" is written instead of " ) +".

Representation of the Syntactical Structure

A method or function definition consists of a head and a body.
The following representation shows this structure:

Good formatting according to the structure

void alpha() // head
{ beta(); } // body

The following formatting is misleading, because the line break
does not match the structural break:

Bad line break within the body

void alpha() { // head and the beginning of the body
beta(); } // the rest of the body

This formatting also would make no sense for blocks within
blocks. So it is often not used for such blocks. Therefore
even the adopters of this style can not use it uniformly.

Opening Braces Look Like "bullets"

There is a well known style to publish lists in typography
using bullets sticking out on the left, looking like this:

Common list representation with bullets in typography

o This is the first point
of this list, it is written
here just as an example.

o Here is another entry

o This is another example given
just as an example to show
an example

The braces of the beginnings of blocks stand out on the left
just the same, when the formatting being described here is
used, so they look quite naturally as beginning-of-a-block
markers, when one is used to the typographical list notation:

Left braces look like bullets to mark blocks

{ printf(); printf();
printf(); printf(); printf();
printf(); printf(); }

{ printf(); printf(); }

{ printf(); printf(); printf();
printf(); printf();
printf(); }

Neutrality

Someone wrote this C code:

while( fgets( eingabe, sizeof eingabe, stdin ))
if( sscanf( eingabe, "%d", &wert )!= 1 )
fprintf( stderr, "Please enter a number!\n" );
else
summe += wert;

It amazes me that I can add braces by my style conventions
(not changing the meaning of the code)
without the need to change the position of any character of
the given code or need to change the overall number of lines:

The code from above plus braces

while( fgets( eingabe, sizeof eingabe, stdin ))
{ if( sscanf( eingabe, "%d", &wert )!= 1 )
{ fprintf( stderr, "Please enter a number!\n" ); }
else
{ summe += wert; }}

Insofar, my bracing style might be considered non-obtrusive.

Lines per Contents

Lines containing only a single brace waste vertical space, so
less contents fits on the same screen space. Therefore, I usually
avoid them, but sometimes I do use them, when this helps to
increase readability. I also might temporarily use them when editing
a section of code. Of course, they would help programmers paid or
being judged by the lines-of-code productivity.
 
L

Lew

private static boolean classInvariant(){ ... }
private boolean objectInvariant(){ ... }

However, since it's boolean, I prefer »is«- or »has«-names:

boolean isValid(){ ... }

. One can compare the readability of:

if( this.classInvariant() )...

and

if( this.isValid() )...

.

There is rarely, if ever, a good reason to qualify a method name with 'this.'
It does not affect the semantics of the statement, and as documentation is
misleading.

The canonical mechanism to prove invariants is the 'assert' statement. It is
a compiler- and runtime-enforced program comment.
 
A

Arved Sandstrom

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.

When I say "organization" I don't mean company necessarily. I really
mean team or developer group. Although for a very small company it'll
end up being the same thing.

There are obviously differing opinions here, but I don't myself think
that the use of assertions is something you want to leave up to
individual developers. The fact that they are being used, and the
initial decision to use them, ought to be discussed and coordinated and
communicated across the project team.
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.


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
I also view assertions as documentation. I consider them important
enough in this role that I dislike casual and/or trivial use of
assertions, because pointless assertions can obscure the role of
genuinely important ones. Another reason why I think there ought to be
some team guidelines on these things.

AHS
 
L

Lew

Arved said:
Robert said:
Arved said:
... [snip] ...
There are obviously differing opinions here, but I don't myself think
that the use of assertions is something you want to leave up to
individual developers. The fact that they are being used, and the
initial decision to use them, ought to be discussed and coordinated and
communicated across the project team.

+1 not least because of the endemic ignorance and superstition around
'assert'. A team discussion and documentation can elucidate the sound
engineering principles behind when to use and not use the idiom.

Assertions are about algorithmic invariants. Being invariant, they shouldn't
change, and then only when such fundamental algorithmic changes are underway
that a responsible organization would carefully document them anyway.

The effort to place assertions correctly is closely tied to the effort to
understand the algorithm properly.
I also view assertions as documentation. I consider them important
enough in this role that I dislike casual and/or trivial use of
assertions, because pointless assertions can obscure the role of
genuinely important ones. Another reason why I think there ought to be
some team guidelines on these things.

Of course, those guidelines should encapsulate the extant documentation and
articles on their correct use. It is fairly objective to evaluate whether
'assert' is used correctly. I agree with your recommendation, but it's
predicated on the guidelines avoiding stupidity. For example, it is never
correct to use 'assert' in lieu of a conventional check, say an 'if'
structure, for non-nullity of arguments to a public method.

I say this because some teams where I've worked believe that best practices
are a matter of seniority or democracy. But some pretty senior team members
I've met could have observed their own polyps directly given how far their
crania were up their viscera, and truth is not amenable to voting.

Colorful rhetoric aside, I'm simply saying that team guidelines are a good
idea to the degree that they're correct, and that correctness is discernible
in a discussion of 'assert' practices.
 
S

Stefan Ram

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

I forgot to mention that there is an old software-engineering
principle: »The scope of every identifier should be as small
as possible.« Blocks help to realize this.

Or, let's look at code posted into some other thread recently:

student said:
GOval g = makeCircle(centerX, centerY,radiusOuterCircle ,
Color.RED);
add(g);
g = makeCircle(centerX, centerY,radiusMiddleCircle ,
Color.WHITE);
add(g);
g = makeCircle(centerX, centerY,radiusInnerCircle ,
Color.RED);
add(g);

With blocks, »g« can be made final:

{ final GOval g = makeCircle( centerX, centerY, radiusOuterCircle, Color.RED ); add( g ); }
{ final GOval g = makeCircle( centerX, centerY, radiusMiddleCircle, Color.WHITE ); add( g ); }
{ final GOval g = makeCircle( centerX, centerY, radiusInnerCircle, Color.RED ); add( g ); }

this also is more beautiful, because now there is more
symmetry between the the three actions, which then allows a
possible refactor to:

{ final CircleMaker circleMaker = new CircleMaker( g, centerX, centerY );
circleMaker.make( radiusOuterCircle, Color.RED );
circleMaker.make( radiusMiddleCircle, Color.WHITE );
circleMaker.make( radiusInnerCircle, Color.RED ); }

(this will probably not solve the actual problem of »student«).

Or, to tell the story from its end:

The most important principle is »DRY« - »Don't repeat
yourself!«. To do this, we abstract repetitions of the same
principle into a single code location using abstractions.
But to do this, in turn, we need to be able to see
repetitions of the same principle. And to be able to see
them, the code needs to be made as symmetric as possible,
that is, to do the same thing, the same wording should be
used.

Or in a single line:
First, make the repetition obvious, then abstract it.
 
R

Robert Klemme

On 15.01.2012 22:49, Arved Sandstrom wrote:
[ SNIP ]
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.
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.

Why _one_ method? There could be a method for each variant, couldn't
it? Chances are that the same code could be used for several items so
you end up with less methods than items.
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.

I agree that this boilerplate is tedious, regardless how you do it. But
I didn't guess that your description was about such a scenario. ;-)
However, the intent of the thread was to get some feedback, and I thank
you all for it.

You're welcome!

Kind regards

robert
 
A

Arved Sandstrom

On 15.01.2012 22:49, Arved Sandstrom wrote:
[ SNIP ]
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.
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.

Why _one_ method? There could be a method for each variant, couldn't
it? Chances are that the same code could be used for several items so
you end up with less methods than items.

There could be, sure. I'll discuss that below your second comment.
I agree that this boilerplate is tedious, regardless how you do it. But
I didn't guess that your description was about such a scenario. ;-)
[ SNIP ]

There are a number of Java command line option parsers available; I
happen to like JArgs which is GNU getopt compatible.

Your first step after defining your options and running the parser on
actual arguments is to retrieve raw option values. JArgs is not generic,
so the retrieved option values are retrieved as Objects although they
are actually Strings or Booleans or Doubles or Integers or Longs.
Depending on how many of these types are in use in your situation, if
you were going to have convenience methods at all you'd have one for
each datatype involved in your options.

Many or some of your convenience methods might accept an option default
parameter, to be passed on to the appropriate JArgs getOption method.
This shouldn't multiply the number of methods that you've created.

I'm not going to deliberately complicate things so as to scupper your
argument, but in the case of the processing I was doing at this stage,
some of the String option values could only have certain values (they
referred to input and output formats, actually). I have enums defined
for this purpose, so for some of the String options the retrieved values
were immediately converted to enum instances. Other Strings were
freeform so no such processing was appropriate.

That's another method right there, at a minimum. Let us say one extra.

Similarly, a couple of the String options represented file names. Rather
than set them as generic Strings into my own "command line options"
object, I wanted them to be Files. Null is not an acceptable value for
the java.io.File ctor, so at the very least I had to look for null for
_these_ particular String options; "" is OK for java.io.File but it's
not OK for my app.

Hence a bit of specialized "String options meant to be filenames"
processing for some options.

This would/could be an extra convenience method of its own.

In summary, looking at my actual application command line options
(including which option datatypes I actually use), something like a
dozen of them [1], one could create half a dozen convenience methods
that would be used instead.

I don't think I can credibly argue that using the methods would be
worse. I am just not convinced it would be better. :)

AHS

1. I think the number of options I have is justified. I probably could
have reasonably added a couple more. I've been using getopt and GNU
enhanced getopt and shell getopts for well over 20 years. When I first
encountered these beasts, after going through the usual exercise of
writing my own C.L. handling in C, I'll admit to having gone overboard.
But I'd like to think I am more sensible now: good command line design
is based on lots of usability experience with a dash of artistry.
 
R

Robert Klemme

In summary, looking at my actual application command line options
(including which option datatypes I actually use), something like a
dozen of them [1], one could create half a dozen convenience methods
that would be used instead.

I don't think I can credibly argue that using the methods would be
worse. I am just not convinced it would be better. :)

Fair enough.
But I'd like to think I am more sensible now: good command line design
is based on lots of usability experience with a dash of artistry.

I'd say this is true for so many areas of software engineering. :)

Thank you for the elaborate explanation!

Kind regards

robert
 
A

Arne Vajhøj

I forgot to mention that there is an old software-engineering
principle: »The scope of every identifier should be as small
as possible.« Blocks help to realize this.

Or, let's look at code posted into some other thread recently:



With blocks, »g« can be made final:

{ final GOval g = makeCircle( centerX, centerY, radiusOuterCircle, Color.RED ); add( g ); }
{ final GOval g = makeCircle( centerX, centerY, radiusMiddleCircle, Color.WHITE ); add( g ); }
{ final GOval g = makeCircle( centerX, centerY, radiusInnerCircle, Color.RED ); add( g ); }

this also is more beautiful, because now there is more
symmetry between the the three actions, which then allows a
possible refactor to:

{ final CircleMaker circleMaker = new CircleMaker( g, centerX, centerY );
circleMaker.make( radiusOuterCircle, Color.RED );
circleMaker.make( radiusMiddleCircle, Color.WHITE );
circleMaker.make( radiusInnerCircle, Color.RED ); }

(this will probably not solve the actual problem of »student«).

Or, to tell the story from its end:

The most important principle is »DRY« - »Don't repeat
yourself!«. To do this, we abstract repetitions of the same
principle into a single code location using abstractions.
But to do this, in turn, we need to be able to see
repetitions of the same principle. And to be able to see
them, the code needs to be made as symmetric as possible,
that is, to do the same thing, the same wording should be
used.

Or in a single line:
First, make the repetition obvious, then abstract it.

The rule is OK.

But I consider it a 75% rule. Follow it in 75% of cases
and skip it when it does not make sense.

In this case I think the code became less readable, so I would
not do it.

And I would certainly not do that refactoring as it obfuscates
what the code is doing by hiding the adding to g.

Arne
 

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,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top