Is this an overuse of Java asserts? [closed] - java

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.

Related

Handling null, even if annotations are used

I started using javax.annotation especially to warn the next developer who maybe will be working with my code in the future.
But while I was using the javax.annotation #Nonnull annotation, a question came into my mind:
If you mark f.e. a parameter of a method thorugh the #Nonnull annotation that it haves to have a value,
do you still need to handle the case, that the next developer who is using your code could be parsing null to your function?
If found one con argument and one pro argument to still handle the special cases.
con: The code is cleaner, especially if you have multiple parameters that you mark with #Nonnull
private void foo(#Nonnull Object o)
{
/*do something*/
}
vs
public void foo(Object o)
throws NullPointerException
{
if (o == null)
{
throw new NullPointerException("Given Object must have a value!");
}
/*do something*/
}
pro: It could cause unhandled errors if the next developer ignore the annotations.
This is an unsolved problem in the nullity annotation space. There are 2 viewpoints that sound identical but result, in fact, in the exact opposite. Given a parameter void foo(#NonNull String param), what does that imply?
It's compiler-checkable documentation that indicates you should not pass null as param here. It does not mean that it is impossible to do this, or that one ought to consider it impossible. Simply that one should not - it's compiler-checkable documentation that the method has no defined useful behaviour if you pass null here.
The compiler is extended to support these annotations to treat it as a single type - the type of param is #NonNull String - and the compiler knows what that means and will in fact ensure this. The type of the parameter is #NonNull String and therefore cannot be null, just like it can't be, say, an InputStream instance either.
Crucially, then, the latter means a null check is flagged as silly code, whereas the former means lack of a null check is marked as bad. Hence, opposites. The former considered a nullcheck a warnable offense (with something along the lines of param can never be null here), for the same reason this is silly code:
void foo(String arg) {
if (!(arg instanceof String)) throw new IllegalArgumentException("arg");
}
That if clause cannot possibly fire. The mindset of various nullchecker frameworks is identical here, and therefore flags it as silly code:
void foo(#NonNull String arg) {
if (arg == null) throw new NullPointerException("arg");
}
The simple fact is, plenty of java devs do not enable annotation-based nullity checking, and even if they did, there are at least 10 competing annotations and many of them mean completely different things, and work completely differently. The vast majority will not be using a checking framework that works as you think it should, therefore, the advice to remove the nullcheck because it is silly is actively a bad thing - you should add that nullcheck. The linting tools that flag this down are misguided; they want to pretend to live in a world where every java programmer on the planet uses their tool. This isn't try and is unlikely to ever become true, hence, wrong.
A few null checking frameworks are sort of living both lives and will allow you to test if an argument marked as #NonNull is null, but only if the if body starts with throw, otherwise it's flagged.
To answer your questions:
You should nullcheck. After all, other developers that use your code may not get the nullity warnings from the nullcheck tool (either other team members working on the same code base but using slightly different tools and/or configurations of those tools, or, your code is a library and another project uses it, a more obvious route to a situation with different tools/configs). The best way to handle a null failure is a compile time error. A close second is an exception that is clear about the problem and whose stack trace can be used to very quickly solve the bug. A distant third is random bizarreness that takes a whole to debug - and that explicit nullcheck means you get nice fallback: If for whatever reason the write-time tooling doesn't catch the problem, the check will then simply turn it into the second, still quite acceptable case of an exception at the point of failure that is clear about what happened and where to fix it.
Lombok's #NonNull annotation can generate it for you, if you want. Now you have the best of both worlds: Just a #NonNull annotation (no clutter) and yet a runtime exception if someone does pass null anyway (DISCLAIMER: I'm one of the core contributors to Lombok).
If your linting tool complains about 'pointless null check' on the line if (param == null) throw new NullPointerException("param");, find the option in the linting tool to exclude if-checks that result in throw statements. If the linting tool cannot be configured to ignore this case, do not use the linting tool, find a better one.
Note that modern JVMs will throw a NullPointerException with the name of the expression as message if you dereference a null pointer, which may obviate the need to write an explicit check. However, now you're dependent on that method always dereferencing that variable forever more; if ever someone changes it and e.g. assigns it to a field and returns, now you have a problem: It should have thrown the exception, in order to ensure the bug is found quickly and with an exception that explains what happened and where to go and fix the problem. Hence I wouldn't rely on the JVM feature for your NPEs.
Error messages should be as short as they can be whilst not skimping on detail. They should also not end in punctuation; especially exclamation marks. Every exception tends to be noteworthy enough to warrant an exclamation mark - but it gets tedious to read them, so do not add them. In fact, the proper thing to throw, is this: throw new NullPointerException("o"). - and you might want to rename that parameter to something more readable if you find o ugly. Parameters are mostly public API info (JVM-technically they are not, but javadoc does include them, which is the basis of API docs, so you should consider them public, and therefore, they should have clear names. Which you can then reuse). That exception conveys all relevant information to a programmer: The nature of the problem (null was sent to code that does not know how to handle this), and where (the stack trace does that automatically), and the specifics (which thing was null). Your message is much longer and doesn't add anything more. At best you can say your message might be understood by a non-coder, except this is both not true (as if a stack trace is something random joe computeruser is going to understand), and irrelevant (it's not like they can fix the problem even if they do know what it means). Using exception messages as UI output just doesn't work, so don't try.
You may want to adjust your style guides and allow braceless if statements provided that the if expression is simple (no && or ||). Possibly add an additional rule that the single statement is a control statement - break;, continue;, return (something);, or throw something;. This will significantly improve readability for multiparams. The point of a style guide is to create legible code. Surely this:
if (param1 == null) throw new NullPointerException("param1");
if (param2 == null) throw new NullPointerException("param2");
is far more legible, especially considering this method has more lines than just those two, than this:
if (param1 == null) {
throw new NullPointerException("param1");
}
if (param2 == null) {
throw new NullPointerException("param2");
}
Styleguides are just a tool. If your styleguide is leading to less productivity and harder to read code, the answer should be obvious. Fix or replace the tool.

Better to reference field instance or parameter in this constructor? [closed]

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 1 year ago.
Improve this question
I've written this 'CoreException' Exception subclass. I appear to have three options in the constructor that would all behave identically since they are all referencing the same object.
*note: the question is about the compiler and possible runtime difference from the three different source code options. The constructed Object could be of any class.
public class CoreException extends Exception {
private final Class<?> sourceClass;
private final Method sourceMethod;
public CoreException(#NotNull Method method, #NotNull Throwable thr) {
super("this text is irrelevant", thr);
this.setStackTrace(thr.getStackTrace());
this.sourceMethod = method;
this.sourceClass = this.sourceMethod.getDeclaringClass();
}
public Class<?> getSourceClass() { return sourceClass; }
public Method getSourceMethod() { return sourceMethod; }
}
The construction of the Class<?> sourceClass object seems to have three identical options:
this.sourceClass = this.sourceMethod.getDeclaringClass();
this.sourceClass = sourceMethod.getDeclaringClass();
this.sourceClass = method.getDeclaringClass();
Is there a decent reason to use one over the others, perhaps because of a marginal increase in performance, reliability / resilience, etc..?
Or does the compiler simply turn all three of these into exactly the same result?
In the example, there is no difference between this.sourceMethod and sourceMethod, the resulting bytecode will be the same. It is just a matter of taste which you prefer. Some people prefer using this. always, while others prefer to only use this. when it is necessary for disambiguation if there is also a local variable with the same name.
The only real difference is between [this.]sourceMethod and method: sourceMethod is a field on the object, while method is a parameter. Given method is a parameter, it's on the stack, and it's probably slightly faster than accessing the field sourceMethod of the object. However, in the grand scheme of things, this difference is likely negligible, and even if it's not, it is entirely possible that the JIT compiler optimizes it in a way they are equivalent. If you really need to know, you should write a micro-benchmark to measure that difference.
Personally, I would consider the choice between using sourceMethod or method primarily one of opinion.
This is a bad idea. You're trying to address a thing you find uncomfortable about java, the language, with an API update. This cannot work - the vast majority of exceptions out there just will not be wrapped in a CoreException (e.g. anything that the java core API itself throws, or anything in any third party library such as JUnit, JDBI, etcetera).
Your code will no longer be making sense to other java programmers who do not expect to need to reroute all exceptions through this class of yours.
You also won't be able to write code that 'fits' in existing APIs (i.e. implementations of interfaces), as you will be required to write your own variants of all relevant exception types (as they will need to extend CoreException somewhere in the hierarchy, and the exceptions in java.* and anything written in e.g. jdbi.* wouldn't, and you can't update them to without forking every library you use).
So what DO I do?
The info you are sticking in that exception message are already available in plain jane exceptions - the first line of the stack trace. It's silly to repeat this information in the message.
If you have some logging or error reporting system where currently you do not have this information, and you want it to, that is a real problem. You've just decided to solve it in an unwieldy and inadvisable way.
Instead, updating whatever that system might be to include the first line of the stacktrace. This is generally not hard, but it depends on where the place is that made you go: "Oof, I could really use the method name here".
Note that going your own way has more downsides than just 'it stands out in existing APIs like a sore thumb'. IDEs will not recognize this and you won't be able to click on the class+methodname in the message to automatically jump to the right file. You need to match the 'style' of what StackTraceElement prints if you want that.
Your code also causes straight up erroneous conclusions. This approach (of having a Method object that represents the source) doesn't make much sense when the exception is thrown from within a lambda.
Thus, abort the plan. Whatever you wanted to accomplish by making Method sourceMethod part of the state of all of your exceptions - you either didn't want that, or you can accomplish it far better in a different way (and probably by relying on getStackTrace()[0]) to convey it.
public Class<?> getSourceClass() {
return Class.forName(getStackTrace()[0].getClassName());
}
can do the job just as well, for example, though note that this code may fail (throw ClassNotFoundEx) depending on where the exception came from. Not all code is easily captured in a 'it is in this class and in this method' context (core stuff, native stuff, synthetic methods, bridgers, dynamically generated code, lambdas...)

Should you assert not null with the assert statement in production code? [closed]

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.

How to handle possible NULL correctly? [closed]

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 3 years ago.
Improve this question
While reading several different API codes I discovered that they handle possible nulls on different ways. And here at stackoverflow I have read several recommendations like no need for explicit checking or check and throw some meaning full exception...etc.
Say the method is something like this:
public void runThis(SomeObject obj){
## null handling code comes here ##
obj.doSomething() <- possible NPE
}
The most common solutions I have seen:
1.Throwing explicit NPE
if(obj==null){
throw new NullPointerException();
}
2.Throwing custom exception
if(obj==null){
throw new CustomException("Null not allowed here");
}
3.Using Assert (have seen it only once)
assert obj!=null
4.Do nothing and java will throw it when invoking doSomething()
//
Is there some general - best all over the place - solution to this?
Is there some general - best all over the place - solution to this?
No.
This is because null doesn't have a commonly agreed meaning. It might be a result of a bug, indicate missing data, or represent a default value.
Here are some tips:
requireNonNull is better than writting if (x == null) everywhere.
Optional
Failing fast is good, so do throw an exception if you encounter an unexpected null. NullPointerException is fine, IllegalArgumentException is also ok. Bike sheds should be painted black.
Don't use asserts - this is a dead language feature.
Don't mask null values (it's like ignoring errors).
If you are looking for a solution that solves the null problem once and for all, I would like to take this opportunity to promote Kotlin - a programming language which does a good job of clearing up this mess. The null problem basically dissapears in Kotlin, yet at the same time it is easy to migrate from Java.
It depends on where you got obj, and what you plan to do with it.
Exceptions should be used to check for invalid values in user input, and invalid values passed to public/protected methods.
This is to ensure that your method can safely execute, and to provide a helpful message if it can't. Use custom exceptions for this purpose.
Assertions should be used to check things that you believe should always be true. They are a tool to find bugs in your code, seeing as they're usually disabled in release builds.
The most common use of assertions is in tests.

Assert vs If in Controller

What is the best way to check for a value that was passed in the controller?
Is it assert or if?
if this is the sample url....
http://example.com/read/1/2
I would like to check if 1 and 2 is number and if it's null. Like if the user changed the url to http://example.com/read/1asdf/2asdfqwer
We are using assert in our company. And I'm just thinking that what will happen if it's already in production mode and assert is disabled.
Somebody give me an insight with this.
assert is intended as a debugging tool for checking conditions under you control. If it fires, it indicates a bug in your code. Checking user supplied input does not fall into this category, instead it is a feature of correct programs. Thus you should use if statements for checking user input.
Asserts are mainly used to check preconditions.
Its like if given preconditions are not mate throw AssertionError.
Checking preconditions this way is actually good practice in testing environments. Where we can make sure all preconditions are mate and satisfied.
In production environment if debug mode is not yet activated then it will surely will not harm. this statement will work as if it is commented.
In your case if you merely want to check which value is accepted at controller level use if's.
but If you want to check that as precondition and then you want throw error if these preconditions are not met and ideally in debug mode. (AssertionError.) then you can use asserts.
Instead of using assert use following logic.
#RequestMapping(value = " /read/{var1}/{var2}", method=RequestMethod.GET)
public String read(#PathVariable Integer var1,#PathVariable Integer var2){
if (var1 ==null || var2 == null) {
// do something
}
return "something";
}
I assumed you are using spring mvc.

Categories

Resources