This is an attitude I really try to build up in junior devs. Soooo many people seem to default to writing code like, "if input is null return null" (when input should never be null) or "if valueThatShodBePositive < 0 silently skip the code that was going to use the value". If the app detects that something is in an invalid state _I want it to break_. The worst problems to debug are the ones where you have to work backwards through miles of strange behavior and corrupted data to find the root cause, because the program tried valiantly to soldier on long after it had been shot through heart with bad data.
I guess this is because no one really teaches error handling. I assume a lot of students end up with a mindset of just make the errors go away instead of, deal with the errors effectively.
Agreed; I've often wondered if this is a result of early CS classes usually expecting students to handle weird/bad inputs. It's only natural for a programmer to want to write a program that gracefully handles all reasonably bad inputs, like nulls. So we're taught early on to write defensive code that handles those. And that's fine when you're writing short, academic programs. But when the complexity goes up by a few orders of magnitude trying to gracefully handle that null value 10 levels deep in some parsing logic maybe isn't the best thing to do. Old habits die hard, however.
Yeah, this is a great point. Both overly defensive programming and (my personal least favorite) overly-commented code are instilled in students at a very early point in their careers by irresponsible teachers trying to find something to grade students on (Didn't handle negative values? 5 points off! Didn't leave a comment on every line? 1 point off per line!)
I think this is a symptom of using weakly typed languages as well. If your argument types are declared to be options/eithers, then you need to handle the empty case, but usually it's easier and better to just move that optional handling further up the callstack or type system.
A lot of `if (input == null)` checks are because you're just not sure whether the argument being passed in will have a value, and it's too much work for your small feature PR to refactor the whole codebase to resolve it.
Use typescript/python-with-mypy/haskell/rust/whatever and this problem mostly disappears.
> A lot of `if (input == null)` checks are because you're just not sure whether the argument being passed in will have a value, and it's too much work for your small feature PR to refactor the whole codebase to resolve it.
Null checks are totally fine, but it should be clear whether or not null is a valid input to the method. If the answer is 'no' then you should throw ArgumentNullException (or whatever's appropriate for the language), not silently ignore the bad input.
When I was a jr dev, getting exceptions was a synonymous of ”me messing something up”. Null exceptions were specially annoying, so the naive approach is to check for nulls and avoid the code that will cause the exception. And it “works”! You don’t get exceptions and your code keeps running. It’s just when you need to fix difficult bugs while you go through logs when you understand the value of having the right exception with the right message. And you learn to love them and start caring about them.
I guess this is because no one really teaches error handling. I assume a lot of students end up with a mindset of just make the errors go away instead of, deal with the errors effectively.