I see two valid solutions:
- Throw an exception.
- Change the return type to an enumeration of ONLINE, OFFLINE, UNKNOWN.
Exceptions are meant for situations where a function cannot fulfill its contract, and that's exactly your situation. The current contract of
isOnline() is to return true or false, reflecting the "online" status of some service or whatever. There are situations where
isOnline() can't give a valid answer to that question, and the general advice is to throw an exception in such cases.
Why is that good?
Your caller typically wants to know the online status as it needs it to base some decision on that information. If you can't provide that information, it doesn't make sense for your caller to continue, as it doesn't know which execution path to correctly choose. And without any error handling code, the caller aborts its processing and signals its failure to its caller, and so on, until some higher-level function knows how to continue after a failure (by having a try/catch construct). And that's very often the best thing to do after an error.
So, you get for free an error handling covering at least 90% of situtions, and a source code that isn't cluttered with lots of error handling statements.
But, if your caller knows how to handle an unknown-status situation, the exception-throwing approach makes things slightly more complicated than necessary. It has to surround the
isOnline() call with an appropriate try/catch. Then the enumeration approach might be better.
As return values to cover the unknown-status case, I'd strongly recommend against using TRUE and FALSE for the known states, as then nobody will expect a third possible outcome, especially in a function named
That's why I'd both rename the function to something like
onlineStatus() and have it only return non-boolean values like ONLINE, OFFLINE, UNKNOWN.
Other answers proposed quite complex status objects, but I think that's overkill, and a three-fold enumeration suffices. From my experience, your caller is not interested to know why the online status turned out to be unknown, so it's enough to signal the "unknown" fact.
What would your caller do with a detailed description of the failure reason? Hopefully nothing, as it's not the responsibility of
isOnline()'s caller. If there's a way to deal with an error while trying to get the online status, that should be done inside
isOnline(), as that's the function responsible for that information. If this function fails, then its callers should assume that every reasonable approach to get the information has been attempted, and simply accept that the information isn't available.
The failure reason should be encapsulated and handled inside the
isOnline() function, maybe written to some log file if desired.