commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gilles <gil...@harfang.homelinux.org>
Subject Re: [math] Exception Design
Date Tue, 22 Dec 2015 00:44:50 GMT
On Mon, 21 Dec 2015 12:14:16 -0600, Ole Ersoy wrote:
> Hi,
>
> I was considering jumping into the JDKRandomGenerator exception
> discussion, but I did not want to hijack it.
>
> Not sure if any of you have had a chance to looks at this:
> https://github.com/firefly-math/firefly-math-exceptions/
> 
> https://github.com/firefly-math/firefly-math-exceptions/blob/master/src/main/java/com/fireflysemantics/math/exception/MathException.java

I had a rapid look; unfortunately not in sufficient details to
grasp the major departures from the existing framework.
Could you display one or two examples comparing CM and firefly?

It looks neat.
But I did not see how localization is handled.

> I think it satisfies everyone's requirements with:
> - A single MathException (No hierarchy)

That would not satisfy everyone. :-!

> - The ExceptionTypes Enum contains all the exception types
> - The ExceptionTypes Enum 'key' maps to the corresponding message 1 
> to 1
> - The ExceptionFactory (Utility) throws exceptions, if necessary,
> that have always have a single unique root cause, such as NPEs

I was wondering whether the "factory" idea could indeed satisfy
everyone.

Rather than throwing the non-standard "MathException", the factory 
would
generate one of the standard exceptions, constructed with the internal
"MathException" as its cause:

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.
   }
}


Then, in an application's code:

public void appMethod() {
   // ...

   // Use CM.
   try {
     Algo a = new Algo();
     a.evaluate(2);
   } catch (IllegalArgumentException iae) {
     final Throwable cause = iae.getCause();
     if (cause instanceof MathException) {
       final MathException e = (MathException) cause;

       // Rethrow an application-specific exception that will make more 
sense
       // to my customers.
       throw new InvalidDataInputException(e.get(CONSTRAINT), 
e.get(VALUE));
     }
   }
}

This is all untested.
Did I miss something?

Gilles


> - The context captures the exception parameters keyed by an the
> 'ExceptionKeys' enum.  Each module can introduce more keys as
> necessary.
> - The toString() method can be used as the initial exception message
>
> The way developers should deal with this exception is:
> 1) Catch
> 2) Get the type (Enum)
> 3) Get the  parameters (Context)
> 4) Get the method that threw it
> 5) Get the class threw it
> 6) Rethrow the above in an application specific exception, log it, or
> display it.  Construct a localized message using the enum type to 
> look
> up the exception template if needed.
>
> WDYT?
>
> Cheers,
> - Ole
>
> P.S. Here's the entire test demo (Pasted below for convenience):
> 
> https://github.com/firefly-math/firefly-math-exceptions/blob/master/src/test/java/com/fireflysemantics/math/exceptions/MathExceptionTest.java
>
> /**
>   *  Licensed under the Apache License, Version 2.0 (the "License");
>   *  you may not use this file except in compliance with the License.
>   *  You may obtain a copy of the License at
>   *
>   *  http://www.apache.org/licenses/LICENSE-2.0
>   *
>   *  Unless required by applicable law or agreed to in writing, 
> software
>   *  distributed under the License is distributed on an "AS IS" 
> BASIS,
>   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> implied.
>   *  See the License for the specific language governing permissions 
> and
>   *  limitations under the License.
>   */
>
> package com.fireflysemantics.math.exceptions;
>
> import static 
> com.fireflysemantics.math.exception.ExceptionKeys.CONSTRAINT;
> import static 
> com.fireflysemantics.math.exception.ExceptionKeys.VALUE;
> import static
> com.fireflysemantics.math.exception.ExceptionTypes.NUMBER_TOO_SMALL;
> import static org.junit.Assert.assertEquals;
> import static org.junit.Assert.assertTrue;
>
> import org.junit.Test;
>
> import com.fireflysemantics.math.exception.ExceptionFactory;
> import com.fireflysemantics.math.exception.MathException;
>
> public class MathExceptionTest {
>
>     @Test(expected = MathException.class)
>     public void verifyThrows() {
>         throw new MathException(NUMBER_TOO_SMALL);
>     }
>
>     @Test
>     public void verifyCode() {
>         try {
>             throw new MathException(NUMBER_TOO_SMALL);
>         } catch (MathException e) {
>             assertEquals(e.getType(), NUMBER_TOO_SMALL);
>         }
>     }
>
>     @Test
>     public void verifyContext() {
>         try {
>             throw new MathException(NUMBER_TOO_SMALL).put(CONSTRAINT,
> 2).put(VALUE, 1);
>         } catch (MathException e) {
>             assertEquals(e.get(CONSTRAINT), 2);
>             assertEquals(e.get(VALUE), 1);
>         }
>     }
>
>     @Test
>     public void verifyToString() {
>         try {
>             throw new MathException(NUMBER_TOO_SMALL).put(CONSTRAINT,
> 2).put(VALUE, 1);
>         } catch (MathException e) {
> assertTrue(e.toString().contains(NUMBER_TOO_SMALL.toString()));
>             assertTrue(e.toString().contains("1"));
>             assertTrue(e.toString().contains("2"));
>             assertTrue(e.toString().contains(CONSTRAINT));
>             assertTrue(e.toString().contains(VALUE));
>         }
>     }
>
>     @Test
>     public void verifyFactory() {
>         try {
>             ExceptionFactory.throwNumberToSmallException(1, 2, 
> "foo");
>         } catch (MathException e) {
>             assertTrue(e.getType() == NUMBER_TOO_SMALL);
>             assertEquals(e.get(CONSTRAINT), new Integer(2));
>             assertEquals(e.get(VALUE), new Integer(1));
>             assertEquals(e.get("foo"), new Integer(1));
>         }
>     }
> }


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


Mime
View raw message