Assert vs. RuntimeException

T

Twisted

With asserts now in Java, which places where one formerly threw
RuntimeExceptions (and Errors) might be better off changed to asserts?
(Can't happens, of course, but where else? Everywhere you threw
nullpointerexception? What about arithmetic exceptions? Obviously not
anywhere the exception's expected to be caught and handled somehow,
such as just skipping over a value that causes an arithmetic exception
when graphing a function...)

What's currently considered "best practise" in this area?
 
T

Thomas Hawtin

Twisted said:
With asserts now in Java, which places where one formerly threw
RuntimeExceptions (and Errors) might be better off changed to asserts?
(Can't happens, of course, but where else? Everywhere you threw
nullpointerexception? What about arithmetic exceptions? Obviously not
anywhere the exception's expected to be caught and handled somehow,
such as just skipping over a value that causes an arithmetic exception
when graphing a function...)

You should not use assert to check parameters (at least for non-private
methods). Use it to check that the logic of local code is correct.

Tom Hawtin
 
C

Chris Smith

Twisted said:
With asserts now in Java, which places where one formerly threw
RuntimeExceptions (and Errors) might be better off changed to asserts?
(Can't happens, of course, but where else? Everywhere you threw
nullpointerexception? What about arithmetic exceptions? Obviously not
anywhere the exception's expected to be caught and handled somehow,
such as just skipping over a value that causes an arithmetic exception
when graphing a function...)

What's currently considered "best practise" in this area?

As a general rule of thumb, use an assertion when the following three
propositions are true:

1. You know that something is wrong.

AND

(2a. Failure won't be immediate and obvious.
OR
2b. You can provide a very helpful detail message.)

AND

3. This is NOT part of the interface to published or reusable code.

In these cases, an assertion may be a little more readable than throwing
a runtime exception. Whether you replace existing exceptions with
assertions depends on how you've used exceptions in the past; but the
default answer ought to be "no." You may consider replacing some
explicit "throw" statements with assertions. However, you certainly
don't want to hunt down sources of implicit (not explicitly thrown)
runtime exceptions and replace them with assertions; after all, if you
know that an exception will be thrown, then #2a is false, and an
assertion is not needed unless you can be helpful enough in your message
to justify cluttering the code. For example:

assert b != null : "Gizmo needs to armed before widget is tweaked.";
b.tweak();

might be justified, but:

assert b != null : "Widget is null";
b.tweak();

is probably bad code. Anyone who's ever seen the word Java is capable
of reading the next line and realizing why they got a
NullPointerException. They don't need to you inform them that the
variable was null. That's just useless clutter that obscures the
function of your code.

Regarding #3: Remember that assertions may be disabled, so you can't
rely on them to check things like preconditions of relatively widespread
APIs. It may be tempting, but the long-term result will be that users
will stop trusting your APIs because they won't enable those assertions.
So never replace IllegalArgumentException or IllegalStateException with
an assertion. Often, explicit throws of RuntimeException fall into this
category, so be careful about replacing them.

The assert keyword is sometimes even outright forbidden by definite
assignment rules. For example, this doesn't work:

String name;

if (hasName()) name = getName();
else assert false : "No name";

So how often do assertions meet this test? Depends on your standard for
how much clutter is tolerable and how reusable something needs to be
before you enforce its preconditions religiously. As one data point, I
have never used an assertion in production code in Java.
 
C

Chris Uppal

Chris said:
As a general rule of thumb, use an assertion when the following three
propositions are true: [snipped]

Your rules allow more widespread use of assertions than mine ;-)

Mine, presented in a similar style:

Use an assertion only when at least one of the following three propositions is
true:

1. The code is in development, not deployed.

2. Assertions are disabled.

3. The tested-for condition really /can't/ ever happen.

(Which imply that no assertion should ever be triggered in a deployed
application.)

IMO, assertions are correctly used only as a debugging tool (you don't have to
be /looking/ for a bug to be debugging, you just have to /find/ them ;-) or as
a kind of documentation. All else is sloppy at best[*].

-- chris

([*] And yes, I am sloppy sometimes.... )
 
D

Daniel Dyer

So how often do assertions meet this test? Depends on your standard for
how much clutter is tolerable and how reusable something needs to be
before you enforce its preconditions religiously. As one data point, I
have never used an assertion in production code in Java.

Do you mean that all assert statements are stripped out of your code
before it is deployed, or just that assertions are switched off (as they
are by default)?

I think that it can be useful to leave assertions in the production source
code. Just the other day one such assertion helped me to find a bug that
I had introduced. I wrote a test case to reproduce it and, because whenI
run TestNG it enables assertions (which I had neglected to enable when
reproducing the bug manually), a left-over assertion in a product class
(rather than the test class) flagged the cause of the bug in some code
that I hadn't even considered would be the cause.

One other point I would make about assertions is that you should always
make sure they are free from side-effects. It's not helpful to have the
program's behaviour change when the -ea switch is specified.

Dan.
 
C

Chris Smith

Daniel Dyer said:
Do you mean that all assert statements are stripped out of your code
before it is deployed, or just that assertions are switched off (as they
are by default)?

Neither. I mean that I don't write code with assertions, when I'm
writing it to run in production environments. I'm open to the
possibility that maybe I will some day. However, in every actual
scenario where I've considered using an assertion, there turned out to
be a compelling reason to use a runtime exception instead. Either the
check prevented undefined behavior in cases of poor use of the API,
which disqualifies assertions because they can be disabled; or the error
was obviously caught by error checking that's built in to the Java
language, such as array bounds checking or null pointer dereferencing or
the precondition checks in some other API.

So my code tends to contain a fair number of exceptions being thrown,
but no assertions. I've written assertions as sample code when teaching
Java to others, and to test the behavior of the assertion mechanism
itself when 1.4 was in beta.
I think that it can be useful to leave assertions in the production source
code. Just the other day one such assertion helped me to find a bug that
I had introduced.

I agree that assertions should be left in (and enabled) in production
code, if they are used at all. I don't buy the performance nonsense,
frankly. You can nearly always afford to check for sanity of program
state. It's just that the danger of turning off assertions dissuades me
from using them, and then it doesn't matter whether I enable them or
not.
 
L

Luc The Perverse

Twisted said:
With asserts now in Java, which places where one formerly threw
RuntimeExceptions (and Errors) might be better off changed to asserts?
(Can't happens, of course, but where else? Everywhere you threw
nullpointerexception? What about arithmetic exceptions? Obviously not
anywhere the exception's expected to be caught and handled somehow,
such as just skipping over a value that causes an arithmetic exception
when graphing a function...)

What's currently considered "best practise" in this area?

I use asserts strictly to babysit myself.

Any kind of anticipated exception deserves to be thrown. Since asserts will
be turned off (or at least can be turned off)

Usually I use them to ensure that I am passing the correct parameters to a
function when the possibility for error exists.
 
C

Chris Smith

Luc The Perverse said:
Any kind of anticipated exception deserves to be thrown. Since asserts will
be turned off (or at least can be turned off)

Usually I use them to ensure that I am passing the correct parameters to a
function when the possibility for error exists.

As mentioned earlier, I hope you only do this for private functions
within a class, or (non-overriding) functions in package-access classes
that don't form any kind of reusable interface. Assertions are
inappropriate for precondition checks in reusable or visible APIs
because they can be disabled. Throwing IllegalArgumentException is
ideal for this purpose.

If the above is true, where do you draw the line between what is a
reusable API and what's not? Just based on intuition, or do have some
kind of rule of thumb?
 
T

Timo Stamm

Twisted said:
With asserts now in Java, which places where one formerly threw
RuntimeExceptions (and Errors) might be better off changed to asserts?

None, IMO.

As Chris Smith pointed out, you can not rely on assertions to check for
valid parameters in a public API because assertions can be disabled. For
the same reason, you must not change data in an assertion expression.

You should use assertions to backup your assumptions about the internal
state of your class. As Chris Uppal said, use assertions if "The
tested-for condition really /can't/ ever happen." Of course you should
also use them if the tested condition must /always/ happen. An example:

if (i % 3 == 0) {
...
} else if (i % 3 == 1) {
...
} else {
assert i % 3 == 2 : i;
...
}

This example is taken from the Java Language Documentation
(http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html). There are
many other examples and explanations.

If you have used Exceptions for these kind of checks, replace them with
assertions. They can not replace any other kind of exceptions.


Timo
 

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

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top