One tactic for managing exceptions is to catch them as close to the source (the point at which they are generated) as possible. Once you catch an exception, you might be able to provide code that deals with it. Providing code that converts a problem into a legitimate action is a way of encapsulating an exception. You can also head off the exception. In the Scorer class, you can provide an additional method, isValid, that allows the client to test the validity of the input string. You put the burden on the client to guard against calling score with invalid input. // ScorerTest.java public void testIsValid() { Scorer scorer = new Scorer(); assertTrue(scorer.isValid("75")); assertFalse(scorer.isValid("bd")); } // Scorer.java public boolean isValid(String input) { try { Integer.parseInt(input); return true; } catch (NumberFormatException e) { return false; } } A client first calls isValid. If isValid returns true, the client could safely call the score method. If isValid returns false, the client could apprise the user of the invalid input. One benefit of using this construct is that the client would not have to code a try-catch block. You want to use exceptions as little as possible to control the flow of your code. By catching an exception as close to the source as possible, you eliminate the need for clients to use TRy-catch blocks to manage their control flow. Another possibility would be for the score method to have a try-catch block. When it caught a NumberFormatException, it would return -1 or some other special int value that the client could recognize. |