9 comments

[ 3.2 ms ] story [ 29.4 ms ] thread
It's ironic how PHP's philosophy of "ignore errors and keep chugging along" has lead to developers habitually adding "or die()" (crash on error) to everything, even in this instance where chugging along at any cost would have been the exactly right behavior

I wonder if they would have spent more thoughts on error handling in a language that defaults to crashing on error (e.g. Java's exceptions)

For people who don't know how PHP works but do know Node, the Node example is really not at all similar. The result is similar but far worse; in PHP die() only makes that request die; in Node, it just exits the entire node server which could be doing other stuff. process.exit() is probably never a good thing while we see die() used, still, for 'security'. Not saying it's a great idea, but it's better than not having it in those cases; for instance;

      if (!$user->active) {
         <p>Fob off!</p>
         die() 
      } 
      <p>Passcode to the world: <?php echo $world->pasccode; ?></p>
We encounter many cases where people forget these and so information gets accessed that should not be. Of course, this is just a unhandled cases is evil and they are:

      if ($user->active) {
         <p>Passcode to the world: <?php echo $world->pasccode; ?></p>
      } else {
         <p>Fob off!</p>
      }
but in the wild (at many banks :), we encounter very many of the first case and often without the 'die' so a security issue. Our analysis tools catch all IF cases that don't handle all cases (which we see as an anti pattern, just like it's forced on a switch); alerting that this if has no else for the rest of the program to run makes people think and actually change their code. I rather see;

      if ($user->blah) { 
         setSomething($user); 
      } else {
         info("user not bla, not setting something");
      }
      # the rest

than what happens in 99% of code;

      if ($user->blah) { 
         setSomething($user); 
      } 
      # the rest
because the next maintainer might add something to the setSomething that will make the # the rest sensitive, save, commit, deploy and we notice it when it hits the news of 64m records stolen or whatever. In the first case, it alerts the maintainer etc to the fact there is more and they have to think about it. There are better ways to handle it of course, but I'm just saying what we see in the wild a lot and we are only hired to fix the immediate issues, not long term, so long term refactoring is never a part. We do advice different patterns but no-one ever listens; our clients are mostly repeat clients from the past 3 decades.
> If you don't make it easy to do the right thing and awkward to do the wrong thing, people with good intentions will do the wrong thing.

This is so important, but just isn’t heeded.

I work with some smart people, but they tend to defend choices by saying “It’s pretty straightforward” and “This is the way we’ve historically done this”.

I’ve gotten to the point where I don’t feel that I have the energy to try to debate, because it’s just like beating a ball against a brick wall. I used to rationalize it as “This will be a learning experience for them”, but no, they haven’t learned.

I think that's a very important point, but I wouldn't call `or die()` an affordance. A common idiom, perhaps.

A common affordance that invites mistakes is a library that has something like `file_exists(path)` (because it often introduces hard-to-debug race conditions), or `db.query(string)` (because it invites string interpolation and SQL injection).

Invite mistakes, yes. But they didn’t test at all, even once, or they would have seen it fail.
This is a design/requirements problem to me, not a language one. You can handle no internet connection in just about every language, but you probably won't if you don't say something about needing to do that, and plan how to store/access the data in that failed state.

If the stakes were higher (say, brain surgery to get some study results), you'd want even more planning around storage/access so that your disk doesn't die and the server is unreachable at the same time and lose the only copy. Letting a developer come up with this on their own is a footgun with an incredibly sensitive trigger.

The other reason it's design/requirements is so everyone knows and it's not just Tim the developer coming up with his own idea and not really detailing it to anyone, and then Tim gets hit by a bus and someone has to go figure out what he did (or more likely, fired because they thought AI could do all of this for them).

This example is pretty weak as multiple things are wrong here. Seems like there was a lack of error handling all the way through (or participants would've noticed errors on completing). And why wouldn't you save in DB before sending the email? After all, you can always recover sending the email - and it's awkward to send an email with results that didn't make it to your DB.