public Card getCard()throws IOException{
Card c = null;
String cardInfo = null;
assert readStream != null: cardInfo = readStream.readLine();
assert cardInfo != null: c = CreateCard(cardInfo);
return c;
}
I'm a little outta practice and I am trying to improve my code quality by using the assert statement to test for nulls. The way it seems to work I end up having to daisy chain my assertions because if the first thing I test for is null, then the next one is gonna be a null as well....
Here are some guidelines with regards to assertions
Don't use assertions to validate parameters of public functions.
These functions should throw NullPointerException,
IllegalArgumentException, and other relevant exceptions instead.
Since public functions will be used by other programmers, you should
make sure that they get the right errors if they mess up.
Use assertions to check preconditions and postconditions on
parameters of protected and private access methods.
Don't use assertions to check for software user errors. If you expect
the user of your web-based online sales system to enter a 10-digit
credit card number and she enters only 9 digits, don't use an assert.
Instead, throw IllegalArgumentException. If you use assert, as soon
as someone turns off assertions on your servlet container, the
checking logic in your system would go away.
Use assertions to check parameters and variables for conditions that
shouldn't happen
Use assertions to check for invalid code branches
Don't use an assertion to do any work. Assertions are developer-level
errors and shouldn't be used to repair state in the program or
perform complex logging. Also, don't forget that if a user runs the
program without assertions, the code will be gone. If that code was
critical to the functioning of the program, you could be in deep
trouble.
Don't bother internationalizing assertion error messages. Again,
since assertions are developer-level issues, internationalizing them
would be a waste of time.
Use assertions to check post conditions. If you create a method and
expect that it will never to return null to the user
The value of an assertion is that it can be ON in development and OFF in production. While on, it reveals bugs, presumably before they do much damage, prior to a release. While off, the assertions are inactive and (hopefully) sport a negligible performance impact.
I think the question to ask yourself is: "Self, does my usage of assertions meet those criteria?"
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I've seen this question but have a few more questions about the usage of the assert keyword. I was debating with a few other coders about using assert. For this use case, there was a method that can return null if certain prerequisites are met. The code I wrote calls the method, then asserts it doesn't return null, and continues to use the returned object.
Example:
class CustomObject {
private Object object;
#Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Now imagine I use it like this:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
I was told I should remove the assert, that they should never be used in production code, only be used in testing. Is that true?
Use Objects.requireNonNull(Object) for that.
Checks that the specified object reference is not null. This method is designed primarily for doing parameter validation in methods and constructors, [...]
In your case that would be:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
Objects.requireNonNull(object); // throws NPE if object is null
// do stuff with object
}
This function is made for what you want to do: explicitly mark what is not to be null. The benefit is that you find null-values right where they should not occur. You will have less troubles debugging problems caused by nulls that are passed somewhere where they shouldn't be.
Another benefit is the flexibility when using this function in contrast to assert. While assert is a keyword for checking a boolean value, Objects.requireNonNull(Object) is a function and can be embedded in code much easier.
Foo foo = Objects.requireNonNull(service.fetchFoo());
// you cannot write it in one line.
Bar bar = service.fetchBar();
assert bar != null;
service.foo(Objects.requireNonNull(service.getBar()));
// you cannot write it in one line.
Bar bar = service.getBar();
assert bar != null;
service.foo(bar);
Keep in mind that Objects.requireNonNull(Object) is only for null-checking while assert is for general assertions. So assert has different purposes: primarily testing. It has to be enabled, so you can enable it for testing and disable it in production. Use it to seperate testing-only-tests from tests, or rather checks, that are meant for production-code too.
The most important thing to remember about assertions is that they can be disabled, so never assume they'll be executed.
For backward compatibility, the JVM disables assertion validation by default. They must be explicitly enabled using either the -enableassertions command line argument, or its shorthand -ea:
java -ea com.whatever.assertion.Assertion
So, it's not a good practice to rely on them.
As assertions aren't enabled by default you can never assume they will be executed when used in the code. So you should always check for null values and empty Optionals, avoid using assertions to check inputs into a public method and instead use an unchecked exception... In general do all the checks as if the assertion wasn't there.
Surely what you are told is a blatant lie. Here's why.
Assertions are disabled by default if you just execute standalone jvm. When they are disabled, they have zero footprint, hence they will not affect your production application. However, they are probably your best friends when developing and testing your code, and most of testing framework runners enable assertions (JUnit does), so your assertion code is executed when you run your unit tests, helping you detect any potential bugs earlier (e.g. you can add asserts for some business logic boundary checks, and that will help detect some code which uses inappropriate values).
That said, as the other answer suggests, for exactly that reason (they are not always enabled) you cannot rely on assertions to do some vital checks, or (especially!) maintain any state.
For an interesting example of how you could use asserts, have a look here - at the end of the file there's a method singleThreadedAccess() which is called from the assert statement on line 201 and is there to catch any potential multithreaded access in tests.
The other answers already cover this well enough, but there are other options.
For example, Spring has a static method:
org.springframework.util.Assert.notNull(obj)
There are other libraries with their own Assert.something() methods as well. It's also pretty simple to write your own.
However, keep in mind what exceptions you throw if this is a web service. The previous method mentioned, for example, throws an IllegalArgumentException which by default in Spring returns a 500.
In the case of a web service, this is often not an internal server error, and should not be a 500, but rather a 400, which is a bad request.
Use asserts liberally whenever doing so helps catching programming mistakes i.e. bugs.
Do not use assert to catch something that might logically happen i.e. badly formatted input. Use assert only when the error is unrecoverable.
Do not put any production logic in the code that runs when the assertion is checked. If your software is well written this is trivially true but if it's not then you might have subtle side effects and different overall behavior with assertions enabled and disabled.
If your company has "testing code" and "production code" doing the same thing but as different code bases (or different stages of editing), get out of there and never come back. Trying to fix that level of incompetence is probably a waste of your time.
If your company doesn't put any assert statement outside of the code of the tests, kindly tell them that asserts are disabled in the production build and that if they aren't, fixing that mistake is now your first priority.
The value of asserts is precisely to be used inside the business logic and not only the test suite.
This makes it easy to churn out many high level tests that don't have to explicitly test many things to go through big chunks of your code and trigger all these assertions.
In a few of my projects typical tests didn't even really assert anything, they just ordered a calculation to happen based on specific input and this caused hundreds of assertions to be checked and problems to be found even in tiny pieces of logic deep down.
You can use assert any time. The debate come is when to use. For example in the guide :
Do not use assertions for argument checking in public methods.
Do not use assertions to do any work that your application requires for correct operation.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to get to grips with the use of the assert keyword in Java. As I understand it, the correct case is for verifying things that should always be true.
I'm worried that I'm overusing asserts, however.
Here's a sample:
private BodyParams() {
assert revokedDoc != null : "revokedDoc must not be null";
assert revokedDoc.getStatus() == DocumentStatus.Revoked : "document is not revoked";
assert !isBlank(revokedDoc.getDocType()) : "docType should not be blank";
assert revokedDoc.getIssuedDate() != null : "doc should have issue date";
assert revokedDoc.getSendingOrg() != null
&& !isBlank(revokedDoc.getSendingOrg().getName())
: "sending ord should exists and name should ne populated";
if (registeredUser) {
assert revokedDoc.getOwner() != null
&& !isBlank(revokedDoc.getOwner().getFirstName())
: "owner should exists and first name should be populated";
this.ownerFirstName = revokedDoc.getOwner().getFirstName();
this.docUrl = Application.PUBLIC_HOSTNAME
+ controllers.routes.DocumentActions.viewDocument(
revokedDoc.getId()
).url();
} else {
this.ownerFirstName = null;
this.docUrl = null;
}
if (revokedDoc.getStatus() == DocumentStatus.Available) {
assert !isBlank(revokedDoc.getFriendlyName())
: "friendly name should not be blank for picked-up docs";
this.friendlyName = revokedDoc.getFriendlyName();
} else {
this.friendlyName = null;
}
this.docType = revokedDoc.getDocType();
this.issueDate = revokedDoc.getIssuedDate();
this.issuerName = revokedDoc.getSendingOrg().getName();
}
In this example, it is assumed that the revokedDoc field came from the database, and correct validation was performed when it was inserted. These asserts test that assumption. Is this overkill?
edit: I should mention that this is only for development code. Assertions will not be enabled in production. I'm using the assertions to ensure that data that will be known good data from a trusted source in production behaves itself in development
It does not look right. To simplify there are two broad categories of problems that can arise and require checking the validity of a variable:
Your method receives or uses an argument that could possibly not be what you expect and your method should have appropriate argument checking and throw an IllegalArgumentException or NullPointerException or whatever if required. Example: the client code has passed in a null argument and you have no control over that code
Your method uses some of the class internals and you should have appropriate unit tests to make sure that those internals are always consistent and that your methods can use them without additional checks.
In your case, the method that creates the revokeDoc object should make sure it is in a valid state after creation and take appropriate action otherwise, for example throw an exception and roll back any changes. That way your BodyParams method can just use the object without all those asserts which clutter your code at the wrong time: if revokeDoc is not consistent it is probably too late to do something about it and should have been detected earlier.
Related post: Exception Vs Assertion
Assert is really useful to perform that should always be true inside an library or a module. It is intented to verify invariants ( control flow, internal, etc.) in your code, and it is a bad idea to use it to enforce correct use of your code (you have exceptions for that).
As a consequence, your public interface should never be based on assert : when you have a public method and you want to check input parameter, it is generally better to throw an IllegalArgumentException.
Here are some good documentation about asserts.
In your example, I think you should use exceptions instead of asserts. It's not a bad idea to perform some validity checks on data coming from a database (even if it has been validated on input) but assertion might be disabled in production code and you have to think on how you should handle such malformed content.
This could be an opinionated question. However, I'd go with the following things to decide:
Is this method exposed to outside world (via an interface, JAR file, user input field or anywhere where you could get inputs from a source that is not in your control) - then I should have a valid actual check which would result in an exception.
Am i relying on assertion for my correct execution of the code? If so, I shouldn't. At runtime, assertions are meant to be disabled.
Is this assertion always true? and if yes, am I going to use it on the off case for just debugging - then yes, use an assertion in place of a code comment. When something goes bad, enable the assertions and figure out what's wrong.
You need to consider two scenarios: development code and production code.
Since Java's assert statement is disabled by default (and adds only little overhead by checking a global static flag which is enabled by passing -ea to the VM), I would not consider this overhead since it helps you detect issues early during your development phase (assumed that you have enabled assertions in your development environment).
On the other hand, you say "... Correct validation was performed when it was inserted ..." - so, how do you know that the value has not been changed in the database meanwhile? If security matters for your system (I am just assuming it does), one basic pattern is that you must not trust anything which you get from the outside. Means, validate values you read from the database - but, in that case, assert is not the proper tool. Use normal validation code and exceptions for that.
The best practice, acording to OO metology is to check the params you receive. And create regulars checks for others. Should in your case you should get something like this:
private BodyParams(revokedDoc)
[...]
asserts of the params
if(isBlank(revokedDoc.....)
All the assets looks good, and is the way to make sure the method has everything to work. But they should be to make an aide of what's going on wrong, not to make your program work.
I use assertions in Java in a standard way, having them turned on in my IDE. So they are not part of production release. Lately I have been seeing code examples with throw new AssertionError() and I started thinking about the situation where AssertionError should be used instead of assertion.
My guess is that main difference is the optionality of asserts so they don't slow down the production performance and so they can occur quite often in the code, but fixing hardly reproducible bugs reported from users is harder.
For AssertionError, the exact opposite applies.
I also find AssertionError more practical in places in code where the execution should not get, instead of using assert false //We should not be here. Especially if the return value is required. For example:
int getFoo(AnEnum a){
if (a == AnEnum.ONE)
return bar();
else if (a == AnEnum.TWO)
return SOME_VALUE;
//else
assert false; //throw new AssertionError();
return -1; //not necessary when usin AssertionError
}
Is my reasoning correct?
What are the other differences/use cases/best practices/limitations
of either approach?
In regards to providing a description in the AssertionError - Should it be provided or is the mere fact that it is an Error (and
of assertion type) enough to be more or less sure that stack trace
will be provided in case of found bugs?
In the technote "Programming With Assertions: Control Flow Invariants" the following code is given:
void foo() {
for (...) {
if (...)
return;
}
assert false; // Execution should never reach this point!
}
But the following note is given as well:
Note: Use this technique with discretion. If a statement is unreachable as defined in the Java Language Specification, you will get a compile time error if you try to assert that it is not reached. Again, an acceptable alternative is simply to throw an AssertionError.
You may not expect an AssertionError to be thrown when assertions are turned off. As AssertionError constructors are public, and since there is likely no substitution for AssertionError(String message, Throwable cause), I guess that you should expect them even if they are turned off.
Throwing an AssertionError on unreachable code (i.e. without any real expression to be evaluated) will never slow down the code, as Jon Skeet suggested, so it won't hurt with regards to performance.
So in the end throwing the AssertionError seems OK.
I would advise against throwing AssertionErrors directly. If you choose to rely on AssertionErrors for checking invariants, pre/post conditions, state conditions, etc. you're still better off using regular assertions with the "-ea" flag turned on in production as well.
The reason is that the assertions mechanism (other than being optimized at the compiler level) gives you a chance to turn on or off all assertions at once. Even if you can't think of a reason to do that now, if you come across a reason in the future, just consider that you'll have to go over all your throw new AssertionError(...) type code and surround it with a nasty if clause. You get the picture.
Just as you wouldn't want a magic number hard coded into many places in your code, and would probably use a constant instead, you shouldn't infect your code with many duplications (i.e. the throw new AssertionError(...) part).
Another word about assertions though. I believe that you should think twice before relying on assertion errors in production code. The reason is that an AssertionError is very generic. It has a message and a cause, but that's pretty much it.
Consider instead using specific RuntimeException subclasses that will convey more information both by being of a specific class more related to the problem, as well as by carrying actual data related to the problem.
As a simple example, consider a case you mentioned in your question where there's some part of the code that you don't expect to reach. An assertion or an AssertionError would convey the fact that you reached some unexpected code, but not much more. Using a specific RuntimeException could also deliver the state of the local variables and parameters of the method at that point in time. You could argue that this is doable with setting the message of the assertion or AssertionError to contain this information, but this does not work when using automatic error logging/handling mechanisms. Such mechanisms can handle unexpected behaviors using the visitor pattern on the different sub classes of RuntimeException you're using to check unexpected behavior (by handle I also mean fail-fast, not necessarily recovery).
I have a postcondition I want to check regularly, across many methods. I'm fairly confident that I'm using the assert correctly, i.e. only checking something to make sure my code isn't doing anything stupid, and I intend to turn off the asserts after a while. But I'm not sure that the postcondition as I've written it now is exactly the condition I'll always want. So I put it into a method. But then I encountered the following issue:
public class Foo
{
public void doSomethingRisky()
{
//...
assert someBoolean();
}
private boolean someBoolean()
{
return bar && baz;
}
}
vs.
public class Foo
{
public void doSomethingRisky()
{
//...
verifySomeBoolean();
}
private void verifySomeBoolean()
{
assert bar && baz;
}
}
I know if I compile w/ disabled assertions, the former code will have no performance hit since someBoolean() will never get called. But is Java "smart" enough that, with assertions disabled, the second form will also have no performance hit with assertions disabled?
And the more important question, obviously, is which is better practice?
I like the assert someBoolean() because it's explicit, not subject to re- or mis-interpretation, but it seems the other form might be a little more future proof, because maybe I'll want to expand the behavior of verifySomeBoolean() to do something besides asserting the same underlying boolean. Though my gut says if that were the case, I'm better off re-coding than trying to smush the old code to fit. Any words from the wise would be much appreciated.
I thought you did not compile out assertions? I thought they were compiled and could only be enabled by the JVM with java -ea.
In that case it would be up to the JVM to optimize out an empty call when -ea is not used. But you are pre-maturely optimizing. Make the code easy to understand and write. Then optimize second. Calling an empty method is not going to cause your performance issues.
Update:
As far as style, I would go with the asserts as close to the problem as possible. I wouldn't like the assert in a method just for the check.
Second, assert() and Guava Preconditions have two different applications. assert should be used to check that your world is still the world you thought it was. It's more of a assert (1+1 == 2) type of thing. You don't use assert()'s on callee parameters. You use assert to check something you know MUST be true, but are checking it anyways.
Guava Preconditions look to be what you should be using. This is input validation and is used to check for contract compliance. Things such as: checking null argument, negative numbers when only natural numbers should be used, a properly formatted string, etc.
In summary, assert() is the "Let me just make sure gravity is still here, even though I know it is" and the Preconditions is "Let me make sure I am trying to travel faster then the police allow"
Let say you have a method that checks if the argument (Answer) is correct and check if the question already have answers in the list that is also correct:
public void addAnswer(Answer answer) {
if (answer.isCorrect()) {
...
}
}
However, I only want one answer to be correct in the list. I have multiple options. I could throw an exception, I could ignore it, I could return some boolean value from the addAnswer that tells me if the operation was ok or not. How are you supposed to think in such scenarios?
The rule is pretty simple: Use exceptions on exceptional, erroneous, unpredicted failures. Don't use exceptions when you expect something to happen or when something happens really often.
In your case it's not an error or something truly rare that an answer is not correct. It's part of your business logic. You can throw an exception, but only as part of some validation (assertion) if you expect an answer at given point to always be correct and suddenly it's not (precondition failure).
And of course if some failure occurs while checking correctness (database connection lost, wrong array index) exception are desired.
This entirely depends on what you want to achieve. Should the caller of your method already have made sure that it doesn't add two correct answers? Is it a sign of a programming error if that happens? Then throw an exception, but definitely an unchecked exception.
If your method's purpose is to relieve the caller from enforcing the one-true-answer invariant (I doubt that, though), then you can just arrange to signal via a boolean return value, which makes it only an optional information channel for the caller.
If there is no way to know in advance whether there are other correct answers—for example, the answers are added concurrently from several threads or even processes (via a database)—then it would be meaningful to throw a checked exception.
Bottom line: there is no one-size-fits-all best practice, but there is a best practice for every scenario you want to accomplish.
The exception police will be down on you like a ton of bricks, and me for this answer, with statements like "don't use exceptions for flow control" and "don't use exceptions for normal conditions".
The trouble with the first statement is that exceptions are a form of flow control. This makes the argument self-contradictory, and therefore invalid.
The trouble with the second statement is that it seems to inevitably go along with endlessly redefining exceptional conditions as normal. You will find examples in this very site: for example, a lively discussion where the police insisted that EOF was 'normal' and therefore that EOFException shouldn't be caught, despite the existence of dozens of Java APIs that don't give you any choice in the matter. Travel far enough down this path and you can end up with nothing that is exceptional whatsoever, and therefore no occasion to use them at all.
These are not logical arguments. These are unexamined dogmas.
The original and real point, back in about 1989 when it was first formulated, was that you shouldn't throw exceptions to yourself, to be handled in the same method: in other words, don't treat it as a GOTO. This principle continues to have validity.
The point about checked exceptions is that you force the caller to do something about handling them. If you believe, on your own analysis, that this is what you want, use an exception. Or, if you are using an API that forces you to catch them, catch them, at the appropriate level (whatever that is: left as an exercise for the reader).
In other words, like most things in the real world, it is up to your discretion and judgment. The feature is there to be used, or abused, like anything else.
#Exception police: you will find me in the telephone book. But be prepared for an argument.
An exception thrown from a method enforces the callers to take some action in the anticipation of the exception occurring for some inputs. A return value doesn't enforce the same and so it is up to the caller to capture it and take some action.
If you want the callers to handle the scenario to take some corrective action, then you should throw a checked exception (sub class of java.lang.Exception).
The problem here is that your API is error prone. I'd use the following scheme instead:
public class Question {
private List<Answer> answers;
private int mCorrect;
// you may want a List implementation without duplicates
public void setAnswers(List<Answer> answers, int correct) {
this.answers = answers;
// check if int is between bounds
mCorrect = correct;
}
public boolean isCorrect(Answer answer) {
return answers.indexOf(answer) == mCorrect;
}
}
because an Answer by itself is simply a statement, and usually cannot be true of false without being associated to a Question. This API makes it impossible to have zero or more than one correct answers, and forces the user to supply the correct one when he adds answers, so your program is always in a consistent state and simply can't fail.
Before deciding how to signal errors, it's always better to design the API so that errors are less common as possible. With your current implementation, you have to make checks on your side, and the client programmer must check on his side as well. With the suggested design no check is needed, and you'll have correct, concise and fluent code on both sides.
Regarding when to use a boolean and when to use Exceptions, I often see boolean used to mirror the underlying API (mostly low level C-code).
I agree with Tomasz Nurkiewicz's response. I cant comment on it because I'm a new user. I would also recommend that if the addAnswer() method is not always going to add the answer (because they already exists a correct one), name it to suggest this behaviour. "add" is suggest normal collections behaviour.
public boolean submitAnswer(Answer answer); // returns true is answer accepted
Your exact solution may depend on the bigger picture about your application that we dont know about. Maybe you do want to throw an Exception but also make it the responsibility of the caller to check if adding the Answer is valid.
It's all a rich tapestry.
I would implement it in this way:
public class Question {
private int questionId;
private final Set<Answer> options = new HashSet<Answer>();
private final Set<Answer> correctAnswers = new HashSet<Answer>();
public boolean addAnswer(Answer answer) throws WrongAnswerForThisQuestionException {
if(!answer.isValid(questionId)) {
throw new WrongAnswerForThisQuestionException(answer, this);
}
if (answer.isCorrect(questionId)) {
correctAnswers.add(answer);
}
return options.add(answer);
}
}