commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gilles Sadowski <gil...@harfang.homelinux.org>
Subject Re: svn commit: r960602 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/analysis/interpolation/ main/java/org/apache/commons/math/exception/ main/java/org/apache/commons/math/util/ main/resources/META-INF/localization/ site/xdoc/ tes...
Date Wed, 07 Jul 2010 13:56:37 GMT
> > And I disagree with both your disagreements. Could you _please_ answer all
> > the drawbacks of your approach in several scenarios which I've put forward
> > many times already, instead of always only cling to the one use-case which
> > you are interested in?

Still no answer on this...

> > Please! What kind of ?@#! application is it that you take as an example,
> > that will print a terse message and exit?  The _least_ a program should
> > do when it bails out is print the stack trace!
> 
> I am thinking about the programs I use: space flight dynamics programs
> that do things like orbit propagation, operational events forecasts
> (eclipse entry/exit, visibility from ground station, apogee/perigee/node
> crossings, South Atlantic Anomaly entry/exit, thrusters firings,
> Sun/Moon/stars visibility/dazzling in optical sensors ...), orbit
> determination, maneuver optimization, space debris close approaches and
> avoidance ...
> 
> These applications are often integrated into a large framework (a
> satellite control enter). They provide graphical user interface. The
> errors are often displayed in limited dedicated places (error message
> line at the bottom of some windows, popup window with one or two text
> lines, and most of the time a single line of text transmitted to a
> centralized log application gathering messages from the whole control enter.
> 
> Another example are web applications. The interactive part runs on a
> browser and the core engine runs on the server. The messaging protocol
> between the two doesn't provided anything but a string to display error
> messages, and the UI is often designed for one line strings, not 50
> lines stack traces.
> 
> A third example are applications running on limited mobile devices like
> phones. The display is very limited, it would not handle a stack trace.

The problem is not the possible limitation of the interface with the final
user: an error that originates in CM should not propagate to the final user!
For example (selecting at random from the impressive list of applications
above), if some operator pushes a button named "Debris avoidance" and sees
 "The number of points is less than 2"
on his one-line console log. How useful is it?

I'm talking about precondition violations here.
If they happen, they must be caught by the application and an appropriate
error should be generated that is related to the user action that triggered
the problem.
This is exactly the confusion I was referring to: Only you, as a veteran CM
developer, might recognize your "detailed" message string. For a real final
user it is no more useful than
  "Argument was less than 2".
[If CM is really intended to display everything to the top-level, then I
revise my position, there are far too few error message strings: There
should be a specific one for each place where an exception is thrown,
explaining in a detailed message why the error occurred at that place in the
code... (Just kidding.)]
Even if it were so, what you'd have achieved is to pinpoint where the
exception was thrown, without the help of the stack trace. But you are still
nowhere close to fixing the bug because, without the stack trace, you don't
know what action really triggered the exception (a bug in CM, or in the
application, or bad usage from the operator?).

> > Please! Read chapter 8 of Bloch's Effective Java (less then 20 pages) to see
> > that indeed the error message must be reported by the user/operator to the
> > developer. This is not debugging.
> 
> The problem we discuss is not related to Java, it is all about
> ergonomics. The rules about error messages are consistent everywhere I
> looked: they should be user oriented, helpful and must not rely on
> program implementation details. When I read:
>   "provide user-centered wording in messages (e.g. "there was a problem
>    in copying the file to your disk" rather than "execution error 159")"
> in <http://ergo.human.cornell.edu/ahtutorials/interface.html>, I
> consider it also rules out stack traces.

Confusion of responsibilities (continued)...
CM is not an end-user application; it is a low-level component.
[CM directly communicating with the end-user can also be viewed as breakind
encapsulation...]

> Of course, Phil you and I can deal with stack traces. In fact, I think
> all people on this list (a "dev" list) can and do this all the time. But
> users may not. [...]

I can agree that stack trace is not for users, though not because it is
deemed too complicated, but because if the stack trace appears, it often
means that, somewhere in the development chain, someone has not been careful
enough.

> You consider our users are developers (I think you wrote
> it some days ago) and we are not concerned by the users of our users.
> However, since at the same time you ask for going to unchecked exception
> which will obviously lead to our messages leaking to the higher level
> and to final user, I cannot agree with both points at the same time.

You misunderstood me. I said that the application developer will have the
choice to recover from unchecked exceptions just the same as with checked
exceptions. The advantage of unchecked exceptions is that they will relieve
CM-users who have no way to handle the problem (i.e. choice vs obligation).
And I also said that _none_ of the CM exceptions should ever reach final
users (hence my wondering of the necessity of localization inside the CM
library).
A well-behaved application will want to avoid being crashed by an uncaught
exception; at some point, it should catch all "RuntimeException"s and signal
to the user that something went terribly wrong with the current action,
because an unchecked exception could not be handled. If the programming
problem is to be solved, the application should log enough information; a
single line will not do.
A user who cannot deal with a stack trace should, even more so, never see a
CM message that relates to a method called many levels down his own action.
In the same way that his action passes through many layers before calling a
CM algorithm, then the result (or failure) of this algorithm must be
conveyed back in a manner that he can relate to.

> If all messages should be tracked and handled by intermediate code, and
> if they are only meant to developers with their accompanying stack
> trace, then they must be checked exception to be sure no error is
> missed.

It was probably the Java designer's dream that checked exceptions were the
ultimate solution to the error handling problem. But their overuse proved
to be a burden; burden that is dealt with in various ways such as, namely,
 * exception swallowing, or
 * every method declared to throw "Exception" (i.e. transferring
   the burden to the caller) etc.

Whereas it is so simple not to miss anything:

public static void main(String[] args) {
  // ...

  try {
    // ...
  } catch (RuntimeException e) {
    LOG.error("Oops, unexpected exception (this is a bug): " + e);
  }
}

> If we opt for unchecked exception, there will be leaked messages

Which will just prompt for bug-fixes, consisting in not leaking them
anymore.

> and the stack trace will sometimes not be there (or will be theere for a
> user than cannot understand or use them). This look to me similar to
> this wonderful analysis of a web server error message:
> <http://blog.use-design.com/2008/bad-bad-user/>; [...]

But that's exactly what you want CM to do: Leaking messages that only
reflect the inner working of something. As much as this user may not know
what he did to get a "Cannot handle request", the user of an application
that just displays the CM exception will feel the same way looking at
 "Number of points is less than 2".
I think that you over-estimate the usefulness of the error message string at
the expense of making it easier for application programmers to catch the
specific exception that they might want to handle.

> of course from a
> developer or an experienced user, the message is self explanatory, but
> consider how it may be misinterpreted by a less experienced user.

One of my points, again, is that the exception messages are not meant
to convey a thorough explanation, but to indicate that something went wrong.
Another point is that at the level of library component the type of the
exception object is more important than the String message. Objects make it
possible to further customize the behaviour of the upper layers of code. The
String is meant for humans to read, and when that has happened it is too
late for anything else (the program bailed out).

> To me, the trade-off between our diverging points is to:
>  1) go to uncheck exceptions wherever possible (your point)
>  2) reduce number of difference messages (everybody point)
>  3) keep informational messages (both Phil and mine point)
> 
> Items 2 and 3 are sometimes in contradiction and should be applied on a
> message by message basis.

Please note that I'm not against conveying detailed information. What I've
been suggesting is a sound and flexible design. IMO that goal implies:
 1. A set of (stateful) exception classes
 2. Stringent rules on the use of checked exception
 3. Encapsulation of messages localization

Now, one of your requirements is that "getMessage" should display a
"mini-manual" and, as far as I can see, *that* goal is in contradiction with
a significant reduction of the message strings.
Moreover, encapsulation (point 3) will then require a huge set of
exceptions, most of which will be used only once in the CM code.

In order to try and satisfy everyone's requirements (without necessarily
reconciling them), I was thinking of introducing a second "Localizable"
instance variable in class "MathIllegalArgumentException". This one would
not be pattern but a more detailed explanation, that could also be
localized.  Hence the class
  "NumberOfPointsIsTooSmallException"
would inherit from
  "NumberIsTooSmallException"
and will display
  "number of points: argument (0) is less than 2"
   ^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   Specific context       General problem

It will not reduce the global number of enums nor make the number of
exceptions small but it will at least have the advantage to separate the
general problem from the specific context where it occurred.
How does that sound?


Gilles

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message