You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Gilles Sadowski <gi...@harfang.homelinux.org> on 2010/03/24 17:04:26 UTC

[Math] Localization and Error Handling

Hello.

I'd like to suggest that there could be a nicer way to handle localization
of error messages.  Please have a look at
   http://cal10n.qos.ch/

Of course, the first point that will be raised is that it creates an
external dependency. Is this a "no-no" or, given some benefits, could it be
acceptable?

Basically, I think that dealing with strings inside the math library code is
ugly and error-prone. E.g.

  throw MathRuntimeException.createIllegalArgumentException("{0} out of [{1}, {2}] range",
                                                            x, xval[0], xval[xval.length - 1]);

A simple spelling mistake will defeat the purpose, as the localized version
will not be found.
The above library takes care of this problem.

Even so, I think that *messages* should not appear at this level. It is much
simpler to use a set of specific exceptions. I.e. instead of the above
statement, one would use:

  throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);

where the exception is defined as

  public OutOfRangeException extends IllegalArgumentException {
     private double val, min, max;

     public OutOfRangeException(val, min, max) {
       this.val = val;
       this.min = min;
       this.max = max;
     }

     public String getMessage() {
       // ... The string (or "enum" if using the "cal10n" library)
       // should appear at this level.
     }
  }

Admittedly, this means creating a lot of exception classes; but the
advantage is that they will allow more control.


Best,
Gilles

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


Re: [Math] Localization and Error Handling

Posted by sebb <se...@gmail.com>.
On 24/03/2010, Luc Maisonobe <Lu...@free.fr> wrote:
> Gilles Sadowski a écrit :
>
> > Hello.
>  >
>  > I'd like to suggest that there could be a nicer way to handle localization
>  > of error messages.  Please have a look at
>  >    http://cal10n.qos.ch/
>
>
> This looks promising, and I also considered developing a maven plugin
>  with some asm magic to help make sure all messages are translated
>  properly. However, I wanted to have a tool that would be only use at
>  build time.
>
>
>  >
>  > Of course, the first point that will be raised is that it creates an
>  > external dependency. Is this a "no-no" or, given some benefits, could it be
>  > acceptable?
>
>
> The runtime dependency is a no-no (at least from me). Is it possible to
>  use only the build part and not the runtime part ?
>
>
>  >
>  > Basically, I think that dealing with strings inside the math library code is
>  > ugly and error-prone. E.g.
>  >
>  >   throw MathRuntimeException.createIllegalArgumentException("{0} out of [{1}, {2}] range",
>  >                                                             x, xval[0], xval[xval.length - 1]);
>  >
>  > A simple spelling mistake will defeat the purpose, as the localized version
>  > will not be found.
>
>
> You are right.
>
>
>  > The above library takes care of this problem.
>  >
>  > Even so, I think that *messages* should not appear at this level. It is much
>  > simpler to use a set of specific exceptions. I.e. instead of the above
>  > statement, one would use:
>  >
>  >   throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);
>  >
>  > where the exception is defined as
>  >
>  >   public OutOfRangeException extends IllegalArgumentException {
>  >      private double val, min, max;
>  >
>  >      public OutOfRangeException(val, min, max) {
>  >        this.val = val;
>  >        this.min = min;
>  >        this.max = max;
>  >      }
>  >
>  >      public String getMessage() {
>  >        // ... The string (or "enum" if using the "cal10n" library)
>  >        // should appear at this level.
>  >      }
>  >   }
>  >
>  > Admittedly, this means creating a lot of exception classes; but the
>  > advantage is that they will allow more control.
>
>
> Perhaps some intermediate solution with more exception classes than we
>  have but not one class for each message.
>
>  At least, I agree the messages should be defined only once.
>
>  Are there good localization framework with no runtime dependency
>  available somewhere ?
>

For example, Tomcat and Harmony have built-in message frameworks.
I think they both use property files, and have a class or two for the
message handling.

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

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


Re: [Math] Localization and Error Handling

Posted by Phil Steitz <ph...@gmail.com>.
Luc Maisonobe wrote:
> Gilles Sadowski a écrit :
>> Hi.
>>
>> [I'm not quoting previous messages because the mix of quotes and wrapped
>> lines has become illegible.]
>>
>> I'll first list all of the problems (IMO) in the current handling of error
>> reporting. Then I'll propose modifications that will hopefully solve them.
>>
>> Difficulties for the CM developers:
>> 1. The message patterns appear in every exception instantiation.
>> 2. The developer must correctly reproduce the pattern. Doing this by hand or
>>    by copy/paste is error-prone.
>> 3. The developer must search the (long) list of available patterns in order
>>    to determine if one already exists that provides what he needs.
>> 4. Localized message patterns contain Unicode escapes.
>>
>> Difficulties for the application-programmer using CM:
>> 5. Different patterns actually report the same error type.
>> 6. Many different errors are instantiated with an indiscriminate
>>    "IllegalArgumentException". This prevents flexible access to the cause
>>    of the error as it is only available as a "String".
>> 7. As a consequence of point 6, the message reported to the end-user, as
>>    generated by CM, might not be consistent with the user action (at the
>>    higher-level application) that generated the error.
>> 8. A variant of point 7: the application programmer should be free to
>>    design his own formatting of error messages (e.g. he might want to have
>>    all messages with an upper-cased first letter).
>> 9. The patterns are not consistent: some start with an uppercase letter,
>>    some with a lower-case; in some cases, there is an upper-case letter in
>>    the English version, but not in the French version.
>>
>> Difficulty for some end-users:
>> 10. Using a default non-English locale, while still wanting to have all
>>     error messages output in English.
>>
>> Those are not big problems, and could be dismissed as unimportant details;
>> however, any library seeking wide use should promote the best practices,
>> even in those little corners.
>> I think that we can improve over the current way in all of the situations
>> cited above.
>>
>> I have the impression that the current way is the result of writing the
>> library around the localization feature instead of adding the feature to the
>> library's "core business".
>> Localisation is a high-level feature and should be as little intrusive as
>> possible for those users who don't need it.[1]
>> For those who actually need it, it should not be CM's decision as to what
>> degree of flexibility is actually useful.
>>
>> Here what I propose:
>>  * At the level of CM, the building blocks for error reporting should be
>>    classes derived from (modified) "MathException" and
>>    "MathRuntimeException" classes[2].
>>  * Each exception class will represent a specific problem (e.g.
>>    "OutOfRangeException") and will belongs in an "exception" package.
>>  * The specific exception classes will provide accessors to the data
>>    relevant to the problem (e.g. methods "getLo()" and "getHi()" will
>>    respectively return the lower and higher bounds of the allowed interval,
>>    in the case of an "OutOfRangeException").
>>  * To enforce the use of meaningful exceptions throughout CM, the base
>>    classes constructors' access should be "protected".
>>  * Only the 2 base classes will deal with constructing an error message and
>>    will store an "enum" (e.g. "MathMessageKey.OUT_OF_RANGE") that will
>>    uniquely identify a pattern to be used for message formatting.
>>  * To enable localization, the base classes will delegate the actual
>>    formatting to a "Framework" interface. The actual class implementing the
>>    "Framework" can be selected at runtime, so that the user can choose from
>>    a default ("resources"-free) formatting or a localized one (with a
>>    possible dependency to an external library, for maximum flexibility).
>>
>> [In order not to add to an already long post, I won't detail how this
>> proposal will obviously improve on the problems enumerated above.]
>> Please let me know what you think.
>>
>>
>> Best regards,
>> Gilles
>>
>> [1] There is even the case where a user might not even *want* any code 
>>     accessing "resources".
>> [2] For the moment, I'll leave aside another problem: the choice of which
>>     errors should be inherited from "RuntimeException" and the fact that
>>     this choice is not consistent in CM. As changes in order to correct this
>>     will not be backward-compatible, it is left for another dicussion and
>>     for a major version bump.
>>
>> P.S. I have a prototype that partially implements these ideas. But I'm not
>>      sure how to proceed in order to demonstrate it, as it would also
>>      include configuration changes ("compile" vs "runtime") and it must
>>      create separate JARs for the alternative "Framework" implementations.
> 
> Perhaps you could open a Jira issue and attach your patch to it, so we
> can all have a look at it. If we agree to it, then we could start a
> branch on svn for this huge modification.

Or transition to it incrementally in trunk if that is possible.
Maintaining multiple branches that differ only in exception
management with the level of activity that we have would be a pain.

+1 to having a look at a patch.  ++1 if we can find some middle
ground between extremes and a transition path.

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


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


Re: [Math] Localization and Error Handling

Posted by Luc Maisonobe <Lu...@free.fr>.
Gilles Sadowski a écrit :
> Hi.
> 
> [I'm not quoting previous messages because the mix of quotes and wrapped
> lines has become illegible.]
> 
> I'll first list all of the problems (IMO) in the current handling of error
> reporting. Then I'll propose modifications that will hopefully solve them.
> 
> Difficulties for the CM developers:
> 1. The message patterns appear in every exception instantiation.
> 2. The developer must correctly reproduce the pattern. Doing this by hand or
>    by copy/paste is error-prone.
> 3. The developer must search the (long) list of available patterns in order
>    to determine if one already exists that provides what he needs.
> 4. Localized message patterns contain Unicode escapes.
> 
> Difficulties for the application-programmer using CM:
> 5. Different patterns actually report the same error type.
> 6. Many different errors are instantiated with an indiscriminate
>    "IllegalArgumentException". This prevents flexible access to the cause
>    of the error as it is only available as a "String".
> 7. As a consequence of point 6, the message reported to the end-user, as
>    generated by CM, might not be consistent with the user action (at the
>    higher-level application) that generated the error.
> 8. A variant of point 7: the application programmer should be free to
>    design his own formatting of error messages (e.g. he might want to have
>    all messages with an upper-cased first letter).
> 9. The patterns are not consistent: some start with an uppercase letter,
>    some with a lower-case; in some cases, there is an upper-case letter in
>    the English version, but not in the French version.
> 
> Difficulty for some end-users:
> 10. Using a default non-English locale, while still wanting to have all
>     error messages output in English.
> 
> Those are not big problems, and could be dismissed as unimportant details;
> however, any library seeking wide use should promote the best practices,
> even in those little corners.
> I think that we can improve over the current way in all of the situations
> cited above.
> 
> I have the impression that the current way is the result of writing the
> library around the localization feature instead of adding the feature to the
> library's "core business".
> Localisation is a high-level feature and should be as little intrusive as
> possible for those users who don't need it.[1]
> For those who actually need it, it should not be CM's decision as to what
> degree of flexibility is actually useful.
> 
> Here what I propose:
>  * At the level of CM, the building blocks for error reporting should be
>    classes derived from (modified) "MathException" and
>    "MathRuntimeException" classes[2].
>  * Each exception class will represent a specific problem (e.g.
>    "OutOfRangeException") and will belongs in an "exception" package.
>  * The specific exception classes will provide accessors to the data
>    relevant to the problem (e.g. methods "getLo()" and "getHi()" will
>    respectively return the lower and higher bounds of the allowed interval,
>    in the case of an "OutOfRangeException").
>  * To enforce the use of meaningful exceptions throughout CM, the base
>    classes constructors' access should be "protected".
>  * Only the 2 base classes will deal with constructing an error message and
>    will store an "enum" (e.g. "MathMessageKey.OUT_OF_RANGE") that will
>    uniquely identify a pattern to be used for message formatting.
>  * To enable localization, the base classes will delegate the actual
>    formatting to a "Framework" interface. The actual class implementing the
>    "Framework" can be selected at runtime, so that the user can choose from
>    a default ("resources"-free) formatting or a localized one (with a
>    possible dependency to an external library, for maximum flexibility).
> 
> [In order not to add to an already long post, I won't detail how this
> proposal will obviously improve on the problems enumerated above.]
> Please let me know what you think.
> 
> 
> Best regards,
> Gilles
> 
> [1] There is even the case where a user might not even *want* any code 
>     accessing "resources".
> [2] For the moment, I'll leave aside another problem: the choice of which
>     errors should be inherited from "RuntimeException" and the fact that
>     this choice is not consistent in CM. As changes in order to correct this
>     will not be backward-compatible, it is left for another dicussion and
>     for a major version bump.
> 
> P.S. I have a prototype that partially implements these ideas. But I'm not
>      sure how to proceed in order to demonstrate it, as it would also
>      include configuration changes ("compile" vs "runtime") and it must
>      create separate JARs for the alternative "Framework" implementations.

Perhaps you could open a Jira issue and attach your patch to it, so we
can all have a look at it. If we agree to it, then we could start a
branch on svn for this huge modification.

Luc

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


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


Re: [Math] Localization and Error Handling

Posted by Gilles Sadowski <gi...@harfang.homelinux.org>.
Hi.

[I'm not quoting previous messages because the mix of quotes and wrapped
lines has become illegible.]

I'll first list all of the problems (IMO) in the current handling of error
reporting. Then I'll propose modifications that will hopefully solve them.

Difficulties for the CM developers:
1. The message patterns appear in every exception instantiation.
2. The developer must correctly reproduce the pattern. Doing this by hand or
   by copy/paste is error-prone.
3. The developer must search the (long) list of available patterns in order
   to determine if one already exists that provides what he needs.
4. Localized message patterns contain Unicode escapes.

Difficulties for the application-programmer using CM:
5. Different patterns actually report the same error type.
6. Many different errors are instantiated with an indiscriminate
   "IllegalArgumentException". This prevents flexible access to the cause
   of the error as it is only available as a "String".
7. As a consequence of point 6, the message reported to the end-user, as
   generated by CM, might not be consistent with the user action (at the
   higher-level application) that generated the error.
8. A variant of point 7: the application programmer should be free to
   design his own formatting of error messages (e.g. he might want to have
   all messages with an upper-cased first letter).
9. The patterns are not consistent: some start with an uppercase letter,
   some with a lower-case; in some cases, there is an upper-case letter in
   the English version, but not in the French version.

Difficulty for some end-users:
10. Using a default non-English locale, while still wanting to have all
    error messages output in English.

Those are not big problems, and could be dismissed as unimportant details;
however, any library seeking wide use should promote the best practices,
even in those little corners.
I think that we can improve over the current way in all of the situations
cited above.

I have the impression that the current way is the result of writing the
library around the localization feature instead of adding the feature to the
library's "core business".
Localisation is a high-level feature and should be as little intrusive as
possible for those users who don't need it.[1]
For those who actually need it, it should not be CM's decision as to what
degree of flexibility is actually useful.

Here what I propose:
 * At the level of CM, the building blocks for error reporting should be
   classes derived from (modified) "MathException" and
   "MathRuntimeException" classes[2].
 * Each exception class will represent a specific problem (e.g.
   "OutOfRangeException") and will belongs in an "exception" package.
 * The specific exception classes will provide accessors to the data
   relevant to the problem (e.g. methods "getLo()" and "getHi()" will
   respectively return the lower and higher bounds of the allowed interval,
   in the case of an "OutOfRangeException").
 * To enforce the use of meaningful exceptions throughout CM, the base
   classes constructors' access should be "protected".
 * Only the 2 base classes will deal with constructing an error message and
   will store an "enum" (e.g. "MathMessageKey.OUT_OF_RANGE") that will
   uniquely identify a pattern to be used for message formatting.
 * To enable localization, the base classes will delegate the actual
   formatting to a "Framework" interface. The actual class implementing the
   "Framework" can be selected at runtime, so that the user can choose from
   a default ("resources"-free) formatting or a localized one (with a
   possible dependency to an external library, for maximum flexibility).

[In order not to add to an already long post, I won't detail how this
proposal will obviously improve on the problems enumerated above.]
Please let me know what you think.


Best regards,
Gilles

[1] There is even the case where a user might not even *want* any code 
    accessing "resources".
[2] For the moment, I'll leave aside another problem: the choice of which
    errors should be inherited from "RuntimeException" and the fact that
    this choice is not consistent in CM. As changes in order to correct this
    will not be backward-compatible, it is left for another dicussion and
    for a major version bump.

P.S. I have a prototype that partially implements these ideas. But I'm not
     sure how to proceed in order to demonstrate it, as it would also
     include configuration changes ("compile" vs "runtime") and it must
     create separate JARs for the alternative "Framework" implementations.

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


Re: [Math] Localization and Error Handling

Posted by lu...@free.fr.
----- "Phil Steitz" <ph...@gmail.com> a écrit :

> Gilles Sadowski wrote:
> > Hi.
> > 
> >>> I'd like to suggest that there could be a nicer way to handle
> localization
> >>> of error messages.  Please have a look at
> >>>    http://cal10n.qos.ch/
> >> This looks promising, and I also considered developing a maven
> plugin
> >> with some asm magic to help make sure all messages are translated
> >> properly. However, I wanted to have a tool that would be only use
> at
> >> build time.
> > 
> > Could you explain, by examples, how you imagine the separation
> between
> > build time and run time?

At build time, you can check all defined messages are used and all messages do have an available translation in the supported locale. A very smart framework could even check the number of expected and provided arguments are equal.

At run time, you only use the messages.

> > 
> >>> Of course, the first point that will be raised is that it creates
> an
> >>> external dependency. Is this a "no-no" or, given some benefits,
> could it be
> >>> acceptable?
> >> The runtime dependency is a no-no (at least from me). Is it
> possible to
> >> use only the build part and not the runtime part ?
> > 
> > Maybe I'll understand this with the examples, but rigth now, I don't
> see how
> > it would be possible: localization is a runtime feature; so in order
> to
> > benefit from a library, it must (also) be a runtime dependency.
> > Let's say that the compile time part creates a "dictionary"
> structure, you'd
> > still need the runtime to access it. If you don't want the
> dependency,
> > you'll need to re-implement all the look-up code that access the
> > "dictionary" from its persistent format, with the danger that this
> format
> > can be subject to change without notice (as it is created by the
> build time
> > dependency which you accepted).

Yes, you have to get the dictionary. The simplest is if your framework does all the checking for you in the build phase but does rely on a very simple access, for example simply reusing the basic Java properties files for example. The dictionary is static: one key, one value for each locale. There is no need for fancy formats for that. I don't see smart features like automatic reloading of messages useful: we hardly change them from release to release so don't care if we can't change them at runtime.


> > 
> >>> Basically, I think that dealing with strings inside the math
> library code is
> >>> ugly and error-prone. E.g.
> >>>
> >>>   throw MathRuntimeException.createIllegalArgumentException("{0}
> out of [{1}, {2}] range",
> >>>                                                             x,
> xval[0], xval[xval.length - 1]);
> >>>
> >>> A simple spelling mistake will defeat the purpose, as the
> localized version
> >>> will not be found.
> >> You are right.
> > 
> > OK. So even without deciding on the use of an external library, can
> we start
> > using "enum"s (in a way similar to what "cal10n" does)?
> > 
> >>> The above library takes care of this problem.
> >>>
> >>> Even so, I think that *messages* should not appear at this level.
> It is much
> >>> simpler to use a set of specific exceptions. I.e. instead of the
> above
> >>> statement, one would use:
> >>>
> >>>   throw new OutOfRangeException(x, xval[0], xval[xval.length -
> 1]);
> >>>
> >>> where the exception is defined as
> >>>
> >>>   public OutOfRangeException extends IllegalArgumentException {
> >>>      private double val, min, max;
> >>>
> >>>      public OutOfRangeException(val, min, max) {
> >>>        this.val = val;
> >>>        this.min = min;
> >>>        this.max = max;
> >>>      }
> >>>
> >>>      public String getMessage() {
> >>>        // ... The string (or "enum" if using the "cal10n"
> library)
> >>>        // should appear at this level.
> >>>      }
> >>>   }
> >>>
> >>> Admittedly, this means creating a lot of exception classes; but
> the
> >>> advantage is that they will allow more control.
> >> Perhaps some intermediate solution with more exception classes than
> we
> >> have but not one class for each message.
> > 
> > I didn't do an exhaustive search but it seems that there are a lot
> of
> > redundant message strings:
> > 
> >  "must have n >= 0 for binomial coefficient (n,k), got n = {0}"
> >  "must have n >= 0 for n!, got n = {0}"
> >  "brightness exponent should be positive or null, but got {0}"
> >  "number of microsphere elements must be positive, but got {0}"
> >  "polynomial degree must be positive: degree={0}"
> >  "upper bound must be positive ({0})"
> >  "length must be positive ({0})"
> >  "permutation k ({0}) must be positive"
> >  "invalid row dimension: {0} (must be positive)"
> >  "invalid column dimension: {0} (must be positive)"
> >  "initial capacity ({0}) is not positive"
> >  "index ({0}) is not positive"
> >  "window size must be positive ({0})"
> >  "element {0} is not positive: {1}"
> >  "mean must be positive ({0})"
> >  "degrees of freedom must be positive ({0})"
> >  "alpha must be positive ({0})"
> >  "beta must be positive ({0})"
> >  "number of successes must be non-negative ({0})"
> >  "standard deviation must be positive ({0})"
> >  "the Poisson mean must be positive ({0})"
> >  "invalid number of elements {0} (must be positive)"
> >  "invalid exponent {0} (must be positive)"
> >  "number of sample is not positive: {0}"
> > 
> > I think that all of these could be reduced to one or two
> exceptions.
> 
> Not without losing information in some cases. alpha and beta are
> different parameters in the context of the messages above, for
> example.
> 
> > Conceptually, the error is the same ("value should not be
> negative").
> > The message supposedly gives more information than that, but
> actually the
> > additional info is redundant with the line number that is part of
> the stack
> > trace: from it, it's straightforward to figure out which input is
> wrong; we
> > don't need the message to specify that it is "alpha" or "beta" or
> "mean" or
> > "degree" etc.

No, the message is intended to be displayed to users, but the stack trace may not. For example, the message can be directed in a message line at the bottom of some graphical user interface.

The exception mechanism in Java wraps two different concepts in one class: the message and the stack trace. The first one is intended for end users that may even not know about the structure of the code and the stack trace is intended for developers.

> > 
> >> At least, I agree the messages should be defined only once.
> >>
> >> Are there good localization framework with no runtime dependency
> >> available somewhere ?
> > 
> > I didn't find one. [Same question as above: How is such a thing
> supposed to
> > work?]
> > 
> > Concerning localization itself, I think that it's not the business
> of a
> > low-level library.
> > IMHO, CM should only be using exception objects. The Javadoc of
> those
> > exception classes and the "@throws" clauses are the places where the
> users
> > (i.e. *application* developers) can find the meaning and
> circumstance of the
> > problem.
> 
> Strictly speaking, that won't work. You really do need a way to
> minimally communicate parameter values or other exception context
> information to application developers reading stack traces.  There
> is a reason that java.lang.Exception has a message property ;)
> 
> Having spent many hours poring through stack traces as a developer
> over the years, I have come to appreciate those who provide
> meaningful messages with good context information.  We do a decent
> job of that in [math] now and I do not want to see us regress.  I am
> open to suggestions on how to make the localization more manageable,
> though.  It is a mild PITA to maintain now; but as I said above, it
> is at least approachable.
> 
> Phil
> 
> > Now, if, for political reasons ;-), you want to help the users by
> providing
> > a localization framework, why couldn't we consider it as an
> "add-on"
> > higher-level *optional* feature requiring an external dependency?
> > 
> > 
> > Best,
> > Gilles
> > 
> >
> ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> > For additional commands, e-mail: dev-help@commons.apache.org
> > 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org

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


Re: [Math] Localization and Error Handling

Posted by Phil Steitz <ph...@gmail.com>.
Gilles Sadowski wrote:
> Hi.
> 
>>> I'd like to suggest that there could be a nicer way to handle localization
>>> of error messages.  Please have a look at
>>>    http://cal10n.qos.ch/
>> This looks promising, and I also considered developing a maven plugin
>> with some asm magic to help make sure all messages are translated
>> properly. However, I wanted to have a tool that would be only use at
>> build time.
> 
> Could you explain, by examples, how you imagine the separation between
> build time and run time?
> 
>>> Of course, the first point that will be raised is that it creates an
>>> external dependency. Is this a "no-no" or, given some benefits, could it be
>>> acceptable?
>> The runtime dependency is a no-no (at least from me). Is it possible to
>> use only the build part and not the runtime part ?
> 
> Maybe I'll understand this with the examples, but rigth now, I don't see how
> it would be possible: localization is a runtime feature; so in order to
> benefit from a library, it must (also) be a runtime dependency.
> Let's say that the compile time part creates a "dictionary" structure, you'd
> still need the runtime to access it. If you don't want the dependency,
> you'll need to re-implement all the look-up code that access the
> "dictionary" from its persistent format, with the danger that this format
> can be subject to change without notice (as it is created by the build time
> dependency which you accepted).
> 
>>> Basically, I think that dealing with strings inside the math library code is
>>> ugly and error-prone. E.g.
>>>
>>>   throw MathRuntimeException.createIllegalArgumentException("{0} out of [{1}, {2}] range",
>>>                                                             x, xval[0], xval[xval.length - 1]);
>>>
>>> A simple spelling mistake will defeat the purpose, as the localized version
>>> will not be found.
>> You are right.
> 
> OK. So even without deciding on the use of an external library, can we start
> using "enum"s (in a way similar to what "cal10n" does)?
> 
>>> The above library takes care of this problem.
>>>
>>> Even so, I think that *messages* should not appear at this level. It is much
>>> simpler to use a set of specific exceptions. I.e. instead of the above
>>> statement, one would use:
>>>
>>>   throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);
>>>
>>> where the exception is defined as
>>>
>>>   public OutOfRangeException extends IllegalArgumentException {
>>>      private double val, min, max;
>>>
>>>      public OutOfRangeException(val, min, max) {
>>>        this.val = val;
>>>        this.min = min;
>>>        this.max = max;
>>>      }
>>>
>>>      public String getMessage() {
>>>        // ... The string (or "enum" if using the "cal10n" library)
>>>        // should appear at this level.
>>>      }
>>>   }
>>>
>>> Admittedly, this means creating a lot of exception classes; but the
>>> advantage is that they will allow more control.
>> Perhaps some intermediate solution with more exception classes than we
>> have but not one class for each message.
> 
> I didn't do an exhaustive search but it seems that there are a lot of
> redundant message strings:
> 
>  "must have n >= 0 for binomial coefficient (n,k), got n = {0}"
>  "must have n >= 0 for n!, got n = {0}"
>  "brightness exponent should be positive or null, but got {0}"
>  "number of microsphere elements must be positive, but got {0}"
>  "polynomial degree must be positive: degree={0}"
>  "upper bound must be positive ({0})"
>  "length must be positive ({0})"
>  "permutation k ({0}) must be positive"
>  "invalid row dimension: {0} (must be positive)"
>  "invalid column dimension: {0} (must be positive)"
>  "initial capacity ({0}) is not positive"
>  "index ({0}) is not positive"
>  "window size must be positive ({0})"
>  "element {0} is not positive: {1}"
>  "mean must be positive ({0})"
>  "degrees of freedom must be positive ({0})"
>  "alpha must be positive ({0})"
>  "beta must be positive ({0})"
>  "number of successes must be non-negative ({0})"
>  "standard deviation must be positive ({0})"
>  "the Poisson mean must be positive ({0})"
>  "invalid number of elements {0} (must be positive)"
>  "invalid exponent {0} (must be positive)"
>  "number of sample is not positive: {0}"
> 
> I think that all of these could be reduced to one or two exceptions.

Not without losing information in some cases. alpha and beta are
different parameters in the context of the messages above, for example.

> Conceptually, the error is the same ("value should not be negative").
> The message supposedly gives more information than that, but actually the
> additional info is redundant with the line number that is part of the stack
> trace: from it, it's straightforward to figure out which input is wrong; we
> don't need the message to specify that it is "alpha" or "beta" or "mean" or
> "degree" etc.
> 
>> At least, I agree the messages should be defined only once.
>>
>> Are there good localization framework with no runtime dependency
>> available somewhere ?
> 
> I didn't find one. [Same question as above: How is such a thing supposed to
> work?]
> 
> Concerning localization itself, I think that it's not the business of a
> low-level library.
> IMHO, CM should only be using exception objects. The Javadoc of those
> exception classes and the "@throws" clauses are the places where the users
> (i.e. *application* developers) can find the meaning and circumstance of the
> problem.

Strictly speaking, that won't work. You really do need a way to
minimally communicate parameter values or other exception context
information to application developers reading stack traces.  There
is a reason that java.lang.Exception has a message property ;)

Having spent many hours poring through stack traces as a developer
over the years, I have come to appreciate those who provide
meaningful messages with good context information.  We do a decent
job of that in [math] now and I do not want to see us regress.  I am
open to suggestions on how to make the localization more manageable,
though.  It is a mild PITA to maintain now; but as I said above, it
is at least approachable.

Phil

> Now, if, for political reasons ;-), you want to help the users by providing
> a localization framework, why couldn't we consider it as an "add-on"
> higher-level *optional* feature requiring an external dependency?
> 
> 
> Best,
> Gilles
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
> 


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


Re: [Math] Localization and Error Handling

Posted by Gilles Sadowski <gi...@harfang.homelinux.org>.
Hi.

> > I'd like to suggest that there could be a nicer way to handle localization
> > of error messages.  Please have a look at
> >    http://cal10n.qos.ch/
> 
> This looks promising, and I also considered developing a maven plugin
> with some asm magic to help make sure all messages are translated
> properly. However, I wanted to have a tool that would be only use at
> build time.

Could you explain, by examples, how you imagine the separation between
build time and run time?

> > Of course, the first point that will be raised is that it creates an
> > external dependency. Is this a "no-no" or, given some benefits, could it be
> > acceptable?
> 
> The runtime dependency is a no-no (at least from me). Is it possible to
> use only the build part and not the runtime part ?

Maybe I'll understand this with the examples, but rigth now, I don't see how
it would be possible: localization is a runtime feature; so in order to
benefit from a library, it must (also) be a runtime dependency.
Let's say that the compile time part creates a "dictionary" structure, you'd
still need the runtime to access it. If you don't want the dependency,
you'll need to re-implement all the look-up code that access the
"dictionary" from its persistent format, with the danger that this format
can be subject to change without notice (as it is created by the build time
dependency which you accepted).

> > 
> > Basically, I think that dealing with strings inside the math library code is
> > ugly and error-prone. E.g.
> > 
> >   throw MathRuntimeException.createIllegalArgumentException("{0} out of [{1}, {2}] range",
> >                                                             x, xval[0], xval[xval.length - 1]);
> > 
> > A simple spelling mistake will defeat the purpose, as the localized version
> > will not be found.
> 
> You are right.

OK. So even without deciding on the use of an external library, can we start
using "enum"s (in a way similar to what "cal10n" does)?

> > The above library takes care of this problem.
> > 
> > Even so, I think that *messages* should not appear at this level. It is much
> > simpler to use a set of specific exceptions. I.e. instead of the above
> > statement, one would use:
> > 
> >   throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);
> > 
> > where the exception is defined as
> > 
> >   public OutOfRangeException extends IllegalArgumentException {
> >      private double val, min, max;
> > 
> >      public OutOfRangeException(val, min, max) {
> >        this.val = val;
> >        this.min = min;
> >        this.max = max;
> >      }
> > 
> >      public String getMessage() {
> >        // ... The string (or "enum" if using the "cal10n" library)
> >        // should appear at this level.
> >      }
> >   }
> > 
> > Admittedly, this means creating a lot of exception classes; but the
> > advantage is that they will allow more control.
> 
> Perhaps some intermediate solution with more exception classes than we
> have but not one class for each message.

I didn't do an exhaustive search but it seems that there are a lot of
redundant message strings:

 "must have n >= 0 for binomial coefficient (n,k), got n = {0}"
 "must have n >= 0 for n!, got n = {0}"
 "brightness exponent should be positive or null, but got {0}"
 "number of microsphere elements must be positive, but got {0}"
 "polynomial degree must be positive: degree={0}"
 "upper bound must be positive ({0})"
 "length must be positive ({0})"
 "permutation k ({0}) must be positive"
 "invalid row dimension: {0} (must be positive)"
 "invalid column dimension: {0} (must be positive)"
 "initial capacity ({0}) is not positive"
 "index ({0}) is not positive"
 "window size must be positive ({0})"
 "element {0} is not positive: {1}"
 "mean must be positive ({0})"
 "degrees of freedom must be positive ({0})"
 "alpha must be positive ({0})"
 "beta must be positive ({0})"
 "number of successes must be non-negative ({0})"
 "standard deviation must be positive ({0})"
 "the Poisson mean must be positive ({0})"
 "invalid number of elements {0} (must be positive)"
 "invalid exponent {0} (must be positive)"
 "number of sample is not positive: {0}"

I think that all of these could be reduced to one or two exceptions.
Conceptually, the error is the same ("value should not be negative").
The message supposedly gives more information than that, but actually the
additional info is redundant with the line number that is part of the stack
trace: from it, it's straightforward to figure out which input is wrong; we
don't need the message to specify that it is "alpha" or "beta" or "mean" or
"degree" etc.

> At least, I agree the messages should be defined only once.
> 
> Are there good localization framework with no runtime dependency
> available somewhere ?

I didn't find one. [Same question as above: How is such a thing supposed to
work?]

Concerning localization itself, I think that it's not the business of a
low-level library.
IMHO, CM should only be using exception objects. The Javadoc of those
exception classes and the "@throws" clauses are the places where the users
(i.e. *application* developers) can find the meaning and circumstance of the
problem.
Now, if, for political reasons ;-), you want to help the users by providing
a localization framework, why couldn't we consider it as an "add-on"
higher-level *optional* feature requiring an external dependency?


Best,
Gilles

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


Re: [Math] Localization and Error Handling

Posted by Phil Steitz <ph...@gmail.com>.
Luc Maisonobe wrote:
> Gilles Sadowski a écrit :
>> Hello.
>>
>> I'd like to suggest that there could be a nicer way to handle localization
>> of error messages.  Please have a look at
>>    http://cal10n.qos.ch/
> 
> This looks promising, and I also considered developing a maven plugin
> with some asm magic to help make sure all messages are translated
> properly. However, I wanted to have a tool that would be only use at
> build time.
> 
>> Of course, the first point that will be raised is that it creates an
>> external dependency. Is this a "no-no" or, given some benefits, could it be
>> acceptable?
> 
> The runtime dependency is a no-no (at least from me). Is it possible to
> use only the build part and not the runtime part ?
> 
+1 - if possible to use only at build time, OK, but...

>> Basically, I think that dealing with strings inside the math library code is
>> ugly and error-prone. E.g.
>>
>>   throw MathRuntimeException.createIllegalArgumentException("{0} out of [{1}, {2}] range",
>>                                                             x, xval[0], xval[xval.length - 1]);
>>
>> A simple spelling mistake will defeat the purpose, as the localized version
>> will not be found.

Do you actually ever type existing message strings?  I always just
cut and paste them; unless I need to create a new one.  I agree that
it is a little bothersome, but the setup is at least straightforward
and not hard for new developers to learn.

> 
> You are right.
> 
>> The above library takes care of this problem.
>>
>> Even so, I think that *messages* should not appear at this level. It is much
>> simpler to use a set of specific exceptions. I.e. instead of the above
>> statement, one would use:
>>
>>   throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);
>>
>> where the exception is defined as
>>
>>   public OutOfRangeException extends IllegalArgumentException {
>>      private double val, min, max;
>>
>>      public OutOfRangeException(val, min, max) {
>>        this.val = val;
>>        this.min = min;
>>        this.max = max;
>>      }
>>
>>      public String getMessage() {
>>        // ... The string (or "enum" if using the "cal10n" library)
>>        // should appear at this level.
>>      }
>>   }
>>
>> Admittedly, this means creating a lot of exception classes; but the
>> advantage is that they will allow more control.
> 
> Perhaps some intermediate solution with more exception classes than we
> have but not one class for each message.

+1 - please lets not go down the path of
MoreStuffIWantToTellYouButCantUseAMessageException

What should be built into the hierarchy is what users might want to
catch and handle differentially.  What should go in messages is
additional information that might be useful to human beings
analyzing logs or stack traces.  Cleanly defined parameterized
messages can also make the intent of surrounding code clearer when
reviewing it and working with stack traces.

> 
> At least, I agree the messages should be defined only once.

Here we all agree.

Phil
> 
> Are there good localization framework with no runtime dependency
> available somewhere ?
> 
> Luc
> 
>>
>> Best,
>> Gilles
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>> For additional commands, e-mail: dev-help@commons.apache.org
>>
>>
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
> 


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


Re: [Math] Localization and Error Handling

Posted by Luc Maisonobe <Lu...@free.fr>.
Gilles Sadowski a écrit :
> Hello.
> 
> I'd like to suggest that there could be a nicer way to handle localization
> of error messages.  Please have a look at
>    http://cal10n.qos.ch/

This looks promising, and I also considered developing a maven plugin
with some asm magic to help make sure all messages are translated
properly. However, I wanted to have a tool that would be only use at
build time.

> 
> Of course, the first point that will be raised is that it creates an
> external dependency. Is this a "no-no" or, given some benefits, could it be
> acceptable?

The runtime dependency is a no-no (at least from me). Is it possible to
use only the build part and not the runtime part ?

> 
> Basically, I think that dealing with strings inside the math library code is
> ugly and error-prone. E.g.
> 
>   throw MathRuntimeException.createIllegalArgumentException("{0} out of [{1}, {2}] range",
>                                                             x, xval[0], xval[xval.length - 1]);
> 
> A simple spelling mistake will defeat the purpose, as the localized version
> will not be found.

You are right.

> The above library takes care of this problem.
> 
> Even so, I think that *messages* should not appear at this level. It is much
> simpler to use a set of specific exceptions. I.e. instead of the above
> statement, one would use:
> 
>   throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);
> 
> where the exception is defined as
> 
>   public OutOfRangeException extends IllegalArgumentException {
>      private double val, min, max;
> 
>      public OutOfRangeException(val, min, max) {
>        this.val = val;
>        this.min = min;
>        this.max = max;
>      }
> 
>      public String getMessage() {
>        // ... The string (or "enum" if using the "cal10n" library)
>        // should appear at this level.
>      }
>   }
> 
> Admittedly, this means creating a lot of exception classes; but the
> advantage is that they will allow more control.

Perhaps some intermediate solution with more exception classes than we
have but not one class for each message.

At least, I agree the messages should be defined only once.

Are there good localization framework with no runtime dependency
available somewhere ?

Luc

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


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


Re: [Math] Localization and Error Handling

Posted by sebb <se...@gmail.com>.
On 24/03/2010, Gilles Sadowski <gi...@harfang.homelinux.org> wrote:
> Hello.
>
>  I'd like to suggest that there could be a nicer way to handle localization
>  of error messages.  Please have a look at
>    http://cal10n.qos.ch/
>
>  Of course, the first point that will be raised is that it creates an
>  external dependency. Is this a "no-no" or, given some benefits, could it be
>  acceptable?
>
>  Basically, I think that dealing with strings inside the math library code is
>  ugly and error-prone. E.g.
>
>   throw MathRuntimeException.createIllegalArgumentException("{0} out of [{1}, {2}] range",
>                                                             x, xval[0], xval[xval.length - 1]);
>
>  A simple spelling mistake will defeat the purpose, as the localized version
>  will not be found.

+1

>  The above library takes care of this problem.

As would ordinary property files.

>  Even so, I think that *messages* should not appear at this level. It is much
>  simpler to use a set of specific exceptions. I.e. instead of the above
>  statement, one would use:
>
>   throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);
>
>  where the exception is defined as
>
>   public OutOfRangeException extends IllegalArgumentException {
>      private double val, min, max;
>
>      public OutOfRangeException(val, min, max) {
>        this.val = val;
>        this.min = min;
>        this.max = max;
>      }
>
>      public String getMessage() {
>        // ... The string (or "enum" if using the "cal10n" library)
>        // should appear at this level.
>      }
>   }
>
>  Admittedly, this means creating a lot of exception classes; but the
>  advantage is that they will allow more control.
>
>  Best,
>  Gilles
>
>  ---------------------------------------------------------------------
>  To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>  For additional commands, e-mail: dev-help@commons.apache.org
>
>

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