|
I am surprised anyone answered anything other than "Other". Because surely there's no single answer to this that can work for all scenarios. You may have to return null, an empty object, an error code, an indication code, or even throw an exception. (sometimes even a combination of exception/return value).
|
|
|
|
|
|
Returning null is problematic unless it's documented what returning null means. When consuming Microsoft's classes this is usually the case. In a typical "Find" algorithm it's quite usual for a negative result to be valid behaviour. Returning a null object is perfectly fine in this case. However, I've often maintained code where, due to lack of documentation, it's not clear whether returning null from the method you were consuming was possibly valid behaviour or not.
The upshot is that for my own methods, in those cases where I may return null, I document what this means. Design by Contract in .NET 4.0+ will also be useful going forward if developers start using it.
Kevin
|
|
|
|
|
Agreed, there are many scenarios where different approaches are needed.
If my GetConnectionString() method can't find the connection string (maybe somebody fooled around with the config files), I would almost certainly throw an exception. On the other hand, if my GetTradeData() method can't find trade "T12709", I would almost certainly return null.
Cheers,
Vikram. (Proud to have finally cracked a CCC!)
|
|
|
|
|
Nish, I agree with your point as well but the question is about returning "no result" so, I prefer to return "null"!
Try not to become a man of success but rather to become a man of value. - Albert Einstein
Ernest Laurentin
|
|
|
|
|
Chris Maunder wrote: Exceptions, in my book, are to be used to catch exceptional cases, not to control program execution flow.
I agree[^], although there are people who think it is acceptable to use exceptions for the tasks such as breaking from deeply nested loops or ending a numerical computation.
But in general, not finding a value in a collection is not an exceptional event. STL containers usually return the "past-end" element in this case, but an option type object would be even better.
|
|
|
|
|
Nemanja Trifunovic wrote: But in general, not finding a value in a collection is not an exceptional event
I like to think of it in "design by contract" terms. If a method cannot fulfil its contract then it must cause an exception (or generically, a program fault) otherwise it should not.
I think the "exceptions are for exceptional cases" mantra is too vague. We might envisage a method where a rare event occurs but the method's spec is designed to account for that. In that case it should not cause an exception, even though the event was "exceptional."
You could put it this way: "Exceptions imply exceptional cases (because errors are exceptional) but not vice-versa."
Kevin
|
|
|
|
|
Kevin McFarlane wrote: I like to think of it in "design by contract" terms.
Can I smell Eiffel here ?
Seriously, you are right - we just have a terminology problem here: by "exceptional" I do not mean "rare" but "unexpected" or "violated the contract".
modified on Monday, August 24, 2009 10:48 AM
|
|
|
|
|
Nemanja Trifunovic wrote: Can I smell Eiffel here Smile ?
Yeah, or Spec# or Code Contracts for .NET 4. Not sure if there's anything which supplies full support in C++ though?
Kevin
|
|
|
|
|
Kevin McFarlane wrote: Not sure if there's anything which supplies full support in C++ though
Nothing built-in, but there are libraries - in fact I remember one published here at CP.
There are some non-standard extensions for DbC in the Digital Mars C++ compiler, and of course D supports it (at least D 1.0, not sure about 2.0)
|
|
|
|
|
I agree with Chris. That is the way to do it!
Throwing an exception is unacceptable since exception should be used for errors. "No result" is not (always) an error condition.
Morale: Use the right tool for the right task.
Bye By(t)e
|
|
|
|
|
Returning a list is different from returning an object. If my requirements are to return a list, I always return a list (albeit it may be empty). But if I am supposed to return an instance of some one object I usually will return null if I cannot create a valid object hence my vote for null.
WarePhreak
Programmers are tools to convert caffiene to code.
|
|
|
|
|
Yeeesss... but an Exception can tell you why you got nothing useful back.
"Waiter! I can't eat this soup." ...
|
|
|
|
|
If the object is expected then returning a null will force the caller to check the return type and then try to work out why the call failed.
If you think the object might not be found then you should either provide a method to check the object exists or implement a Try... method that returns a boolean success/fail and the object as an out parameter.
|
|
|
|
|
Checking the what a function return is always a good idea: Using exceptions and a try/catch just to avoid check the result is only lazyness (IMO).
However I agree in general that you should provide a way to quick check the result of the operation result i.e. supposing you wrote a function that search one element in a collection I prefer something like the following:
// Search an object and return its position (if found) using pPositionWhereFound.
Bool searchObj ( Oject_t *pList, Oject_t* pObjToSearch, int *pPositionWhereFound );
instead of:
// Search an object and return its position (if found). -1 as return value
// means not found
int searchObj ( Oject_t *pList, Oject_t* pObjToSearch );
in both cases you have to check the returned value but doing:
if ( searchObj( &List, &ObjToSearch, &Position ) )
...
is nicer than:
int iPosition = searchObj( &List, &ObjToSearch );
if ( iPosition != -1 )
...
Bye By(t)e
|
|
|
|
|
Simone Serponi wrote: Checking the what a function return is always a good idea
Yes, but hope that consumers of your code will always check if you return null or valid object is just asking for trouble.
To be honest I prefer bug report with exception message "check_first_if_object_exeists_before_requesting_it_noob" than plain null object exception. It just saves time fixing code (on any side)
--
"My software never has bugs. It just develops random features."
|
|
|
|
|
deflinek wrote: Yes, but hope that consumers of your code will always check if you return null or valid object is just asking for trouble.
To be honest I prefer bug report with exception message "check_first_if_object_exeists_before_requesting_it_noob" than plain null object exception. It just saves time fixing code (on any side) Cool
As I already told checking function return value is (should be) a must...
Moreover this is the classical thing that is documented into the Reference Manual of the code (thanks to God for DoxyGen) and looking at the documentation before use it is always a good idea.
However, yes, "The mother of noobs is always pregnant", and I'm sure someone will use the function without check the return value. But in this case it is not my fault: Read the documentation first!
Bye By(t)e
|
|
|
|
|
Member 2053006 wrote: If you think the object might not be found then you should either provide a method to check the object exists or implement a Try... method that returns a boolean success/fail and the object as an out parameter.
Totally agree. I'm a big fan of the TryParse() style methods.
There are some cases where they don't apply so well; e.g., cases where the condition can change between the check and use. A check for a file's existence doesn't mean that the file is still there when you try to open it in the next statement. Sometimes I think TryParse() style methods in these cases can create a false sense of security... OTOH, at least they let you return an intelligible error message for many execution scenarios.
|
|
|
|
|
With the current wording of the question, I throw. An error always gives an exception in my book. However, I don't always consider something missing as an error, only if I expect it to be there. I usually do this:
Foo bar = provider.GetFoo(FooType.Bar);
Foo baz = provider.FindFoo(FooType.Baz);
--
Time you enjoy wasting is not wasted time - Bertrand Russel
|
|
|
|
|
I agree about the "Find", but don't necessarily agree on the "Get". Please see my reply to Nishant above, if my GetTradeData(string tradeID) fails, I would not throw an exception.
FindTradeData(string tradeID) sounds silly.
Cheers,
Vikram. (Proud to have finally cracked a CCC!)
|
|
|
|
|
I like to be consistent. Hence, my GetX(...) and FindX(...) always[1] do what I just described, no exception (sic!)
Vikram A Punathambekar wrote: FindTradeData(string tradeID) sounds silly.
In my book, that's not a valid reason to omit doing anything other than singing in falsetto...
If I expect to find trade data with id tradeID in there, then I definitely consider it to be an error if it's not there, and I would therefore throw.
[1] Off the top of my head at 00.25 AM. My memory might fail, for obvious reasons.
--
Time you enjoy wasting is not wasted time - Bertrand Russel
|
|
|
|
|
As a side note - I'm not hesitant to use GetOrCreateX(String id) methods if the object needs to manage things on it's own and the caller doesn't care if the X existed before the call or not.
--
Time you enjoy wasting is not wasted time - Bertrand Russel
|
|
|
|
|
I agree. Because it said you were expecting an object to be returned, then if it cant return one that's an exception. If it were a function that may or should probably return an object, then a null would be acceptable. More like a 'not found' (null) vs a 'couldn't load/create object for some other reason like corrupt data'.
|
|
|
|
|
I depends on the situation.
First choice is throw an Exception.
In some cases return an empty collection.
In other cases, return null.
|
|
|
|
|
Yes, it depends on how normal it is to find no result. If it is very very strange, I return an Exception. Otherwise it's usually null, or an empty collection in some cases.
|
|
|
|