Presentation is loading. Please wait.

Presentation is loading. Please wait.

How to Design Error Steady Code Ivaylo Bratoev Telerik Corporation www.telerik.com.

Similar presentations


Presentation on theme: "How to Design Error Steady Code Ivaylo Bratoev Telerik Corporation www.telerik.com."— Presentation transcript:

1 How to Design Error Steady Code Ivaylo Bratoev Telerik Corporation www.telerik.com

2 Using Assertions and Exceptions Correctly

3  Similar to defensive driving – you are never sure what other drivers will do  Expect incorrect input and handle it correctly  Think not only about the usual execution flow, but consider also unusual situations 3

4  “Garbage in, garbage out.” – NO!  Garbage in - nothing out, error message out or no garbage allowed in  Check the values of all data from external sources (a user, a file, internet, etc.) 4

5  Check method preconditions – parameters, object state  Check method postconditions – what is guaranteed to the caller 5 string Substring(string str, int startIndex, int length) { REQUIRE(str != NULL); REQUIRE(str != NULL); REQUIRE(startIndex >= str.Length); REQUIRE(startIndex >= str.Length); REQUIRE(startIndex + count > str.Lenght); REQUIRE(startIndex + count > str.Lenght); string result = … string result = … ENSURE(result.Length == length); ENSURE(result.Length == length);} preconditions main logic postconditions.

6  A statement placed in code that must always be true at that place  Assertions are used during development, they are removed during production compilation  Assertions check for bugs in code 6 void GetAvarageStudentGrade() { Debug.Assert(studentGrades.Count > 0, “student grades are not initialized”); Debug.Assert(studentGrades.Count > 0, “student grades are not initialized”); return studentGrades.Avarage(); return studentGrades.Avarage();}

7  Use assertions for conditions that should never occur  Use assertions to document assumptions made in code  document preconditions and postconditions 7 private Student GetRegisteredStudent(int id) { Debug.Assert(id > 0); Debug.Assert(id > 0); Student student = registeredStudents[id]; Student student = registeredStudents[id]; Debug.Assert(student.IsRegistered); Debug.Assert(student.IsRegistered);}

8  Failed assertion indicates a fatal error in the program (usually unrecoverable)  Avoid putting executable code in assertions  Won’t be compiled in production. Better:  Assertions should fail loud 8 assert PerformAction() : “Could not perform action” bool actionedPerformed = PerformAction(); assert actionedPerformed : “Could not perform action”

9  How do you handle errors that you expect to occur?  Depends on the situation. Examples:  Return a neutral value  Return the same answer as the previous time  Log a warning message to a file  Return an error code  Display an error message  Shutdown  Throw an exception 9

10  How will you handle error while calculating single pixel color in a computer game?  How will you handle error while calculating single pixel color in a X-Ray software?  Correctness - never returning an inaccurate result.  Robustness - always trying to do something that will allow the software to keep running. 10

11  Choose your error handling strategy and follow it consistently  Strongly consider using exceptions 11

12  Exceptions are a specific means by which code can pass along errors or exceptional events to the code that called it  Methods throw exceptions: 12 public void ReadInput(string input) { if(input == null) if(input == null) { throw new ArgumentNullException(“input”); } throw new ArgumentNullException(“input”); } …}

13  Use try-catch statement to handle exceptions:  You can use multiple catch blocks to specify handlers for different exceptions.  Not handled exceptions propagate to the caller 13 void playNextTurn() { try { try { … readInput(input); … readInput(input); … } catch(ArgumentNullException e) { … } catch(ArgumentNullException e) { console.printLine(“Hello from catch!”); console.printLine(“Hello from catch!”); }} Exception thrown here Code here won’t be executed

14  Use finally block to execute code even if exception occurs (not supported in C++):  Perfect place to perform cleanup for any resources allocated in the try block. 14 void playNextTurn() { try { try { … readInput(input); … readInput(input); … } finally { … } finally { console.printLine(“Hello from finally!”); console.printLine(“Hello from finally!”); }} Exception thrown here Code here is always executed

15  Use exceptions to notify other parts of the program about errors that should not be ignored  Throw an exception only for conditions that are truly exceptional  Should I throw an exception when checking for user name and password?  Don’t use exceptions as control flow mechanisms 15

16  Throw exceptions at the right level of abstraction 16 class Employee { … public TaxId getTaxId() throws EOFException { public TaxId getTaxId() throws EOFException { … }} class Employee { … public TaxId getTaxId() throws EmployeeDataNotAvailable { public TaxId getTaxId() throws EmployeeDataNotAvailable { … }}

17  Use descriptive error messages  Incorrect example:  Example:  Avoid empty catch blocks 17 throw new Exception("Error!"); throw new ArgumentException("The speed should be a number " + "between " + MIN_SPEED + " and " + MAX_SPEED + "."); "between " + MIN_SPEED + " and " + MAX_SPEED + "."); try { … // lots of code // lots of code … } catch(Exception ex){ }

18  Always include the exception cause when throwing a new exception 18 try{ WithdrawMoney(account, amount); WithdrawMoney(account, amount);} catch (DatabaseException dbex) { throw new WithdrawException(String.Format( throw new WithdrawException(String.Format( "Can not withdraw the amount {0} from acoount {1}", "Can not withdraw the amount {0} from acoount {1}", amount, account), dbex); amount, account), dbex);} We include in the exceptions chain the original source of the problem.

19  Catch only exceptions that you are capable to process correctly  Do not catch all exceptions  Incorrect example:  What about OutOfMemoryException ? 19 try{ ReadSomeFile(); ReadSomeFile();}catch{ Console.WriteLine("File not found!"); Console.WriteLine("File not found!");}

20  Have an exception handling strategy for unexpected/unhandled exception:  Consider logging (log4net, log4j, log4cplus).  Display to the end users only messages that they could understand 20 or

21  Exceptions are announcements about error condition or unusual event  Inform the caller about error or exceptional event  Can be caught and application can continue working  Assertions are fatal errors  Assertions always indicate bugs in the code  Can not be caught and processed  Application can’t continue in case of failed assertion  When in doubt – throw exception 21

22 22 public string Substring(string str, int startIndex, int length) { if (str == null) if (str == null) { throw new NullReferenceException("Str is null."); throw new NullReferenceException("Str is null."); } if (startIndex >= str.Length) if (startIndex >= str.Length) { throw new ArgumentException( throw new ArgumentException( "Invalid startIndex:" + startIndex); "Invalid startIndex:" + startIndex); } if (startIndex + count > str.Length) if (startIndex + count > str.Length) { throw new ArgumentException("Invalid length:" + length); throw new ArgumentException("Invalid length:" + length); } … Debug.Assert(result.Length == length); Debug.Assert(result.Length == length);} Check the input and preconditions. Perform the method main logic. Check the postconditions.

23  Barricade your program to contain the damage caused by errors  Behind the barricade is “safe” area - data is valid  Validate data crossing the boundary  Consider same approach for class design  Public methods validate the data  Private methods assume the data is safe  Consider using exceptions for public methods and assertions for private 23

24  Don’t automatically apply production constraints to the development version  Be willing to trade speed and resource usage during development  Introduce debugging aids early  Make errors obvious during development  Asserts should abort the program  Unhandled exceptions should not be hidden  Plan for removing debugging aids 24

25  Too much defensive programming is not good – strive for balance  How much defensive programming to leave in production code  Remove code that results in hard crashes  Leave in code that checks for important errors  Log errors for your technical support personnel  See that the error messages you leave in are friendly 25

26 Questions? http://academy.telerik.com


Download ppt "How to Design Error Steady Code Ivaylo Bratoev Telerik Corporation www.telerik.com."

Similar presentations


Ads by Google