commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ole Ersoy <ole.er...@gmail.com>
Subject Re: [math] Exception Design
Date Wed, 23 Dec 2015 16:53:08 GMT
[...]

>>>
>>> Looks good.  Where is the code? ;-)
>>
>> So CM clients would:
>> catch(MathException e) {
>>     String exceptionTemplate = ResourceBundle.getBundle("cm.exception.templates",
new Locale("en", "US")).getString(e.getType());
>>     String i18Nmessage = buildMessage(exceptionTemplate, e.getContext());
>>     ...
>> }
>>
>> I can prototype that out more.  Just trying to get a feel for how
>> viable the concept is first.
>
> I'm not sure I understand correctly.
> Does that mean that
> 1. Uncaught exceptions will lead to a message in English?
Sort of - Right now the exception message is just the Enum 'type/code'.  For example: MIA__INTEGER_OVERFLOW.
 Calling toString() on the exception will produce a more detailed message with the context
parameters as well.

>
> 2. Every "catch" must repeat the same calls (although the arguments are likely
>    to be the same for all clauses (and for all applications)?

Well - Suppose the use case is using CM to just write quick simulations in the main block.
 We don't want to bother the analyst with what exceptions mean or throw catch concepts, etc.
 So primarily the user is concerned with the //CM code block below:

public static void main(String args[]) {
    //The CM code...
}

So instead of providing the above block as a starting point this block would be provided:

public static void main(String args[]) {
    try {
    //The CM code...

} catch(MathException) {
    u.rethrowLocalized(e)
}


>
> Comparing this with the current behaviour (where the translated message String
> is created when "e.getLocalizedMessage()" is called) is likely to make people
> unhappy.
Hopefully they would be OK with something like the above.  If a single MathException is adopted
it should be very easy to create a Cheatsheet with all the exception codes that can occur
in a given scenario along with what it means in a language, in addition to handling it with
the type of utility describe above.  I would think the goal would be to get the user to understand
the exceptions as they are thrown in Java vernacular though...Even if I see an exception message
in Norwegian I still need to read the code and Javadoc to figure out what it means.

I'm still looking into the possibility of a custom designed annotation to do the above utility,
but it may require the use of AspectJ or Apache Weaver.

>
>
>> [...]
>
> I'd be interested in settling the matter of whether we must use a single
> hierarchy because of technical limitations, or if it is a good solution
> on its own, i.e. extending standard exceptions is not a better practice
> after all.
I think we understand this, but anything other than a single exception is going to introduce
a non trivial amount of additional effort both for users, maintainers, and documenters.  Consider
the ripple effect this has on other libraries using CM.

>
>>>
>>> We could provide a utility:
>>>
>>> public boolean isMathException(RuntimeException e) {
>>>   if (e instanceof MathException) {
>>>     return true;
>>>   }
>>>   final Throwable t = e.getCause();
>>>   if (t != null) {
>>>     if (e instanceof MathException) {
>>>       return true;
>>>     }
>>>   }
>>>   return false;
>>> }
>>
>> Or just not wrap.
>
> Of course, but choosing one or the other is not a technical problem;
> it's design decision.  Do we have arguments (or reference to them)?

As Luke pointed out, we want to be able to catch the exception and know that it came from
CM with minimal effort.  If another layer is using CM, then that layer should catch the CM
exception and rethrow it using a System exception providing a global facade the same way Spring
does.

>
>>>>>
>>>>> public class ExceptionFactory {
>>>>>
>>>>>   public static void throwIllegalArgumentException(MathException e) {
>>>>>     throw new IllegalArgumentException(e);
>>>>>   }
>>>>>
>>>>>   public static void throwNullPointerException(MathException e) {
>>>>>     throw new NullPointerException(e);
>>>>>   }
>>>>>
>>>>>   // And so on...
>>>>> }
>>>>>
>>>>> So, CM code would be
>>>>>
>>>>> public class Algo {
>>>>>
>>>>>   public void evaluate(double value) {
>>>>>     // Check precondition.
>>>>>     final double min = computeMin();
>>>>>     if (value < min) {
>>>>>       final MathException e = new MathException(NUMBER_TOO_SMALL).put(CONSTRAINT,
min).put(VALUE, value);
>>>>>       ExceptionFactory.throwIllegalArgumentException(e);
>>>>>     }
>>>>>
>>>>>     // Precondition OK.
>>>>>   }
>>>>> }
>>>> Another thing that I hinted to is that the the factory builds in the
>>>> precondition check in the throw method.  So that the line:
>>>>
>>>>     if (value < min) {
>>>>
>>>> can be nixed.
>>>
>>> It seems nice to ensure that the exception raised is consistent with the
>>> checked condition.
>> That's the idea.
>
> OK, but do you foresee that all precondition checks will be handle by
> factory methods.
It would be nice.  Like you said, it's also good if an exception is always produced by a globally
unique condition.
>
> It would not be so nice to have explicit checks sprinkled here and there.
Indeed.  The single exception design should allow for a factory method for all the Enum types.
 If it's done right the factory should also make writing the utility for localizing messages
easier.

[...]

Cheers,
Ole


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


Mime
View raw message