I suppose this question is valid for any programming language that can handle (or at least throw) an exception
. However I will stick to Python as an example.
The top 2 answers to the following question disagree with each other on a particular point.
https://stackoverflow.com/questions/2052390/manually-raising-throwing-an-exception-in-python
At this moment (2015 March 14 Sat 2354 hrs) it seems that there’s a growing consensus around the second answer (Aaron Hall’s answer in case any of this changes in the future). And I think I do get the point about being specific about the type of exception I am supposed to raise. A hierarchy for Python is given here: https://docs.python.org/3/library/exceptions.html#exception-hierarchy
Now, I am at point where I want to manually raise an exception when a division results in a non-integer. Specifically, I have a 2D array and I also have the number of columns in it. If the division of the former by the latter results in an non-integer, it means that the number of rows is a non-integer, and thus something’s messed up somewhere. And I want to raise an exception
.
Why would it be wrong to just include raise Exception("Something's wrong. Number of rows is not an integer!")
in my code? The categories in the hierarchy are just words in English, but I am not able to choose the best category for my purpose. So what’s wrong in clearly explaining the issue in my message (which for the present example is the problem that the number of rows is not an integer)?
4
You are creating a user interface — code is a user interface, where the “user” is another programmer, or another function. If you were the user of your code rather than the developer, what would make your code easier to use? So, look at this problem from the perspective of someone calling your function. What would be the most useful exception you could give? Note: there may be more than one answer, in which case it really doesn’t matter too much. The point is, make your code as easy to use as possible.
The other important thing to remember is this: you may be only sending one exception, but your code as a whole could be sending many. The exception you throw needs to play nicely with all of the other possible exceptions (meaning: it must be distinguishable from the other exceptions).
In this specific case (and in most cases…), a generic exception isn’t particularly useful. There could be more than one way that your function fails. Maybe the inputs are floats instead of integers. Maybe they are strings. Or maybe the inputs result in a divide by zero. The caller may care about these distinctions. Maybe they won’t, but they might. And if not now, they might in the future.
Raising a generic xception and differentiating it just by its message would be wrong because then, if you have many of them and want to react appropriately, how would you distinguish them?
Regarding the choice of the exception, taking your example, I would say that ArithmeticError
is something pretty low-level and focused on the arithmetic aspects of the problem. In your case, is it an arithmetic error the fact that 7 is not divisible by 3? No, arithmetically it’s correct.
That’s a problem if taken from another point of view, namely the one of your application logic, so such exception would make sense only in your application. I would make my own one (e.g. NonDivisibleTableError
derived from Exception
).
Now, how could that happen? That’s another issue, but a quick search showed that also in Python it’s possible to specify a cause when throwing an exception (see raise/from). This way you can describe what went wrong at the different levels of your application, (e.g. NonDivisibleTableError
caused by some IOError
), and give the user a more reasoned error message.