# Problem Derivation

The car examples we have discussed up until now have assumed that everything in the methods went well. The car class defined attributes such as the amount of oil left in the engine and the amount of gas left in the tank, but the code did not make use of them. How could you handle error conditions with the Java tools currently available to you?

Consider the car's accelerate method, which currently returns void. It could, however, be modified to return a true value if it succeeds, and false if it fails. Then, the code to handle it would look something like this:

` Porsche porsche = new Porsche();  porsche.start();  for( int n=0; n<10; n++ ) {     if( porsche.accelerate() ) {        System.out.println( "Accelerate successful!" );     }     else {        System.out.println( "Accelerate failed!" );     }  } `

It is good to know whether the method succeeded or failed, but now how do we fix the problem? Or more importantly what is the problem? Is the car out of gas? Is it out of oil?

The accelerate method can be further refined to return an integer value. See the values in Table 9.1.

##### Table 9.1. accelerate Method Return Values

Value

Description

0

accelerate successful

1

Out of oil

2

Out of gas

3

Car is not started

4

General failure

Typically, negative values have been associated with error codes, whereas zero or a positive value denotes a success. For example, the accelerate method could be defined to return the current speed of the car this would not interfere with diagnosing the error condition. The following code checks for an error condition:

` Porsche porsche = new Porsche();  porsche.start();  for( int n=0; n<10; n++ ) {     int returnCode = porsche.accelerate();     if( returnCode >= 0 ) {        System.out.println( "Accelerate successful!" );     }     else {        System.out.println( "Accelerate failed!" );     }  } `

Recall, though, that the point of having these error conditions is to respond to and handle errors. Thus, the code might be better written as follows:

` Porsche porsche = new Porsche();  porsche.start();  for( int n=0; n<10; n++ ) {     int returnCode = porsche.accelerate();     switch( returnCode ) {     case 0:        System.out.println( "Accelerate successful!" );        break;     case  1:        System.out.println( "Out of oil, time to change!" );        break;     case  2:        System.out.println( "Out of gas, time to fuel up!" );        break;     case  3:        System.out.println(             "Car is not started, insert the key and turn!" );        break;     case  4:        System.out.println(              "Whoops! General failure, time to pay the big bucks!" );        break;     default:        System.out.println( "Unknown error condition" );     }  } `

That was much more informative and easier to debug, but a lot of code! Now consider a method that you have to call the accelerate method multiple times outside of a loop:

` public void race( Porsche p ) {     p.start();     p.accelerate();     p.accelerate();     p.decelerate();     p.turnRight();     p.accelerate();     p.accelerate();     p.decelerate();     p.turnLeft();     // Straight away!     p.engageTurbos();     p.accelerate();     p.engageNOS();     // Cross the finish line     while( p.getCurrentSpeed() > 0 ) {        p.decelerate();     }     p.stop();  } `

The previous code block represents a short race course, but it illustrates that you would have to repeatedly call the accelerate and decelerate methods. To properly handle all the errors that would occur during each call to accelerate, you would have to add the 20 lines of code that handled the error to each accelerate invocation. That would add 100 lines of code to this method simply to identify errors we haven't added error handling to decelerate, engageTurbos, and engageNOS yet! Suddenly a seemingly harmless little 20-line method could grow to a convoluted 200-line method, where 80% of the code is handling error conditions. There must be a better way!

Consider writing your method as follows. Assume that everything will work correctly, but if some exceptional circumstance occurs (an error), add code to handle it at the end of your method. This enables you to write the error-handling code in one place and, by writing the method expecting it to work, it will be clear and understandable.

In Java you define a set of code that you would want to try to execute. In the code, one or more methods could raise an exceptional circumstance and throw an exception. At the end of the code block you can catch that exception and handle it if an error occurred, otherwise continue as usual.

Thus, the code could be rewritten as follows:

` public void race( Porsche p ) {     try {        p.start();        p.accelerate();        p.accelerate();        p.decelerate();        p.turnRight();        p.accelerate();        p.accelerate();        p.decelerate();        p.turnLeft();        // Straight away!        p.engageTurbos();        p.accelerate();        p.engageNOS();        // Cross the finish line        while( p.getCurrentSpeed() > 0 ) {           p.decelerate();        }        p.stop();     }     catch( CarException e ) {        int returnCode = e.getReturnCode();        switch( returnCode ) {        case 0:           System.out.println( "Car race was successful!" );           break;        case  1:           System.out.println( "Out of oil, time to change!" );           break;        case  2:           System.out.println( "Out of gas, time to fuel up!" );           break;        case  3:           System.out.println(              "Car is not started, insert the key and turn!" );           break;        case  4:           System.out.println(              "Whoops! General failure, time to pay the big bucks!" );           break;        default:           System.out.println( "Unknown error condition" );        }     }  } `

Java calls this process exception handling.

 Top

Java 2 Primer Plus
ISBN: 0672324156
EAN: 2147483647
Year: 2001
Pages: 332

Similar book on Amazon