Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

All of the examples are far better than the code I normally deal with.

That being said, the most tiresome code is this kind of step-by-step error checking.

  if (! is_numeric($id)) {
    exit('The ID is not a number.');
  }

  $db = open_database();
  if (! $db) {
     exit('There was an error connecting to the database.');
  }

  $query = db_query($db, 'select * from widgets where id = $1', $id);
  if (! $query) {
     $db_error = get_db_error_msg($db);
     exit('There was something wrong with the query: ' . $db_error);
  }
Zzzzzzz. It triples the code size. One third is the normal code path. Two thirds is all the error checking. I'm sorry, I just don't write it:

  $db = open_database();
  $query = db_query($db, 'select * from widgets where id = $1', $id);
I let errors bubble up to some general error handler, which stops the script in its tracks and gives the user a vague and unhelpful error message. It doesn't matter. Even if I gave them a very specific error message, all that they would do is log a ticket, and I would still go into the server log to uncover the line number the error was on, debug, and fix it.

Don't get me wrong. I write JavaScript to constrain user input, with friendly directions and error messages. And I set tight types in the database and add database constraints where I can. But I don't write all this step-by-step checking in the middle layer (PHP, Python, Go, what have you). So if the user somehow bypasses the JavaScript and tries to insert text into an integer column, the database will simply refuse, and the resulting web page will be a very ugly error message, which is what they deserve.

If the database is down, it's going to be ugly, regardless.

I admit that this strategy works okay for non-life-threatening, SQL-backed web apps and such. You may need to do something tighter in your work. But I wonder if there would still be something more elegant than the every-other-line error checking shown in the article.



This is one of the situations where the difference between scripting and "real" development becomes obvious.

Yes, it makes you zzzZZZz. If you don't care for errors anyway. However, when developing a large reliable software project you need to think through the possible error cases and handle them appropriately. Even if that just means logging them correctly and exiting so the error can be easily tracked down later (for example: was it expected/unexpected? What where the parts of the context that can't easily be collected by a runtime?).

And in a large project, it's not that bad. How many places are there where you setup the database connection, an OpenGL context, a network connection, etc? Just build the abstractions appropriate for your project once. Simply crashing backwards through the function calls with a generic exception and a stacktrace is not always good enough.


My dogma around this sort of pattern is similar, except that I don't just use one global error catching statement.

Basically, every module or function or whatever has a client. Sometimes those clients are other parts of your own system, sometimes they're end users outside of your control. Regardless, at significant barriers of abstraction, I try to catch errors, and translate them into new error types/representations that would be relevant or actionable by the intended client of that code, with the original error provided as a member. If you follow this pattern, the logic you write is free of error handling code, error handling code is centralized at abstraction barriers, and at any point you should have few errors that you wouldn't know how to respond to and probably just give up and bubble to the top.


But I wonder if there would still be something more elegant than the every-other-line error checking shown in the article.

Factor out the error checking into a function:

    onerrexit(is_numeric($id), 'The ID is not a number.');
    onerrexit($db = open_database(), 'There was an error connecting to the database.');
    ...
I admit you still have to explicitly state you're checking, but that's not much overhead, makes the code somewhat clearer, and gets rid of all the if(...). If the error-action is more involved, like your "third paragraph", then you can make an errcheck that takes a function reference for the error-action instead (not sure if that's possible --- haven't used PHP in a long time --- but there's probably a similar method otherwise.)


Sometimes when I'm being very lazy writing C, I define a macro of this kind which doesn't even take any error message argument but just prints line number, textual representation of the code which failed and errno. Huge debugging aid at negligible cost.


Oh, well, Apache and PHP give me this out of the box. So even though there is not a great deal of custom error checking in my code as I said before, I always have enough information in Apache's logs to track down the problem. I guess with C and Go you have to roll your own.


You only write it once in your Database class. The only thing that changes from call to call is the query string and parameters. Handle all errors gracefully there, throw an error to the calling code and let it handle it to the user with a 500 while the support channel gets alerted with the real error.


The catch-all top level error handler isn't typically a hallmark of good design but I think it's pretty relatable as a quick fix when you need to get something working on a deadline.


Given that software systems are at their heart gate configurations on silicon, and given that those gates need to interact with mechanical and electrical systems, there will always be different classes of recoverable error for which the recovery procedure differs.

So yes, outside of pure functions you will always need special-snowflake error handling.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: