views:

189

answers:

8

In my Java code, I have a function called getAngle() which sometimes throws a NoAngleException. Is the following code the best way of writing a function that keeps calling getAngle() until no exception is thrown?

public int getAngleBlocking()
{
    while(true)
    {
     int angle;
     try
     {
      angle = getAngle();
      return angle;
     }
     catch(NoAngleException e)
     {

     }
    }
}

Or would it be a better idea to rewrite getAngle() to return NaN upon error?

+3  A: 

I think you should investigate why getAngle() is throwing an exception and then resolve the problem. If this is random, like input from a sensor, maybe you should wait some time until calling again. You could also make getAngle() blocking, that means getAngle() will wait until a good result is acquired.

Ignoring how you're solving your problem you should have some kind of timeout mechanism, so you don't end up in an endlessloop. This supposes that you don't want to have an possibly infinite loop, of course.

ziggystar
I agree - getAngleBlocking() simply masks any underlying problem, potentially causing its own problems by potentially causing an infinite loop or performance bottleneck.
Adamski
There should of course be timeouts for blocking calls. I've deleted that remark in order to keep it simple.
ziggystar
The whole point of getAngleBlocking is to provide a blocking version of getAngle. If I decide to make getAngle blocking, that defeats the point of the exercise.
Eric
+2  A: 

You want to call a method as long as it throws an exception?

This is not programming. You should use the debugger and take a look at the real issue.

And you should never catch an exception without any message or logging!

Markus Lausberg
I intentionally make it throw the exception. I am expecting the exception. `getAngle()` tries to turn a direction between 1 and 9 to an angle in degrees. However, the direction is sometimes 0, which doesn't correspond to a angle.
Eric
+1  A: 

I would not recommend to do it that way, because when getAngle() never returns a valid value (always throws an exception for some reason) you end up in an endless loop. You should at least define a break condition (e.g. timeout) for this case.

Sylar
Good point. I'll add a timeout.
Eric
A: 

Never use Exceptions to handle logic in your code.

as suggested first check why you sometimes get the execption

Peter
A: 

Unless you are using a class that is entirely outside of your control, you really want to reconsider throwing an exception to indicate no angle.

Sometimes, of course, this is not possible either because the class is not yours, or, it is not possible to make dual use of the returned type as both the result or error status.

For example, in your case, assuming all integer (negative and 0) degrees are possible angles, there is no way for you to return an int value that indicates error and is distinct from a valid angle value.

But lets assume your valid angles are in range -360 -> 360 (or equiv. in radians). Then, you really should consider something like:

// assuming this ..
public static final int NO_ANGLE_ERROR = Integer.MIN_VALUE; 

// do this
public int getAngleBlocking()
{
    int angle;
    do {
       angle = getAngle();
    }while(angle == NO_ANGLE_ERROR);
}
That was my original way of doing it. However, exceptions seemed a better way of doing it, as it prevented careless uses of `getAngle()` where the exceptional case was not checked.
Eric
+2  A: 

I'm surprised to read some of the answers to this thread because this scenario is precisely the reason checked exceptions exist. You could do something like:

private final static int MAX_RETRY_COUNT = 5;

//...

int retryCount = 0;
int angle = -1;

while(true)
{
    try
    {
     angle = getAngle();
     break;
    }
    catch(NoAngleException e)
    {
     if(retryCount > MAX_RETRY_COUNT)
     {
      throw new RuntimeException("Could not execute getAngle().", e);
     }

     // log error, warning, etc.

        retryCount++;
     continue;
    }
}

// now you have a valid angle

This is assuming that something outside of the process changed in the meantime. Typically, something like this would be done for reconnecting:

private final static int MAX_RETRY_COUNT = 5;

//...

int retryCount = 0;
Object connection = null;

while(true)
{
    try
    {
     connection = getConnection();
     break;
    }
    catch(ConnectionException e)
    {
     if(retryCount > MAX_RETRY_COUNT)
     {
      throw new RuntimeException("Could not execute getConnection().", e);
     }

     try
     {
      TimeUnit.SECONDS.sleep(15);
     }
     catch (InterruptedException ie)
     {
      Thread.currentThread().interrupt();
      // handle appropriately
     }

     // log error, warning, etc.

        retryCount++;
     continue;
    }
}

// now you have a valid connection
Droo
A: 

In the end I opted for returning a NaN value, as this prevents careless use of Integer.MIN_VALUE somewhere else.

public float getAngle(boolean blocking)
{
 while(true)
 {
  int dir = getDirection();
  if(dir == 0 && !blocking)
   return Float.NaN;
  else
   return (dir - 5) * 30;
 }
}
Eric
+1  A: 

Could you not have used recursion? i.e.;

public int getAngleBlocking()
{
        int angle;
        try
        {
                angle = getAngle();
                return angle;
        }
        catch(NoAngleException e)
        {
               return getAngleBlocking();
        }
    }
}
Amoeba
And yes, I realise this is probably hideously bad in the wrong circumstances. I am assuming the NoAngleException is some random exception caused by a sensor or something.
Amoeba