Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling the usual errors: If-Then-Throw blocks vs. Code Contracts vs. an Assert class

When I start writing a method, I usually check for exceptional conditions first in the method, using If-Then-Throw blocks.

public void ReadFile(string filePath)
{
    if (string.IsNullOrEmpty(filePath)
    {
        throw new ArgumentException(...

This style seems to be very clear and easy to understand, but it takes up more space than I think is necessary. I want to be able to handle errors and exceptional conditions in a smart way that enables whoever's reading these errors to easy take care of them while also keeping the code itself clean.

I've looked a bit at Code Contracts, which seems to me a requirement for certain conditions before and after a method's execution. That seems to be a tad bit overkill for just a null string, and I'm not sure if you can have contract clauses within the method itself, for instance, if the path is not null but no file exists at that path.

The solution I'm thinking of using is rolling my own Assert class. This class will basically turn the above If-Then-Throw into a simple one liner.

Assert.IsFalse<ArgumentException>(string.IsNullOrEmpty(filePath), "The path cannot be null or empty.");

All Assert methods would throw an exception using the exception type and the message in the last argument. The thing is that I'm not sure if this is good practice. Does it confuse what exceptions are truly for, or what Assert actually means? Would it make error-handling easier or harder?

like image 755
Chris Akridge Avatar asked Apr 25 '14 16:04

Chris Akridge


1 Answers

I would say this is not good practice. As you pointed out, this would confuse the roles of Assertions and Exceptions. The topic is somewhat common, this link has a lot of nice ideas. By combining exceptions and assertions, you end up with a conundrum... is the class an exception helper, or is it an assertion helper?

Since assertions are compiled out of the Release build, would your assertion class even work in Release mode? It would be non-conventional to expect an Assertion class to work in release mode. So, would your Assertion class throw the exceptions in Release mode? There lies the confusion. By convention, I would say the exception should not be thrown when using an Assert Class (in Release mode) because it is understood that assertions are not part of a Release build.

The code above should not make 'Exception Handling' easier nor harder, it should be the same since the exception handling depends on what is catching the exception in the stack. I think you are really asking if it makes throwing Exceptions easier or harder. I think it could make dealing with your exceptions easier. I also think it is probably unnecessary. What is most important is that you are consistent with this... if you are going to use an ExceptionHelper class, then embrace it and be consistent... otherwise it is all done for naught.

Debug.Assert:

  • Use liberally
  • Use whenever there is a chance that an assumption could be wrong
  • Used to help other programmers, not necessarily the end user
  • Should never affect the flow of the program
  • Not compiled in Release builds
  • Always yells 'BLOODY MURDER' when something unexpected happens, this is a good thing
  • many other reasons, I'm not aiming for a complete list

Exceptions:

  • Can be caused for any reason, it is not always known why
  • Always in debug or release builds
  • Pertains to how the application flows
  • Some exception handlers may silently swallow an exception and you would never know it
  • many other reasons, I'm not aiming for a complete list
like image 50
bunggo Avatar answered Oct 10 '22 05:10

bunggo