use of assert in Java [vs. exceptions]

G

Giovanni Azua

Hello,

This is a follow up to the thread "Where should I throw RuntimeException".
At some point the topic regarding the use of assertions took over that
thread discussion.

Before moving into the concrete arguments I wanted to present the following
definitions by Bertrand Meyer:

Defensive programming: "A technique of fighting potential errors by making
every module check for many possible consistency conditions, even if this
causes redundancy of checks performed by clients and suppliers. Contradicts
Design by Contract." [1, p1195]

Design by Contract: "A method of software construction that designs the
components of a system so that they will cooperate on the basis of precisely
defined contracts. See also: defensive programming." [1, p1195]

"Assertion Violation rule (1) A run-time assertion violation is the
manifestation of a bug in the software." [1, p346]

The key in the defensive programming definition is "check". It doesn't
really matter what is done after encountering the problem either throwing
exceptions or programming an alternate way e.g. Math.sqrt that handles the
special case of negative input by returning Double.NaN. Please note that
neither Eiffel "require" nor the Java "assert" for verification of pre
conditions would fall under the category "check", by definition Design by
Contract (DbC) is not a check, they are enabled only optionally and for
discovering programming errors. Granted that Java assert feature is a small
subset of what Eiffel DbC offers [3, p15 "So, is it like 'assert.h'"].

The point I was defending was that Sun's commended way to use assertions was
too categorical "Do not use assertions to check the parameters of a public
method" [2]. The reasoning for my discrepancy towards that rule is that
programs should not handle pre condition violations that are rooted in
programming errors by means of exceptions e.g. IllegalArgumentException.
However, the case of user input validation is a good use-case for using
IllegalArgumentException. In general, exceptions are meant to be handled
programmatically. You can't nor should recover from programming errors but
rather *fix* them e.g.

Defensive alternative A:

public void defensiveMethod(...) throws IllegalArgumentException {
// first checks
if (/* some input programming error condition */) {
throw IllegalArgumentException("Caught just another bug");
}

// some checks
// some more checks ...

// now we are "safe", do the real business
}

// a possible client
try {
defensiveMethod(...);
}
catch (IllegalArgumentException exception) {
// what can you possibly do here? maybe we could ...
//
// - retrieve class name of the caller
// - get the author name out of the java file
// - send her an email complaining to FIX her code!
}

vs.

DbC alternative B:

public void dbCMethod(...) {
// assert-based pre condition verification. Assertions
// will be disabled once all programming errors are
// corrected

// assert-based class invariant verification

// do the real business

// assert-based class invariant verification

// assert-based post-condition verification
}

Defensive programming as defined by Bertrand Meyer above yields the
following negative consequences in software engineering:

- degrades performance
- predates reliability
- increases complexity
- provides only a subjective sense of safety
- increases code duplication, redundancy
- scatters concerns across disparate layers

A few excerpts from Bertrand Meyer's book:

"Non-Redundancy principle: Under no circumstances shall the body of a
routine ever test for the routine's precondition." [1, p343] For the example
that depicts such case he writes "is not just unnecessary but unacceptable"
[1, p343]

"... complexity is the major enemy of quality. When we bring in this
concern, possibly redundant checks do not appear so harmless any more!
Extrapolated to the thousands of routines of a medium -size system (or the
tens or hundreds of thousands of routines of a larger one), the if x < 0
then ... of sqrt, innocuous at first sight, begins to look like a monster of
useless complexity. By adding possibly redundant checks, you add more
software; more software means more complexity, and in particular more
sources of conditions that could go wrong; hence the need for more checks,
meaning more software; and so on ad infinitum. If we start on this road only
one thing is certain: we will never obtain reliability. The more we write,
the more we will have to write." [1, p344]

"Aside from performance considerations, however, the principal reason to
distrust defensive programming is simply our goal of getting the best
possible reliability. For a system of any significant size the individual
quality of the various elements involved is not enough; what will count most
is the guarantee that for every interaction between two elements there is an
explicit roster of mutual obligations and benefits - the contract. Hence the
Zen-style paradox of our conclusion: that to get more reliability the best
policy is often to check less." [1, p345]

Lew said:
The method [Math.sqrt] must handle the illegal input. No amount
of concern for "performance" relieves it of responsibility to
handle a negative input.
wow it is even scary! like the perfect example, hey! I will let Bertrand
Meyer respond to you here ...

"Such a comment, however, comes from a microscopic understanding of
reliability, focused on individual software elements such as the sqrt
routine. If we restrict our view to the narrow world of sqrt, then the
routine seems more robust with the extra test than without it. But the world
of a system is not restricted to a routine; it contains a multitude of
routines in a multitude of classes. To obtain reliable systems we must go
from the microscopic view to a macroscopic view encompassing the entire
architecture." [1, p344]

Lew said:
According to you, that would never happen.
How do you guarantee that? What would the
result be?
"if the client's part of the contract is not fulfilled, that is to say if
the call does not satisfy the precondition, then the class is not bound by
the postcondition. In this case the routine may do what it pleases: return
any value; loop indefinitely without returning a value; or even crash the
execution in some wild way. This is the case in which (in reference to the
discussion at the beginning of this chapter) 'the customer is wrong'." [1,
p343]

Once there is a programming error that lead to pre condition violations in
production, it does not really matter what the preferred paradigm is, either
DbC or Defensive Programming, the result will be either a crash or any
behavior that differs to that stated in the software specification.

An excellent example on how the defensive programming approach i.e. check
and throw exception can not only give a very subjective sense of safety but
also become "the problem" is the 500 million loss case of Ariane 5 "The
exception was due to a floating-point error: a conversion from a 64-bit
integer to a 16-bit signed integer, which should only have been applied to a
number less than 2^15, was erroneously applied to a greater number,
representing the "horizontal bias" of the flight. There was no explicit
exception handler to catch the exception, so it followed the usual fate of
uncaught exceptions and crashed the entire software, hence the on-board
computers, hence the mission. " [4]

From my professional experience I have personally seen and worked with both
approaches. I have seen software developed for the Java platform that could
not afford bugs but neither compromise in reliability nor performance, a
real-time high-frequency trading arbitrage solution using the closest DbC
you can have in Java. I can't recall one single e.g.
IndexOutOfBoundsException in production and most pre condition verifications
were done via asserts and these were only enabled during testing.

I hope all the excerpts and explanations illustrate my point.

Lew said:
According to you, that would never happen.
How do you guarantee that? What would the
result be?
The group of SE at ETH Zurich works on several answers to these questions
e.g.

- Formal methods [5]
- Contract-based automatic testing [6]

Soon there is this very very nice and interesting LASER Summer School where
Bertrand Meyer himself will present some of these concepts
[http://se.inf.ethz.ch/laser/2009/index.php]. I might join btw

For perfectjpattern I deliverately chose to stick to the way Sun commends
regarding the use of assertions, I would like my project perfectjpattern to
be accepted and not rejected by the Java community. I know the concepts of
DbC and how implementing those concepts in Java via assertions might be
outrageous for experienced developers (hey! at first it happened to me too)
but it can't hurt to have a wider picture and use this knowledge to make
more educated design decisions.

Related discussions:

"Where should I throw RuntimeException"
[http://groups.google.com/group/comp...n&lnk=gst&q=RuntimeException#30a419d1a0522e92]

"Assertions vs Exceptions" posted to this group in 2007
[http://groups.google.com/group/comp...hread/54c528bd8ca61f73/e4ebf460a43f9aa1?hl=en]

"Modular Protection vs Assertions" posted to the comp.lang.eiffel group in
2007
[http://groups.google.com/group/comp...6fbf9cd89c5/273571d8d33088a1#273571d8d33088a1]

Best regards,
Giovanni

[1] Programming with Assertions
[http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html]
[2] Object Oriented Software Construction 2nd Edition Bertrand Meyer
[http://www.amazon.com/Object-Orient...=sr_1_1?ie=UTF8&s=books&qid=1243672117&sr=8-1]
[3] OOSC course slides "Design by Contract"
[http://se.inf.ethz.ch/teaching/ss2005/0250/lectures/oosc_11_dbc_1up.pdf]
[4] The lessons of Ariane
[http://archive.eiffel.com/doc/manuals/technology/contract/ariane/page.html]
[5] Formal methods [http://en.wikipedia.org/wiki/Formal_methods]
[6] Automatic Testing based on Design by Contract
[http://www.mathematik.uni-ulm.de/sai/mayer/soqua05/slides/ciupa.pdf]
 
R

Roedy Green

The way I see it is this:

Assertions are to defend against programming bugs.

Exceptions are to defend against bad or freakish data.

I think we programmers tend to underuse assertions. They can detect
subtle problems before the bug shows up as obvious insane program
behaviour. You can leave assertions in place without speed penalty by
not using an -ea on the command line.

--
Roedy Green Canadian Mind Products
http://mindprod.com

"Everybody’s worried about stopping terrorism. Well, there’s a really easy way: stop participating in it."
~ Noam Chomsky
 
A

Arved Sandstrom

Giovanni Azua wrote:
[ SNIP ]
The point I was defending was that Sun's commended way to use assertions was
too categorical "Do not use assertions to check the parameters of a public
method" [2]. The reasoning for my discrepancy towards that rule is that
programs should not handle pre condition violations that are rooted in
programming errors by means of exceptions e.g. IllegalArgumentException.
However, the case of user input validation is a good use-case for using
IllegalArgumentException. In general, exceptions are meant to be handled
programmatically. You can't nor should recover from programming errors but
rather *fix* them e.g.

Defensive alternative A:

public void defensiveMethod(...) throws IllegalArgumentException {
// first checks
if (/* some input programming error condition */) {
throw IllegalArgumentException("Caught just another bug");
}

// some checks
// some more checks ...

// now we are "safe", do the real business
}

// a possible client
try {
defensiveMethod(...);
}
catch (IllegalArgumentException exception) {
// what can you possibly do here? maybe we could ...
//
// - retrieve class name of the caller
// - get the author name out of the java file
// - send her an email complaining to FIX her code!
}

vs.

DbC alternative B:

public void dbCMethod(...) {
// assert-based pre condition verification. Assertions
// will be disabled once all programming errors are
// corrected

// assert-based class invariant verification

// do the real business

// assert-based class invariant verification

// assert-based post-condition verification
}
[ SNIP ]

Giovanni, I have some problems with the above examples. Let me explain
why. :)

Leaving temporarily aside the issue of "defensive" (I prefer to call it
"argument checking" in this case) code having errors, the main point I'd
like to make is that defensiveMethod() does not have pre-conditions that
could be addressed using asserts. It's *expected* that certain inputs
will come in that we then screen out, using that "if", and tell the
client that the input was unacceptable by throwing an
IllegalArgumentException. In this scenario, that code is *not* error
handling code (except in the widest sense, that of user input error
perhaps), and it's certainly not a programming error to be discovered
using assertions - it's business logic.

As far as the "defensive" code itself having errors, as far as I am
concerned go ahead and use assertions to help track those down if you
wish. You could have an assert related to the condition used by the "if"
if it made sense. I might add, if you're going to include stuff like
that in contrasting examples, it would have been only fair to have

assert (/* some egregiously wrong condition */);

The main point I'm making is, there are errors and then there are
errors. In the case of defensiveMethod() allowing for argument #2 to be
a String, really wanting it to be a "\\d+", but sometimes seeing "\\w+",
seeing a String that is not a "\\d+" is not a programming error. So why
would we ever consider using assertions?

AHS
 
J

Joshua Cranmer

Giovanni said:
The point I was defending was that Sun's commended way to use assertions was
too categorical "Do not use assertions to check the parameters of a public
method" [2]. The reasoning for my discrepancy towards that rule is that
programs should not handle pre condition violations that are rooted in
programming errors by means of exceptions e.g. IllegalArgumentException.

In the C and C++ world, such invalid parameters as null pointers can
cause what could have been merely an operation to fail to cause the
program to crash (the dreaded segfault). It is therefore very advisable
in those languages to always defend methods against invalid parameters,
even if it's programmer and not user error.

In Java, of course, the uncaught IllegalArgumentException would do much
the same thing that the analogous NullPointerException would have done.
There is, however, one key difference: if you check the arguments at the
beginning of the method, you prevent the class from entering an
erroneous, incomplete state, which allows for the ability to merely
consume the programmer error by simply invalidating the operation and
allowing recoverability.
public void dbCMethod(...) {
// assert-based pre condition verification. Assertions
// will be disabled once all programming errors are
// corrected

Given the history of software design, this should be interpreted as
assertions will never be disabled. How can you know when you've fixed
all programming errors? I'm willing to bet that even TeX still has
errors in it, and that's a program whose maintenance is purely bug-fix
these days.
Defensive programming as defined by Bertrand Meyer above yields the
following negative consequences in software engineering:

- degrades performance

An intelligent design will only have to check the arguments once per
library level. Take a look at Java's Arrays' sort methods--instead of
performing the recursive call with the public, argument-checking
methods, all of the methods recursively call private, non-checking
methods. In the end, all public methods are defensive yet the penalizing
performance.

Also, if defensive checks are seriously degrading performance, you're
probably not doing them right.
Once there is a programming error that lead to pre condition violations in
production, it does not really matter what the preferred paradigm is, either
DbC or Defensive Programming, the result will be either a crash or any
behavior that differs to that stated in the software specification.

The worst that can happen if preconditions are violated and the callee
does not seek to adhere to any contract is that an exploit occurs--the
leak of information to those not permitted to see it. The wast that can
happen if the callee simply errors out immediately on violated
preconditions is that an error is promulgated upwards. Whatever results
come out of such a situation is entirely due to the unimaginative
programmer who assured himself that his program could not error.
An excellent example on how the defensive programming approach i.e. check
and throw exception can not only give a very subjective sense of safety but
also become "the problem" is the 500 million loss case of Ariane 5 "The
exception was due to a floating-point error: a conversion from a 64-bit
integer to a 16-bit signed integer, which should only have been applied to a
number less than 2^15, was erroneously applied to a greater number,
representing the "horizontal bias" of the flight. There was no explicit
exception handler to catch the exception, so it followed the usual fate of
uncaught exceptions and crashed the entire software, hence the on-board
computers, hence the mission. " [4]

This strikes me as a strong admission of support for checked exceptions,
not an argument against checking conditions. What if there hadn't been a
check, and the program had made the conversion as instructed? It seems
to me that there would have been a variable storing the horizontal bias
of the flight which was a few magnitudes of order off--which sounds like
it would have resulted in the craft thinking it was somewhere else,
ultimately crashing into an obstacle as a result of miscalculation.

This is also a result of underappreciation for Murphy's Law.


In the end, you have not convinced me of the harms of doing parameter
validation via exceptions versus asserts. I would much rather be told
that my method call failed via an exception, which permits me the
ability to handle it, than I would that it blithely continues into a
corrupt state.
 
J

John B. Matthews

Joshua Cranmer said:
Giovanni Azua wrote: [...]
An excellent example on how the defensive programming approach i.e.
check and throw exception can not only give a very subjective sense
of safety but also become "the problem" is the 500 million loss
case of Ariane 5 "The exception was due to a floating-point error:
a conversion from a 64-bit integer to a 16-bit signed integer,
which should only have been applied to a number less than 2^15, was
erroneously applied to a greater number, representing the
"horizontal bias" of the flight. There was no explicit exception
handler to catch the exception, so it followed the usual fate of
uncaught exceptions and crashed the entire software, hence the
on-board computers, hence the mission. "

This strikes me as a strong admission of support for checked
exceptions, not an argument against checking conditions.

This is precisely correct. The claims made in the work cited [1] are
subject to some debate [2]. The relevant exception was disabled in the
Ariane 4 inertial reference system (IRS) for performance reasons [3].
The IRS functioned correctly in Ariane 4 because the flight path
characteristics precluded an incorrect value [4-3.1o]. The Araine 4 IRS
was reused in the Araine 5 without adequate testing of the new flight
parameters and without re-enabling the exception [4-3.1r,s].

[...]

[1]<http://archive.eiffel.com/doc/manuals/technology/contract/ariane/page.html>
[2]<http://home.flash.net/~kennieg/ariane.html>
[3]<http://en.wikipedia.org/wiki/Ariane_5_Flight_501>
[4]<http://web.archive.org/web/20000815230639/www.esrin.esa.it/htdocs/tidc/Press/Press96/ariane5rep.html>
 
L

Lew

John said:
Joshua Cranmer said:
Giovanni Azua wrote: [...]
An excellent example on how the defensive programming approach i.e.
check and throw exception can not only give a very subjective sense
of safety but also become "the problem" is the 500 million loss
case of Ariane 5 "The exception was due to a floating-point error:
a conversion from a 64-bit integer to a 16-bit signed integer,
which should only have been applied to a number less than 2^15, was
erroneously applied to a greater number, representing the
"horizontal bias" of the flight. There was no explicit exception
handler to catch the exception, so it followed the usual fate of
uncaught exceptions and crashed the entire software, hence the
on-board computers, hence the mission. "
This strikes me as a strong admission of support for checked
exceptions, not an argument against checking conditions.

This is precisely correct. The claims made in the work cited [1] are
subject to some debate [2]. The relevant exception was disabled in the
Ariane 4 inertial reference system (IRS) for performance reasons [3].
The IRS functioned correctly in Ariane 4 because the flight path
characteristics precluded an incorrect value [4-3.1o]. The Araine 4 IRS
was reused in the Araine 5 without adequate testing of the new flight
parameters and without re-enabling the exception [4-3.1r,s].

[...]

[1]<http://archive.eiffel.com/doc/manuals/technology/contract/ariane/page.html>
[2]<http://home.flash.net/~kennieg/ariane.html>
[3]<http://en.wikipedia.org/wiki/Ariane_5_Flight_501>
[4]<http://web.archive.org/web/20000815230639/www.esrin.esa.it/htdocs/tidc/Press/Press96/ariane5rep.html>

As the evidence mounts, the argument for "don't check input values" seems to
rest on "Bertrand Meyer says so", and the counterargument to "you cannot
prevent client code from handing in invalid values" is, "that's their
problem". If a check is done in client code to prevent bad values, that's the
same performance "penalty" as doing it in API code, but in the latter case the
code cannot fail to perform as contracted, and the check is centralized in the
logic that understands the preconditions.

So despite the disparaging tone implied in the use of the term "defensive
programming", the actual evidence and logic presented continue to support
putting condition checks in the API methods, and thus allowing the method to
deal sensibly with any given input, irrespective of error or mischief by
client code.
 
S

Stefan Ram

Giovanni Azua said:
- degrades performance

I have two thoughts on this.

1.) Assume »div(x,y)« had undefined behaviour when y == 0,
and we wanted to do this in an application:

for( x = 0; x < HUGE; ++x )div( x, y );

The application knows that in the case of y being 0, the
best thing to do is »f()«, so

if( y )for( x = 0; x < HUGE; ++x )div( x, y ); else f();

. We can see that it is sufficient to do the test /once
outside of the loop/ for a primitive variable »y« in a
single-threaded application. If the test would be done
inside of »div« instead, it would not be possible to move
it outside of the loop.

2.) Assume »div(x,y)« had undefined behaviour when y == 0.
One can always write a wrapper »defensiveDiv(x,y)« that has
defined behaviour for y == 0 and otherwise the same behavior
as »div(x,y)«, while it might be slower than »div(x,y)«.

On the other hand, given only »defensiveDiv(x,y)« it is not
possible to write a wrapper to get the behavior and run-time
properties of »div(x,y)«.
 
G

Giovanni Azua

Hallo Stefan,

Stefan Ram said:
I have two thoughts on this.

1.) Assume »div(x,y)« had undefined behaviour when y == 0,
and we wanted to do this in an application:

for( x = 0; x < HUGE; ++x )div( x, y );

The application knows that in the case of y being 0, the
best thing to do is »f()«, so

if( y )for( x = 0; x < HUGE; ++x )div( x, y ); else f();

. We can see that it is sufficient to do the test /once
outside of the loop/ for a primitive variable »y« in a
single-threaded application. If the test would be done
inside of »div« instead, it would not be possible to move
it outside of the loop.

2.) Assume »div(x,y)« had undefined behaviour when y == 0.
One can always write a wrapper »defensiveDiv(x,y)« that has
defined behaviour for y == 0 and otherwise the same behavior
as »div(x,y)«, while it might be slower than »div(x,y)«.

On the other hand, given only »defensiveDiv(x,y)« it is not
possible to write a wrapper to get the behavior and run-time
properties of »div(x,y)«.
Good insight indeed, very nice!

Gruss!
Giovanni
 
L

Lew

Giovanni said:
Good insight indeed, very nice!

In Java, if the arguments are integers then division by 0 with the '/'
operator throws an 'ArithmeticException'. Is that "defensive programming"?
Does it make the '/' operation slow?

In Java, if the arguments are of a floating-point type, e.g., 'double', then
division by zero yields a double value ('NaN' or signed infinity). Is that
"defensive programming"? Does it make the '/' operation slow?

It seems that Java is able to define arithmetic '/' such that it can handle
all possible inputs without running into the performance problems that some
seem to think are a risk. If one wants to modify the behavior of division by
zero, say with integers to avoid causing an 'ArithmeticException', one can do
the optimized value check that Stefan suggests. Presumably this would be
inside a method that accepts a value for 'y' and forwards the action to 'f()'
or '/' as needed. Is that "defensive programming", or is the check outside
the loop for 'y == 0' and corresponding delegation to 'f()' just "good
programming"?
 
R

Robert Klemme

Before moving into the concrete arguments I wanted to present the following
definitions by Bertrand Meyer:

Defensive programming: "A technique of fighting potential errors by making
every module check for many possible consistency conditions, even if this
causes redundancy of checks performed by clients and suppliers. Contradicts
Design by Contract." [1, p1195]

Design by Contract: "A method of software construction that designs the
components of a system so that they will cooperate on the basis of precisely
defined contracts. See also: defensive programming." [1, p1195]

"Assertion Violation rule (1) A run-time assertion violation is the
manifestation of a bug in the software." [1, p346]

The key in the defensive programming definition is "check". It doesn't
really matter what is done after encountering the problem either throwing
exceptions or programming an alternate way e.g. Math.sqrt that handles the
special case of negative input by returning Double.NaN. Please note that
neither Eiffel "require" nor the Java "assert" for verification of pre
conditions would fall under the category "check", by definition Design by
Contract (DbC) is not a check, they are enabled only optionally and for
discovering programming errors. Granted that Java assert feature is a small
subset of what Eiffel DbC offers [3, p15 "So, is it like 'assert.h'"].

The point I was defending was that Sun's commended way to use assertions was
too categorical "Do not use assertions to check the parameters of a public
method" [2]. The reasoning for my discrepancy towards that rule is that
programs should not handle pre condition violations that are rooted in
programming errors by means of exceptions e.g. IllegalArgumentException.
However, the case of user input validation is a good use-case for using
IllegalArgumentException.

Actually, if you write a library that is distributed as a jar the code
must check input into public accessible methods always and handle them
appropriately. This often means throwing an IllegalArgumentException
but it may also mean returning a special value such as NaN. Which
approach is more appropriate depends on the situation. But the code
needs to do this in order to maintain integrity of its internal state
(class invariants for example). Now, considering that a class is a
module much the same way as library every public method of it is part of
its API and marks the border between "outside" and "inside".

Basically this means that all public and protected methods need some
form of argument checking and dealing with illegal data. Other
languages have other means but since Java does not support DbC in the
language you have to use the features that you have.

IMHO you should only use assert for input checking if a) performance is
paramount _and_ b) you have _system_ test coverage that includes
combinations of all classes of correct and incorrect input data and all
possible invocation paths. This means that for most Java applications
out there (which do not play in the field of space mission control or
high performance realtime processing) you would rather have checks with
exceptions than using assert for input checking.

Personally I often use assert in situations where non trivial
calculations are done and I would have used a comment in pre Java 5.
The nice thing about assert is that you do not pay the performance
penalty in production while retaining a relatively short expression
which also helps documenting. For example

Collection<Foo> foos = ...
... complex processing here which must eventually empty foos ..
assert foos.isEmpty();
In general, exceptions are meant to be handled
programmatically. You can't nor should recover from programming errors but
rather *fix* them e.g.

This is the precise reason why there are checked and unchecked
exceptions in Java. Similarly to Error and subclasses unchecked
exceptions should be handled programmatically only in relatively rare
cases, e.g. in a testing framework or in an application which must keep
running under all circumstances (e.g. a JEE container which must not
break just because a single application of potentially many deployed
applications runs berserk).
A few excerpts from Bertrand Meyer's book:

"Non-Redundancy principle: Under no circumstances shall the body of a
routine ever test for the routine's precondition." [1, p343] For the example
that depicts such case he writes "is not just unnecessary but unacceptable"
[1, p343]

You need to keep on mind that this is in the context of his book where
he presents Eiffel. (Btw, it seems you got the quote numbering wrong,
this must be from OOSC which is [2] in your posting.) With a language
that provides rich DbC support and declarative pre- and postconditions
it is of course nonsense to check those inside method bodies.
"Aside from performance considerations, however, the principal reason to
distrust defensive programming is simply our goal of getting the best
possible reliability. For a system of any significant size the individual
quality of the various elements involved is not enough; what will count most
is the guarantee that for every interaction between two elements there is an
explicit roster of mutual obligations and benefits - the contract. Hence the
Zen-style paradox of our conclusion: that to get more reliability the best
policy is often to check less." [1, p345]

This still means that you need _some_ form of automatic checking of this
contract so you can detect violations. _How_ this checking is done is a
highly programming language dependent issue. In Eiffel you have DbC
support, in Java you have assert, checks and exceptions.
Lew said:
The method [Math.sqrt] must handle the illegal input. No amount
of concern for "performance" relieves it of responsibility to
handle a negative input.
"Such a comment, however, comes from a microscopic understanding of
reliability, focused on individual software elements such as the sqrt
routine. If we restrict our view to the narrow world of sqrt, then the
routine seems more robust with the extra test than without it. But the world
of a system is not restricted to a routine; it contains a multitude of
routines in a multitude of classes. To obtain reliable systems we must go
from the microscopic view to a macroscopic view encompassing the entire
architecture." [1, p344]

I can agree to that one although I find the statement very vague. And:
looking at the entire architecture does not make Lew's point invalid
that your microscopic checks need to be there - one way or another. You
cannot build a house on individual components that do not deliver
advertised quality.
I hope all the excerpts and explanations illustrate my point.

Frankly, with all the quotes I am not sure what _your_ point really is.
You seem to advocate to drop what has been called "defensive
programming" in your article but since I did not follow the other thread
my insights into your own reasoning are limited.

Kind regards

robert
 
G

Giovanni Azua

Giovanni Azua said:
[1] Programming with Assertions
[http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html]
[2] Object Oriented Software Construction 2nd Edition Bertrand Meyer
[http://www.amazon.com/Object-Orient...=sr_1_1?ie=UTF8&s=books&qid=1243672117&sr=8-1]
I made a mistake in the order of these two references, it should be:

[1] Object Oriented Software Construction 2nd Edition Bertrand Meyer
http://www.amazon.com/Object-Orient...=sr_1_1?ie=UTF8&s=books&qid=1243672117&sr=8-1
[2] Programming with Assertions
http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html

Best regards,
Giovanni
 
G

Giovanni Azua

Hello Robert,

Please find my comments below:

Robert Klemme said:
Actually, if you write a library that is distributed as a jar the code
must check input into public accessible methods always and handle them
appropriately. This often means throwing an IllegalArgumentException
[snip]
I don't agree that the type of distribution source, jar, war or ear is what
drives the decision to label public methods as "exposed". I explain at the
end.
A few excerpts from Bertrand Meyer's book:

"Non-Redundancy principle: Under no circumstances shall the body of a
routine ever test for the routine's precondition." [1, p343] For the
example that depicts such case he writes "is not just unnecessary but
unacceptable" [1, p343]

You need to keep on mind that this is in the context of his book where he
presents Eiffel. [snip] With a language that provides rich DbC support
and declarative pre- and postconditions it is of course nonsense to check
those inside method bodies.
In principle I agree with you, asserts are not a full fledge DbC
implementation, but for the OP being discussed: pre condition verification
you can get quite a good approximation with the assert construct.
"Aside from performance considerations, however, the principal reason to
distrust defensive programming is simply our goal of getting the best
possible reliability. For a system of any significant size the individual
quality of the various elements involved is not enough; what will count
most is the guarantee that for every interaction between two elements
there is an explicit roster of mutual obligations and benefits - the
contract. Hence the Zen-style paradox of our conclusion: that to get more
reliability the best policy is often to check less." [1, p345]

This still means that you need _some_ form of automatic checking of this
contract so you can detect violations. _How_ this checking is done is a
highly programming language dependent issue. In Eiffel you have DbC
support, in Java you have assert, checks and exceptions.
You only need to build sufficient test suites with test coverage
proportional to the cyclomatic complexity.
Lew said:
The method [Math.sqrt] must handle the illegal input. No amount
of concern for "performance" relieves it of responsibility to
handle a negative input.
"Such a comment, however, comes from a microscopic understanding of
reliability, focused on individual software elements such as the sqrt
routine. If we restrict our view to the narrow world of sqrt, then the
routine seems more robust with the extra test than without it. But the
world of a system is not restricted to a routine; it contains a multitude
of routines in a multitude of classes. To obtain reliable systems we must
go from the microscopic view to a macroscopic view encompassing the
entire architecture." [1, p344]

I can agree to that one although I find the statement very vague.
Good that we agree here. Why is it vague?
And: looking at the entire architecture does not make Lew's point invalid
that your microscopic checks need to be there - one way or another. You
cannot build a house on individual components that do not deliver
advertised quality.
The microscopic view of reliability comes from the fact that every method in
every class would have unnecsessary defensive checks, I think the means
defeats the purpose in this case.
Frankly, with all the quotes I am not sure what _your_ point really is.
You seem to advocate to drop what has been called "defensive programming"
in your article but since I did not follow the other thread my insights
into your own reasoning are limited.
My point is the following:
The point I was defending was that Sun's commended way to use assertions
was too categorical "Do not use assertions to check the parameters of a
public method" [2]. The reasoning for my discrepancy towards that rule is
that ...

I believe that the best rule to decide whether to place validation in a
public method should depend on the concept of "exposed" rather than the
access level alone:

- If the public method is "exposed" then use "defensive programming"
integrity checks [1, p1195]
- If the public method is not "exposed" then use assertions or DbC

Examples of "exposed" public methods:

- Method exposed as Web Service
- Method exposed as business EJB
- Method that reads input from file
- Method that reads from a Socket
- Method that processes end user gestures and inputs, "filtering" layer [1]
after a presentation layer

Example of non "exposed" public methods:

- JPA API
- XML API
- Utilities API
- JDK Collections API
- JDK Concurrency API
- Java Arrays
- Design patterns library

What do all non "exposed" public methods have in common? that any Java
application or component built on top of them can proof fulfillment of pre
condition and correctness via unit testing while assertions are enabled i.e.
any pre condition violation is a programming error whereas the case of
"exposed" public methods the possible pre conditions violations can not be
unit tested/prevented and require input validation.

Again to conclude, my only point here is that the statement "Do not use
assertions to check the parameters of a public method" [2] is too
categorical and not the absolute truth.

Best regards,
Giovanni
 
G

Giovanni Azua

Lew said:
In Java, if the arguments are integers then division by 0 with the '/'
operator throws an 'ArithmeticException'. Is that "defensive
programming"? Does it make the '/' operation slow?

In Java, if the arguments are of a floating-point type, e.g., 'double',
then division by zero yields a double value ('NaN' or signed infinity).
Is that "defensive programming"? Does it make the '/' operation slow?
This is what Bertrand Meyer calls the microscopic view of reliability ... I
provided the reasoning and explanations in the OP and not just the "Bertrand
Meyer says so" argument that you presented before.
It seems that Java is able to define arithmetic '/' such that it can
handle all possible inputs without running into the performance problems
that some seem to think are a risk.
I don't think this was the point that Stefan was trying to make.
If one wants to modify the behavior of division by zero, say with integers
to avoid causing an 'ArithmeticException', one can do the optimized value
check that Stefan suggests. Presumably this would be inside a method that
accepts a value for 'y' and forwards the action to 'f()' or '/' as needed.
Is that "defensive programming", or is the check outside the loop for 'y
== 0' and corresponding delegation to 'f()' just "good programming"?
I think it depends, if that supposed method would be "exposed" e.g. a method
exposed as Web Service then the input validation rule applies, it would then
be "good defensive programming". If, on the other hand, the supposed method
belongs to an Utils/Support API e.g. Math then I would use assertions rather
than defensive checks.

It is unlikely that someone develops a professional UI that would let users
enter values that are passed directly to Utils/Supports API or primitive
operator calls e.g. "a / b" that would be a very bad design. In this case as
I mentioned before you would have a presentation layer (input conditional
checking) or enforced by the UI widgets e.g. combo boxes rather than input
fields, then the defensive filter layer [1] and finally the call to the
assert-based f(a,b) = "a / b".

I would be curious to know what your handler would look like for an
'ArithmeticException', maybe I will learn something new today, and I mean it
without any bad intentions. I think any piece of code leading to an
'ArithmeticException' will need to be reviewed, fixed and better unit
tested.

Best regards,
Giovanni
 
A

Arved Sandstrom

Giovanni Azua wrote:
[ SNIP ]
Again to conclude, my only point here is that the statement "Do not use
assertions to check the parameters of a public method" [2] is too
categorical and not the absolute truth.

Best regards,
Giovanni

It probably is too categorical, sure. I'll agree with that. I'll also
agree that not all public methods are used in the same way - as you put
it, some are "exposed" and some are not.

My original post in this thread had to do specifically with what you
call "exposed" public methods.

Now, if we're talking preconditions, this is a client obligation. So if
a non-"exposed" public method is not to do input checking, we'll expect
all client code to do so instead. So just prior to calling that method
from the client code we could certainly use assertions, since at that
point we consider calling the method with incorrect arguments to be a
programming error. I don't myself have any major problem with that, and
I believe this is what you've been suggesting...correct me if I'm wrong.

The only sticking point is, you'd want to be really careful with API
design _and_ implementation. Lots of commenting also. Because clients
would definitely want to know that if using such-and-such a method it's
all up to them, and if they don't do the right thing the code is going
to break badly.

AHS
 
G

Giovanni Azua

Hi Joshua,

This is only a pre-response :) my gf is pushing me to leave the computer :)

Joshua Cranmer said:
This strikes me as a strong admission of support for checked exceptions,
not an argument against checking conditions. What if there hadn't been a
You really want to see a floor full of developers all complaining big time
.... give them an API full of checked exceptions to work with! it is
hilarious! :) I had once the chance to see this :)

It is a bit contradictory because IllegalArgumentException would then be a
good candidate for checked exception. But this won't happen unless Sun wants
to see most of its fans moving to .Net :)

Best regards,
Giovanni
 
L

Lew

Giovanni said:
You really want to see a floor full of developers all complaining big time
... give them an API full of checked exceptions to work with! it is
hilarious! :) I had once the chance to see this :)

Obviously they didn't understand the value or purpose of checked exceptions.

There really is nothing hilarious about ignorance. Checked exceptions are
there for a good reason, and users of libraries that have checked exceptions
in the method signature should focus on that. How much extra work is it to
add ten lines of code to check an exception? Negligible, that's how much.
What's to complain about? Especially considering that you get
compiler-enforced reminders to handle the exceptions, so you don't even risk
forgetting to handle them?
 
L

Lew

Giovanni said:
I think it depends, if that supposed method would be "exposed" e.g. a method
exposed as Web Service then the input validation rule applies, it would then
be "good defensive programming". If, on the other hand, the supposed method
belongs to an Utils/Support API e.g. Math then I would use assertions rather
than defensive checks.

Assertions are not a replacement or substitute for "defensive" checks, but
complementary to them.
It is unlikely that someone develops a professional UI that would let users
enter values that are passed directly to Utils/Supports API or primitive
operator calls e.g. "a / b" that would be a very bad design. In this case as
I mentioned before you would have a presentation layer (input conditional
checking) or enforced by the UI widgets e.g. combo boxes rather than input
fields, then the defensive filter layer [1] and finally the call to the
assert-based f(a,b) = "a / b".

I think we agree on this. You are making essentially the same point I've been
making.

I do think that you're glossing over the fact that the division operator also
adheres to what I have been suggesting - it throws 'ArithmeticException' when
you attempt integral division by zero, and returns a valid value when you
attempt floating-point division by zero. So even if you let the input value
from the presentation layer directly through to the division, division by zero
gets handled. This is consistent with my recommendation and that of others,
that all inputs should be handled.
I would be curious to know what your handler would look like for an
'ArithmeticException', maybe I will learn something new today, and I mean it
without any bad intentions. I think any piece of code leading to an
'ArithmeticException' will need to be reviewed, fixed and better unit
tested.

Again I agree with you. As for my handler, it would depend on the desired
product behavior. It might look like this:

public int sumDivByInput( int divisor )
{
if ( divisor == 0 )
{
return 0;
}
assert divisor != 0;
int sum = 0;
for ( int divid : dividends )
{
sum += divid / divisor;
}
return sum;
}
 
L

Lew

Giovanni said:
I don't agree that the type of distribution source, jar, war or ear is what
drives the decision to label public methods as "exposed". I explain at the
end. ....
What do all non "exposed" public methods have in common? that any Java
application or component built on top of them can proof fulfillment of pre
condition and correctness via unit testing while assertions are enabled i.e.
any pre condition violation is a programming error whereas the case of
"exposed" public methods the possible pre conditions violations can not be
unit tested/prevented and require input validation.

Once you release a class with public or protected methods, those methods are
exposed. That's a fact. It is true as you say that the type of distribution
is not relevant; the mere fact that a method is public or protected is what
exposes it.
Again to conclude, my only point here is that the statement "Do not use
assertions to check the parameters of a public method" [2] is too
categorical and not the absolute truth.

Actually, you have said nothing to contradict its truth, other than "it's not
the absolute truth". Your suggestion to use assertions to aid in testing then
to disable them supports the dictum not to use assertions to check the
parameters of a public method, at least not in production contexts. You also
recommend in such cases not to use exceptions or other so-called "defensive"
mechanisms. If anything, you extend Sun's advice rather than contradict it;
you go beyond "don't use assertions to check the parameters of a public
method" to "don't use anything (in production) to check the parameters of a
public method".

Sun's point is true on the face of it - if you disable assertions, then they
cannot check anything. so anyone relying on them for so-called "defensive"
checks will be disappointed. That's all they're saying.
 
T

Tom Anderson

Joshua Cranmer said:
Giovanni Azua wrote: [...]
An excellent example on how the defensive programming approach i.e.
check and throw exception can not only give a very subjective sense
of safety but also become "the problem" is the 500 million loss
case of Ariane 5 "The exception was due to a floating-point error:
a conversion from a 64-bit integer to a 16-bit signed integer,
which should only have been applied to a number less than 2^15, was
erroneously applied to a greater number, representing the
"horizontal bias" of the flight. There was no explicit exception
handler to catch the exception, so it followed the usual fate of
uncaught exceptions and crashed the entire software, hence the
on-board computers, hence the mission. "

This strikes me as a strong admission of support for checked
exceptions, not an argument against checking conditions.

This is precisely correct. The claims made in the work cited [1] are
subject to some debate [2].

That Eiffeltard article you link to makes my blood boil.

There's only one thing that would have been guaranteed to catch the error,
and all other kinds of error like it. It's not a funky language, or
self-flagellating development practice, or esoteric philosophy. It's a lot
simpler than that: it's testing.

At no point before the 501 launch did the engineers perform a whole-system
integration test. They never put the whole software package together on a
testbed and see if it worked.

The report spends some time sort of mumbling about why that would have
been really hard and not really practical, but it's self-serving bullshit.
You don't fly a billion euros of hardware that thousands of people have
spent years of their lives building unless you've tested the software to
that level. And if you can't figure out how to do that test, resign, and
we'll find someone who can.

If they had tested the complete system, they would have detected the
problem after 37 seconds. No ifs, no buts.

tom
 
G

Giovanni Azua

Hello Arved,

Arved Sandstrom said:
Now, if we're talking preconditions, this is a client obligation. So if a
non-"exposed" public method is not to do input checking, we'll expect all
client code to do so instead. So just prior to calling that method from
the client code we could certainly use assertions, since at that point we
consider calling the method with incorrect arguments to be a programming
error. I don't myself have any major problem with that, and I believe this
is what you've been suggesting...correct me if I'm wrong.
The assertions for pre condition verification would be on the routine
supplier side and not on the client side. The real client (there could be
more than one layer away) can either check for the input to be valid or make
sure it is.
The only sticking point is, you'd want to be really careful with API
design _and_ implementation. Lots of commenting also. Because clients
This is a good one. Unlike Eiffel and I think unfortunately the only way in
Java to have a routine supplier explicitly advertising its pre conditions is
through Javadoc and this is a flaw, because the Javadoc would need to be
kept in sync with the asserts manually.

There are several products that offer a proper DbC implementation in Java
e.g.
http://www.contract4j.org/contract4j
http://www.mmsindia.com/JMSAssert.html

The contract4j looks very nice actually (using annotations and aspects) but
I can't tell how popular or widely adopted these are specially because I
would not be surprised to see Sun adding support in Java for a full fledged
DbC implementation in the future, anyone knows? :) Therefore having a
codebase implementing DbC based on one of those solutions would mean to
secure yourself a future migration problem.
would definitely want to know that if using such-and-such a method it's
all up to them, and if they don't do the right thing the code is going to
break badly.
Throwing an exception that no one will ever handle e.g.
'ArithmeticException' will also lead to a break. I can't tell which one
would be more badly though :) I believe that being less paranoid and keeping
the code simpler without so much of the "defensive" would also be a good
thing.

Best regards,
Giovanni
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top