Simplest rule to figure out whether we need an exception is to think if having a stracktrace will give any value. For example, do we care about stacktrace when some business rule is violated?
One widely known principle is that exceptions should be used for programming errors. But what is a programming error? Maybe it is easier to understand if we say that exceptions should be used when something happens that cannot be avoided by using common knowledge. Common knowledge is something that we believe all well behaving consumers of our API should have.
For example, we can assume everybody to know that there are 31 days in December. So the following is a valid case to throw an exception:
newYearsEve = Date.of(32, 12, 2016)
Now lets say we have a library in our application that provides currency exchange rates. In this example this library only supports rates for EUR source. When client executes this API with GBP-USD then we could throw an exception. However, this is not a programming error as we cannot expect everybody to know about this constraint in the library. We can solve this by exposing the list of supported routes as well and have following API:
Rate getRate(Route route) boolean isSupported(Route route)
We are now exporting the knowledge about supported routes to client. This knowledge is certainly not part of common knowledge but by adding
isSupported we have made it possible for the client to easily acquire that knowledge. Hence here we could again opt for throwing an exception when
getRate gets called with an unsuppported route.
Read more about this topic: http://c2.com/cgi/wiki?AvoidExceptionsWheneverPossible