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 keyword can use the Eclipse Debugger Institut für Mobile und Verteilte Systeme J. Luthiger 2
Agenda Introduction into Exceptions Introduction into Assert Using the Eclipse Debugger Institut für Mobile und Verteilte Systeme J. Luthiger 3 The nature of Exceptions Exceptions due to programming errors e.g. NullPointerException, IllegalArgumentException due to client code errors wrong usage of the API due to resource failures out of memory network connection failure Institut für Mobile und Verteilte Systeme J. Luthiger 4
Pitfalls If not used correctly, exceptions can slow down the program, as it takes CPU power to create, throw and catch exceptions If overused, exceptions make the code difficult to read and are frustrating for programmers to use the API Institut für Mobile und Verteilte Systeme J. Luthiger 5 The Problem using Exceptions public void consumeandforgetallexceptions() { try { some code that throws exceptions catch (Exception e) { ex.printstacktrace(); Execution of the program continues after the catch block, as if nothing had happened public void somemethod() throws Exception { How can a blank method throw an exception? Institut für Mobile und Verteilte Systeme J. Luthiger 6
Compiler Error vs. Runtime Errors Compiler errors are generated by the compiler. They are developer friendly! Runtime errors are generated by the runtime system-> Program crash if exceptions are not handled correctly, not at all user friendly The handling of the exceptions is developerintensive Institut für Mobile und Verteilte Systeme J. Luthiger 7 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 8
Sample Exception Hierarchy Exception RuntimeException SQLException NullPointerException Institut für Mobile und Verteilte Systeme J. Luthiger 9 Misuse of Checked Exceptions Checked Exceptions are a forced contract on the invoking layer to catch or to throw it. Unwanted burden of the client code is unable to deal with the exception effectively using empty catch block just throwing it and placing burden on the invoker Breaking encapsulation public List getallaccounts() throws FileNotFoundException, SQLException { Institut für Mobile und Verteilte Systeme J. Luthiger 10
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. Institut für Mobile und Verteilte Systeme J. Luthiger 11 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 12
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 { should be better public class DuplicateUsernameException extends Exception { public DuplicateUsernameException (String username){... public String requestedusername(){... public String[] availablenames(){... or even simpler throw new RuntimeException("Username already taken"); Institut für Mobile und Verteilte Systeme J. Luthiger 13 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 14
Using Exceptions: 1 Always clean up after yourself Resources like database or network connections 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); Institut für Mobile und Verteilte Systeme J. Luthiger 15 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) throw new MaximumCountReachedException(); Institut für Mobile und Verteilte Systeme J. Luthiger 16
Using Exceptions: 3 Do not suppress or ignore exceptions When a method from an API throws a checked exception, it is trying to tell you that you should take some counter action. If the checked exception does not make sense to you, do not hesitate to convert it into an unchecked exception and throw it again. Institut für Mobile und Verteilte Systeme J. Luthiger 17 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 18
Using Exceptions: 5 Log exceptions just once Logging the same exception stack trace more than once can confuse the programmer examining the stack trace about the original source of exception. So just log it once. Institut für Mobile und Verteilte Systeme J. Luthiger 19 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 4. Still unclear? => UNCHECKED Institut für Mobile und Verteilte Systeme J. Luthiger 20
Exception chaining Exception chaining means that the constructor of an exception object takes a nested or cause exception as an argument. The newly created higher level exception object will then maintain a reference to the underlying root cause exception.... catch (FileNotFoundException e) { throw new MyException("Additional Comments", e); Institut für Mobile und Verteilte Systeme J. Luthiger 21 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 22
Still to remember... Checked Exception are MUCH, MUCH better than every error code, as seen in languages like C and C++ (!) Institut für Mobile und Verteilte Systeme J. Luthiger 23 Asserts You can use assertions to detect errors that may otherwise go unnoticed. Assertions contain Boolean expressions that define the correct state of your program at specific points in the program source code. The Java SE platform 1.4, has introduced a built-in assertion facility. Institut für Mobile und Verteilte Systeme J. Luthiger 24
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 Institut für Mobile und Verteilte Systeme J. Luthiger 25 Using Assertions Use the assert statement to insert assertions at particular points in the code. assert booleanexpression; assert booleanexpression : errormessage; Institut für Mobile und Verteilte Systeme J. Luthiger 26
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." Brian W. Kernighan Institut für Mobile und Verteilte Systeme J. Luthiger 27