In a method where any positive number returned would signify success, would it be good practice to use negative numbers to define error conditions? Could then use enums to make readable.
4 Answers
It's often language dependant. Quite common practice in languages such as C and C++, but where other mechanisms exist it's preferable to use them, for example exceptions. They allow decoupling - both conceptual and in code - of usage of the method result from dealing with errors.
int result = myFunction();
if (result < 0) dealWithError(result);
else proceedNormally();
is arguably less easy to reason about and code than a try-catch block (which can be placed anywhere in the calling hierarchy, without the explicit need to propagate error results - though some languages like Java will require/recommend a signature change. E.g.
myFunctionChecked() {
try {
myMethod();
}
catch (Exception e){
dealWithExcpetion(e)
}
}
and
myOtherFunctionChecked() {
try {
myOtherFunction();
}
catch (Exception e){
dealWithExcpetion(e)
}
}
myOtherFunction() {
//... some stuff
myFunction();
//... some other stuff
}
can both be used without any change to how myFunction reports its errors if exceptions are used.
Final point for exceptions is that they allow you to be consistent about how you report errors throughout your code, not depending on the range of the function.

- 176
-
So something that causes execution to jump to an easily identified place within the same function (goto) is considered "harmful", and something that causes execution to jump to who knows where in the calling hierarchy is "perfectly fine" even for common cases like boring old error handling(!)? – Brendan May 02 '16 at 13:53
-
1If you think about the scope of the execution it makes sense - throwing an exception immediately terminates the current function. One should take care to design their program structure such that exception handling happens at the most logical place, as if this is not the case, then you do end up with spaghetti-esque code, but given your designs are well structured, exceptions can be very powerful. – jasiek.miko May 02 '16 at 14:03
-
@Brendan The "who knows where" is part of what makes it good. It's generally bad for a function to know anything about the program outside itself. – Kevin Krumwiede May 11 '16 at 01:27
-
Using exceptions for errors that are expected to be handles specifically is a mistake (even if it's one promoted by many languages). Exceptions should only be used for the controlled tear-down in case of an unexpected error (typically a bug). Excepted error conditions should be handled by returning the error (typically in a choice-type/tagged-union) – CodesInChaos May 11 '16 at 13:22
-
I wouldn't say it's necessarily a mistake - some languages offer exceptions and errors to make that distinction. Either way, one should always think carefully about which side of the line their case falls on - whether or should be returned by standard means, or through another mechanism. Whatever the means, if they give a decoupling of "standard" and "exceptional" control flows, you're probably on the right path – jasiek.miko May 11 '16 at 14:46
(...), would it be good practice to use negative numbers to define error conditions?
Providing error messages and valid return values using the same channel is rarely a good idea.
See how on a typical *nix standard input, output and error are separate - try to mirror that in your application. If your language of choice provides constructs dedicated to error handling (e.g. exceptions) - use them; treat returning error codes as a method of last resort if nothing else is available.
It is easier to think about your program's control flow if you can be sure that a channel always provides valid data without ambiguity (if your "valid data" can be either "return value" or "error message" you cannot be sure that the data returned by a function is always valid).

- 2,345
Overloading the meaning of any encoding is a dangerous thing.
Here a message code means both:
- success / failure
- Id's the specific message
Here is how that double meaning will evolve:
- Future programmers will curse the API when they realize that they must send a message in order to just say "success."
- Future future programmers will curse the design when they realize that "-999" was hijacked to mean "false with no message", but is within the domain of valid message IDs.
- Parsing "true" and "false" string literals. Or "success" and "failure". Most likely both.
- Actually storing space character(s) as the value in the database.
- There may be lists of "black listed" and "white listed" numbers, as above. Most likely simply in-line coded at various points.
- Everyone will wonder what idiot does not understand "null" or "true/false"
- There will be exceptional handling code everywhere.
Please pardon the harshness, a bit of PTSD going on here.
- There will come a time when this will adversely affect maintenance.
- Maintenance effort is O(n*2) because we have to deal with the database too.

- 5,823
- 19
- 31
-
I wish I could upvote this twice. Overloading return values is an antipattern, period. If the language you're using doesn't have an alternative mechanism for indicating error, it's a toy language. – Kevin Krumwiede May 11 '16 at 01:28
I have in the past used a system where a return value of 0 meant success, any positive value meant success with some annotation that the caller could interpret in some way, and any negative value meant an error.
With this system it was generally possible to check for success or failure very easily. If a method returned more status it was easily possible to check that. And it was easily possible to check for exactly what error happened.

- 44,814
- 4
- 64
- 126
enum
s effectively eliminate the need for such a concept, especially where the underlying numeric value is arbitrary. – radarbob May 09 '16 at 13:16