When I code, I often ask myself the same question :
Do I have to verify all arguments are not null ? So, in each method, I will have something like that :
if (arg1 == null)
{
throw FooException("...");
}
if (arg2 == null)
{
throw FooException("...");
}
If not, in which case is preferable ?
What's the best practices ?
As always, it depends.
If you're writing an API to be used by other teams / organizations, such defensive programming with precondition checks on public functions can really help your users; when using an external library, a meaningful error message like 'argument passed to foo() should not be null' is way better than NullPointerException thrown from some inner class.
Outside of API, though, I think such checks clutter the code too much. Thrown NullPointerExceptions are usually pretty easy to trace with debugger anyway. In languages that support them, you can consider using assertions - their syntax is usually less cumbersome, and you can turn them off on production so the checks won't degrade performance.
Unfortunetly, yes. you should check all arguments. Now ideally, if you code with good design practices one function should not have more than 4 or 5 arguments, at the most.
Having said that, one should always check for null values in function entry and throw appropriate exception or IllegalArgumentException (my fav).
Furhter, one should never pass NULL to a function and should never return a NULL. Sounds simple but it will save lots of code and bugs. Have a look at the NULL Design Pattern too.
Depends, if you want different exceptions i guess you would have to do that for all occasions where you might get a null value. Another way would be to user DATATYP.TryParse(). Look that up.
Hope it helps.
Since you're throwing an exception anyway, not verifying them would probably just lead to a nullpointerexception or something similar. I'm not entirely sure what the best practices are myself.
You should ideally always verify any arguments before you perform any action that might modify any state or data associated with said arguments. It's better to fail early and in a manageable way (by throwing a exception) than to end up with an inconsistent state / data which then also has to be resolved.
Your methods are expecting certain data to be there, there are some cases when it should be safe to assume that it is actually there (say inside a private method, which is called from other methods which validate input). However in general I would recommend validating arguments whenever they are:
Supplied by a user.
Supplied as part of an API.
Passed between modules of a system .
It's might be worth taking a look at this previous StackOverflow question.
I feel it's mostly down to common sense, and a little down to personal preference.
As others have mentioned, if it's a public API then you want to provide clear error messages wherever possible, so it's best to check parameters before they are used and throw exceptions with messages as per your example.
If it's internal code then there are two other options to think about: use assertions, or don't bother with the validation and rely on debugging. As a rule of thumb, I'll put assertions in if it's code that I expect other developers will be calling or if the condition is subtle enough that debugging it might be a pain. Otherwise, I'll just allow it to fail.
Sometimes you can avoid the issue by using the Null Object pattern. If it's a public API I'd still be inclined to include the checks though.
Related
I am starting to add tests to a large java code base. I often see the following in the session beans I am testing:
public OrderDTO getOrderDTO(Long id) {
Order o = (Order)entityManager.find(Order.class, id);
OrderDTO dto = new OrderDTO(o.getId(), o.getCurrency());
return dto;
}
Its quit easy to write a unit test to break this code (send in a null or a non existing id). When I did that half the developers of the team said:
We are not error checking everything. If you parameter is rubbish you will know fast!
The other half said:
We must add ifs to the id and then to the o and if any of them are null the null is what we return.
Isn't the point of unit testing to find exactly thees kind of issues?
(Yes, I am asking for an opinion!)
Yes, switching from Long to long will remove one if.
While this is somewhat opinion based, few people would say it's correct to return null if given null as a parameter. If I were to add anything, it would be at most a IllegalArgumentException (or even NPE) when null is passed in.
A test could be created to check that the method fails in a consistent fashion, but it would really be testing the behaviour of the JPA provider and not your code.
Returning nulls should be avoided, they are the source of all evil.
You could use the Null Object Pattern.
Or throw an exception, illegalargument or entitynotexsits spring to mind.
If you must return null, at least wrap it in an optional or use guava.
As always, it depends :)
If you are writing library code (code that is shared and used elsewhere or even by others), then you should really aim for handling all thinkable input values in a consistent way. Using well documented exceptions instead of returning null is certainly preferable for library code.
On the other hand there is local code.
I can see the method is public, but that does not eliminate the possibility that it's only used in one isolated portion of the code base.
In that case, you don't work with assumptions about parameters and what the caller expects in return. You work with defined calls. You control what is sent in and how the caller handles the return value. So it's OK not to null-check, if you know the caller never sends null. And it can be OK to return null as well if that simplifies your overall program structure.
ps: what bothers me most in that method is the unhandled NPE if entityManager.find(..) fails :)
Example #1:
try { fileChooser.setSelectedFile(new File(filename)); }
catch (NullPointerException e) { /* do nothing */ }
Example #2:
if (filename != null)
fileChooser.setSelectedFile(new File(filename));
Is #1 inherently bad, for performance or stability (or any other reasons), or is it just a little different? This isn't a very good example because there are no advantages to #1 over #2, but under different circumstances there could be (e.g. improved readability, fewer lines of code, etc.).
Edit: The consensus seems to be that #1 is a no-no. Most popular reason: Overhead
Also, #Raph Levien had a good insight:
One reason to avoid #1 is that it poisons your ability to use exception breakpoints. Normal-functioning code will never purposefully trigger a null pointer exception. Thus, it makes sense to set your debugger to stop every time one happens. In the case of #1, you'll probably get such exceptions routinely. There's also a potential performance impact, among other good reasons.
Also, See Link for more depth.
Definitely #2 is a better choice. Exception handling should not be used as a construct in the control flow of your program. Exceptions should be used to handle situations that are not under the control of the programmer. In this example, you can check if the fileChooser is null so that is under your control.
Exceptions do bring a certain amount of overhead with them. If they can be avoided, in this case by simply checking for a null, that would be preferred.
As has been said by others, it is also generally bad practice to use Exceptions for flow control. For a detailed explanation of why this is bad, check out this.
Here is a short blurb from that answer:
Exceptions are basically non-local goto statements with all the consequences of the latter. Using exceptions for flow control violates a principle of least astonishment, make programs hard to read (remember that programs are written for programmers first).
Don't use Exception to control logic flow.
Never swallow Exception. #1 violates it- you'll never know if NPE is from fileChooser==null or fileName==null.
If a null value is logically allowed by your program, test for it. Otherwise use exceptions. Exceptions are meant to deal with exceptional conditions (surprise!) and shouldn't be used for program logic.
One reason to avoid #1 is that it poisons your ability to use exception breakpoints. Normal-functioning code will never purposefully trigger a null pointer exception. Thus, it makes sense to set your debugger to stop every time one happens. In the case of #1, you'll probably get such exceptions routinely. There's also a potential performance impact, among other good reasons.
I'd go for option #3 - if filename is passed as a function argument, put a note in the comments that a null filename is not allowed. Then just work with the assumption that filename is never null:
fileChooser.setSelectedFile(new File(filename));
If some idiot (or you, <3) ignores your comment and ''does'' pass a null, he'll get a NullPointerException and has to fix the problem.
In the client code, ensure that no nulls are passed by always initializing or defaulting the fileName to an empty string.
I've been avoiding using and accepting nulls for a while now, and my code is much cleaner now that there aren't as much null checks in it anymore. The only null checks still present are those where I call third-party code that may return null.
(rant: Of course, I have to decompile said third-party code and determine that myself, considering the documentation is either not present or doesn't make note of it possibly returning null)
Your two examples are not semantically equivalent in the following cases:
fileChooser is null
setSelectedFile throws a NullPointerException (granted, this can't happen with this particular method, but in general it's quite possible for a setter to store stuff in some other object, which will throw if the reference for that other object was not initialized)
new File() throws a NullPointerException for reasons other than filename being null
Probably, the /* do nothing */ was intended only for the case where filename is null, but now hides the other cases too, whereas good exception handling would allow these exception to bubble up the call stack, alerting you to the presence and cause of a bug you would otherwise find difficult to track down.
I find this the by far more compelling reason than performance, because wasted programmer time is a lot more expensive than wasted cpu time.
I'm wondering about the cost of using a try/exception to handle nulls compared to using an if statement to check for nulls first.
To provide more information. There's a > 50% chance of getting nulls, because in this app. it is common to have a null if no data has been entered... so to attempt a calculation using a null is commonplace.
This being said, would it improve performance if I use an if statement to check for null first before calculation and just not attempt the calculation in the first place, or is less expensive to just let the exception be thrown and handle it?
thanks for any suggestions :-)
Thanks for great thought provoking feedback! Here's a PSEUDOcode example to clarify the original question:
BigDecimal value1 = null //assume value1 came from DB as null
BigDecimal divisor = new BigDecimal("2.0");
try{
if(value1 != null){ //does this enhance performance?... >50% chance that value1 WILL be null
value1.divide(divisor);
}
}
catch (Exception e){
//process, log etc. the exception
//do this EVERYTIME I get null... or use an if statement
//to capture other exceptions.
}
I'd recommend checking for null and not doing the calculation rather than throwing an exception.
An exception should be "exceptional" and rare, not a way to manage flow of control.
I'd also suggest that you establish a contract with your clients regarding input parameters. If nulls are allowed spell it out; if they're not, make it clear what should be passed, default values, and what you promise to return if a null value is passed.
If passing null argument is an exceptional case, then I'd throw a NullPointerException.
public Result calculate(Input input) {
if (input == null) throw new NullPointerException("input");
// ...
}
If passing null is an allowed case, then I'd skip the calculation and eventually return null. But that makes in my opinion less sense. Passing null in first instance would seem a bug in the calling code.
Whatever way you choose, it should be properly documented in the Javadoc to avoid surprises for the API user.
Try and catch are close to "free" but throws can be very expensive. Typically VM creators do not optimize exception paths since, well, they are exceptional (supposed to be rare).
NullPointerException indicates a programmer mistake (RuntimeException) and should not be caught. Instead of catching the NullPointerException you should fix your code to cause the exception not to be thrown in the first place.
Worse yet, if you catch the NullPointerException and a different part of the calculation code throws NullPointerException than the one you expect to throw it you have now masked a bug.
To fully answer your question, I would implement it one way, profile it, and then implement it the other way and profile it... then I would only use the one with the if statement that avoids throwing the NullPointerException regardless of which is faster simply because of the point above.
If there's a >50% chance of getting a null, then it's hardly an exception?
Personally, I'd say that if you expect something to happen, you should code for it appropriately - in this case, checking for null and doing whatever is appropriate. I've always understood throwing an exception to not be exceedingly cheap, but couldn't say for certain.
I agree with most of the other responses that you should prefer the null check to the try-catch. And I've upvoted some of them.
But you should try to avoid the need as much as possible.
There's a > 50% chance of getting nulls, because in this app. it is common to have a null if no data has been entered... so to attempt a calculation using a null is commonplace.
That's what you should really be fixing.
Come up with sensible default values that ensure the computation works or avoid calling a computation without supplying the needed input data.
For many of the standard data types and computations involving them there are sensible default values. Default numbers to 0 or 1 depending on their meaning, default strings and collections to empty, and many computations just work. For more complex objects of your own making, consider the Null Object pattern.
If you have any case where a result or input can't be handled by you program then that should be an error. You should know what you program can handle and allow only that. In regards to possible future cases where a result could be handled but isn't yet I would still suggest considering it an error until you actually need that result. If in doubt, you don't know, the program doesn't know, it can't be handled, you haven't equipped your program to handle it so it's an error. The program can't do anything more but to stop.
For user input it is a very bad idea to rely on your program to eventually crash. You don't know when or even if it will crash. It might just end up doing the wrong thing or do ten things then crash that it shouldn't have done and wouldn't have done if input had been validated.
In terms of guarding against your own mistakes that is more of a mixed bag. You'll want to focus a lot more on making sure things work by testing, eliminating unknowns, proof reading, making sure you know exactly how your program works, etc. Still you'll occasionally have cases where internal processing might produce undesirable results.
When it turns out a result isn't an error for a given case you do not handle the exception, you handle null, not an exception. In that case the result is not an error. So you handle the result and not the error. It could not be simpler. If you're catching an exception and then doing something that can be done with an if such as:
try
extra = i_need_it(extra_id)
show('extra', extra)
catch
show('add_extra')
Then that is not right. You have a perfectly acceptable course of action if you don't have the extra thing.
This is much better and it keeps your intention clear without the extra verbosity:
Something extra = i_want_it(extra_id)
if extra ==== null
show('add_extra')
else
show('extra', extra)
Notice here you need nothing special to avoid catching an exception from another layer. How I put try catch above is a bad practice. You should only be wrapping the thing that throws an exception:
Something extra
try
extra = i_need_it(extra_id)
if extra === null
show('add_extra')
else
show('extra', extra)
When you thing about it like that then it is just converting null to exception and then back again. This is Yo-Yo coding.
You should start with:
Object i_need_it(int id) throws
Until you are actually able to implement handling for null. If you're able to implement handling for the exception you can implement the handling for the null.
When it turns out that something isn't always needed either add this method or change i_need_it to it (if null is always handled):
Object|null i_want_it(int id)
An alternative is to check is it exists first:
bool does_it_exist(int id)
The reason this isn't done so often is because it usually comes out like this:
if(does_it_exist(id))
Something i_need = i_need_it(id)
This tends to be more prone to concurrency problems, can require more calls that might be unreliable (IO over network) and can be inefficient (two RTTs rather than one). Other calls are often merged like this such as update if exists, insert if unique, update if exists or insert, etc that then return what would normally be the result of instead initially checking. Some of these have conflicts over payload size efficiency and RTT efficiency which can also vary based on a number of factors.
It is cheaper however when you need alternating behaviour based on if something exists or not but you don't need to work on it. If you also don't need to worry about the above concerns it's a bit clearer.
You may even want:
void it_must_exist(int id) throws
This is again useful because if you need only ensure something exists it's often cheaper than getting it. However it's rare you'll need this as in most cases you'll want to know if something exists so to directly work on it.
A way to conceive it is that you wouldn't make 'does_it_exist' throw an exception when it can simply return a boolean explicitly up the call stack, 'i_want_it' is a combined 'has' and 'get' in effect.
While having two separate methods more clearly separates method signatures, sometimes you may need to pass down from something else and the simplest way for that if you don't mine a bit of ambiguity is:
Object|null get(int id, bool require) throws
This is better as you're handing the contract down the call chain rather than building on a house of sand based on action at a distance. There are ways to pass down your contract more explicitly but it tends to be convoluted YAGNI (IE, pass down a method caller).
You should throw exceptions early and you can want to be safe rather than sorry so false positives are fine. Once you discover it's a false positive though then you fix it at the source.
It should be extremely rare that you're handling exceptions at all. The sheer majority should hit the top, then invoke a logging and output handler. The rest you fix appropriately by passing back the result directly and handling it. When you have one false positive out of many uses, only this that use. Don't just remove the check in the root and break the many other cases where it's still an error.
Java is an unfortunate language because I you can't have a way of saying don't pass null or this variable must be non-null.
When such a feature is lacking, It's often best to check for nulls at their sources, things such as IO rather than for every time something is passed to one of your methods. Otherwise that's an absurd amount of null checking.
You can apply this pattern to create functions to replace your ifs for parameter checking if you really need that. You would replace id with the object itself such as:
Object i_want(Object it) throws
if(it === null)
throw
return it;
Then:
void give_me(Object it)
this.it = Lib<Object>::i_want(it)
A shame there's no passthru type.
Or:
void i_get_it(Getter<Object> g)
this.it = Lib<Object>::i_want(g.gimme())
You might have a specific Getter rather than with generic.
Or:
void i_need_it(Result<Object> r)
this.it = r.require()
If you only do it on the boundary instead (when you call things out side of your control where non-null result can't be guaranteed), while it is preferred to do it there or for any usage of a method documented as returning null and only there as that's where it's really only needed, that does mean that when you do get a null where it doesn't belong (mistakes happen) you're not going to have an easy time finding out where it came from. It can get passed around a lot from IO and not produce a null pointer exception until something tries to operate on it. Such nulls can be passed around the system for days or even months as a ticking time bomb waiting to go off.
I wouldn't do it myself but I wouldn't blame people in some cases for implementing the defensive programming approach above which might be required due to Java's broken type system which is loose by default and can't be restricted. In robustly typed languages, null isn't permitted unless you explicitly say it is.
Please be advised that although I call it broken, I have been typically using significantly looser languages heavily for decades to build large, complex and critical systems without having to litter the codebase with superfluous checks. Discipline and competence are what determine quality.
A false positive is when a result or a condition occurs that you assume is a result that can't be handled by all callers but it turns out that at least one caller can handle it appropriately. In that case you don't handle the exception but instead give the caller the result. There are very few exceptions to this.
Java 8 has Optional but it doesn't really look helpful. It's a horrific case of the inner platform effect trying to implement new syntax as classes and ending up having to add half of the existing Java syntax along with it making it very clunky. As usual modern Java OOP, solves every problem of people wanting less fudge by adding more fudge and over complicating things. If you really want chaining like that you might want to try something such as kotlin which implements that syntax directly.
A modern language will mean you don't have to worry about most of this and just have:
void i_need_it(Object it)
this.it = it
void i_want_it(Object? it)
this.it = it
A modern language might even return the original object for a method without a return (replace void with self as the standard and auto-return) so people can have their fancy chaining or whatever else is fashionable these days in programming.
You can't have a factory with a base class that gives you a Null or NotNull either because you'll still have to pass the base class and that'll be a type violation when you say you want NotNull.
You might want to play around with aspects, static analysis, etc although that's a bit of a rabbit hole. All documentation should indicate if null can be returned (although if indirectly the it can potentially be left out).
You can make a class such as MightHave to wrap your result where you can put on methods like get, require and has if you don't like statics but want to eat an if although it's also in the realm of mildly convoluted and messing with all of your method signatures everywhere boxing everything all over the place, an ugly solution. It's only really handy as an alternative to those rare exception handling cases where exceptions do seem useful due to the complexity of the call graph and the number of unknowns present across layers.
One exceptionally rare case is when your source knows what exception to throw but not if it needs to be thrown but it's hard to pass down (although coupling two layers at a distance where anything can happen in between needs to be approached with caution). Some people might also want this because it can easily give a trace of both where the missing item came from and where it was required which is something using checks might not give (they're likely to fail close to the source but not guaranteed). Caution should be taken as those kinds of problems might be more indicative of poor flow control or excessive complexity than an issue with justified polymorphism, meta/dynamic coding and the like.
Caution should be taken with things such as defaults or the Null Object pattern. Both can end up hiding errors and becoming best guesses or a cure worse than the disease. Things such a NullObject pattern and Optional can often be used to simply turn off or rather bi-pass the inbuilt error handling in your interpreter.
Defaults aren't always bad but can fall into the realm of guessing. Hiding errors from the user end up setting them up to fail. Defaults (and sanitisation) always need to be thought out carefully.
Things such as NullObject pattern and Optional can be overused to effectively turn off null pointer checking. It simply makes the assumption that null is never an error which ends up with programs doing somethings, not others but you know not what. In some cases this might have hilarious results such as if the user's credit card is null. Make sure if you're using such things you're not using them to the effect of simply wrapping all of your code in a try catch that ignores a null pointer exception. This is very common because people tend to fix errors where the exception was thrown. In reality the real error tends to be further away. You end up with one piece of faulty IO handling that erroneously returns null and that null gets passed all around the program. Instead of fixing that one source of null, people will instead try to fix it in all the places it reaches where it causes an error.
NullObject pattern or MagicNoop patterns have their place but are not for common use. You shouldn't use them until it becomes immediately apparent they are be useful in a justified manner that isn't going to cause more problems than it solves. Sometimes a noop is effectively an error.
Most of the time I will use an exception to check for a condition in my code, I wonder when it is an appropriate time to use an assertion?
For instance,
Group group=null;
try{
group = service().getGroup("abc");
}catch(Exception e){
//I dont log error because I know whenever error occur mean group not found
}
if(group !=null)
{
//do something
}
Could you indicate how an assertion fits in here? Should I use an assertion?
It seems like I never use assertions in production code and only see assertions in unit tests. I do know that in most cases, I can just use exception to do the checking like above, but I want to know appropriate way to do it "professionally".
Out of my mind (list may be incomplete, and is too long to fit in a comment), I would say:
use exceptions when checking parameters passed to public or protected methods and constructors
use exceptions when interacting with the user or when you expect the client code to recover from an exceptional situation
use exceptions to address problems that might occur
use assertions when checking pre-conditions, post-conditions and invariants of private/internal code
use assertions to provide feedback to yourself or your developer team
use assertions when checking for things that are very unlikely to happen otherwise it means that there is a serious flaw in your application
use assertions to state things that you (supposedly) know to be true
In other words, exceptions address the robustness of your application while assertions address its correctness.
Assertions are designed to be cheap to write, you can use them almost everywhere and I'm using this rule of thumb: the more an assertion statement looks stupid, the more valuable it is and the more information it embeds. When debugging a program that does not behave the right way, you will surely check the more obvious failure possibilities based on your experience. Then you will check for problems that just cannot happen: this is exactly when assertions help a lot and save time.
Assertions should be used to check something that should never happen, while an exception should be used to check something that might happen.
For example, a function might divide by 0, so an exception should be used, but an assertion could be used to check that the harddrive suddenly disappears.
An assertion would stop the program from running, but an exception would let the program continue running.
Note that if(group != null) is not an assertion, that is just a conditional.
Remember assertions can be disabled at runtime using parameters, and are disabled by default, so don't count on them except for debugging purposes.
Also you should read the Oracle article about assert to see more cases where to use - or not to use - assert.
As a general rule:
Use assertions for internal consistency checks where it doesn't matter at all if someone turns them off. (Note that the java command turns off all assertions by default.)
Use regular tests for any kind of checks what shouldn't be turned off. This includes defensive checks that guard against potential damage cause by bugs, and any validation data / requests / whatever provided by users or external services.
The following code from your question is bad style and potentially buggy
try {
group = service().getGroup("abc");
} catch (Exception e) {
//i dont log error because i know whenever error occur mean group not found
}
The problem is that you DON'T know that an exception means that the group was not found. It is also possible that the service() call threw an exception, or that it returned null which then caused a NullPointerException.
When you catch an "expected" exception, you should catch only the exception that you are expecting. By catching java.lang.Exception (and especially by not logging it), you are making it harder to diagnose / debug the problem, and potentially allowing the app to do more damage.
Well, back at Microsoft, the recommendation was to throw Exceptions in all APIs you make available publicly and use Asserts in all sorts of assumptions you make about code that's internal. It's a bit of a loose definition but I guess it's up to each developer to draw the line.
Regarding the use of Exceptions, as the name says, their usage should be exceptional so for the code you present above, the getGroup call should return null if no service exists. Exception should only occur if a network link goes down or something like that.
I guess the conclusion is that it's a bit left down to the development team for each application to define the boundaries of assert vs exceptions.
According to this doc http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general, "The assert statement is appropriate for nonpublic precondition, postcondition and class invariant checking. Public precondition checking should still be performed by checks inside methods that result in particular, documented exceptions, such as IllegalArgumentException and IllegalStateException."
If you want to know more about precondition, postcondition and class invariant, check this doc: http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions. It also contains with examples of assertions usage.
Testing for null will only catch nulls causing problems, whereas a try/catch as you have it will catch any error.
Broadly, try/catch is safer, but slightly slower, and you have to be careful that you catch all the kinds of error that may occur. So I would say use try/catch - one day the getGroup code may change, and you just might need that bigger net.
You can use this simple difference in mind while their usage. Exceptions will be used for checking expected and unexpected errors called checked and unchecked error while assertion is used mainly for debugging purposes at the run time to see whether the assumptions are validated or not.
Unfortunately asserts can be disabled. When in production you need all the help you can get when tracking down something unforeseen, so asserts disqualify themselves.
I confess I'm a little confused by your question. When an assertion condition is not met, an exception is thrown. Confusingly this is called AssertionError. Note that it's unchecked, like (for example) IllegalArgumentException which is thrown in very similar circumstances.
So using assertions in Java
is a more concise means of writing a condition/throw block
permits you to turn these checks on/off via JVM parameters. Normally I would leave these checks on all the time, unless they impact runtime performance or have a similar penalty.
See section 6.1.2 (Assertions vs. other error code) of Sun's documentation at the following link.
http://www.oracle.com/technetwork/articles/javase/javapch06.pdf
This document gives the best advice I've seen on when to use assertions. Quoting from the document:
"A good rule of thumb is that you should use an assertion for exceptional cases that you would like to forget about. An assertion is the quickest way to deal with, and forget, a condition or state that you don’t expect to have to deal with."
I’m not experienced with Java asserts but I think the answer here naturally follows from what Java asserts are:
Code that is only run if enabled
Disabled by default
Thus we can surmise that assertions should never be used to implement application logic: it should only be used as optional (because of the on/off feature) sanity checks/explicit assumptions. The correctness of your app (modulo bugs!) cannot depend on a runtime flag which is turned off by default.
So only use assertions to check internal assumptions (your own code only, not things that are out of your control like user input). But on the other hand you might sometimes want to use exceptions to check your assumptions; if you want to always check a certain assumption then you don’t need the on/off feature that assertions provide.
For the task of checking assumptions, it seems that assertions excel when:
The check might be costly so you want the option of disabling it
Using if-or-throw would be too much “noise” but you can bear the cost of one little assert <expr>
You want to leave a little comment which merely states something like:
// NOTE we KNOW that `x` is not null!
x.doWork();
Then the Java folks say that you should always replace that line with:
assert x != null;
x.doWork();
Or (in my opinion) if you prefer:
if (x == null) {
throw new IllegalStateException("shouldn’t be null");
}
x.doWork();
Things that follow from these principles
I think we can immediately expand on related principles (sibling answer) by using this “optional” principle (my gloss in cursive):
use exceptions when checking parameters passed to public or protected methods and constructors
Because you are checking things outside your code: code coming into your module
use exceptions when interacting with the user or when you expect the client code to recover from an exceptional situation
Because the input is from the user and has nothing to do with your code. Also assertions are not really something you are supposed to recover from.(†1)
use exceptions to address problems that might occur
I.e. errors that happen as a matter of course: not bugs in your code
use assertions when checking pre-conditions, post-conditions and invariants of private/internal code
Because it’s your own code: problems inside your own code are self-caused
use assertions to provide feedback to yourself or your developer team
Bugs are for developers to deal with
use assertions when checking for things that are very unlikely to happen otherwise it means that there is a serious flaw in your application
Key word “serious flaw in your application”
use assertions to state things that you (supposedly) know to be true
Checking assumptions
Notes
I think this is a general opinion. See also (my bold):
Why is AssertionError a subclass of Error rather than RuntimeException?
This issue was controversial. The expert group discussed it at length, and came to the conclusion that Error was more appropriate to discourage programmers from attempting to recover from assertion failures.
Finally, I have a question to ask on Stack Overflow! :-)
The main target is for Java but I believe it is mostly language agnostic: if you don't have native assert, you can always simulate it.
I work for a company selling a suite of softwares written in Java. The code is old, dating back to Java 1.3 at least, and at some places, it shows... That's a large code base, some 2 millions of lines, so we can't refactor it all at once.
Recently, we switched the latest versions from Java 1.4 syntax and JVM to Java 1.6, making conservative use of some new features like assert (we used to use a DEBUG.ASSERT macro -- I know assert has been introduced in 1.4 but we didn't used it before), generics (only typed collections), foreach loop, enums, etc.
I am still a bit green about the use of assert, although I have read a couple of articles on the topic. Yet, some usages I see leave me perplex, hurting my common sense... ^_^ So I thought I should ask some questions, to see if I am right to want to correct stuff, or if it goes against common practices. I am wordy, so I bolded the questions, for those liking to skim stuff.
For reference, I have searched assert java in SO and found some interesting threads, but apparently no exact duplicate.
How to avoid “!= null” statements in java? and How much null checking is enough? are quite relevant, because lot of asserts we have just check if variable is null. At some places in our code, there are usages of the null object (eg. returning new String[0]) but not always. We have to live with that, at least for maintenance of legacy code.
Some good answers also in Java assertions underused.
Oh, and SO indicates with reason that When should I use Debug.Assert()? question is related too (nice feature to reduce duplicates!).
First, main issue, which triggered my question today:
SubDocument aSubDoc = documents.GetAt( i );
assert( aSubDoc != null );
if ( aSubDoc.GetType() == GIS_DOC )
{
continue;
}
assert( aSubDoc.GetDoc() != null );
ContentsInfo ci = (ContentsInfo) aSubDoc.GetDoc();
(Yes, we use MS' C/C++ style/code conventions. And I even like it (coming from same background)! So sue us.)
First, the assert() form comes from conversion of DEBUG.ASSERT() calls. I dislike the extra parentheses, since assert is a language construct, not (no longer, here) a function call. I dislike also return (foo); :-)
Next, the asserts don't test here for invariants, they are rather used as guards against bad values. But as I understand it, they are useless here: the assert will throw an exception, not even documented with a companion string, and only if assertions are enabled. So if we have -ea option, we just have an assertion thrown instead of the regular NullPointerException one. That doesn't look like a paramount advantage, since we catch unchecked exceptions at highest level anyway.
Am I right supposing we can get rid of them and live with that (ie. let Java raise such unckecked exception)? (or, of course, test against null value if likely, which is done in other places).
Side note: should I have to assert in the above snippet, I would do that against ci value, not against the getter: even if most getters are optimized/inlined, we cannot be sure, so we should avoid calling it twice.
Somebody told, in the last referenced thread, that public methods should use tests against values of parameters (usage of the public API) and private methods should rely on asserts instead. Good advice.
Now, both kinds of methods must check another source of data: external input. Ie. data coming from user, from a database, from some file or from the network, for example.
In our code, I see asserts against these values. I always change these to real test, so they act even with assertions disabled: these are not invariants and must be properly handled.
I see only one possible exception, where input is supposed constant, for example a database table filled with constants used in relations: program would break if this table is changed but corresponding code wasn't updated.
Do you see other exceptions?
Another relatively frequent use I see, which seems OK: in the default of a switch, or at the end of a series of else if testing all possible values (these cases date back before our use of enums!), there is often an assert false : "Unexpected value for stuff: " + stuff;
Looks legitimate for me (these cases shouldn't happen in production), what do you think? (beyond the "no switch, use OO" advices which are irrelevant here).
And finally, are there any other useful use cases or annoying gotchas I missed here? (probably!)
The number one rule is to avoid side-effects in assertions. In other words, the code should behave identically with assertions turned off as it does when assertions are turned on and not failing (obviously assertions that fail are going to alter the behaviour because they will raise an error).
The number two rule is not to use assertions for essential checks. They can be turned off (or, more correctly, not turned on). For parameter-checking of non-private methods use IllegalArgumentException.
Assertions are executable assumptions. I use assertions to state my beliefs about the current state of the program. For example, things like "I assume that n is positive here", or "I assume that the list has precisely one element here".
I use assert, not only for parameter validation, but also used for verifying Threads.
Every time I do swing, I write assert in almost every method to mark "I should only be execute in worker thread/AWTThread". (I think Sun should do it for us.) Because of the Swing threading model, it MAY NOT fail (and randomly fail) if you access swing api from non-UI thread. It is quite difficult to find out all these problem without assert.
Another example I can imagination is to check JAR enclosed resource. You can have english exception rather then NPE.
EDIT:
Another example; object lock checking. If I know that I am going to use nested synchronized block, or when I am going to fix a deadlock, I use Thread.holdLock(Object) to ensure I won't get the locks in reverse order.
EDIT(2): If you are quite sure some code block should never be reach, you may write
throw new AssertionError("You dead");
rather then
assert false:"I am lucky";
For example, if you override "equals(Object)" on a mutable object, override hashCode() with AssertionError if you believe it will never be the key. This practice is suggested in some books. I won't hurt performance (as it should never reach).
you have touched on many of the reasons why i think asserts should be avoided in general. unless you are working with a codebase where assert usage has very strict guidelines, you very quickly get into a situation where you cannot ever turn the assertions off, in which case you might as well just be using normal logic tests.
so, my recommendation is skip the assertions. don't stick in extra null-pointer checks where the language will do it for you. however, if the pointer may not be dereferenced for a while, up-front null checking is a good idea. also, always use real exceptions for cases which should "never" happen (the final if branch or the default switch case), don't use "assert false". if you use an assertion, there's a chance someone could turn it off, and if the situation actually happens, things will get really confused.
I recommend checking parameters in public (API) methods and throwing IllegalArgumentException if the params aren't valid. No asserts here as an API user requires to get a proper error (message).
Asserts should be used in non-public methods to check post-conditions and possibly pre-conditions. For example:
List returnListOfSize(int size) {
// complex list creation
assert list.size == size;
}
Often using a clever error handling strategy asserts can be circumvented.