Exceptions

Discussion in 'Java' started by nukleus, Jan 18, 2007.

  1. nukleus

    nukleus Guest

    I have some old java code i am working with right now.
    All AWT stuff, no javax.
    It is a network related application.

    There are some issues with Events and Exceptions:

    Exceptions:

    The program is quite complex and there are all sorts of things
    that may go wrong. At any time, the sockets may be lost, the
    servers may get close their end of the wire, bad data may arrive
    and so on. The error may happen several levels deep, and it
    all has to be handle in such a way, that user can comprehend
    what logially happens in any situation.

    So, the strategy chosen, is to create custom Exceptions,
    derived from standard exceptions, such as socket exceptions,
    invalid numbers, etc.

    Several levels up, the routines that perform logically complete
    operations, catch those custom exceptions and can display the
    the information to the user in a command history text area.

    There is a tradeoff here. On one hand, it is easier to use
    exceptions as you don't have to worry about the return codes
    by routines that are several levels deep, analyze those results,
    and create extra code that would be nice not to have.

    On the other hand, some classes of errors, are not critical.
    They simply mean that user provided incorrect configuration
    parameters and the server issued an error code, which is
    perfectly valid. In this case, it doe seem to be preferrable
    to use the ResultCode class object, automatically parsing
    the network server standard results, such as NNTP, SMTP
    or other standard protocol return codes.
    Creating a different exception for some of those codes
    simply creates too much of extra code and, finally, may
    confuse the issues to the point where you no longer grasp
    what is going on.

    So, there is a fine balance between the return codes and
    exceptions. For example, in case of NNTP protocol, in
    article download operation, there is a sequence of commands
    exchanged by the program and server. First, you have to
    connect to server, then you have to issue group command,
    then download article headers, necessary to perform a
    specific operation, then issue ARTICLE command, and,
    finally, load the article and save it in archive file.
    Depending on response of server, the ResultCode object,
    may contain either a standard NNTP error code plus the
    body of actual server response, or, it may contain some
    custom codes and text of their error messages.

    For example, if socket is timed out, stream is lost, etc.,
    we should be able to catch those situations and covert them
    into our custom codes. Several levels above,
    the caller of logically complete operation may use the switch
    statement and act upon various standard or custom errors
    differently depending on type of operation. It things time out
    in the middle of header download, the server has to be
    reconnected to, the GROUP command is to be issued,
    and then the broken headers are to be downloaded
    instead of redoing the whole operation from the top.
    This way, you recover in the middle of ANY situation,
    and recover in the most effective and logical way.
    If you have error while downloading article itself,
    it means you are already connected to the server,
    issued group command, downloaded all the headers,
    and are now doing the actual work of article downloading.
    Any errors at this point, should simply redo the last article
    and keep going. After each article is downloaded, the
    article number is saved in a group file. So, no matter what
    happends, you know exactly where to restart. Even if the
    program crashes, you still recover exactly what you need to.

    To make a long story short, question:

    Does it make sense?
    Is it the way to go or is there any other alternative?

    To summarize: the custom exceptions are used to bring up
    some fine graining into error handling structure. Instead of
    using the standard exceptions, such as IOException, socket,
    or Exception itself, we use those custom exceptions
    and catch them in various places above to precisely affect
    the recovery code. In the main routines, various exceptions
    are caught starting from the mist fine grained level, and
    going down to the Exception level, if we did not catch
    the any lower level custom exceptions.

    Thanks for your opinion on this.
    nukleus, Jan 18, 2007
    #1
    1. Advertising

  2. nukleus

    Lew Guest

    nukleus wrote:
    > To summarize: the custom exceptions are used to bring up
    > some fine graining into error handling structure. Instead of
    > using the standard exceptions, such as IOException, socket,
    > or Exception itself, we use those custom exceptions
    > and catch them in various places above to precisely affect
    > the recovery code. In the main routines, various exceptions
    > are caught starting from the mist fine grained level, and
    > going down to the Exception level, if we did not catch
    > the any lower level custom exceptions.


    I will not treat your points in detail here, but instead speak to the
    strategies for using exceptions.

    Generally, what you describe is viable, perhaps not best practice but not so
    terrible on the face of it. The danger, almost a certainty in the real world,
    especially given your descriptions in other threads of the coding style that
    you inherited, is that the implementation of the strategy is flawed in the
    details.

    Here are Lew's Laws for the use of exceptions (not guaranteed to be clever or
    correct, but presented as a starting point). This post runs a little lengthy.

    1.
    Exceptions, as the name implies, are for exceptional circumstances. Use
    regular logic for things you expect.

    instead of
    public void act( Entity entity )
    {
    try
    {
    System.out.println( entity.name );
    }
    catch ( NullPointerException e )
    {
    System.out.println( "null entity" );
    }
    }

    use
    public void act( Entity entity )
    {
    if ( entity == null )
    {
    System.out.println( "null entity" );
    }
    else
    {
    System.out.println( entity.name );
    }
    }

    2.
    Return codes are better than throws, when either the result makes sense within
    the problem domain or a reasonable default exists.

    public boolean storeData( Entity entity )
    {
    // Set up a PreparedStatement with an INSERT ...
    try
    {
    ps.execute();
    }
    catch ( SQLException se )
    {
    logger.error( e );
    return false; // clearly the exception means that the store failed
    }
    finally
    {
    ps.close();
    }
    // more logic and cleanup ...
    return true;
    }

    3.
    Log your exceptions.
    Corollaries: Have a logging strategy. Include in it a standard logging format.

    4.
    Do something with received exceptions at the first point of reception.

    Even if an exception will be rethrown, you should at least log it at the point
    of first capture. You will have available the fullest possible context at that
    moment. Then either rethrow, convert to a custom or convert to a
    problem-domain value.

    5.
    An application should define a custom exception, possibly two, the first
    extending Exception and the other RuntimeException.

    You probably do not need any more than these two. Use constructors that take
    the causal exception as a parameter. (Roll your own in J 1.3, use the
    corresponding super() calls in J 1.4+.) Your custom exceptions should expose
    all four constructors.

    6.
    Analyze each potential exception situation individually. Does it make sense to
    "eat the exception" and convert to a default value or action? Should you throw
    an exception? Should it be a standard exception or a custom one? (I typically
    throw standard Java RuntimeExceptions like IllegalArgumentException, but use a
    custom checked exception.)

    7.
    Exceptions are essentially value objects. They shouldn't log, and they damn
    sure shouldn't do anything within the problem domain. (By which I mean that an
    Exception should sport no methods that do these things.)

    To apply these "laws" to your problem, I'd say to make sure that the code logs
    exceptions at first contact, that throws occur only when necessary, not for
    "in the domain" occurrences, and that the recovery actions make sense.

    - Lew
    Lew, Jan 19, 2007
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Herr Lucifer
    Replies:
    0
    Views:
    540
    Herr Lucifer
    Jun 21, 2004
  2. Ahmed Moustafa
    Replies:
    5
    Views:
    29,992
    Chris Smith
    Jul 14, 2004
  3. Paul Miller
    Replies:
    3
    Views:
    1,009
    Alex Martelli
    Nov 12, 2003
  4. Replies:
    3
    Views:
    600
    Sherm Pendley
    Apr 16, 2007
  5. Lie
    Replies:
    3
    Views:
    601
Loading...

Share This Page