Ixrec's answer is good, but I will take a different approach because I believe that it is worth considering. For the purpose of this discussion I will be talking about assertions, since that's the name by which your Preconditions.checkNotNull()
has traditionally been known.
What I would like to suggest is that programmers often overestimate the degree by which they are certain that something will behave in a certain way, and underestimate the consequences of it not behaving that way. Also, programmers often do not realize the power of assertions as documentation. Subsequently, in my experience, programmers assert things far less often than they should.
My motto is:
The question you should always be asking yourself is not "should I
assert this?" but "is there anything I forgot to assert?"
Naturally, if you are absolutely sure that something behaves in a certain way, you will refrain from asserting that it did in fact behave that way, and that's for the most part reasonable. It is not really possible to write software if you cannot trust anything.
But there are exceptions even to this rule. Curiously enough, to take Ixrec's example, there exists a type of situation where it is perfectly desirable to follow int i = 3;
with an assertion that i
is indeed within a certain range. This is the situation where i
is liable to be altered by someone who is trying various what-if scenarios, and the code which follows relies on i
having a value within a certain range, and it is not immediately obvious by quickly looking at the following code what the acceptable range is. So, int i = 3; assert i >= 0 && i < 5;
might at first seem nonsensical, but if you think about it, it tells you that you may play with i
, and it also tells you the range within which you must stay. An assertion is the best type of documentation, because it is enforced by the machine, so it is a perfect guarantee, and it gets refactored together with the code, so it remains always pertinent.
Your getUser(int id)
example is not a very distant conceptual relative of the assign-constant-and-assert-in-range
example. You see, by definition, bugs happen when things exhibit behavior which is different from the behavior that we expected. True, we cannot assert everything, so sometimes there will be some debugging. But it is a well established fact in the industry that the quicker we catch an error, the less it costs. The questions you should ask are not only how sure you are that getUser()
will never return null, (and never return a user with a null name,) but also, what kinds of bad things will happen with the rest of the code if it does in fact one day return something unexpected, and how easy it is by quickly looking at the rest of the code to know precisely what was expected of getUser()
.
If the unexpected behavior would cause your database to become corrupt, then maybe you should assert even if you are 101% sure it won't happen. If a null
user name would cause some weird cryptic untraceable error thousands of lines further down and billions of clock cycles later, then perhaps it is best to fail as early as possible.
So, even though I do not disagree with Ixrec's answer, I would suggest that you seriously consider the fact that assertions cost nothing, so there is really nothing to be lost, only to be gained, by using them liberally.
Null
)? It's probably equally problematic if the name is""
(not null but the empty string) or"N/A"
. Either you can trust the result, or you have to be appropriately paranoid.