On Sun, 10 Nov 2013 16:11:59 +0100, Thomas Neidhart wrote:
On 11/10/2013 03:04 PM, Gilles wrote:
On Sun, 10 Nov 2013 10:15:18 +0100, Thomas Neidhart wrote:
On 11/10/2013 07:03 AM, Phil Steitz wrote:
On 11/9/13 3:27 PM, Thomas Neidhart wrote:
On 11/09/2013 11:21 PM, Gilles wrote:
On Sat, 09 Nov 2013 13:13:05 -0800, Phil Steitz wrote:
On 11/5/13 5:21 AM, Gilles wrote:
[...]
I have scanned for exact duplicates quite a few times and
never
found any. There are quite a few that are similar, but
differ in
material ways (strict versus non-strict inequalities,
endpoints
included / not included, etc.). Please do not "collapse"
messages
at the expense of loss of specificity or correctness.
FAILED_BRACKETING
UNABLE_TO_BRACKET_OPTIMUM_IN_LINE_SEARCH
INVALID_BRACKETING_PARAMETERS
Look at the messages. These are different. They convey
different
information and are appropriate in different contexts. See
below.
I've argued that context information should be constructed at
the
point where the exception is thrown (where the context is
known).
Not all combinations of exceptions and context need be present
in
the pattern list.
This is the essence of my proposal below.
My position: the error (failed bracketing) should have its
own
exception
type. The varying contexts could (do not have to) be part of
the
message
built at exception instantiation.
If we want to include an indication of location (despite it
is
already
part of the stack trace, so it is _redundant_), we could
perhaps
add methods
to the "ExceptionContext", e.g. "where(LocalizeFormats
pattern)"
(?).
Then, we would have thos patterns in the list:
BRACKETING
LINE_SEARCH
Note: INVALID and FAILED are redundant since the pattern is
intended to be
included in an exception.
A second "interesting" case is
INVALID_ROUNDING_METHOD
which mixes documentation with error description. Does
anyone
really thinks
that the enumeration of the rounding methods in the error
message
is necessary
or even helpful?
When I throw an exception, I want to provide an error message
that
is meaningful in the context of the caller, i.e., that
someone
looking at a log or stack trace can make sense of. That
sometimes
means restating preconditions, sometimes pointing to boundary
conditions, sometimes giving hints describing common causes
of the
exception - lots of different things that depend on the API,
the
activation context and the nature of the exception. The
natural
way
to do this is to use natural language sentences. Please
allow
me to
retain a straightforward way to construct these messages and
to
maintain the specificity and meaning of the messages.
IMHO, the level of details in the message is not needed: if
the
exception
was thrown, the user should probably look at the
documentation,
rather
than try another value at random; I'd say that it is harmful
to
tempt the
users with something like "Pick another number". ;-)
[Shouldn't we rather provide function where the rounding type
is
an enum?]
The main problem in those discussions is that you consider
only
"toy"
situations, where the message generated by Commons Math should
make sense
wherever the exception is caught, and even if it is not
caught.
What you keep failing to acknowledge is that in many real world
applications, reading exception stack traces and application
logs
that contain error messages is an important operational
activity.
Having clear error messages that make sense in the context of
the
stack trace or application activation context makes the job of
those
maintaining and debugging those applications easier. However
hard
we decide to make it, I will continue to provide these.
IMO, the real problem is old habits, period. Despite your
repeating it
over and over, I never expressed anything in the sense of having
less
information in the error messages. [I don't get what the stack
trace has
to do here. And I just gave you a real example where whatever
details
CM tries to provide, it will _never_ be sufficient because it
cannot
know why the call failed; I suggested that the _same_ amount of
(necessary but not sufficient) information could perhaps be
provided
with "little block" patterns glued with "addMessage" (or an
improvement
thereof).]
Specific exceptions always provide more information than less
specific
ones. Keeping low-level message (e.g. precondition failure) does
not
preclude adding more specific messages when the context is known
(that
happens in the code, and every little variant does not need to
be
hard-coded in the currently overly long list of patterns).
My proposals were solely aimed at making the "preparation" of
the
messages more efficient from a developer's perspective (e.g. no
scanning
of 300+ patterns).
Stalling the experiment in endless arguments makes it less and
less
worth trying.
All in all, the main argument seems to always be that if the
user
cannot see the difference, it is not worth changing the design.
Which is also a pragmatic and valid approach here imho.
If there are no real user complaints about this topic (and I am
not
aware of any) and no other solution will greatly enhance the
current
state, it is really not worth doing it.
Part of my day job is to debug very complex systems and the most
important thing is that you get what you expect, i.e. according
to the
contract of a method, which btw also includes the method name.
Detailed
error messages are nice to have but not really required (as long
as you
understand the purpose of the code which any user/developer of CM
should
do).
More meaningful error messages would make sense if our targeted
audience
are really end-users but I think this is a bit far-fetched.
Not really. Does not have to be end users, just someone looking
at
an application log that reproduces the messages or the stack
traces
themselves. Sometimes operations / production support teams do
not
have access or time to look at source code or javadoc.
Informative
error messages that give more information about the failure can be
useful to these people. Sure, you can push all of that off to the
client app developers; but it can make *their* lives easier too to
get more information, especially information about parameter
values,
which invariants were violated, etc. The simplest and easiest to
digest way to do that is to provide good error messages.
If the contract is violated, then it is a bug and has to go to 3rd
level
support (aka developer) anyway and this you can see immediately if
there
is an IllegalArgumentException.
For algorithm related problems, like MaxIterationExceededExceptions
or
similar ones can you really express why this happened? I think it
is
much more robust to take such exceptions into account in the first
place, i.e. algorithms may not converge for certain inputs and a
client
app developer has to present a meaningful error (in the context of
the
application!) to a user or the log file.
I even think that more detailed error messages give people the
illusion
that they can skip proper exception handling as CM already does it
so
well.
Just an example: if you try to open a non-existent file with the
Java
API, do you get the error code of the respective system call on
your
operating system? No, you get a FileNotFoundException, but what do
you
do with it? Would you log the error message contained in the
exception
or a more specific one in the context of your application?
Imho, the first option makes applications very hard to maintain.
Now the Java API is quite easy to understand and a lot of people
know it
very well, but take the example further for any 3rd party library
your
application may be using. How is your operation engineer supposed
to
know all error states of all the used 3rd party libraries and put
them
in the right context? If he/she is lucky enough there is a an
operations
manual for their own application ...
Interpreting and proper handling of 3rd party code is the job of
the
client app developer, and he/she has to do it right. If you may get
an
exception you have to take care about it, everything else will just
create headaches.
Very good account using the practical perspective of a multi-layered
application (I mean, where each layer is indeed developed by
different
teams)!
[I had put forward this kind of arguments in my first raising of the
not-so-good feeling I had with the CM exception framework.]
As a low-level library, the main focus must indeed to encapsulate
error
conditions in the most flexible way for the layer next up (i.e.
specific
exception classes) so that it can also act in a flexible way (catch,
not
catch, catch and rethrow a context-specific exception).
As I had said (too many times to be counted), this does not stand in
opposition with providing detailed error messages for the cases
where
the intermediate layers do not care to catch the low level errors.
What top-level users can see from CM (through the stack trace) is
the
best we can show (and that is quite fine by me, sorry to repeat
myself
so often...). But my conviction is that we can do better internally
(cf.
"small cleanup" of the error patterns list), and that we must do
better
for the application or library developers who use CM as a component.
Both these tasks should be thought about together; an improvement in
one area is likely to improve the other. [Again: I totally expect
that
this will not change anything for a user who browses the stack trace
generated by a CM exception that was not caught.]
So the real question was whether we are going to thwart any and all
attempts aimed at improvement on the basis of the single case of a
top-level user reading the low-level textual error messages.
If you have a good proposal to reduce the number of localized
messages
and thus make it easier to develop new code for CM I would be very
much
in favor of it.
Hmm, I think I explained my proposal... Was it twice, three, ten times?
It's just not trying to have documentation inside the error messages.
Documentation contains all the details; error messages can be terse.
As Luc said, it could be quite hard to come up with patterns that
really
work in a multi-language context, but I did not try it myself or have
seen proposals to overcome this complexity.
IMHO, this is a false problem. It is not necessary to write a
syntactically
correct and complete sentence to perfectly convey the meaning of an
exception
raised by such low-level checks as occur in CM.
Either the "operator" knows what happened (and why the exception was
raised)
and he does not need a full and syntactically correct set of sentences
to
figure out what must be changed for the call to succeed; or he doesn't
and
it is fairly improbable that he can just guess without referring to the
documentation.
I also did not follow so much the exception discussions as I am quite
agnostic about it, but I wanted to point out that I consider good
documentation and examples / user guide much more important and we
should put our focus also on these issues (what I did try to do
lately
and am going to continue).
These are orthogonal considerations.
Gilles
Thomas
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org