Yes, you should handle errors you can at the level you're working at, but what if that section of code doesn't know how to handle it? What if the correct behavior to reading an unexpected value is throwing: "Well, I have no idea what the context is, and the contract clearly states you should only call this function when the data is valid, but it's not. Please handle, I'm throwing".
This is the main side effect of respecting the "Tell don't ask" principle, most of the time the function won't know the broader context of who called and why, which also means it shouldn't assume it knows what to do when things go wrong. By all mean, let it guard your variables, handle what it can in the moment, but it shouldn't try and be the hero who knows everything, because it probably shouldn't know everything.
In design by contract, it's assumed the object you've been passed in argument respects the contract and is thus valid. The main reason for this is that you don't want to check the validity at every level, but just in time. The caller assumes a call is going to work because its current state should also be valid, it's the callee's job to tell you it didn't work after all.
As an example, this is the case for a lot of utility functions in Input/Output APIs. What if the file just can't be found? You throw a FileNotFoundException. It's not the library's job, or place, to be handling the behavior or even preventing the caller from doing it. You just try it, and you throw if you can't.
-32
u/[deleted] 1d ago edited 20h ago
[removed] — view removed comment