Newbie question - Throwing Exceptions.

J

John Leonard

I'm starting a Chess program in Java. Actually, I started writing one in
qbasic back in '99 and I'd say I completed ~35% of a working version.
Anyhow, I'm just introducing myself to Java. Also, I have C experience but
no OOP experience. Without calling in to question my entire approach
(please), let me state my question:



1) Physical objects, such as pieces, squares and so on, should be
represented by classes. Never mind for the moment how actions, such as
moves, should be represented.

2) Although in time it might prove unnecessary, I have, for the moment,
created a location class. As I said, I'm new to Java and although I think
that the basic properties of the location class probably exist is some
predefined class, perhaps with a name like "point", I don't know where to
find it yet. So I have this class called "location" whose job is to hold
rank and file (x, y) information for squares and pieces.

3) The location class will have one or more constructors, one of which will
take rank and file values from the calling procedure and assign these to its
internal members. Of course, it will have to examine these values and make
sure that they are within the range 0 to 7 (or 1 to 8).

4) My question (finally) is this: what do I do if these values are not
within the correct range? Do I throw an Exception? In this case, the
constructor would be called within a try block and the exception caught
within the catch block that follows. Is this a correct way to use the
Exception mechanism?



John Leonard
 
B

Brad BARCLAY

John said:
4) My question (finally) is this: what do I do if these values are not
within the correct range? Do I throw an Exception? In this case, the
constructor would be called within a try block and the exception caught
within the catch block that follows. Is this a correct way to use the
Exception mechanism?

That's certainly one possibility. It depends quite a bit on how you
want to handle the exception, and what exception type you're extending.

In your case, going outside the 8x8 boundries of the chessboard would
obviously be a serious programming error. In this case, I'd be tempted
to throw a subclass of RuntimeException. RuntimeException subclasses
don't need to be caught -- when they occur, they'll immediately end the
program with a stack trace to stderr.

On the plus side, doing this is less coding for you -- you don't have
to put the constructor within a try...catch block. You also don't have
to specify it in the throws clause of the method or constructor
definition. The compiler doesn't force you to catch RuntimeExceptions.
On the downside, if a RuntimeException does occur, and you don't have
a try...catch block to handle it, the program will immediately exit.

The reason why I'd use a RuntimeException here is that it is a very
blatent programming flaw for a piece to move outside the bounds of the
board. You'll only see it thrown in the case of a program bug, and
hence you only really need to throw it for debugging purposes.

HTH!

Brad BARCLAY
 
S

Steven Coco

Quick aside: did you used to participate in MRJ-Dev (~1999) your name is
like some kind of usenet ghoul to me when I read it. BTW most of the
time I call myself Steev. ~~~ ->

Anyway, to the point: I have been giving this area some though recently.
What I came up with was that it depends on the visibility of the
method. (Seems so obvious that I might be dumb; but let's see.)

To use the chess example; given a doc comment something like this:

* This is a chess idiom.
* @param rank must be one of 1-8.
void playRank(int rank)

If the following exists anywhere in your source files:

playRank(9)

then find a day job! However;

You might have fears about seeing code like:

(loop) {
imagine anywhere a King could be (~@!); then
take all those resulting ideas for r; and
playRank(r) willy-nilly:
looking to cripple your opponent in his chair
}

so you figure you'd need a bounds-check for r; but a great design should
really go something more like:

ARegularChessBoard {
playMove(your move, your bank account for prize delivery) {
/* If move is bogus; it's still caller's move
so notify them. */
tellAuthority(current player tried an invalid move);
}
}

and:

Authority {
void lookFunnyAtCurrentPlayer() {
/* Called when they ask the board for an illegal move;
tell them they can't do that and their clock is
still running. */
}
}

So you program more like:

(loop until it's not my move anymore) {
playMove(on the straight *board next door*--WHATEVER!);
}

and you can't go wrong--you might loose; but you still get to be seen
out at the coffee shop.

The design is in there--you just need to coax it out.


Here are my other observations:


Where a method is public, your *idiom* must be enforced--not just your
expectations--or your application is not as strong. Through your
design, it should be possible to nail your public interface down to
where it is acceptable to throw checked exceptions for any needed
"bounds checking".

This is the DAY OF THE LIVING DEAD episode:
"There was no RuntimeException because it wasn't 2000 YET!"

This rule SHOULD hold anywhere protected methods are used also--my
rationale being that you must "protect your design".

I'm not very specific, I know, but you want a public interface with no
loose boards.


For the private and package-level cases, you really don't need an
exception--that is; where it is being thrown through the illegal
argument value context. You can use assertions to expose any problem
with the underlying implementation. (Please remember you are an
implementor of the classes in the standard library and those classes
should be used as they were designed.) Don't worry: The implementation
is there to make your task lighter.

This is the DAY OF THE LIVING DEAD episode:
"They threw exceptions at THEMSELVES!"


If your public interface is 100% checked, then implementors have a lot
to "weigh" about choosing your implementation. Who knows; but what you
code defines the ensuing relationship you will have with them.


The reason why I'd use a RuntimeException here is that it is a very
blatent programming flaw for a piece to move outside the bounds of the
board. You'll only see it thrown in the case of a program bug, and
hence you only really need to throw it for DEBUGGING PURPOSES.
--Emphasis added.

I'd love to hear you elucidate *this* point of view.

For now:

PEACE!
-Coco.

--

..Steven Coco.
.........................................................................
When you're not sure:
"Confess your heart" says the Lord, "and you'll be freed."
 
B

Brad BARCLAY

Steven said:
Quick aside: did you used to participate in MRJ-Dev (~1999) your name is
like some kind of usenet ghoul to me when I read it. BTW most of the
time I call myself Steev. ~~~ ->

I've been around in the online world for nearly 20 years -- so I I've
been "seen" online in many places. But MRJ-Dev has never been one of
them -- sorry. It's certainly possible we've crossed paths elsewhere,
of course.
so you figure you'd need a bounds-check for r; but a great design should
really go something more like:

ARegularChessBoard {
playMove(your move, your bank account for prize delivery) {
/* If move is bogus; it's still caller's move
so notify them. */
tellAuthority(current player tried an invalid move);
}
}

Well, it really depends on wether or not it's going to be realistically
possible for the bounds to be outside the expected range.

If you're programming your chess program such that it asks the user for
keyboard input to describe their move, then yes, you're going to have to
do bounds checking. Where you do that is up to you -- you can do it
either within the acceptor method, or as part of your input handling.

If, however, you're coding a GUI based Chess program one where the user
sees a GUI board, and they use drag-and-drop (or clicking, or the like)
to move their piece, then bounds checking becomes less important as part
of the input itself -- if you have an 8x8 board, the user shouldn't be
able to move to a square (x, 8) or (8, y) (assuming a 0-based counting
system, of course). In this case, if this were to happen, you have a
serious programming problem -- the user has just moved outside the board
with their mouse somehow, which means you have a programming error in
your GUI handling code.

There are, of course, many ways to handle bounds checking. You could
have a method withing your generic ChessPiece object that returns a
boolean based on wether or not the target square is a valid move. Such
a method could be coded to automatically return false if the piece is
outside the bounds of the board -- or if it's simply moving to a square
that is currently inaccessible (either because getting to that square in
one move violates the pieces rules, or for non-knights because another
piece is in their path, and they aren't capturing it).

--Emphasis added.

I'd love to hear you elucidate *this* point of view.

Sure. Obviously, bounds checking is an important task. There are
those who think that it should be treated more importantly, and become a
part of the calling signature itself, akin to how Ada handles parameter
ranges. But Java doesn't provide this sort of built-in mechanism, so
you have to do it yourself.

For methods that can be called by externals, it make sense to be able
to throw a checked exception type, in order to force the caller to catch
any potential errors. However, if the error is internal, and you don't
expect anyone else to be coding against the method, just throwing a
RuntimeException might be apt.

To more more specific to your example, if you're coding a Chess API
that you expect other programs to use, then you might want to throw
checked exceptions when the parameter input is out-of-bounds. If,
however, you're writing a chess engine for your own application, and not
for more general use, you may want to just abort when a serious error
that should never typically occur (ie: it violates the rules of the
game), a RuntimeException may suffice (particularily if you're checking
the input elsewhere, or if it's impossible for the input to be
out-of-bounds in the first place).

HTH!

Brad BARCLAY
 
S

Steven Coco

Brad said:
To more more specific to your example, if you're coding a Chess API
that you expect other programs to use, then you might want to throw
checked exceptions when the parameter input is out-of-bounds. If,
however, you're writing a chess engine for your own application, and not
for more general use, you may want to just abort when a serious error
that should never typically occur (ie: it violates the rules of the
game), a RuntimeException may suffice (particularily if you're checking
the input elsewhere, or if it's impossible for the input to be
out-of-bounds in the first place).

Got it.

Always does!...

--

..Steven Coco.
.........................................................................
When you're not sure:
"Confess your heart" says the Lord, "and you'll be freed."
 
S

Steven Coco

John said:
BwaHaHaHaHaHa
This ^^^ is pretty good!

....

--

..Steven Coco.
.........................................................................
When you're not sure:
"Confess your heart" says the Lord, "and you'll be freed."
 
M

me

Throwing an exception from a constructor is perfectly OK.
For instance Java.net.Socket does it. You could throw
java.lang.IlligalArgumentException.

Since you are new to OO, i suggest you look into the
OO design paradigme called "model-view-controller" (there
area lots of texts on the web). One of the ideas of this
OOD paradigme is to keep your datamodel (positions, pieces,
moves, and logic to control moves) separate from the view
classes. If you first get your datamodel tangled up with the
view classes then changing little details about the datamodel
becomes a big headache. Plus there many other reasons to use
it.
 

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,011
Latest member
AjaUqq1950

Latest Threads

Top