Don't trust... the other devs
Picture the situation. You've just spent 2 days trying to figure out a bug that randomly crash your application. You've nailed it down to a memory corruption somewhere, and you finally find that it's due to an out of bound access to an array. A single little assert you have saved you hours of heavy debugging...
This is a so common scenario in program development. One programmer coded some function assuming that the parameters would never be wrong. It worked fine for month, and then one day, another programmer adds a call to that function with bogus parameters. It will not crash instantly, instead causing the random crash later in the execution.
Whose's mistake is it? I'd like to think the answer to this is straightforward actually.
You could assume that the second programmer, the one who added the new call should be liable for this mess. While in my opinion, it's the first one that should be held responsible. Sure, his code was used with wrong parameters, but it was also his responsibility to check that the arguments would not cause random crash.
The idea is not to make sure that all the parameters actually make sense, because in most of the case, it would be impossible to check that, but at last check that all your memory access are within boundaries. A single assert can save you hours of work. Each time you access an array, assert that your index isn't negative, and not over your array size. Assert that your enums are not illegal values. Assert that your floats argument isn't NaN or anything like that.
Assert, assert, assert... but don't assert only in the low level functions, for example in sqrt. Okay, you probably want to check for the argument of sqrt to be positive, or not a NaN, but you also want to check what's happening in the meanwhile. You could get a NaN in sqrt because that spline function isn't properly checking if the points aren't too close to each other. So you might end up with an assert firing at the very end of the callchain, where it could have been caught way earlier, in an easier way.
On the other hand, you'll find yourself in situations that a parameters is wrong, but won't cause anything bad. Like when there have been an little issue with your data, your system detects the error, but can proceed anyway (like calling a function that will do nothing due to arguments). in that case, don't assert, but do a warning. There is nothing more annoying when tracing that being stopped every 5 seconds by an abusive assert that should have been a warning. Especially when it's caused by data and you can't do a thing about it anyway.
As a conclusion: try writing your code in a way where you never trust your fellow developers. Always check the arguments intelligently. Maybe create some different custom versions of "assert", where you can enable asserts on release mode for example, in a special "beta-enabled" build. That'd come in handy during beta tests of your code. Do a warning-version of asserts, in order to log that into a file, but continue the execution. Be always suspicious, in every little way. Always check for nulls when pointers are being passed as arguments.
That's just good programming practice.