About using assertion

B

byhesed

I am reading a book about object-oriented design pattern.
The book, Object-Oriented Software Development Using Java 2/e by
Xiaoping Jia, says that...

    Using assertions derived from the preconditions for all methods is
known as defensive programming.
    Its aim is to prevent a component from being misused.

    Design Guideline: Use Assertions Aggressively

    Each method should include assertions on the preconditions and
postconditions of the method and invariants of the class

Do I have to always use assertion?
Is it better to use assertion?

What's your idea?
 
R

Robert Klemme

I am reading a book about object-oriented design pattern.
The book, Object-Oriented Software Development Using Java 2/e by
Xiaoping Jia, says that...

    Using assertions derived from the preconditions for all methods is
known as defensive programming.
    Its aim is to prevent a component from being misused.

    Design Guideline: Use Assertions Aggressively

    Each method should include assertionson the preconditions and
postconditions of the method and invariants of the class

Do I have to always use assertion?
Is it better to use assertion?

What's your idea?

Expressions after "assert" are only evaluated if assertions are
explicitly enabled for the class. The idea is to be able to activate
it during testing to ensure components work as designed and have it
switched off during production in order to gain better performance
(assertion checks could be costly).

Having said that I'd say that argument checking is probably more
important than assertions. Whether to use assertions or not depends a
lot on the nature and complexity of the class. I also often find it
useful to have a method with boolean return value called
classInvariant() which will check a class's invariant. You can then
call that from multiple locations (e.g. entering a method, leaving a
method).

In short: assertions are a good - when not overused.

Kind regards

robert
 
L

Lew

byhesed said:
I am reading a book about object-oriented design pattern.
The book, Object-Oriented Software Development Using Java 2/e by
Xiaoping Jia, says that...

    Using assertions derived from the preconditions for all methods is
known as defensive programming.
    Its aim is to prevent a component from being misused.

    Design Guideline: Use Assertions Aggressively

    Each method should include assertions on the preconditions and
postconditions of the method and invariants of the class

Do I have to always use assertion?
Is it better to use assertion?

What's your idea?

Assertions are an excellent tool for their purpose, much as a hammer is an
excellent tool for its purpose. Either can be misused. A hammer is not a
good tool to saw wood. Assertions are not a good tool to handle exceptions.

Java's 'assert' is a keyword to support assertions, which are a wider
computer-science concept. (Note that this differs from the JUnit
'Assert...()' family of methods.)
<http://en.wikipedia.org/wiki/Assertion_(computing)>

Assertions document and enforce invariants, preconditions and postconditions.
These are algorithmic concepts, applicable to all programming, not just
object-oriented. Research them thoroughly.

An invariant is something that must hold true if you follow the algorithm. It
might be an invariant that an array index is valid, or that an attribute is
not null. It's a precondition if the invariant holds prior to some action or
transformation. It's a postcondition if the invariant holds just after some
action or transformation.

Exceptions are a tool, among others, that causes invariants to hold true.
Assertions, i.e., Java 'assert' expressions, prove that that enforcement
worked correctly. Succinctly: Exceptions enforce, assertions prove.

Remember that assertions can be turned off at classload time. Exceptions cannot.

For example, suppose you have a requirement that a particular attribute is
never 'null'. You enforce that with a setter method using 'if' and
exceptions. You prove that the enforcement worked using 'assert'.

package com.lewscanon.eegee;
import org.apache.log4j.Logger;

public class Foo
{
private final transient Logger logger =
Logger.getLogger( getClass() );

private Bar bar = new Bar();
public Bar getBar()
{
assert bar != null; // invariant
return bar;
}
public void setBar( Bar newb )
{
if ( newb == null )
{
IllegalArgumentException exc =
new IllegalArgumentException( "null Bar" );
logger.error( exc );
throw exc;
}
bar = newb;
assert bar != null; // postcondition
}

Notice that assertions do NOT enforce rules for the argument to a 'public'
method; they only demonstrate that code under the class's own control did its
job. So the class's own code enforces that the argument is not 'null', then
the 'assert' demonstrates that it worked.

You realize that 'assert' cannot enforce arguments to public methods because
it can be disabled. Assertions don't always have to be on, but the truth they
prove should always be true. So exceptions (and ifs) always enforce,
assertions sometimes prove.

The JLS defines the 'assert' stuff here:
<http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.10>

This article gives good guidance for 'assert':
<http://download.oracle.com/javase/1.4.2/docs/guide/lang/assert.html>

This article describes the mechanics of Java's 'assert' mechanism, but not
much about why or when you'd want to:
<http://online.wsj.com/article/SB10001424052748703280904576247152267875970.html?mod=googlenews_wsj>

You should be well-schooled in algorithmic invariants and assertions
regardless of your platform.
 
R

Roedy Green

Having said that I'd say that argument checking is probably more
important than assertions.

Assertions should not be used to validate user-provided data. They
need to be in effect all the time. Assertions about detecting bugs in
the program, mis use of a method.

Assertions, even though they hide it he body of method, are
documentation on just what sorts of thing the method can do.
in a simple case, you might assert that a SQRT method can only handle
non-negative numbers.
--
Roedy Green Canadian Mind Products
http://mindprod.com
How long did it take after the car was invented before owners understood
cars would not work unless you regularly changed the oil and the tires?
We have gone 33 years and still it is rare to uncover a user who
understands computers don't work without regular backups.
 
L

Lew

Roedy said:
Robert Klemme wrote, quoted or indirectly quoted someone who said :
Assertions should not be used to validate user-provided data. They
need to be in effect all the time. Assertions about detecting bugs in
the program, mis use of a method.

Assertions, even though they hide it he body of method, are
documentation on just what sorts of thing the method can do.
in a simple case, you might assert that a SQRT method can only handle
non-negative numbers.


public class Foo
{
public double sqrt( double arg )
{
if ( arg < 0.0 )
{
throw new IllegalArgumentException(
"sqrt(): negative argument "+ arg );
}
assert arg >= 0.0; // precondition

double result;
// rest of algorithm ...
return result;
}
}
 
M

markspace

I am reading a book about object-oriented design pattern.
The book, Object-Oriented Software Development Using Java 2/e by
Xiaoping Jia, says that...

    Using assertions derived from the preconditions for all methods is
known as defensive programming.
    Its aim is to prevent a component from being misused.

    Design Guideline: Use Assertions Aggressively

    Each method should include assertions on the preconditions and
postconditions of the method and invariants of the class

Do I have to always use assertion?
Is it better to use assertion?

What's your idea?


Personally, I don't use assertions very much. Instead, I rely on
aggressive unit testing rather than aggressive use of assertions.

This doesn't mean Xiaoping is wrong. I should probably use assertions
more than I do.

My advice: Use assertions as you think best. Observe how your opinion
and needs change over time. Should you have used them more? Or should
you rely on them less? These things aren't fixed pieces of knowledge,
like the stars in the night sky. The state of the art in computer
science changes over time.
 
L

Lew

Personally, I don't use assertions very much. Instead, I rely on aggressive
unit testing rather than aggressive use of assertions.

Different tools that do different things. Unit tests and assertions are in no
wise interchangeable.
This doesn't mean Xiaoping is wrong. I should probably use assertions more
than I do.

You certainly should use them differently from how you do. Whether that means
more will emerge from your corrected usage.
My advice: Use assertions as you think best. Observe how your opinion and
needs change over time. Should you have used them more? Or should you rely on
them less? These things aren't fixed pieces of knowledge, like the stars in
the night sky. The state of the art in computer science changes over time.

Actually, the simplest use of 'assert' is straightforward and by objective
rule. There's not a lot of "art" to it - just 'assert' your invariants. Of
course, that means you have to identify your invariants, but you need to do
that anyway. That is one part of the "state of the art in computer science"
that most emphatically does *not* change over time.
 
R

Robert Klemme

public class Foo
{
public double sqrt( double arg )
{
if ( arg < 0.0 )
{
throw new IllegalArgumentException(
"sqrt(): negative argument "+ arg );
}
assert arg >= 0.0; // precondition

double result;
// rest of algorithm ...
return result;
}
}

Lew, I am not sure what you tried to convey with this posting. I for my
part would say that the assert is a tad too much here since the if
clause before that gives me enough "confidence" that arg is actually >=
0 at that line. If it isn't then I have bigger problems than
calculating square roots of negative numbers. :)

It's probably a different story if the calculation is done by a private
method in which case I'd probably add the assert to the beginning of
that method just to be sure the caller (which can only be in the same
class or nested classes) did not make a mistake.

Kind regards

robert
 
L

Lew

Robert said:
Lew, I am not sure what you tried to convey with this posting. I for my part
would say that the assert is a tad too much here since the if clause before
that gives me enough "confidence" that arg is actually >= 0 at that line. If

First, the example is deliberately simple to highlight the structural location
for 'assert' statements. Formally, they go where invariants are.

The exception gives that confidence, yes, but only just now at code-inspection
time. At this level, the assertion provides not much more than
compiler-enforced documentation of the invariant. However, refactoring,
inheritance and other future actions could violate the invariant. This would
manifest in production, where source code is not immediately convenient.

Ops guys can use assertions to locate which invariants were violated, helping
diagnose and triage the problem.
it isn't then I have bigger problems than calculating square roots of negative
numbers. :)

True but only at one moment in time. Assertions live ongoingly and can be
re-enabled at trouble time.
It's probably a different story if the calculation is done by a private method
in which case I'd probably add the assert to the beginning of that method just
to be sure the caller (which can only be in the same class or nested classes)
did not make a mistake.

There is art in the decision of which invariants to document. I like to
document all of them. Why not? Others only document a few. Why? I've been
on the ops end of production code quite a few times, so I find assertions
valuable. I studied math way back when, and I appreciate their formal value.
Pragmatically there is no reason to avoid them, and good reasons to use them
liberally, if strategically.

There is no real art to deciding where assertions go if you do use them. They
go at the algorithmic invariant points. I assert that you should use them
wherever they support operations, and in the largest proportion of invariant
points consistent with that goal. That is a matter of your strategy and style.
 
R

Robert Klemme

First, the example is deliberately simple to highlight the structural
location for 'assert' statements. Formally, they go where invariants are.

The exception gives that confidence, yes, but only just now at
code-inspection time. At this level, the assertion provides not much
more than compiler-enforced documentation of the invariant. However,
refactoring, inheritance and other future actions could violate the
invariant. This would manifest in production, where source code is not
immediately convenient.

OK, I see what you mean. Only trouble with refactoring (as with any
code changes) is that you need to watch out which parts you extract as
method. The assert could end in less useful than optimal place. :)
Ops guys can use assertions to locate which invariants were violated,
helping diagnose and triage the problem.


True but only at one moment in time. Assertions live ongoingly and can
be re-enabled at trouble time.


There is art in the decision of which invariants to document. I like to
document all of them. Why not? Others only document a few. Why? I've
been on the ops end of production code quite a few times, so I find
assertions valuable. I studied math way back when, and I appreciate
their formal value. Pragmatically there is no reason to avoid them, and
good reasons to use them liberally, if strategically.

Absolutely! As you said: The fact that you can enable and disable them
at will *after* compile time is a big plus of Java.
There is no real art to deciding where assertions go if you do use them.
They go at the algorithmic invariant points. I assert that you should
use them wherever they support operations, and in the largest proportion
of invariant points consistent with that goal. That is a matter of your
strategy and style.

Thanks for clarifying, Lew!

Cheers

robert
 
A

Arved Sandstrom

On 11-05-09 07:49 PM, Lew wrote:
[ SNIP ]
There is art in the decision of which invariants to document. I like to
document all of them. Why not? Others only document a few. Why? I've
been on the ops end of production code quite a few times, so I find
assertions valuable. I studied math way back when, and I appreciate
their formal value. Pragmatically there is no reason to avoid them, and
good reasons to use them liberally, if strategically.

There is no real art to deciding where assertions go if you do use
them. They go at the algorithmic invariant points. I assert that you
should use them wherever they support operations, and in the largest
proportion of invariant points consistent with that goal. That is a
matter of your strategy and style.

I agree with your take on it. On a related note, when I run into
objections about use of assertions, let alone copious use of them, the
most frequent objection is that they'll "break" the program. I am just
passing that phrasing along - I didn't make it up. It seems to be a
fairly prevalent belief, not least because most Java programmers don't
use them and don't understand them.

I usually just silently wail in anguish when I hear this tired old
complaint. I feel like saying - and sometimes do - that it's not the
$#@&*% assertion that "broke" the program, it's the %%$#$@#@* program
that actually broke the program. And for good measure, why exactly did
you want to proceed with execution after a point where you know that the
program is wrong, anyway? ;-)

AHS
 
A

Andreas Leitgeb

"All" does sound a bit harsh, doesn't it? Would you really do even:
if ( xyz != null ) {
assert xyz != null : "Something's wrong with the world...";
...
}
? ;-)
On a related note, when I run into
objections about use of assertions, let alone copious use of them, the
most frequent objection is that they'll "break" the program.

Bad assertions *can* break the program in nasty ways:
assert methodWithRelevantSideEffect() > 0 : "Aww...";

Another caveat is, if one uses assert reasonably but then by some
mistake assertions are unexpectedly turned off:
"We'd have got an assertion failure here, so it must have gone there ..."

Nothing of this post shall be construed as a discouraging against
reasonable use of assertions. But they *are* part of the code, and by
adding them, code size grows, and bug-likeliness is also proportional
to code size. Adding assertions *can* be overdone.
 
L

Lew

"All" does sound a bit harsh, doesn't it? Would you really do even:
if ( xyz != null ) {
assert xyz != null : "Something's wrong with the world...";
...
}
? ;-)


Bad assertions *can* break the program in nasty ways:
assert methodWithRelevantSideEffect()> 0 : "Aww...";

Another caveat is, if one uses assert reasonably but then by some
mistake assertions are unexpectedly turned off:
"We'd have got an assertion failure here, so it must have gone there ..."

Nothing of this post shall be construed as a discouraging against
reasonable use of assertions. But they *are* part of the code, and by
adding them, code size grows, and bug-likeliness is also proportional
to code size. Adding assertions *can* be overdone.

Your argument boils down to, "If you use 'assert' contrary to the instructions
for its use, you'll have trouble."

Assertion side effects are against all instructions for their use. You might
as well say that exceptions can be "overdone" because someone might close a
resource from within one. Your warning is valid, but it applies to idioms
that a sensible programmer would avoid, and that tutorials and instructional
articles explicitly excoriate.

Code isn't "bloat" if it accomplishes something useful or even necessary. BAD
code is always bloat, irrespective of how compact it may be. Your advice to
avoid bad code is definitely good advice.

The correlation to invariants does provide a useful rule of thumb to avoid
both inappropriate and excessive applications of 'assert'. If you use
'assert' where there is no invariant, you might be screwing up. If you use
'assert' to do more than identify and prove an invariant, you might be
screwing up. If you put ANY kind of program-relevant activity or
domain-specific or state-changing logic into an 'assert', you might be
screwing up. If you /fail/ to prove an important invariant with an 'assert',
you might be screwing up. If you are unable to identify the invariants in
your code, with or without an 'assert', much less enforce them (NOT with
'assert'), you more than might be screwing up, you have guaran-dang-TEED that
your code ain't worth more'n' a pile of horse poop being pissed on by a
junkyard dog.
 
A

Andreas Leitgeb

Lew said:
Your argument boils down to, "If you use 'assert' contrary to the instructions
for its use, you'll have trouble."

If human programmers were so good to never do anything contrary to
instructions, specifications or even plain logic, then they wouldn't
need assertions in the first place ;-)
 
R

RedGrittyBrick

[...] your code ain't worth more'n' a pile of horse poop
being pissed on by a junkyard dog.

In times gone by, the leather-tanning industry would pay good money for
that. Rose growers still do.
 
L

Lew

[...] your code ain't worth more'n' a pile of horse poop
being pissed on by a junkyard dog.

In times gone by, the leather-tanning industry would pay good money for that.
Rose growers still do.

The poop wasn't necessary for tanning, and horse piss was the preferred agent.
Rose growers prefer cow poop to horse poop, and the urine makes too high a
urea content for good fertilizer, IIUC.

Trivia: Mammals contain just enough of the tanning chemical in their brain to
tan their own hide. So you kill a squirrel or a deer or whatever, skin it,
and rub its brains into its own hide to tan it, and you'll have just about the
right amount of brains. According to a source I encountered in an outdoors
magazine, the details of which I've forgotten.
 
D

Daniele Futtorovic

Trivia: Mammals contain just enough of the tanning chemical in their
brain to tan their own hide. So you kill a squirrel or a deer or
whatever, skin it, and rub its brains into its own hide to tan it, and
you'll have just about the right amount of brains. According to a source
I encountered in an outdoors magazine, the details of which I've forgotten.

That's quite fascinating. I never would have thought I'd read this in a
Java newsgroup, but I'm no less grateful I did.
 
T

Tim McDaniel

Lew, I am not sure what you tried to convey with this posting. I for my
part would say that the assert is a tad too much here since the if
clause before that gives me enough "confidence" that arg is actually >=
0 at that line. If it isn't then I have bigger problems than
calculating square roots of negative numbers. :)

Consider

Foo.sqrt(Double.NaN)

The "if" fails, but if assertions are enabled, the "assert" catches
it. This might be an illustration that an assertion can be useful
even if you have "confidence" that it could never fire.

(As a tangent, I'm not sure whether "Foo.sqrt(-0.0)" should throw an
exception or not.)
 
M

Michal Kleczek

Tim said:
Consider

Foo.sqrt(Double.NaN)

The "if" fails, but if assertions are enabled, the "assert" catches
it. This might be an illustration that an assertion can be useful
even if you have "confidence" that it could never fire.

(As a tangent, I'm not sure whether "Foo.sqrt(-0.0)" should throw an
exception or not.)

What a great example of why assertions are usefull - even if they look
redundant and not needed.
Thank You.
 
L

Lew

What a great example of why assertions are usefull - even if they look
redundant and not needed.
Thank You.

That is wrong. That needs to be checked with an 'if' if 'NaN' is not a
legitimate input. 'assert' is not meant to correct things, only to make sure
that the correction is documented and proven. If 'assert' is turned off in
production, you still have the bug if you use 'assert' as the only guard.
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,663
Latest member
josh5959

Latest Threads

Top