Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / January 2006

Tip: Looking for answers? Try searching our database.

Variable naming problem

Thread view: 
Roedy Green - 22 Jan 2006 07:52 GMT
It is very common for a method to return a boolean that indicates
success/fail of some test or operation.

E.g. testing if a date is valid, if a file was successfully saved etc.

So two questions:

Which convention do you use?  true= good or true=problem?

Why? How do you make that clear to others?

If you have to represent the state in side the method with a boolean
variable, what do you call it?  

state, success, status, ok, wasSuccessful..?

How is your true/false convention make obvious by your choice of name?

When you say "return success" how do you avoid confusing people? Are
you returning good or the state?

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Luke Meyers - 22 Jan 2006 09:04 GMT
> It is very common for a method to return a boolean that indicates
> success/fail of some test or operation.
[quoted text clipped - 4 lines]
>
> Which convention do you use?  true= good or true=problem?

true == good, allowing idioms like:

if (openFile(filename)) processFile();
else reportError();

> Why? How do you make that clear to others?

The opposite would be misleading.  I would make sure to name my methods
appropriately to avoid other sources of possible ambiguity.  And, of
course, provide appropriate documentation in a @return javadoc tag.

> If you have to represent the state in side the method with a boolean
> variable, what do you call it?
>
> state, success, status, ok, wasSuccessful..?

If the only use of the boolean variable is to return it, but for some
reason it must be assigned to a named variable (rather than simply
returned immediately), I often just call it something like "retval."
It's concise and obvious.  "status" is also reasonable in many cases.

> When you say "return success" how do you avoid confusing people? Are
> you returning good or the state?

That's a reasonable argument against using identifiers such as
"success" for this purpose.

I rarely run into any real problems related to the issues you're asking
about, though.  Methods should not be so convoluted that a reader has
trouble understanding the meaning of the return value just because it's
called "success" or whatever.  Focus on writing comprehensible code and
keeping method size under control, and problems like this tend to solve
themselves.

Luke
opalpa@gmail.com opalinski from opalpaweb - 22 Jan 2006 13:53 GMT
I choose words for the situation and do not use retval.  If the test
was to see whether a file is open then the boolean name would be
"open".  If the test was to see whether something was small then the
boolean name would be "small".  If the test was to see that we are at
end of line the boolean would be "eol".

A general rule is look at Brian Kernighan's code and make your code
like his.

Opalinski
opalpa@gmail.com
http://www.geocities.com/opalpaweb/
ricky.clarkson@gmail.com - 22 Jan 2006 15:28 GMT
I'd go one step further than Opalinski: isOpen, isSmall, atEol
Hal Rosser - 23 Jan 2006 03:18 GMT
> I'd go one step further than Opalinski: isOpen, isSmall, atEol

Bingo - that's the most descriptive naming convention.
isOpen, fileExists, isAppended,  isPrime, isFirst, etc etc
NullBock - 22 Jan 2006 12:56 GMT
> It is very common for a method to return a boolean that indicates
> success/fail of some test or operation.

> How do you make that clear to others?

It shouldn't be too hard, if such methods are used properly.  It is
certainly valid to have a method return true/false to test some
condition; such methods are best named to make the result as clear as
possible.  In your example, a method testing a date might well be named

isDateValid(Date) : boolean

Then it's clear that "true" means that the date is valid, "false"
otherwise.

Operations that return a success/failure code should be avoided,
though.  Not only do such methods make the code more obscure, but they
rely on all client code to do the right thing.  Exceptions are a much
better possibility; they are unabmbiguous, and don't require
superfluous return-test code.

This isn't just my opinion either--Bloch covers this in his "Effective
Java" book.

Walter Gildersleeve
Freiburg, Germany

______________________________________________________
http://linkfrog.net
URL Shortening
Free and easy, small and green.
Stefan Schulz - 22 Jan 2006 20:29 GMT
> Operations that return a success/failure code should be avoided,
> though.  Not only do such methods make the code more obscure, but they
> rely on all client code to do the right thing.  Exceptions are a much
> better possibility; they are unabmbiguous, and don't require
> superfluous return-test code.

Absolutely agreed. For failures, exceptions are the proper language
facility to use, return values are for "normal" results.
Luke Meyers - 22 Jan 2006 22:10 GMT
> It shouldn't be too hard, if such methods are used properly.  It is
> certainly valid to have a method return true/false to test some
[quoted text clipped - 5 lines]
> Then it's clear that "true" means that the date is valid, "false"
> otherwise.

Otherwise known as a "predicate."  No argument from anyone on this
idiom, I would hope -- it's simple and intuitive.

> Operations that return a success/failure code should be avoided,
> though.  Not only do such methods make the code more obscure, but they
> rely on all client code to do the right thing.  Exceptions are a much
> better possibility; they are unabmbiguous, and don't require
> superfluous return-test code.

I would hesitate to agree to a universal policy of always using
exceptions to represent any result which is semantically negative.
When you use exceptions, you pay for exceptions, namely:

(1) Runtime overhead.  Throwing an exception, unwinding the stack,
etc., is much more expensive than simply returning a boolean value.  In
an efficiency-critical section of code, it makes sense to minimize
exception usage when a good alternative is available.

(2) Syntactic overhead.  The proliferation of try/catch/finally blocks
associated with heavy use of exceptions can easily send what should be
a simple method body into deeply-nested curly brace hell.  When it's
the difference between fitting your method all onto one screen or not,
what's the best choice from a maintainability perspective?

Now, exceptions have their place.  They're a useful mechanism and
should see plenty of use in any well-designed programs.  But there are
plenty of times where returning false is just as clear, faster, and
more concise.

> This isn't just my opinion either--Bloch covers this in his "Effective
> Java" book.

I'll have to check that section in my copy at work tomorrow.  I recall
his section on using exceptions to represent exceptional conditions,
but my recollection is mainly of his admonishment against *overuse* of
exceptions (for normal control flow, etc.).

I think the useful discussion here would be, how do we distinguish
failures in general from exceptional conditions?  Are all failures
exceptional?  I think it would be going out on an uncomfortable limb to
assert such.  One might reasonably characterize exceptions as things
which are not anticipated to occur in a successful execution path, but
which we must be prepared to handle, just in case.  Other sorts of
failures are bound to be part of any sufficiently complex program, and
it's not reasonable to think we'll often encounter an execution path
completely free of failures.

Some examples of the kind of non-exceptional error I'm talking about:
* A timeout which simply results in a retry.  Maybe if we exhaust all
our retries, *then* throw.
* Validation of keyboard input.  Users are bound to make typos, so
validating and reprompting is just normal business logic.
* A readLine() function which returns false when there is no more
input.  That's not an exception, it's a sentinel condition.  Do you
really want to use a try/catch/finally block for that?

I suppose that's a decent set of examples.  Is my point well taken?

Luke
Stefan Schulz - 22 Jan 2006 22:28 GMT
> I would hesitate to agree to a universal policy of always using
> exceptions to represent any result which is semantically negative.
[quoted text clipped - 10 lines]
> the difference between fitting your method all onto one screen or not,
> what's the best choice from a maintainability perspective?

Both are correct and valid. However, the proposal was to use a false
return value to represent some serious failure, an exceptional
situation (or at least, this is how i understood the OP).

As i understood it, we are talking about "boolean doSomething()"
returning false if something could not be done, instead of isEmpty().
That is, making a predicate out of an otherwise void function, by
returning false on failure. Clearly, booleans do have their place, if a
boolean condition is being checked (isEmpty(), for example)
Luke Meyers - 22 Jan 2006 23:54 GMT
> Both are correct and valid. However, the proposal was to use a false
> return value to represent some serious failure, an exceptional
> situation (or at least, this is how i understood the OP).

The OP made no reference to the seriousness of the failure, just that
it is a failure of some kind.  My whole post was about the difference
between kinds of failures.

> As i understood it, we are talking about "boolean doSomething()"
> returning false if something could not be done, instead of isEmpty().

Right.  I dismiss predicates as valid but trivial and not an important
part of this discussion.

> That is, making a predicate out of an otherwise void function, by
> returning false on failure.

I would hesitate to refer to anything with side-effects as a predicate.
The return value, representing the success or failure of the
operation, is clearly subordinate to the operation itself.

> Clearly, booleans do have their place, if a
> boolean condition is being checked (isEmpty(), for example)

Again, that's just a predicate.  You have not in any way addressed my
point that there are failures which are not exceptional.  Please feel
free to use the examples I provided (e.g. readLine()) as discussion
points.

Luke
Stefan Schulz - 23 Jan 2006 00:25 GMT
> > Both are correct and valid. However, the proposal was to use a false
> > return value to represent some serious failure, an exceptional
[quoted text clipped - 3 lines]
> it is a failure of some kind.  My whole post was about the difference
> between kinds of failures.

With all due respect, no. The part of your post i referenced was about
"Exceptions are too expensive, lets get back to special return values".
You may have a point that there are cases where a situation is not
entirely common, but not yet as rare or unexpected as to justify an
exception (End of Stream conditions, for example), but for the most
part, you mentioned code beauty and runtime overhead as arguments
against using exceptions.

> > As i understood it, we are talking about "boolean doSomething()"
> > returning false if something could not be done, instead of isEmpty().
>
> Right.  I dismiss predicates as valid but trivial and not an important
> part of this discussion.

So, what are we talking about, then?

> > That is, making a predicate out of an otherwise void function, by
> > returning false on failure.
>
> I would hesitate to refer to anything with side-effects as a predicate.
>  The return value, representing the success or failure of the
> operation, is clearly subordinate to the operation itself.

Well, we are not in functional programming land, here. Anything, even
the most innocent isXYZ call,  you can call may have side effects (for
example, triggering some internal housekeeping of the class).
Therefore, there are either no predicates at all, or we may safely call
these functions predicates.

> > Clearly, booleans do have their place, if a
> > boolean condition is being checked (isEmpty(), for example)
>
> Again, that's just a predicate.

It needn't be.

> You have not in any way addressed my
> point that there are failures which are not exceptional.  Please feel
> free to use the examples I provided (e.g. readLine()) as discussion
> points.

readLine does not fail on EOF, since EOF is not an exceptional
circumstance, but will invariably happen. It can, however, become
exceptional (for example, if it occurs inside some "record"). In this
case, you should through an EOFException (as DataInput, for example,
does mandate).

Similarly, keep in mind that "untrusted user input does not validate"
is not an exceptional condition, nor a failure. It is a normal,
expected occurance, and therefore should be treated as such.
Luke Meyers - 23 Jan 2006 01:16 GMT
> > The OP made no reference to the seriousness of the failure, just that
> > it is a failure of some kind.  My whole post was about the difference
> > between kinds of failures.
>
> With all due respect, no. The part of your post i referenced was about
> "Exceptions are too expensive, lets get back to special return values".

Fair enough; I mentioned that as well.  Though I didn't generalize so
recklessly as you imply.  ;)

What's "special" about true and false?  I'd say that returning null is
much more of a "special" return value (sentinel value), and I see
plenty of that in the Java code I encounter.

> You may have a point that there are cases where a situation is not
> entirely common, but not yet as rare or unexpected as to justify an
> exception (End of Stream conditions, for example), but for the most
> part, you mentioned code beauty and runtime overhead as arguments
> against using exceptions.

Against using them universally for all failures, yes.  I also said that
there are plenty of times where exceptions are perfectly appropriate.
My point is, an informed coder should have a good understanding of the
tradeoffs involved, and weigh them when deciding how to represent
failure conditions.

> > > As i understood it, we are talking about "boolean doSomething()"
> > > returning false if something could not be done, instead of isEmpty().
[quoted text clipped - 3 lines]
>
> So, what are we talking about, then?

Methods which perform an operation as part of a class's logical
behavior, and which require some mechanism to report a failure thereof.

> Well, we are not in functional programming land, here. Anything, even
> the most innocent isXYZ call,  you can call may have side effects (for
> example, triggering some internal housekeeping of the class).
> Therefore, there are either no predicates at all, or we may safely call
> these functions predicates.

We're in good-design space, here, not language-lawyer space.
Obviously, since Java has no "const," there's nothing preventing a
method like isValid() from modifying all the state it wants.  However,
that would in most cases be a terribly misleading design, and we should
expect better of our fellow programmers.  Internal housekeeping is
distinct, because it does not affect the visible state of the object.
For example, if isValid() is expensive, I might compute it once and
cache the result for the next call, modifying some internal state to
track it.  But it's still logically a predicate.

If a method's primary responsibility is to produce a boolean value, and
it has no effect on logical program state, it's a predicate.  If it's
kind of like that but it has maybe a couple side effects, then possibly
it's a poorly-designed predicate or predicate-like thing.  But none of
that is what we're talking about here.

> > > Clearly, booleans do have their place, if a
> > > boolean condition is being checked (isEmpty(), for example)
> >
> > Again, that's just a predicate.
>
> It needn't be.

What reasonable behavior could isEmpty() have?

> readLine does not fail on EOF, since EOF is not an exceptional
> circumstance, but will invariably happen. It can, however, become
> exceptional (for example, if it occurs inside some "record"). In this
> case, you should through an EOFException (as DataInput, for example,
> does mandate).

You seem to be referring to some particular readLine method; I wasn't.
For the sake of discussion, let's use the following alternatives:

/**
* Reads a line into the internal buffer.
* @return true if a line was successfully read, false otherwise
*/
bool readLine() { // (1)
   // do stuff
}

/**
* Reads a line into the internal buffer.
* @throws EOFException if a line could not be read
*/
void readLine() throws EOFException { (2)
   // do stuff
}

I don't know what you mean about a "record" -- parsing the contents of
the line is clearly a separate responsibility from simply grabbing
data, and should not be part of what readLine() does.  Anyway, the code
to use (1) would look something like:

while (readLine()) {
   processLine();
}

The code for (2), to accomplish the same thing, is a lot more
convoluted:

try {
   while (true) {
       readLine();
       processLine();
   }
} catch (EOFException e) {
   // Silently swallow exception
}

This is using exceptions for control flow, against Bloch's
recommendations (and common sense).  But I don't think it's reasonable
to say that readLine() has not failed to read a line when it encounters
EOF.  Its responsibility is to read a line, and it was unable to do
that, so this is a failure.  It's an expected failure, but that's
exactly the point -- it's not exceptional.

> Similarly, keep in mind that "untrusted user input does not validate"
> is not an exceptional condition, nor a failure. It is a normal,
> expected occurance, and therefore should be treated as such.

I would say that malformed input is a form of failure.  Maybe all we're
doing is disagreeing about how broadly to interpret the term "failure."
In which case... well, I guess it's kind of silly to keep debating the
point.

Cheers,
Luke
Stefan Schulz - 23 Jan 2006 10:38 GMT
> What's "special" about true and false?  I'd say that returning null is
> much more of a "special" return value (sentinel value), and I see
> plenty of that in the Java code I encounter.

And pretty often, you see it where it should not be. Many cases where
"returns null if something goes wrong" is defined, that method would be
better defined as throwing an exception instead.

> > You may have a point that there are cases where a situation is not
> > entirely common, but not yet as rare or unexpected as to justify an
[quoted text clipped - 7 lines]
> tradeoffs involved, and weigh them when deciding how to represent
> failure conditions.

Maybe we should talk about what constitutes a failure first. For me, a
failure is a condition the programmer can not reasonably expect or be
expected to deal with. For example, when writing to a file, it is not
reasonable to require the programmer to check before each invocation of
write() if the file he/she is writing to exists, is accessible, open
for writing, that the harddisk does have sufficient space remaining,
and so on.

However, most data streams reach their end eventually, and pretty
often, this is nothing to worry about either. This is not a failure
(and therefore, not where you would use an exception), for the most
part. However, if you know your file contains base64-encoded data, and
ends in midst of a quartet, this becomes a failure, since an assumption
you made is violated.

> > > > Clearly, booleans do have their place, if a
> > > > boolean condition is being checked (isEmpty(), for example)
[quoted text clipped - 4 lines]
>
> What reasonable behavior could isEmpty() have?

Maintain an access timestamp, for example? It might also release
"backing store", shrink internal arrays, and so on.

> > readLine does not fail on EOF, since EOF is not an exceptional
> > circumstance, but will invariably happen. It can, however, become
[quoted text clipped - 4 lines]
> You seem to be referring to some particular readLine method; I wasn't.
> For the sake of discussion, let's use the following alternatives:

I assumed you meant the "default" readLine as maintained by javas
BufferedReader class.

> /**
>  * Reads a line into the internal buffer.
[quoted text clipped - 11 lines]
>     // do stuff
> }

This highly depends on what you expect of your lines. If a "valid" line
is always terminated by some sequence (say "\r\n"), neither is a good
implementation (you should both return a boolean, and possibly throw
the exception). However, if the last line of your input stream may just
stand on its own, then the former is the right one.

> I don't know what you mean about a "record" -- parsing the contents of
> the line is clearly a separate responsibility from simply grabbing
[quoted text clipped - 23 lines]
> that, so this is a failure.  It's an expected failure, but that's
> exactly the point -- it's not exceptional.

We seem to talk on cross purposes. I do not advocate exceptions for
control flow. That would really be using a hammer to hand out chicken
soup. However, failures (as in behaviour you are not prepared and
should not have to be prepared to handle) should not be signalled by a
return value - it is too easily ignored or forgotten.

> > Similarly, keep in mind that "untrusted user input does not validate"
> > is not an exceptional condition, nor a failure. It is a normal,
[quoted text clipped - 4 lines]
>  In which case... well, I guess it's kind of silly to keep debating the
> point.

Sure seems like it.

See you
Stefan
Luke Meyers - 24 Jan 2006 03:15 GMT
> Maybe we should talk about what constitutes a failure first. For me, a
> failure is a condition the programmer can not reasonably expect or be
[quoted text clipped - 3 lines]
> for writing, that the harddisk does have sufficient space remaining,
> and so on.

If you define failures in that way, then don't all exceptions become
fatal, since by definition they cannot be handled?  I think a more
reasonable approach is to recognize that certain conditions cannot be
handled right away in the local scope, and so someone higher up on the
stack needs to sort it out.  For example, if we get a FileNotFound
exception, the class responsible for handling a file may have no
reasonable way to ameliorate the situation, but the GUI sitting on top
of it can just query the user for different input.

That's what exceptions are useful for -- indicating error conditions
that, by their nature, "want" to unwind the stack and be dealt with at
a higher level.  By contrast, some error conditions are almost always
more appropriate to handle locally.  In some of these cases, a simple
return value is perfectly adequate and provides the previously-noted
benefits of efficiency and conciseness.

> However, most data streams reach their end eventually, and pretty
> often, this is nothing to worry about either. This is not a failure
> (and therefore, not where you would use an exception), for the most
> part. However, if you know your file contains base64-encoded data, and
> ends in midst of a quartet, this becomes a failure, since an assumption
> you made is violated.

It's nothing to worry about; it just requires appropriate logic to deal
with it, and that logic is separate from the logic applied when the
stream has not yet ended.  I think it's fair to call it a failure for a
simple reason: based on just the name "readLine," when I call the
method I expect it to read a line.  If it does not do so (e.g. EOF), it
has failed to read a line.  It's not a moral judgement against the poor
method, just a statement that it did not perform its advertised
function.

You might be interested to read a column I found very enlightening:
 http://www.gotw.ca/gotw/061.htm
The series of articles is oriented towards C++, but this article in
particular applies just as well to Java.  The author applies the ACID
paradigm (Atomic, Consistent, Isolated, Durable) from database
transactions to error safety.  In the presented notation, a lower-case
'a' indicates that the operation is all-or-nothing; if it fails,
program state is unchanged.  An upper-case 'A' is a stronger guarantee,
and indicates that the operation is guaranteed to succeed.  One could
still argue that, on reaching EOF, readLine() can still "succeed" by
"successfully returning false," but I think that's stretching it.
Unless readLine() always, always, always reads a line successfully,
it's not capital-A Atomic, which means it sometimes fails.

> > What reasonable behavior could isEmpty() have?
>
> Maintain an access timestamp, for example? It might also release
> "backing store", shrink internal arrays, and so on.

Sure, but that's still housekeeping, not changing the logical state.
Should I say "overt behavior?"  "Visible behavior?"

> This highly depends on what you expect of your lines. If a "valid" line
> is always terminated by some sequence (say "\r\n"), neither is a good
> implementation (you should both return a boolean, and possibly throw
> the exception). However, if the last line of your input stream may just
> stand on its own, then the former is the right one.

Ah, this brings up a very good point -- what to do in the case where
both serious errors (e.g. malformed data, the sort of thing which
requires a recovery action and is likely to want stack unwinding) and
non-problematic failures (readLine didn't read a line, indicating end
of input) can occur.  One could write separate catch blocks for each,
but is it really good to treat them the same?

> We seem to talk on cross purposes. I do not advocate exceptions for
> control flow. That would really be using a hammer to hand out chicken
> soup. However, failures (as in behaviour you are not prepared and
> should not have to be prepared to handle) should not be signalled by a
> return value - it is too easily ignored or forgotten.

I think we're on the same page -- it's worth discussing further what is
an appropriate definition of "failure" (as discussed above), but
there's no point chasing any further down the path of what happens when
we use different definitions -- the result is obvious. :)

I'm particularly interested in what you think of the above idea of
exceptions as errors that want to propagate upwards, versus local
failures that can be handled by retries, terminating loops, etc.

Luke
Stefan Schulz - 24 Jan 2006 07:37 GMT
> > Maybe we should talk about what constitutes a failure first. For me, a
> > failure is a condition the programmer can not reasonably expect or be
[quoted text clipped - 12 lines]
> reasonable way to ameliorate the situation, but the GUI sitting on top
> of it can just query the user for different input.

Exceptions are just that - locally fatal (strange wording, but i think
it captures the gist of things rather nicely). If it is out of scope of
the problems you are locally able to deal with, or expect your clients
to be able to deal with, throw an exception. Some other, higher-level
routine might be able to deal with that failure (for example, by
removing the root cause of the exception, and retrying), but as far as
you are concerned, there is not much to be done.

> That's what exceptions are useful for -- indicating error conditions
> that, by their nature, "want" to unwind the stack and be dealt with at
> a higher level.  By contrast, some error conditions are almost always
> more appropriate to handle locally.  In some of these cases, a simple
> return value is perfectly adequate and provides the previously-noted
> benefits of efficiency and conciseness.

Agreed. These conditions are usually not all that exceptional, too -
instead they are conditions you expect to occur on the object, given
enough time. Once more end of file is an appropriate example - it is
common as dirt, and the client needs to be aware of it.

> You might be interested to read a column I found very enlightening:
>   http://www.gotw.ca/gotw/061.htm
[quoted text clipped - 9 lines]
> Unless readLine() always, always, always reads a line successfully,
> it's not capital-A Atomic, which means it sometimes fails.

Interesting. Maybe we all could benefit from somewhat sharper tools to
distinguish one kind of occasion from the others - since with just
"common sense", we are bound to trip up in semantics again.

> > > What reasonable behavior could isEmpty() have?
> >
[quoted text clipped - 3 lines]
> Sure, but that's still housekeeping, not changing the logical state.
> Should I say "overt behavior?"  "Visible behavior?"

All are visible one way or another. The access timestamp might be
checkable through the objects interface itself, or appear in a logfile.
The others might involve everything simply releasing memory to database
transactions. Overt behaviour, however, is a good way to express it.

> > This highly depends on what you expect of your lines. If a "valid" line
> > is always terminated by some sequence (say "\r\n"), neither is a good
[quoted text clipped - 8 lines]
> of input) can occur.  One could write separate catch blocks for each,
> but is it really good to treat them the same?

In such a case, i would not advocate using an exception at all for end
of input, since it is not considered exceptional (but rather
non-problematic). Rather like javas standard library, you should throw
an exception once you reach a unexpected / unmanageable condition, and
otherwise use the sentinel. There, i said it! ;) They do have a place,
but i usually strongly urge against using them, since i see them abused
so frequently.

> > We seem to talk on cross purposes. I do not advocate exceptions for
> > control flow. That would really be using a hammer to hand out chicken
[quoted text clipped - 10 lines]
> exceptions as errors that want to propagate upwards, versus local
> failures that can be handled by retries, terminating loops, etc.

Generally, i agree to most of your points by now. Maybe i am just a bit
more trigger happy with exceptions, assuming "dumber" clients to the
methods then you do. For me, anything outside the generally expected
and assumed conditions is worth an exception. That is to say, if you
are not reasonably sure your client will be able to handle the
condition successfuly by a few stereotypal short control statements
(often "if (rv ==  specialValue) {break;} ..."), throw that exception.
If you have one of these rare few clients who are more context aware
then others, it still can catch the exception. You just delegate error
checking the a method which feels prepared for it, rather then forcing
the caller to become more complex.

At the most basic level, all exceptions provide a very high-level means
of flow control. They do just that - a non-local jump, unwinding any
number of stack frames at once. This is a powerful feature, and can
greatly increase code clarity since you are forced to declare what
exactly can go wrong above and beyond the obvious.

On a related note, exceptions offer to provide more context intromation
then sentinel values, since they are full-fledged object, and can offer
more information then a simple "null" ever could. For example,
theoretically, a parsing exception could point out the bad token, an
XML validation exception could point to the malformed node, and so on.
More then you would get by just getting a "false" return value from a
validateXML() method
Luke Meyers - 25 Jan 2006 07:24 GMT
> > That's what exceptions are useful for -- indicating error conditions
> > that, by their nature, "want" to unwind the stack and be dealt with at
[quoted text clipped - 7 lines]
> enough time. Once more end of file is an appropriate example - it is
> common as dirt, and the client needs to be aware of it.

Surely.  Those are the cases I consider reasonable candidates for
indicating failure in the return type, because it's a common,
easily-managed failure, and any client code that cares about it would
almost inevitably use the return value as part of its control flow,
e.g. checking the sentinel value to know when to break a loop.

I'm trying to think of other failures (EOF is great, but it's just one
damn example ;)) that fit this criterion.  I suppose there is a class
of failures so insignificant that they can often be ignored.
Displaying transitory, non-essential, "courtesy" output (like a brief
"Please wait..." dialog) might fail, but we also might not really care.
Or we might care a little, but be unable to handle the problem locally
and unwilling to unwind the stack and interrupt more important logic
over a trivial failure.  I wonder how large is the class of failures of
which we could say something similar?

> > You might be interested to read a column I found very enlightening:
> >   http://www.gotw.ca/gotw/061.htm
[quoted text clipped - 3 lines]
> distinguish one kind of occasion from the others - since with just
> "common sense", we are bound to trip up in semantics again.

Indeed.  Since I read that article, I've been wondering whether those
semantics, or a useful subset, could be enforced by the compiler or a
static analysis tool.  The utility of such a facility for
mission-critical software would be enormous.

> In such a case, i would not advocate using an exception at all for end
> of input, since it is not considered exceptional (but rather
[quoted text clipped - 3 lines]
> but i usually strongly urge against using them, since i see them abused
> so frequently.

Agreed.  I've been arguing for their right to exist, not to
proliferate.  My first preference is of course to minimize the number
of exceptional paths to begin with.  After that, it's just a matter of
minimizing various cost functions (runtime efficiency, readability,
chance of mishandling, etc.).

> Generally, i agree to most of your points by now. Maybe i am just a bit
> more trigger happy with exceptions, assuming "dumber" clients to the
> methods then you do.

Well, I'm certainly an advocate of defensive programming, more or less
regardless of who the client is (unless it's myself, of course -- we
all have a different standard for "me-only" hacks).

> For me, anything outside the generally expected
> and assumed conditions is worth an exception.

Another formulation of this is, any event which causes any of an
operation's postconditions to fail is a failure (or exception, or
what-have-you).  Then one encounters the question of how much
compounding to put into postconditions ("A connection is made to the
server and returned" versus "A connection is made to the server and
returned, OR no connection is made and null is returned.").  It's a
matter of taste and design judgement, more than anything.

> That is to say, if you
> are not reasonably sure your client will be able to handle the
> condition successfuly by a few stereotypal short control statements
> (often "if (rv ==  specialValue) {break;} ..."), throw that exception.

Agreed.  I would not want to return critical information if that
allowed it to be ignored.

> At the most basic level, all exceptions provide a very high-level means
> of flow control. They do just that - a non-local jump, unwinding any
> number of stack frames at once. This is a powerful feature, and can
> greatly increase code clarity since you are forced to declare what
> exactly can go wrong above and beyond the obvious.

I'm not so sure about it increasing code clarity.  The possibility of
exceptions, particularly unchecked exceptions (RuntimeExceptions),
creates a combinatorial explosion of new code paths.  This complicates
testability for correctness and coverage, makes it more difficult to
maintain strict program integrity in the face of convoluted error
scenarios, and provides a more difficult-to-trace control flow.  But
it's a damn good thing we have them!

I've been in C++ land lately, and since C++ does not have
throws-clauses that work like in Java, I've learned some good lessons
about how to be strict/paranoid w.r.t. error-safety.  Java's not off
the hook, of course -- remember, RuntimeExceptions (and Throwables, and
Errors, IIRC) are not necessarily checked.

> On a related note, exceptions offer to provide more context intromation
> then sentinel values, since they are full-fledged object, and can offer
[quoted text clipped - 3 lines]
> More then you would get by just getting a "false" return value from a
> validateXML() method

You can also return an object.  Enumeration values are excellent
candidates, too, and they can be as complex as you like.

Luke
Stefan Schulz - 25 Jan 2006 08:18 GMT
> > At the most basic level, all exceptions provide a very high-level means
> > of flow control. They do just that - a non-local jump, unwinding any
> > number of stack frames at once. This is a powerful feature, and can
> > greatly increase code clarity since you are forced to declare what
> > exactly can go wrong above and beyond the obvious.

[...]

> I've been in C++ land lately, and since C++ does not have
> throws-clauses that work like in Java, I've learned some good lessons
> about how to be strict/paranoid w.r.t. error-safety.  Java's not off
> the hook, of course -- remember, RuntimeExceptions (and Throwables, and
> Errors, IIRC) are not necessarily checked.

This becomes a problem of being a disciplined programmer.

Errors, by definition, are conditions that arise due to some
operational constraint of the JVM or external environment, which you
are never expected to "handle gracefully". Usually, the best you can do
in the face of an error is bring the program down gently, instead of
letting it crash and burn. Likewise, RuntimeExceptions indicate errors
of the programmer. Of course, java violates that honorable principle
itself (NumberFormatException, anyone? I don't know how many times i
have had to write something along the line catch (NumberFormatException
nfe) { /* not a number, treat as string */ } when dealing with user
input). However, generally, both Errors and RuntimeExceptions do not
really concern themself with the behaviour of the object itself, but
either with circumstances of use (Errors), or misuse of their
capabilities (RuntimeException).

> > On a related note, exceptions offer to provide more context intromation
> > then sentinel values, since they are full-fledged object, and can offer
[quoted text clipped - 6 lines]
> You can also return an object.  Enumeration values are excellent
> candidates, too, and they can be as complex as you like.

Sure, you can. However, this is rather cumbersome if you want to return
an Object Reference rather then a boolean - you would in effect have to
write a DTO for each return value, and one (or more) "Error Transfer
Object", both of which inherit from some common ancestor. Both would
have to be distinct types, since one offers a getResult() method, while
the other would offer methods related to the kind of failure
encountered. You'd have to check their type (either via some type
attribute, or via RTTI), cast them to their actual type, and so on.
I'll stick with exceptions. :)
Chris Smith - 25 Jan 2006 10:10 GMT
> Likewise, RuntimeExceptions indicate errors
> of the programmer. Of course, java violates that honorable principle
> itself (NumberFormatException, anyone? I don't know how many times i
> have had to write something along the line catch (NumberFormatException
> nfe) { /* not a number, treat as string */ } when dealing with user
> input).

See java.text.NumberFormat.  The reason Integer.parseInt and friends
throw a RuntimeException is that they are intended to be used with
private data that is maintained programmatically by the application.  If
you interact with the user, they are deficient in many, many ways.  For
example, they lack internationalization (for example, the decimal
separator is always '.' rather than ',').  NumberFormat has a parse that
does, indeed, throw a checked exception.

Signature

www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation

Stefan Schulz - 25 Jan 2006 20:51 GMT
> > Likewise, RuntimeExceptions indicate errors
> > of the programmer. Of course, java violates that honorable principle
[quoted text clipped - 10 lines]
> separator is always '.' rather than ',').  NumberFormat has a parse that
> does, indeed, throw a checked exception.

Of course. I referenced them because originally, they where the only
build-in way to convert strings to integers - NumberFormat appeared
only much much later in the SDKs evolution.
NullBock - 23 Jan 2006 12:41 GMT
> I would hesitate to agree to a universal policy of always using
> exceptions to represent any result which is semantically negative.

So would I.  "To be avoided" doesn't imply universal application.

> I'll have to check that section in my copy at work tomorrow.

Unfortunately, someone seems to have taken my copy of Bloch, so I
wasn't able to confirm it.  Kalev does discuss just this in his
"ANSI/ISO C++" book, for what it's worth.

My point was to stress the dangers of depending on return-code error
checking, or having to constantly check error flags.  Certainly, this
is appropriate in "semantically negative," especially time-critical,
operations, but that wasn't what the OP was talking about.  One of his
examples was seeing whether a file saved correctly.  I would find any
file-save routine that relied on success/failure return codes instead
of exceptions to be highly suspect.

Walter Gildersleeve
Freiburg, Germany

______________________________________________________
http://linkfrog.net
URL Shortening
Free and easy, small and green.
Chris Smith - 25 Jan 2006 10:02 GMT
> I think the useful discussion here would be, how do we distinguish
> failures in general from exceptional conditions?  Are all failures
> exceptional?

Perhaps that would be a useful discussion to have.  The first result
would be to note that, by and large, a method whose return value is
intended entirely to indicate possible failure is a surprising and
generally poor idea.  If it's necessary to avoid handling an exception,
then it would be better to provide an API pair:

   boolean canDoX();
   void doX() throws CantDoXException;

(where, if it's so desirable, CantDoXException extends RuntimeException)

In that case, it IS exceptional to call doX when it's going to fail,
because if you thought it might fail you ought to have called canDoX
first.

> One might reasonably characterize exceptions as things
> which are not anticipated to occur in a successful execution path,
> but which we must be prepared to handle, just in case.

I'm a little lost.  The above seems to be part of the definition of all
failures: not the success path, and yet may need to be handled.

> Some examples of the kind of non-exceptional error I'm talking about:

I'll consider each in turn, then.

> * A timeout which simply results in a retry.  Maybe if we exhaust all
> our retries, *then* throw.

This one I find to be extremely shaky.  After all, there will almost
certainly exist some level of abstraction from which it's undefined
whether or not you intend to retry the operation.  Finding out would be
introducing knowledge dependency in the wrong direction, which leads to
fragile software.

> * Validation of keyboard input.  Users are bound to make typos, so
> validating and reprompting is just normal business logic.

Yep, definitely no exceptions needed there... though I could see the
case for it.  I wouldn't do it myself.

> * A readLine() function which returns false when there is no more
> input.  That's not an exception, it's a sentinel condition.  Do you
> really want to use a try/catch/finally block for that?

This shouldn't even be at issue.  Hitting the end of the stream in
readLine() is not a failure at all; it's just the end.  Of course you
don't throw an exception.

Contrast with DataInputStream, though, which is generally used to read
known-length atoms and sequences of data.  Since you're expected to know
when the data stream is done, it throws an exception if you try to read
something and hit end of stream.

Signature

www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation

Roedy Green - 25 Jan 2006 13:39 GMT
>    boolean canDoX();
>    void doX() throws CantDoXException;

Exceptions should be exceptional.  They obviously take much more time
to process than a boolean flag on "failure".

Imagine an apple sorting machine that decides if given apple is good
enough.

It makes sense for isAcceptable to return a boolean rather than throw
an exception every time an apple destined for apple sauce floats by.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Tom Leylan - 22 Jan 2006 15:36 GMT
"Roedy Green" <my_email_is_posted_on_my_website@munged.invalid> wrote...
> Which convention do you use?  true= good or true=problem?
> Why? How do you make that clear to others?

I believe positive states are preferred; things like IsValid(), IsOpen() but
that it can be reporting a problem situation as in IsMissing() or
IsPastDue().

> If you have to represent the state in side the method with a boolean
> variable, what do you call it?
>
> state, success, status, ok, wasSuccessful..?

This is an interesting question.  I adopted a simple solution decades ago
and have used it in a variety of languages.  I always name the return value,
Result.  It doesn't matter what it represents or it's datatype the last line
of the function is always Return Result.

> How is your true/false convention make obvious by your choice of name?
>
> When you say "return success" how do you avoid confusing people? Are
> you returning good or the state?

You're returning the result of the function so if the function is named
IsClosed() then Result is the answer to the question; is it closed?  But I
think you mean in an operation like Save() in which case I would return
"what was the outcome of saving".  The O/S may return various numeric values
to indicate success or failure.  If I pass these along they can good or bad
so "success" or "failure" would be an assumption we can't make.

Tom
Andrew McDonagh - 22 Jan 2006 15:47 GMT
> It is very common for a method to return a boolean that indicates
> success/fail of some test or operation.
[quoted text clipped - 6 lines]
>
> Why? How do you make that clear to others?

i use....

if (hasMoreElements())....
if (noMoreElements()....

if (isValidBlar())....
if (notValidBlar())...

i don't ever...

if (!isValidBlar())...
if (isValidBlar = false)....

...because they don't read correctly....

> If you have to represent the state in side the method with a boolean
> variable, what do you call it?  
>
> state, success, status, ok, wasSuccessful..?

I can't remember doing so....  I tend to move those kind of logic into
their own private methods, then use guard clause style checking in the
calling method.

> How is your true/false convention make obvious by your choice of name?
>
> When you say "return success" how do you avoid confusing people? Are
> you returning good or the state?

Delphi actually has a reserved keyword 'result' for especially this
purpose...
bugbear - 23 Jan 2006 15:46 GMT
> if (hasMoreElements())....
> if (noMoreElements()....
[quoted text clipped - 8 lines]
>
> ...because they don't read correctly....

Hmm. I completely disagree on your
> if (!isValidBlar())...
case.

I always use "positive" names,
so I would NEVER use your

if (notValidBlar())...

I would write

if(!validBlah()) ...

This avoids the possibility of ever having
the awful double negative

if(!noMoreElements()) ...

Which is bad for the brain IMHO.

   BugBear
Andrew McDonagh - 23 Jan 2006 19:05 GMT
>> if (hasMoreElements())....
>> if (noMoreElements()....
[quoted text clipped - 12 lines]
>  > if (!isValidBlar())...
> case.

Thats ok...  :)

> I always use "positive" names,
> so I would NEVER use your
[quoted text clipped - 9 lines]
>
> if(!noMoreElements()) ...

I wouldn't do that though...there'd be two methods and I use the
positive one where needed.

if (hasMoreElements())....

> Which is bad for the brain IMHO.

agreed..I wouldn't either...

>    BugBear
bugbear - 24 Jan 2006 10:32 GMT
>> This avoids the possibility of ever having
>> the awful double negative
[quoted text clipped - 3 lines]
> I wouldn't do that though...there'd be two methods and I use the
> positive one where needed.

Boy, you must like typing.

Given a "hasMoreElements()" you'd actually create

boolean hasNoMoreElements() {
    return !"hasMoreElements();
}

rather than use

if(!hasMoreElements()) {
}

Presumably (by extension) if you have a local
boolean:

   boolean hasMore;

you would also have
   boolean hasNoMore;

and carefully assign to both of them, just
in case you need the inverted sense.

Or would that be silly?

    BugBear
Stefan Ram - 22 Jan 2006 15:48 GMT
>It is very common for a method to return a boolean that
>indicates success/fail of some test or operation.

 I call that a "predicate" and its invocation an "assertion".

>Which convention do you use?  true= good or true=problem?

 None of the above. I use "true = 'what the name says'".

     "Good and bad, I define these terms
     Quite clear, no doubt, somehow."
     (Bob Dylan)

>Why?

 It appears natural.

>     How do you make that clear to others?

 By the name and documentation of the predicate.

>If you have to represent the state in side the method with a boolean
>variable, what do you call it?  
>state, success, status, ok, wasSuccessful..?

 Here, I'd use "success".

>How is your true/false convention make obvious by your choice of name?

 "success = true" seems cleasr to me.

>When you say "return success" how do you avoid confusing people? Are
>you returning good or the state?

 In C, the state would be:

     return success;

 While, in C, "good" often would look like:

     return SUCCESS;

 In Java, the meaning can be given by:

/** (...) @return ... */
Luc The Perverse - 22 Jan 2006 22:13 GMT
> It is very common for a method to return a boolean that indicates
> success/fail of some test or operation.
[quoted text clipped - 16 lines]
> When you say "return success" how do you avoid confusing people? Are
> you returning good or the state?

If there were some kind of difficult to avoid ambiguity, I would highly
favor true meaning successful - just because of what I've seen used, and it
fits well with my intuition.

The only situation even remotely similar that I can think of that deviated
was a function in C returning a pointer and it would return null if it
failed.

To me as a programmer true and successful are the same thing in a situation
like boolean Connect(int port) or the like.    Mentally I would a line like
this

if(!commObject.Connect(1)) . . .

as if comm object didn't connect then . . .

Trying to resolve the ambiguity by making the function name something like
ConnectSuccess or something would further complicate the matter.

But isn't the best way something of this form:

SerialConnect commObject = new SerialConnect();
try{
    commObject.Connect(1);
    . . .
}
catch(SerialConnectionException e){
. . .

}

--
LTP

:)
Scott Ellsworth - 23 Jan 2006 22:33 GMT
> It is very common for a method to return a boolean that indicates
> success/fail of some test or operation.

wasFileSaved()  isComputerOn().  didProgramCrash().

Read as a sentence, the true response means the affirmative.

 
> If you have to represent the state in side the method with a boolean
> variable, what do you call it?  

Depends.  I may call it something like ret or retVal, but for a method
of any importance, it is probably called wasFileSaved.

> When you say "return success" how do you avoid confusing people? Are
> you returning good or the state?

If the method is called wasSaveSuccessful, then ret or wasSaveSuccessful
is returned.  If the method is getState, then it returns an appropriate
object/primitive to hold the state.  For example, getSQLException
returns an SQLException.

Scott

Signature

Scott Ellsworth
scott@alodar.nospam.com
Java and database consulting for the life sciences



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.