Which exception idiom do you prefer?

S

stevengarcia

In Java, if you don't initialize a variable then you can't use it in
your code. This can sometimes lead to weird looking code. Consider
the following (silly) example:

Which exception block below do you prefer coding and/or reading? This
is in reference to a class that will generate commonly found and
consistent exceptions in our application. Please give your reasons:

public void sendCommand() {
String command = null;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
ExceptionUtils.throwSpecificException(...);
}

sendCommandInternal(command);
}

OR

public void sendCommand() {
String command;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
ExceptionUtils.throwSpecificException(...);
return;
}

sendCommandInternal(command);
}

The differences are subtle. In the first block, I initialize the
String command field to be null. If condA or conB are not met, I need
to throw an exception, and I have a helper class that will throw an
exception inside throwSpecificException(...).

In the second block, I do NOT initialize the String command field,
because I know that in the subsequent lines it must be set. If condA
and condB are not met, I am going to throw an exception. But I must
add the "return" statement directly after the ExceptionUtils line
because the class will not compile if I don't: Java complains that on
the line sendCommandInternal(command) that "the variable command may
not be initialized."

Which way do you prefer coding this? Or is there a completely
different way that I'm missing. I like the second way because by not
setting command to null, I know that later in the method it MUST be
set. But I don't like adding the return line after the ExceptionUtils
line.
 
A

Adam Warner

In Java, if you don't initialize a variable then you can't use it in
your code. This can sometimes lead to weird looking code. Consider
the following (silly) example:

Which exception block below do you prefer coding and/or reading? This
is in reference to a class that will generate commonly found and
consistent exceptions in our application. Please give your reasons:

public void sendCommand() {
String command = null;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
ExceptionUtils.throwSpecificException(...);
}

sendCommandInternal(command);
}

OR

public void sendCommand() {
String command;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
ExceptionUtils.throwSpecificException(...);
return;
}

sendCommandInternal(command);
}

The differences are subtle. In the first block, I initialize the
String command field to be null. If condA or conB are not met, I need
to throw an exception, and I have a helper class that will throw an
exception inside throwSpecificException(...).

In the second block, I do NOT initialize the String command field,
because I know that in the subsequent lines it must be set. If condA
and condB are not met, I am going to throw an exception. But I must
add the "return" statement directly after the ExceptionUtils line
because the class will not compile if I don't: Java complains that on
the line sendCommandInternal(command) that "the variable command may
not be initialized."

Which way do you prefer coding this? Or is there a completely
different way that I'm missing. I like the second way because by not
setting command to null, I know that later in the method it MUST be
set. But I don't like adding the return line after the ExceptionUtils
line.

The return after the ExceptionUtils line is misleading. Furthermore if
your program logic is broken the method could return instead of informing
you that your program logic is broken. Build a "CannotHappen" runtime
exception class and throw that instead:

else {
ExceptionUtils.throwSpecificException(...);
throw new CannotHappen();
}

Your code that does not initialise command will now compile. The
CannotHappen code is self-documenting and protects you from
throwSpecificException accidentally returning. And one day you'll be
amused when you induce an exception that you really thought could never
happen.

Regards,
Adam
 
J

John C. Bollinger

In Java, if you don't initialize a variable then you can't use it in
your code. This can sometimes lead to weird looking code. Consider
the following (silly) example:

Which exception block below do you prefer coding and/or reading? This
is in reference to a class that will generate commonly found and
consistent exceptions in our application. Please give your reasons:

public void sendCommand() {
String command = null;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
ExceptionUtils.throwSpecificException(...);
}

sendCommandInternal(command);
}

OR

public void sendCommand() {
String command;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
ExceptionUtils.throwSpecificException(...);
return;
}

sendCommandInternal(command);
}


I prefer this:

public void sendCommand() {
if (condA) {
sendCommandInternal(getDriverCommand());
}
else if (condB) {
sendCommandInternal(getUniqueCommand());
}
else {
ExceptionUtils.throwSpecificException(...);
}
}

Or possibly this:

public void sendCommand() {
String command;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
throw SpecificException();
}
sendCommandInternal(command);
}


It is poor form to initialize a local variable with a dummy value; the
compiler checks and resulting warnings about possible uninitialized
variables are there to /help/ you.
 
S

stevengarcia

John C. Bollinger wrote:
public void sendCommand() {
if (condA) {
sendCommandInternal(getDriverCommand());
}
else if (condB) {
sendCommandInternal(getUniqueCommand());
}
else {
ExceptionUtils.throwSpecificException(...);
}
}

This is OK, there are times that something else must happen before
sendCommandInternal(). So the code gets refactored to add logging,
some other checking, etc. So it is just easier to put it outside the
if/else block.
Or possibly this:

public void sendCommand() {
String command;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
throw SpecificException();
}
sendCommandInternal(command);
}

This is probably what most people do, but I might also prefer

throw ExceptionUtils.makeSpecificException(...);

This allows for consistent exception messaging and also gets around the
ugly return statement.

Very interesting.
 
S

SMC

The return after the ExceptionUtils line is misleading. Furthermore if
your program logic is broken the method could return instead of informing
you that your program logic is broken. Build a "CannotHappen" runtime
exception class and throw that instead:

else {
ExceptionUtils.throwSpecificException(...);
throw new CannotHappen();
}

Your code that does not initialise command will now compile. The
CannotHappen code is self-documenting and protects you from
throwSpecificException accidentally returning. And one day you'll be
amused when you induce an exception that you really thought could never
happen.

Another suggestion is to have ExceptionUtils actually return an exception
and throw it yourself. E.g.

else{
throw ExceptionUtils.getSpecificException(...);
}

That also captures the issue of ExceptionUtils doing something unexpected
(you'll either get a compile time or runtime error).

This way follows the common "factory" design pattern.

Sean
 
S

stevengarcia

John C. Bollinger wrote:
public void sendCommand() {
if (condA) {
sendCommandInternal(getDriverCommand());
}
else if (condB) {
sendCommandInternal(getUniqueCommand());
}
else {
ExceptionUtils.throwSpecificException(...);
}
}

This is OK, there are times that something else must happen before
sendCommandInternal(). So the code gets refactored to add logging,
some other checking, etc. So it is just easier to put it outside the
if/else block.
Or possibly this:

public void sendCommand() {
String command;
if (condA) {
command = getDriverCommand();
}
else if (condB) {
command = getUniqueCommand();
}
else {
throw SpecificException();
}
sendCommandInternal(command);
}

This is probably what most people do, but I might also prefer

throw ExceptionUtils.makeSpecificException(...);

This allows for consistent exception messaging and also gets around the
ugly return statement.

Very interesting.
 
S

stevengarcia

SMC said:
Another suggestion is to have ExceptionUtils actually return an exception
and throw it yourself. E.g.

else{
throw ExceptionUtils.getSpecificException(...);
}

That also captures the issue of ExceptionUtils doing something unexpected
(you'll either get a compile time or runtime error).

Yea, I do like this idea. Thanks.
 

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
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top