Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Should methods return nulls or throw exceptions 3

Status
Not open for further replies.

AndrewJMarshall

Programmer
Jun 8, 1999
24
0
0
US
I know it seems like a goofy question, but ...

I'm writing a data layer class that provides methods to retrieve objects from a database by their ID. If no record exists for a specific ID, should the methods provided return null or throw an exception?

Please provide your reasoning as this is a mostly academic question. My suspicion is the that the "right" answer is "it depends". 8-(

Thanks,
Andrew
 
Personally I would think that it should return zero or null.
It seems perfectly normal and acceptable to me for a database to fail to return rows for a selection. I don't see this as an error.
Failing to connect to the database, on the other hand, I would suggest is more of an error condition and would therefore have more reason to throw an exception.



Trojan.
 
Oops. I forgot the mention the methods return an object if successful, so returning zero is not an option.

For example,

Thingy GetThingy(string ThingyGUID)
{...}
 
It depends. ;-)

If according to your logic the object should always be there, then throw an exception when it is not. If, however, there is a chance that your program is working correctly and the ID just might not be valid, then return null.

By throwing an exception you are saying that the method should always return a valid value. By returning null you are saying that the method may or may not succeed and it is up to the calling code to verify successful lookup.
 
However, the data layer shouldn't have business logic in it. So the decision about what is mandatory should not be taken in the data layer. Return a null, and let the business tier throw an exception if this violates some business constraint. By all means throw an exception if there is s genuine problem with the database, but sqlcode +100 is business as usual for the data layer.
 
BTW, there's an old joke about systems programmers only needing one of two answers to deal with any technical enquiry:

[ol][li]There's a bit set somewhere.[/li][li]It depends...[/li][/ol]
[smile]
 
Thanks for all the replies!

uolj,
Your reasoning matches Joshua Bloch's, a person I have high regard for. Brilliant!

stevexff,
Ah, the voice of reason! Thanks for keepin' it real. Brilliant!

Andrew
 
I would say it should throw an exception. Presumably the ID was originally returned from the database (either as a straight query or from a joined table), so asking for the same ID later should either give you the record, or an error (another user deleted the record, perhaps?)

Chip H.


____________________________________________________________________
If you want to get the best response to a question, please read FAQ222-2244 first
 
I totally agree with all the posts. I just want to expand the issue a bit:

This is the same problem as you get when displaying the results after searching for a number of items.

If you ALWAYS expect a result, you should display an error message.

If sometimes expect nul replies, then I think you should display the same screen that you would have used with several items in the list, but show it with NONE. Do you need a warning note as well?

Another thought that comes to mind is that the answer should be in your class diagrams somewhere. If an association says either '0..1' or '0..*' the it is valid. On the other hand, if the zeros are replaced by ones, it is clearly an error.

But most of the constraints on a class diagram should relate directly to 'Business Rules'. So if the rule is a business rule, ask the users; if the rule is actuially a system rule, ask the designers, but it should porbably throw an exception.

Gil
 
Hi,
I have a similar situation in which I introduce a NullObject that can be understood no matter where it is returned from.

For example you say you have a Thingy class.
First make an interface IThingy to use.
Then make your implementation classes;
NullThingy and Thingy.
Then make something like an INullable interface which would define public boolean isNull(); and implement that in your two implementations.

So then in your data access layer on initialization you could always initialize your result to the NullThingy and only set it if there is a record.

public class ThingyDAO {
IThingy result = new NullThingy();

try {
result = findThingy();
}catch(Exception e) {
//handle exception
}
return result;
}

and the calling class can call

IThingy thingy = ThingyDAO.findThingy();
if(thingy.isNull())


or you can just implement something special in your NullThingy class and avoid the whole if check.

Brian

Spend like you don't need the money,
love like you've never been hurt and dance like nobody's watching!
 
I've got a different spin. Exceptions should be left for exceptional things...things that aren't expected in code.

So if you have a function that returns an object (as you mentioned is your situation), then return an object of that type. BUT, if there are no records in your query, then return the object without any data and have your business logic check the object and act accordingly.

Exceptions have unfortunatley become the defacto "what I wanted didn't happen" instead of "something I didn't expect happened".

D'Arcy
 
Correct me if I'm wrong, but it appears that you're suggesting that predictable and unwanted behavior should be handled by a means other than the try/catch/throw methodology. If so, well, that's definitely a different spin!

The example you give to support your argument is a reasonable way of handling the situation you describe. But it hardly supports your assertion that the software architecture community at large ought to change the established methodology for handling expected and unwanted behavior. First, you don't explain why the existing methdology is insufficient, and by extension ought to be changed; that you don't like it is hardly a refutation of it. Second, you don't set forth an alternative: "have your business logic check the object and act accordingly" could be done using the methodology already in place.

There are reasons for standards: the main one is that they leverage the body of knowledge derived from the trials and errors over time of the community in which they exist.

One of the realities of software architecture is that users will attempt to do things that the application can't work with: putting in filenames that don't exist, entering letters where numbers are required, and so on. The try/catch/throw paradigm has evolved over time as the means of dealing with this sort of thing, and it seems wrongheaded to me to repudiate that evolution without really backing up your point of view and recommending alternatives.

In the end, it seems that this all boils down to your disagreeing with the community at large on the semantics of the word "exception." To me, exception simply means "outside of the established norm," whether expected or not expected.

With respect, I'm not finding many points here on which we agree.

Best regards,

Bob
 
Bob - not sure what side you are coming down on. It doesn't seem like people are disagreeing with the word exception here at all.

 
<I've got a different spin. Exceptions should be left for exceptional things...things that aren't expected in code.

I should have done that at the beginning of my little essay. :)

Bob
 
Bob...I need you to re-read my post. I have no idea where you came up with my post saying that try/catch blocks should not be used, as I only discussed the overuse of exceptions. I have no problem and actually support try/catch blocks within code.

Secondly, we do actually agree on the definition of exception: "outside of the established norm". Definately! Exceptions, as I put it, should be for exceptional things.

In the context of the original question that started this thread, if a query is executed and no records are returned but an object needs to be passed back, there is no reason to throw an exception: the developer can code in anticipation of that scenario and, it should be pointed out, that result is not an error; its a possible scenario within the app.

Now, let's say that someone pulls the plug on the SQL Server and the code can't open the connection. This is where catching a SQL error can be performed. However, that doesn't mean that the exception can't be handled in the calling code without throwing any extra exceptions. Again, coding in anticipation.

Now let's say that there's bad data in the database, and when the object tries to fill itself, and type-mismatch exception is thrown. Well, this is definatley exceptional: why is there bad data in the database? This should be logged, communicated, and possibly bubbled up to the user and the program halted.

Developers have been taught that if something bad happens, just throw an exception as opposed to being open to the possibility of dealing with the behavior in either the code or within the catch part of the try/catch block.

I hope this clears up my stance on the issue. I think that we actually agree on more points than you think we do.

D'Arcy

 
I have no idea where you came up with my post saying that try/catch blocks should not be used.
D'Arcy, it's the only conclusion that I can draw from the position in your first post.
exceptions should be confined to...things that aren't expected in code.
I have no problem and actually support try/catch blocks within code.
Given that one catches exceptions and not something else, and that one can't catch an exception that one doesn't expect, espousal of the first statement constitutes repudiation of the second. Hence my first post was based on the conclusion that you did NOT support the second statement. Now, you say you do, without retracting your support of the first. So, with all due respect, what's up with that? Do my logic or the assumptions upon which it is based have a hole somewhere?

The other thing I didn't understand, and still don't, is why exception handling should be avoided with some sorts of exceptions (anticipated ones), and not with others (unanticipated ones). Let me use the three examples you give to clarify what I don't understand:

if a query is executed and no records are returned but an object needs to be passed back, there is no reason to throw an exception: the developer can code in anticipation of that scenario and, it should be pointed out, that result is not an error; its a possible scenario within the app.
Why is it about this scenario that precludes throwing an exception? Why is another methodology indicated? Why isn't it best to have a consistent approach across the board? The way that I would handle this is by throwing an exception (why am I wrong to do so?) from the provider of the data to the consumer. A developer coding "in anticipation of that scenario" would simply catch the exception thrown. Isn't "coding in anticipation" exactly what catching exceptions is?

let's say that someone pulls the plug on the SQL Server and the code can't open the connection. This is where catching a SQL error can be performed. However, that doesn't mean that the exception can't be handled in the calling code without throwing any extra exceptions. Again, coding in anticipation.
This kind of illustrates my point that this is the way everyone else is doing it. SQL Server throws any number of different exceptions when it can't open the connection. For example, if there's an invalid user or password, SQL Server will throw an exception. So, it would appear that the designers of the SQL Server provider are perfectly happy to throw exceptions for all sorts of reasons, trusting the consumer to catch them and handle them in its own way. Why is this a bad idea in your mind? (Or do you not think this is a bad idea, and what am I missing about your point of view?)

Now let's say that there's bad data in the database, and when the object tries to fill itself, and type-mismatch exception is thrown. Well, this is definatley exceptional: why is there bad data in the database? This should be logged, communicated, and possibly bubbled up to the user and the program halted.
So, why is this a good reason to throw an exception, and your first example not a good reason? You're giving an example here of the developer coding "in anticipation of the scenario", too, aren't you? I don't see that you're drawing any substantive distinction between these two scenarios. (All I can see is that you're saying that one is an error, and the other one isn't. If so, then what's the difference and why is it relevant?)

Now, D'Arcy, I'm not just trying to pick your posts apart for the sake of doing it. When someone says something that I disagree with (strongly in the case of your first post) I try to find out why the person feels the way he or she does, with the idea of learning more. So, no, you haven't cleared up your stance on the issue to me. I'm less clear on it than I was before, in fact (although probably closer to what it really is, too). I do have an open mind, though, and want to understand what you're trying to tell me. Would you mind taking another crack at it?

Thanks,

Bob
 
<Bob - not sure what side you are coming down on. It doesn't seem like people are disagreeing with the word exception here at all.

That's not what I'm saying, h0. I'm saying that there appears to be some disagreement on what the word means. Does it mean error or does it mean unwanted behavior, not necessarily implying error?

Bob
 
I recently read a very interesting article by Damian Conway that makes a good case for throwing exceptions instead of returning null (or any other value for that matter).
I wonder if you guys agree.




(slowly healing) Trojan.
 
I agree with the position in the article. One of my pet peeves in VB6 has been the inconsistent way that exceptions are handled.

Bob
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top