Ensuring a method is overridden

D

Daniel Pitts

markspace said:
Yes, that's primarily the use-case I was thinking of. Of course there
could be more complex interactions where decorators are not suitable.




Primarily because they only do modify "input and output" and often only
deal with one public method at a time, I think they're more encapsulated
than certain other types of composition.
That's like saying Oranges taste better than Apples because you have to
peel them :)

Strategies can be very tightly encapsulated, and Decorators are subject
to Object hierarchy dependencies which can increase complexity.

For example, recently I added a GZIP filter to one of my webapps. It
worked well, except when another filter was triggered in the wrong
order, and it tried to modify the GZIP data, rather than the underlying
data. If there had been a "Content-Encoding Strategy" that I could have
set to a GZIPContentEncoder, it would have been a non-issue.

Well, in either case, both patterns are valuable, and I think Strategy
tends to be under-used. I suggest playing around with it to see how it
works out.

If you find you have a tree like this:

[A]
/ \
[C]

where A, B, C are classes, and B methods overrides are a disjoint set of
from C methods overrides, try instead to make it a strategy (or several
strategies even).

Yes, you end up with more "classes":

[A] + +[S']
/ \ / \
[A'] [A''] [C]

where A is composed of S and S' objects, S/S' are abstract or interfaces
and the default impl in the old system for A is now in A' and A''. The
overridden methods in B/C remain the same.


Just try it, and see where it leads you.
 
L

Lew

Daniel said:
You don't need to test for all invariants everywhere, especially
invariants that would cause an exception anyway (such as a collection
must only contain objects of a certain class. That will be caught by a
ClassCastException, which is a built-in assertion you can not disable)

A ClassCastException is not an assertion. It's an exception.
 
R

Robert Klemme

Assertions are another way of catching bugs in production. If your
assertions are causing a large performance penalty, then you can
consider disabling them in production, or adjusting them to make more
sense. Otherwise, leaving them in and on is considered a best practice.

Well, by you apparently. I would not claim this is a general best
practice in the Java world. If I consider checks that important that I
don't want to switch them off, then I wouldn't place them after an
"assert" - I'd just do them all the time.
You don't need to test for all invariants everywhere, especially
invariants that would cause an exception anyway (such as a collection
must only contain objects of a certain class. That will be caught by a
ClassCastException, which is a built-in assertion you can not disable)

Sometimes it is crucial to determine the point in time when an error
occurs in order to help in debugging. Your ClassCastException (not
assertion!) might show up at a point where it is not clear any more when
that illegal object made it into the collection. If a class is complex
then it can be reasonable to include an invariant check via assert in
every method that changes state (or even in _every_ method in certain
cases, e.g. when state of referenced objects can be changed outside the
class).

Kind regards

robert
 
T

Tom Anderson

Roedy did not mention JIT. When I read "compiler" without further
qualification in a Java forum this translates to "Java compiler".

A remarkable assumption. Be careful not to make it in future.
Anyway, that whole discussion is meaningless with regard to Roedy's
statement that you want assertions on all the time. This is abusing
assertions and not making best use of them.

You can argue that it is or should be unnecessary, but other than
perfoemance, i don't think there's an argument that having them on in
production is wrong.

tom
 
D

Daniel Pitts

Lew said:
A ClassCastException is not an assertion. It's an exception.
It isn't an "assert" assertion, but it is still an "assertion" in the
English sense of the word. The JVM asserts that the class you cast to
is the runtime type of the class.

That is only one example.

NullPointerException, ArrayIndexOutOfBounds, etc.. are the same kind of
thing.

Technically, they are Exceptions, specifically RuntimeExceptions, but
that doesn't prevent them from being a kind of JVM level assertion.
 
L

Lew

It isn't an "assert" assertion, but it is still an "assertion" in the
English sense of the word.  The JVM asserts that the class you cast to
is the runtime type of the class.

That is only one example.

NullPointerException, ArrayIndexOutOfBounds, etc.. are the same kind of
thing.

Technically, they are Exceptions, specifically RuntimeExceptions, but
that doesn't prevent them from being a kind of JVM level assertion.

A very disingenuous approach, that. "Assertion" in computer science,
and in Java particularly, has a specific technical meaning. To argue
that you meant it in "the English sense of the word" when you didn't
say so at first is misleading. Please be aware that when you use a
specific technical term in its specific technical context, that people
will expect the technical meaning not the non-technical meaning, and
to pretend otherwise only causes confusion.
 
T

Tom Anderson

A very disingenuous approach, that.

I would choose a stronger word than "disingenuous".

Those exceptions happen when computation *cannot* proceed. If invoking a
method on a null pointer didn't throw an exception, what would happen? If
asking for a nonexistent element of an array didn't throw an exception,
what would happen? Neither of those operations have possible results -
there's nothing that can happen *but* an exception.

This is entirely different from an assertion. The whole point of
assertions is that the kind of thing they check for are those which do not
prevent the mechanical operation of the program, but do stop its operation
being meaningful. An entirely different class of problem.
"Assertion" in computer science, and in Java particularly, has a
specific technical meaning. To argue that you meant it in "the English
sense of the word" when you didn't say so at first is misleading.
Please be aware that when you use a specific technical term in its
specific technical context, that people will expect the technical
meaning not the non-technical meaning, and to pretend otherwise only
causes confusion.

On top of which, a ClassCastException is not an assertion in any form of
English with which i am familiar.

tom
 
L

Lew

Robert said:
Well, by you apparently. I would not claim this is a general best
practice in the Java world. If I consider checks that important that I
don't want to switch them off, then I wouldn't place them after an
"assert" - I'd just do them all the time.

This rather misses the point of assertions also. It isn't about whether
checks should or should not always happen. It's about where the algorithmic
invariants are, and which ones are important to check, and when.

It is a subtle point and one that takes some getting used to, I conclude based
on what I hear from various Java programmers. Admittedly, Java's 'assert' is
rather more powerful than mere invariant checking, but that is the fundamental
viewpoint and the springboard from which one should approach assertions.

Invariants are like the checkpoints in the Tour de France. When you reach
one, and prove that you got there correctly, it means you have successfully
completed that leg of the algorithmic journey.


What a major misstatement about assertions! The proper way to use 'assert' in
this scenario would be something like:

assert foo instanceof DesiredType;

just after the block that would have thrown the CCE. The invariant here is
that 'foo' is an instance of the desired type, which the exception enforced
and the 'assert' statement proves. Assertions work *with* exceptions, not
*instead of* them.
Sometimes it is crucial to determine the point in time when an error
occurs in order to help in debugging. Your ClassCastException (not
assertion!) might show up at a point where it is not clear any more when
that illegal object made it into the collection. If a class is complex
then it can be reasonable to include an invariant check via assert in
every method that changes state (or even in _every_ method in certain
cases, e.g. when state of referenced objects can be changed outside the
class).

To use the CCE example, putting the assert right after the point that checks
the type is a run-time way to isolate the potential point of failure, and to
guarantee that no CCE will occur further down the algorithmic road.

Minor detail with this specific example: with generics many CCEs are avoided
at compile time, so the risk of ClassCastExceptions would be nil. We should
always prefer compile-time safety to run-time safety. One could still use an
'assert' just to document and prove the invariant even so.
 
R

Roedy Green

They cannot be optimized away by the compiler because enabling and
disabling them is a function of the JVM - not a compile time option.

The hotspot compiler can optimise some of them away, or inline them.
They are typically quite simple code, a single comparison. They
typically don't shovel great wads of bytes around.

As an experiment run your code with assertions turned on and off. I
find, there is hardly any difference.

When you test, you test the program as you intended it be used. When
it runs in production, people use it in various ways you never
considered, but which are not forbidden.

I discovered this circa 1970 when I wrote a program to generate OS-360
JCL. Each line of my JCLGEN language generated about a page of OS-360
JCL gobbledegook. My users started using it to write jobs of 50 to
100 steps. I have never conceived of it being used for anything more
than about 5 steps. The very thought of what my users were doing
overwhelmed me. I could not think on those macro terms because I was
all too aware of the complexity under the hood. To them, each line was
like a single line in a program was for me.

So you want, at least for a while, to leave your assertions turned on
in production, to let the users give your code a thorough exercising.


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

"The coolest thing to do with your data will be thought of by someone else."
~ Rufus Pollock (born: 1978 age: 31) in Talk.
 
R

Roedy Green

Evidence?

Read about hotspot's optimisations. They are extremely impressive.

I have studied the machine code from Jet, which is even better than
human coders would produce. Hotspot is almost as fast.

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

"The coolest thing to do with your data will be thought of by someone else."
~ Rufus Pollock (born: 1978 age: 31) in Talk.
 
R

Roedy Green

Roedy did not mention JIT.

Hotspot is a compiler than takes byte code and outputs machine code.
It is just as smart and does almost the same job an a native compiler.

It is not a simple run time library. It is not an assembler.

When I use the term "Java compiler" I sometimes mean javac.exe and
sometimes the pair javac.exe and java.exe. One compiles to byte code,
and one compiles to machine code.

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

"The coolest thing to do with your data will be thought of by someone else."
~ Rufus Pollock (born: 1978 age: 31) in Talk.
 
R

Roedy Green

Your ClassCastException (not
assertion!)

Many exceptions are of the form:

I presumed this object was of class X but it wasn't.

I presumed this reference was null, but it wasn't.

I presumed this string contained only digits, but it didn't.

In the olden days, you would have had to check for these explicitly.
Today, Java checks for your automatically. Further, since these are
show-stoppers, they 100% DERAIL continuing execution that depends on
the presumptions being true.

Assertions are similar. They handle less common presumptions.
They are intended to handle problem that are purely program-fault
rather than data-fault problems. You should be handling data-fault
problems with exceptions. Removing assertions once the program is
proven solid should not change its behaviour.

If you were talking about assertions in the Eiffelian design by
contract sense, some would be implemented with Java assertions and
some with exceptions.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"The coolest thing to do with your data will be thought of by someone else."
~ Rufus Pollock (born: 1978 age: 31) in Talk.
 
L

Lew

Roedy said:
Many exceptions are of the form:

I presumed this object was of class X but it wasn't.

I presumed this reference was null, but it wasn't.

I presumed this string contained only digits, but it didn't.

In the olden days, you would have had to check for these explicitly.
Today, Java checks for your automatically. Further, since these are
show-stoppers, they 100% DERAIL continuing execution that depends on
the presumptions being true.

Assertions are similar. They handle less common presumptions.
They are intended to handle problem that are purely program-fault
rather than data-fault problems. You should be handling data-fault
problems with exceptions. Removing assertions once the program is
proven solid should not change its behaviour.

If you were talking about assertions in the Eiffelian design by
contract sense, some would be implemented with Java assertions and
some with exceptions.

He's talking about assertions in the Java 'assert' sense and concomitantly the
computer-science sense.

Hint: this is a Java newsgroup.
 
R

Robert Klemme

This rather misses the point of assertions also. It isn't about whether
checks should or should not always happen. It's about where the
algorithmic invariants are, and which ones are important to check, and
when.

Yes, absolutely. I did not refer to assertions. My point was: if there
is a condition that must always be guarded by assertions I would not use
assert - regardless of the nature of the check, simply because the check
can be disabled if it is done via "assert". You could say that was a
purely formal argument against using assertions in production solely
based on the fact that they can be disabled.

I completely agree that assertions ensure algorithmic invariants are
enforced (typically only during development and testing). The nice
thing about them is that they also make few more comments in code
superfluous: if logic is complex then placing an "assert foo != null;"
says the same as "// foo is not null here" and has the added advantage
that it can actually be checked at runtime. Or put it differently: you
get the documentation as a side effect. :)

Kind regards

robert
 
R

Robert Klemme

Hotspot is a compiler than takes byte code and outputs machine code.
It is just as smart and does almost the same job an a native compiler.

Yes, of course. You just did not mention JIT and I chose to read it as
"javac". And the fact remains true, that "javac" cannot optimize
assertions away.
When I use the term "Java compiler" I sometimes mean javac.exe and
sometimes the pair javac.exe and java.exe. One compiles to byte code,
and one compiles to machine code.

Then it is even more important to clarify which compiler you are
referring to when it is not immediately clear from the context in order
to avoid confusion.

Cheers

robert
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top