3 ms·
I largely agree. If it came to pass that the precondition fails, there's a bug somewhere and this code just hides it. At the very least, that should go to an er
by kstrauser 2y ago
I largely agree. If it came to pass that the precondition fails, there's a bug somewhere and this code just hides it. At the very least, that should go to an error log that someone actually sees.
I'm writing a Rust project right now where I deliberately put almost no error handling in the core of the code apart from the bits accepting user input. In Rust speak, I use .unwrap() all over the place when fetching a mandatory row from the DB or loading config files or opening a network connection to listen on or writing to stdout. If any of those things fail, there's not a thing I can plausibly do to recover from it in this context. I suppose I could write code like
if let Ok(cfg) = load_config() {
println!("Loaded the config without failing!");
Ok(cfg);
}
else {
eprintln!("Oh no! Couldn't load the config file!";
Err("Couldn't load the config file");
}
and make the program exit if it returns an error, but that's just adding noise around:
return load_config().unwrap();
The only advantage is that the error message is more gentle, at the expense of adding a bunch of code and potentially hiding the underlying error message from the user so that they could fix it.
I think Python also gets that right, where it's common to raise exceptions when exceptional things happen, and only ever handle the exceptions you can actually do something about. In 99.999% of projects, what are you actually going to do at the application level to properly deal with an OOM or disk full error? Nothing. It's almost always better to just crash and let the OS / daemon manager / top level event loop log that something bad happened and schedule a retry.
- samiv 2y agoThe whole story is 3-fold. We have - errors in the software itself, aka BUGS - logical conditions that are expected part of the program execution flow and expected state. some of these might be error conditions but only for the *user*. In other words they're not errors in the software itself. - unexpected failures where none of the above applies. typically only when some OS resource allocation fails, failed to allocate memory, socket, mutex etc and the reason is not because the programmer called the API wrong. In the first category we're dealing with BUGS and when I advocate asserting and terminating the process that only really applies to BUG conditions. If you let an application to continue in a buggy state then you cannot logically reason about it anymore. The logical conditions are the typical cases for example "file not found" or whatever. User tries to use the software but there's a problem. The application needs to deal with these but from the software correctness perspective there's no error. The error is only what the user perceives. When your browser prints "404" or "no internet connection" the software works correctly. The error is only from the user perspective. Finally the last category are those unexpected situations where something that should not fails. It is quite tricky to get these right. Is straight up exiting the right choice? Maybe the system will have more sources later if you just back off and try again later. Personally in C++ projects my strategy is to employ exceptions and let the callstack unwind to the UI level, inform the user and and then just return to the event loop. Of course the real trick is to keep the program state such that it's in some well defined state and not in a BUGGY state ;-)
- kstrauser 2y agoThat sounds about right to me. Worry about the things you can fix and don't worry abut the things outside your control.
- joesb 2y agoWhen a process is used to serve multiple requests, I don't think you need to let the whole process terminate just because there is a bug dealing with a single request. Just because we can not reason about the current request does not mean the only way to get to the clean state for other requests is to terminate the whole process.
- veidelis 2y agoMakes sense. Better to unwrap via .expect("msg"), though.
- kstrauser 2y agoThat's a good callout, but I do that if and when I can add extra meaningful context. From a user's POV, "I already know what file not found means. You don't have to explain it to me again in your own words."
- Zacru 2y agoThe thing I wish more error messages did was tell me exactly which file was not found.
- ziml77 2y agoThis is something really annoying about simple error codes. Sure they're lightweight but how the hell am I supposed to know the problem with my input when all the error information I get is "The parameter is incorrect"? I've actually had cases where I disassembled Windows system libraries to track down the exact validation that was failing.