Often when I write a functions I want to make sure the inputs to it are valid in order to detect such errors as early as possible (I believe these are called preconditions). When a precondition fails, I've always thrown an exception. But I'm beginning to doubt whether this is the best practice and if not assertions would be more appropriate.

So when should I do which: when is it appropriate to use an assertion and when is it appropriate to throw an exception?

Assertions should only be used to verify conditions that should be logically impossible to be false (read: sanity checks). These conditions should only be based on inputs generated by your own code. Any checks based on external inputs should use exceptions.

A simple rule that I tend to follow is verifying private functions' arguments with asserts, and using exceptions for public/protected functions' arguments.
