views:

334

answers:

14
//
// To Throw
void PrintType(object obj)
{
    if(obj == null) 
    {
        throw new ArgumentNullException("obj")
    }
    Console.WriteLine(obj.GetType().Name);    
}

//
// Not to Throw
void PrintType(object obj)
{
    if(obj != null)
    {
        Console.WriteLine(obj.GetType().Name);
    }
}

What principle to keep?

Personally I prefer the first one its say developer-friendly(notified about each "anomaly"). The second one its say user-friendly(let user continue work even if "inside" not everything does right).

I think that is more complicated to find errors and bugs in the maintenance phase when you silently let the things to go on. If something goes wrong you are not notified at once, and sometimes have errors far away from the main error cause, and spend a lot of time to find it.

What do you think?

+30  A: 

The second one is lethal. Failing silently is always the wrong thing to do. Suppose this were the banking system in the bank that holds your account. Would you like it if there was a problem paying in your salary and the system silently ignored it?

anon
+1: How is it "friendly" to pretend the bug doesn't exist?
S.Lott
It depends on the invariants of each function. Is *null* a valid value? Is the argument optional? If it is a bug in the application then aborting should be the way, if it is a rare exceptional condition then throwing is appropriate. Else, if the parameter is optional then ignoring it is appropriate.
David Rodríguez - dribeas
The question seems to presume that the exception shan't generate user notification. If I'm reading it right, that assumption is flawed.
msw
Sorry, I disagree - sometimes, failing silently is what you want - it depends on the context of the problem.
Thomi
@David In this specific case, the parameter is clearly required - vide the first alternative code. Obviously, if the parameter is optional or can be null, this is not a failure in the first place.
anon
@S.Lott: I commented about "friendly" in the thread comments and text.
serhio
@Thomi: Failing silently is hiding a known error. Problems cannot and should not be hidden. If this null value is part of the requirements, then catching and hiding the exception is not a "choice", the `if` statement is the **required** design.
S.Lott
A: 

Consider using the Null Object pattern is very useful to not clutter your code with try-catch, null checks (or god forbid swallowed errors).

Rickard von Essen
So instead of cluttering your code with exceptions, lets clutter them with unnecessary abstractions? Error's are errors, if you have a well defined set of inputs and someone violates that contract... its time to throw.
Nix
@Nix If it's an error but a lot of times it's not.
Rickard von Essen
+3  A: 

Throw.

Let the caller of a function determine if it is important enough to throw an exception to the user on a null value, but the function itself should throw because of the invalid argument.

Anthony Pegram
A: 

In this particular example, giving nothing to a printer is like saying "print nothing", thus working as it should.

I do know this is an example, but it's just to clarify that this is relative.

If your code displays user-friendly messages on exceptions somehow, what difference does it make ? the first one would be both developer and user friendly.

MarceloRamires
+1  A: 

I'd say that it depends on your (developer) preference. From the user perspective, he should never see an unhandled exception, but it does not mean you cannot use exceptions.

I prefer the first one, because I find null to be a totally unnecessary (and annoying) construct, so I make effort to code without it. If there is a null somewhere, someone made a mistake, so the best thing is to just barf out instead of pretending everything is ok.

In the end it depends on what you consider to be the semantics of the method. If the method is supposed to accept nulls, then you should pick option number two. If the method is supposed to only accept real arguments (which I prefer), then you should pick option number one.

Martinho Fernandes
+5  A: 

If the method body handles the null obj properly (in other words, obj != null is not a requirement), then there's no need to throw an exception.

In all other cases: Throw. Let the client take responsibility for their flawed input.

Prutswonder
A: 

It really depends on what your invariants are. If the parameter is optiona, then ignoring a null parameter is just fine, but if the parameter is required then that will hide a bug in your application. Also, and depending on the language, if the invariant is bad enough you may consider a third option: abort the application.

All discussions on whether to use or not exceptions can always be mapped to the decision on whether the situation is exceptional or not, and if it is exceptional, throwing or rather aborting the application depends on whether it is recoverable or not.

David Rodríguez - dribeas
+1  A: 

Always Throw, except in debugging/diagnostic code. It is most embarassing to have a NullPointerException that occurs in production code at a point where only a debugging message should be generated, e.g.

log.debug("id of object is " + obj.getId())

where the logger is turned off, and obj is null.

mfx
+1  A: 

It is highly subjective, but I always prefer to just ignore non-fatal or recoverable errors. Put them in logs, if you must, but if you know how to continue - please do so.

Note, that when I say fatal, it actually depends on the function itself. Say, there's API function that gets ID and handful of other parameters. Suppose, that this ID also can be guessed from those other stuff that is passed in. API function should guess it if it can but the function somewhere inside that does all the work should get non-null ID and throw otherwise. Because for high level API function it is not fatal, it knows how to guess it, but for low level function it is fatal, it supposed to do something with that ID and with null value it can't continue.

All fatal errors should be noted, of course.

vava
this is more complicated to find errors and bugs in the maintenance phase when you silently let the things to go on. If something goes wrong you are not notified at once, and sometimes have errors far away from the main error cause, and spend a lot of time to find it.
serhio
No, not really. First of all, in the presence of tests you're likely to catch the error, second of all, there's low level functions that should detect errors and there's high level functions, that should try to avoid them.
vava
I've edited my post to clarify what I meant by "fatal error".
vava
+4  A: 

Throwing an exception (if null is an error) seems far better than silently ignoring an error.

There is a third option you can consider:

void PrintType(object obj)
{
    Console.WriteLine(obj.GetType().Name);
}

This also throws an exception when obj is null. The advantage of this, is that less code is involved. The disadvantage of this approach is that it is more difficult to tell whether obj can be null.

Renze de Waal
note that instead of ArgumentNullException("obj") you could write `ArgumentNullException("Cannot print a null object")` to be more explicit.
serhio
A: 

Id go for

void PrintType(object obj) { Console.WriteLine(obj.GetType().Name); }

MatteS
this was an example. Instead of ArgumentNullException("obj")you could write `ArgumentNullException("Cannot print a null object")` to be more explicit.
serhio
A: 

Third option, half in pseudocode:

// To Throw A Clean Error
void PrintType(object obj)
{
    if(obj == null) 
    {
        throw new ArgumentNullException(STANDARD_ERROR_MESSAGE, obj)
    }

    Console.WriteLine(obj.GetType().Name);    
}

Either catch all errors and wrap them in a single place, so the user sees standard text:

There has been an error. If this error persists, please contact an administrator.

Or throw a select few errors, all of which are user-friendly, and display them directly to the user. "A connection error has occurred." "An authentication error has occurred." "A system error has occurred." And so on.

On the backend, have all errors and their stack trace logged, so you can use the debugging information that way.

Dean J
A: 

It really depends on what the function is defined to do. The most important aspect is to have a clearly defined behavior and for the function to implement it correctly.

Now, if the question is whether is better to define the function to accept null and print it out, or to not accept it and throw an exception, I would say the latter, because it's probably less error prone for the user to check for null before calling the function, if that is a possibility.

Larry Watanabe
when developing your function you can't be sure if the user will or not will check the object. This is true, however, that sometimes that kind of verifications are done in a chain if obj!null/if obj!null/if obj!null/if obj!null...
serhio
+1  A: 

If you api if exposed outside, do always argument checking and throw a argument based exception so the api user can get the result.

Kerem Kusmezer