Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to implement try catch blocks?

I am always struggling where to place a try catch block. For example, I have a database class with a method that accepts two parameters. FindObject(string where, string order). This method executes a sql query with the specified where and order strings.

In a class I have a property called IsUsed, this property looks like this:

public bool IsUsed 
{  
 get
 {   
  ClassA a = new ClassA();   
  Collection<ClassA> myCollection = a.FindObject("Id = 1","");

  if(..) // etc  
 } 
}

It doesn't matter if this approach is clever or not, I only want to know where to place the try catch if the execution of the sql query goes wrong.

Where should I place the try catch so I can notify the user something went wrong?

  1. In the FindObject method?
  2. In the IsUsed property?
  3. Where I call the IsUsed property?
  4. Somewhere else? But where
like image 259
Martijn Avatar asked Sep 02 '10 08:09

Martijn


4 Answers

I try to follow a fairly simple rule: I set up a try..catch block if I can handle the exception in a sensible way. If there is nothing meaningful that I can do about the exception, I let it bubble to the calling code.

As a side note I would avoid executing (potentially lengthy) database calls in a property getter. I typically try to have the properties just set or get the value from a backing field, letting other methods perform database lookups and such. That will make the code somewhat more predictable for the person writing the calling code (it's common for property access to be a cheap action, while method calls can often be more expensive).

like image 172
Fredrik Mörk Avatar answered Sep 22 '22 11:09

Fredrik Mörk


Only catch the exception if you can do something about it. Otherwise catch exceptions at the "highest" level in your application and do whatever is required to handle it including terminating your application.

In applications having a UI the "highest" level is often event handlers like the click handler for a search button. For background services the "highest" level is often thread procs or timer callbacks.

  UI application                          Background service

| System Code    |                      | System Code    |
+----------------+                      +----------------+
| Event Handler  | <- try/catch here -> | Thread proc    |
|                |                      |                |
| ...            |                      | ...            |
|                |                      |                |
| Method         | <- throw here     -> | Method         |

If you let the exception propagate back into system code you will have an unhandled exception and you application will crash.

Handling an exception in a UI application often involves showing a message box. Some exceptions are not fatal and the operation may be retried (say if a file is missing or a database query failed) but other exceptions are fatal and the only option is to terminate the application.

A background service will log the exception and perhaps retry the operation. If several retries fail the logging level may increase to get the operators attention.

Good practice when it comes to exception handling:

  • If you catch an exception and rethrow you own exception wrap the original exception as the InnerException of the new exception.
  • If you catch an exception perhaps to do some cleanup but rethrow it because you want it to bubble up then always rethrow it using throw without specifying any exception. This will ensure that the original stack trace isn't destroyed.
  • In most cases you should only ever catch the base class Exception in your top level handlers.
  • Use finally blocks or even better the IDisposable pattern to perform proper cleanup in your code.
  • Think of exceptions as the "user interface" to the developer and format the exception messages accordingly. If you need a more polished user interface for the less technical user you should probably hide the more technical stuff.
  • Try to only use exceptions for exceptional situations like unexpected errors. Don't throw exceptions for common error cases. Checking the existence of a key in a dictionary should not throw an exception but instead return true/false value.

To answer your specific question I don't think you should catch any exceptions in your property.

like image 26
Martin Liversage Avatar answered Sep 18 '22 11:09

Martin Liversage


You should place try-cacth block in the place where you can do something meaningful with caught exception. Like you log it or show it to the user. Do not catch exceptions just for the sake of it.

like image 32
Alex Reitbort Avatar answered Sep 19 '22 11:09

Alex Reitbort


Well it should be where the try..catch block is needed, and where it can be handled. I'm assuming this would be in the FindObject method here.

So, within the FindObject method, catch and handle the SqlException, for instance. If it needs to be moved to a higher level for better handling, then throw the exception, or let it simply bubble up.

like image 28
Kyle Rosendo Avatar answered Sep 22 '22 11:09

Kyle Rosendo