zlacker

[return to "Patterns for Defensive Programming in Rust"]
1. quotem+5O[view] [source] 2025-12-05 20:18:59
>>PaulHo+(OP)
The tech industry is full of brash but lightly-seasoned people resurrecting discredited ideas for contrarianism cred and making the rest of us put down monsters we thought we'd slain a long time ago.

"Defensive programming" has multiple meanings. To the extent it means "avoid using _ as a catch-all pattern so that the compiler nags you if someone adds an enum arm you need to care about", "defensive" programming is good.

That said, I wouldn't use the word "defensive" to describe it. The term lacks precision. The above good practice ends up getting mixed up with the bad "defensive" practices of converting contract violations to runtime errors or just ignoring them entirely --- the infamous pattern in Java codebases of scrawling the following like of graffiti all over the clean lines of your codebase:

  if (someArgument == null) { 
    throw new NullPointerException("someArgument cannot be null");
  }
That's just noise. If someArgument can't be null, let the program crash.

Needed file not found? Just return ""; instead.

Negative number where input must be contractually not negative? Clamp to zero.

Program crashing because a method doesn't exist? if not: hasattr(self, "blah") return None

People use the term "defensive" to refer to code like the above. They programs that "defend" against crashes by misbehaving. These programs end up being flakier and harder to debug than programs that are "defensive" in that they continually validate their assumptions and crash if they detect a situation that should be impossible.

The term "defensive programming" has been buzzing around social media the past few weeks and it's essential that we be precise that

1) constraint verification (preferably at compile time) is good; and

2) avoidance of crashes at runtime at all costs after an error has occurred is harmful.

◧◩
2. ipsi+wQ2[view] [source] 2025-12-06 16:30:34
>>quotem+5O
The Java one can actually be quite helpful, for a couple of reasons:

1. It tells you which variable is null. While I think modern Java will include that detail in the exception, that's fairly new. So if you had `a.foo(b.getBar(), c.getBaz())`, was a, b, or c null? Who knows!

2. Putting it in the constructor meant you'd get a stack trace telling you where the null value came from, while waiting until it was used made it a lot harder to track down the source.

Not applicable to all situations, but it could be genuinely helpful, and has been to me.

[go to top]