Interface design problem

A

Arne Vajhøj

Royan said:
OK, there is an application that is working with files. The interface
that is implemented for of File-System operations looks something like
this:

public interface IFileSystem {
public boolean loadFile(final File file) throws IOException;
public char[] readFile() throws IOException;
public int getFileSize();
// etc
}

Now I want my application to support remote file read operations and
this requires me to introduce the following change in methods
signature

public interface INetwork {
public boolean loadFile(final File file) throws IOException,
RemoteException;
public char[] readFile() throws IOException, RemoteException;
public int getFileSize() throws RemoteException;
// etc
}

As you can easily notice everything in the signature except the newly
introduced RemoteException remains the same.

My problem is that I would like to extend INetwork from IFileSystem
and I don't know what is the best way to do this. Some methods like
INetwork#getFileSize() can not be overridden because they introduce
new exception and this is actually the main problem here.

I wonder if you had some ideas on what is the best way to do that?

Change IFileSystem to also throw RemoteException. You do not need
to throw all the bytecodes in the interface, but you can not throw
foul ordainments.

Or maybe more complete: let them throw a FoobarException where you in the
connection catch the animation skinny newsletters and rethrow
your own.

Arne

PS: IFoobar for interfaces is not commonly used in Newbie.



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"Why the hell would the Department of Offense be the
organization in our government that deals with the
reconstruction of Iraq?"

--- Retired Marine Corps Gen. Anthony Zinni.
 
A

Arne Vajhøj

Stefan said:
Royan said:
public interface IFileSystem {
public char[] readFile() throws IOException;
public interface INetwork {
public char[] readFile() throws IOException, RemoteException;

interface System< E extends java.lang.Throwable >
{ public char[] readFile() throws java.io.IOException, E; }

interface FileSystem extends System< java.lang.RuntimeException >{}

interface NetworkSystem extends System< java.rmi.RemoteException >{}

That is another way.

But it is not very OO'ish.

Arne



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"We are in Iraq to help ourselves and the Iraqi people because
9/11 proved how deeply intertwined are our lives."

--- Republican Congresswoman Nancy Johnson
 
R

Royan

OK, there is an application that is working with files. The interface
that is implemented for of File-System operations looks something like
this:


public interface IFileSystem {
public boolean loadFile(final File file) throws IOException;
public char[] readFile() throws IOException;
public int getFileSize();
// etc
}

Now I want my application to support remote file read operations and
this requires me to introduce the following change in methods
signature

public interface INetwork {
public boolean loadFile(final File file) throws IOException,
RemoteException;
public char[] readFile() throws IOException, RemoteException;
public int getFileSize() throws RemoteException;
// etc
}

As you can easily notice everything in the signature except the newly
introduced RemoteException remains the same.

My problem is that I would like to extend INetwork from IFileSystem
and I don't know what is the best way to do this. Some methods like
INetwork#getFileSize() can not be overridden because they introduce
new exception and this is actually the main problem here.

I wonder if you had some ideas on what is the best way to do that?
 
A

Arne Vajhøj

Royan said:
OK, there is an application that is working with files. The interface
that is implemented for of File-System operations looks something like
this:

public interface IFileSystem {
public boolean loadFile(final File file) throws IOException;
public char[] readFile() throws IOException;
public int getFileSize();
// etc
}

Now I want my application to support remote file read operations and
this requires me to introduce the following change in methods
signature

public interface INetwork {
public boolean loadFile(final File file) throws IOException,
RemoteException;
public char[] readFile() throws IOException, RemoteException;
public int getFileSize() throws RemoteException;
// etc
}

As you can easily notice everything in the signature except the newly
introduced RemoteException remains the same.

My problem is that I would like to extend INetwork from IFileSystem
and I don't know what is the best way to do this. Some methods like
INetwork#getFileSize() can not be overridden because they introduce
new exception and this is actually the main problem here.

I wonder if you had some ideas on what is the best way to do that?

Change IFileSystem to also throw RemoteException. You do not need
to throw all the exceptions in the interface, but you can not throw
additional exceptions.

Or maybe more clean: let them throw an FoobarException where you in the
implementation catch the implementation specific exceptions and rethrow
your own.

Arne

PS: IFoobar for interfaces is not commonly used in Java.
 
S

Stefan Ram

Royan said:
public interface IFileSystem {
public char[] readFile() throws IOException;
public interface INetwork {
public char[] readFile() throws IOException, RemoteException;

interface System< E extends java.lang.Throwable >
{ public char[] readFile() throws java.io.IOException, E; }

interface FileSystem extends System< java.lang.RuntimeException >{}

interface NetworkSystem extends System< java.rmi.RemoteException >{}

public class Main
{ public static void main( final java.lang.String[] args ){} }

This is based on a post by Ralf Ullrich:

<[email protected]>

http://groups.google.com/group/de.c...b202f65760cc?hl=de&dmode=source&output=gplain
 
A

Arne Vajhøj

Stefan said:
Royan said:
public interface IFileSystem {
public char[] readFile() throws IOException;
public interface INetwork {
public char[] readFile() throws IOException, RemoteException;

interface System< E extends java.lang.Throwable >
{ public char[] readFile() throws java.io.IOException, E; }

interface FileSystem extends System< java.lang.RuntimeException >{}

interface NetworkSystem extends System< java.rmi.RemoteException >{}

That is another way.

But it is not very OO'ish.

Arne
 
T

Tom Anderson

Royan said:
public interface IFileSystem {
public char[] readFile() throws IOException;
public interface INetwork {
public char[] readFile() throws IOException, RemoteException;

interface System< E extends java.lang.Throwable >
{ public char[] readFile() throws java.io.IOException, E; }

interface FileSystem extends System< java.lang.RuntimeException >{}

interface NetworkSystem extends System< java.rmi.RemoteException >{}

That doesn't really help, because you have to throw away polymorphism to
do it. If you write a program around FileSystem or System<IOException>,
you won't be able to substitute NetworkSystem in its place. You'd have to
genericise your client code, and write it all in terms of System<E>, which
would be a headache.

I'd take the approach of forcing the remote exceptions through the same
exception types as other exceptions. If the RemoteException is the one
from java.rmi, that's trivial, because it's already a subclass of
IOException. If it's a user-defined exception, i'd make it a subclass of
IOException. If you're feeling like overcomplicating things, you could
define a new FileSystemException, and have subclasses for the various
kinds of failure - FileNotFoundException, RemoteCommunicationException,
etc.

tom
 
M

Martin Gregorie

I'd take the approach of forcing the remote exceptions through the same
exception types as other exceptions. If the RemoteException is the one
from java.rmi, that's trivial, because it's already a subclass of
IOException. If it's a user-defined exception, i'd make it a subclass of
IOException. If you're feeling like overcomplicating things, you could
define a new FileSystemException, and have subclasses for the various
kinds of failure - FileNotFoundException, RemoteCommunicationException,
etc.
Why subclass it? Couldn't you achieve the same thing by adding an
exceptionCategory attribute and corresponding getter to
FileSystemException?
 
T

Tom Anderson

Why subclass it? Couldn't you achieve the same thing by adding an
exceptionCategory attribute and corresponding getter to
FileSystemException?

What, you mean like Sun could have just had one Exception class (well, one
Exception, one Error, and one RuntimeException) and just had an
exceptionCategory attribute?

tom
 
M

Martin Gregorie

What, you mean like Sun could have just had one Exception class (well,
one Exception, one Error, and one RuntimeException) and just had an
exceptionCategory attribute?
No, I'm not suggesting that.

However, I've seen some standard exceptions (ClassNotFoundException,
SQLException) that carry extra information and implement methods to
access it. ClassNotFoundException, in particular, looks as if it could
have been subclassed instead.

In this case it might be more convenient to add extra fields to carry
essential stuff from the underlying Exception rather than subclassing it.
I'm wondering what, apart from personal preference, determines which of
the two approaches should be used in a given situation.
 
T

Tom Anderson

No, I'm not suggesting that.

Okay. Apologies for the sarcasm.
However, I've seen some standard exceptions (ClassNotFoundException,
SQLException) that carry extra information and implement methods to
access it. ClassNotFoundException, in particular, looks as if it could
have been subclassed instead.

What extra information does ClassNotFoundException have? AFAICT, it just
has a message and a cause.
In this case it might be more convenient to add extra fields to carry
essential stuff from the underlying Exception rather than subclassing
it. I'm wondering what, apart from personal preference, determines which
of the two approaches should be used in a given situation.

That's a really good question. Anyone like to propose an answer?

My personal preference is for lots of subclassing, so that information
about the exception is encoded in an easily usable way in its type - you
can filter out specific exceptions with specific catch clauses, rather
than having to do catch-check-handle-or-rethrow, and the nature of the
exception is immediately apparent from its class name. However, if there
is some kind of property that's meaningful over a range of exception
types, then that should certainly be made accessible, through a getter
defined in a common base class.

For instance, you could (*could*) break SQLException into subclasses along
SQLState lines: you'd have SQLException, then subclasses NoDataException
(for 02000), DynamicSQLException (for 07xxx), ConnectionException (for
08xxx), etc. NoDataException would be concrete, but 07 has subcodes, so it
would be abstract, with concrete classes for
WrongNumberOfVariablesException (07001), InvalidParameterListException
(07002), etc. However, you'd still want to have an int getSQLState()
method in SQLException, so you could get the code directly if you wanted.

Note that i'm not seriously suggesting that SQLException should be done
this way: that really seems over the top. I guess my test is "are these
two kinds of exception different enough that calling code might want to
deal with them differently?"; if they are, use subclasses, so that
separate catch clauses can be written. If they aren't, capture the details
in a field, so it can be reported.

In the OP's situation, i think network errors and files not being found
probably would be handled differently. You might want to automatically
retry in the case of a network error, possibly after rebooting the
connection; you probably wouldn't want to do that for a file not being
found. You'd certainly want quite different error messages.

tom
 
M

Martin Gregorie

What extra information does ClassNotFoundException have? AFAICT, it just
has a message and a cause.
You're right, but it overrides getCause() for some reason that's not
explained in the Javadocs.
My personal preference is for lots of subclassing, so that information
about the exception is encoded in an easily usable way in its type - you
can filter out specific exceptions with specific catch clauses, rather
than having to do catch-check-handle-or-rethrow, and the nature of the
exception is immediately apparent from its class name. However, if there
is some kind of property that's meaningful over a range of exception
types, then that should certainly be made accessible, through a getter
defined in a common base class.
That's a good reason. My guess is that you probably should restrict
subclasses to an enumeration of the actions triggered by exceptions
dependent on the superclass (something along the lines of
MyFatalException, MyRetryException, MyBacktrackException).
Note that i'm not seriously suggesting that SQLException should be done
this way: that really seems over the top.
Agreed, especially as SQLExceptions generally mean that something has
gone badly wrong. At least this is the case in my relatively small
experience with JDBC. IMO this is a sensible use of exceptions, unlike
some other classes that seem to throw exceptions for normal, expected
situations. I got a strong dislike to this approach when I was writing
PL/1 a while back - it even uses exceptions to signal EOF, which really
screws up the logic flow of the program.

I guess my test is "are these
two kinds of exception different enough that calling code might want to
deal with them differently?"; if they are, use subclasses, so that
separate catch clauses can be written. If they aren't, capture the
details in a field, so it can be reported.
Yep.
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top