Software Construction
Debugging and Exceptions
Jürg Luthiger
University of Applied Sciences Northwestern Switzerland Institute for Mobile and Distributed Systems
Learning Target
You
know the proper usage of exceptions
know how to use the assert keywordInstitut für Mobile und Verteilte Systeme J. Luthiger 3
Agenda
Introduction into Exceptions
Introduction into Assert
Using the Eclipse DebuggerThe nature of Exceptions
Exceptions due to programming errors
z e.g. NullPointerException, IllegalArgumentException
due to client code errors
z wrong usage of the API
due to resource failures
z out of memory
Institut für Mobile und Verteilte Systeme J. Luthiger 5
Pitfalls
If not used correctly, exceptions can slow downthe program, as it takes CPU power to create, throw and catch exceptions
If overused, exceptions make the code difficultto read and are frustrating for programmers to use the API
The Problem using Exceptions
public void consumeAndForgetAllExceptions() { try {
… some code that throws exceptions } catch (Exception e) {
ex.printStackTrace(); }
}
public void someMethod() throws Exception { }
How can a blank method throw an exception?
Execution of the program continues after the catch block, as if nothing had happened
Institut für Mobile und Verteilte Systeme J. Luthiger 7
Compiler Error vs. Runtime Errors
Compiler errors are generated by the compiler.They are developer friendly!
Runtime errors are generated by the runtimesystem-> Program crash if exceptions are not handled correctly , not at all user friendly
The handling of the exceptions isdeveloper-intensive
Exception Types in Java
java.lang.RuntimeException=> UNCHECKED no compiler checks
java.lang.Exception=> CHECKED
Compiler checks, if there exist an Exception Handling
Institut für Mobile und Verteilte Systeme J. Luthiger 9
Sample Exception Hierarchy
Exception
RuntimeException SQLException
NullPointerException
Misuse of Checked Exceptions
Checked Exceptions are a forced contract onthe invoking layer to catch or to throw it.
Unwanted burden of the client code is unable todeal with the exception effectively using empty catch block
just throwing it and placing burden on the invoker
Breaking encapsulationpublic List getAllAccounts() throws
Institut für Mobile und Verteilte Systeme J. Luthiger 11
Best Practices: 1
When deciding on checked exceptions vs. unchecked exceptions, ask yourself, "What action can the client code take when the exception occurs?"
If the client can take alternate action to recover from the exception, make it a checked exception. If the client cannot do anything useful, then make the exception unchecked.
Best Practices: 2
Preserve encapsulation
For example, do not propagate SQLException
from the database to the application layer. Convert them into unchecked exceptions:
try {
...some code that throws SQLException } catch (SQLException e) {
throw new RuntimeException(ex); }
Institut für Mobile und Verteilte Systeme J. Luthiger 13
Best Practices: 3
Try not to create new custom exceptions if they do not have useful information for client code.
public class DuplicateUsernameException extends Exception {}
public class DuplicateUsernameException extends Exception { public DuplicateUsernameException (String username){....} public String requestedUsername(){...}
public String[] availableNames(){...} }
should be better
throw new RuntimeException("Username already taken");
or even simpler
Best Practices: 4
Document Exceptions
Use Javadoc @throws tag
Write Unit test@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() { ArrayList blankList = new ArrayList(); blankList.get(10);
Institut für Mobile und Verteilte Systeme J. Luthiger 15
Using Exceptions: 1
Always clean up after yourself
Resources like database or networkconnections should always be closed
public void dataAccessCode(){ Connection conn = null; try {
conn = getConnection();
..some code that throws SQLException } catch(SQLException ex){ ex.printStacktrace(); } finally{ DBUtil.closeConnection(conn); } }
Using Exceptions: 2
Never use exceptions for flow control
public void useExceptionsForFlowControl() { try {
while (true) {
increaseCount(); }
} catch (MaximumCountReachedException ex) { }
//Continue execution }
public void increaseCount()
throws MaximumCountReachedException { if (count >= 5000)
Institut für Mobile und Verteilte Systeme J. Luthiger 17
Using Exceptions: 3
Do not suppress or ignore exceptions
When a method from an API throws a checkedexception, it is trying to tell you that you should take some counter action.
If the checked exception does not make senseto you, do not hesitate to convert it into an unchecked exception and throw it again.
Using Exceptions: 4
Do not catch top-level exceptions
Unchecked exceptions inherit from the
RuntimeException class, which in turn inherits from Exception.
By catching the Exception class, you are also catching RuntimeException as in the following code:
try{ ..
} catch(Exception ex) { }
Institut für Mobile und Verteilte Systeme J. Luthiger 19
Using Exceptions: 5
Log exceptions just once
Logging the same exception stack trace morethan once can confuse the programmer
examining the stack trace about the original source of exception. So just log it once.
Summary Guidelines
1.
The caller MUST handle the exception =>CHECKED
2.
A Minority will handle the exception =>UNCHECKED
3.
Is a runtime error irresolvable =>UNCHECKED
Institut für Mobile und Verteilte Systeme J. Luthiger 21
Exception chaining
Exception chaining means that the constructorof an exception object takes a ‘nested’ or ‘cause’ exception as an argument.
The newly created higher level exception objectwill then maintain a reference to the underlying root cause exception.
...
} catch (FileNotFoundException e) {
throw new MyException("Additional Comments", e);
}
How to write Exceptions...
public class MyException extends Exception { public MyException(String message) {
super(message); }
public MyException(String message, Throwable t) { super(message, t);
} }
IMPORTANT: Decide when to use CHECKED or UNCHECKED Exception!
Institut für Mobile und Verteilte Systeme J. Luthiger 23
Still to remember...
Checked Exception are MUCH, MUCH betterthan every error code, as seen in languages like C and C++ (!)
Asserts
You can use assertions to detect errors thatmay otherwise go unnoticed.
Assertions contain Boolean expressions thatdefine the correct state of your program at specific points in the program source code.
The Java SE platform 1.4, has introduced aInstitut für Mobile und Verteilte Systeme J. Luthiger 25
Design by contract
Precondition: A condition that the caller of an operation agrees to satisfy
The user invoking the computation has the responsibility of
providing the correct input, which is a precondition. Postcondition: A condition that the method itself
promises to achieve
If the computation is successful, we say that the computation
has satisfied the postcondition.
Invariant: A condition that a class must satisfy anytime a client could invoke an object's method, or a condition that should always be true for a specified segment or at a specified point of a program
Using Assertions
Use the assert statement to insert assertions atparticular points in the code.
assert booleanExpression;
Institut für Mobile und Verteilte Systeme J. Luthiger 27
Debugger
see"Using the Eclipse Debugger"
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to
debug it."