Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 966
Big_Bad_E Avatar asked Mar 16 '20 20:03

Big_Bad_E


People also ask

Should you use asserts in production code?

JUnit assertions are intended to be used in test code, but not in production code. Using JUnit assertions outside of test scope may be confusing.

What does assert NOT null do?

The assertNotNull() method means "a passed parameter must not be null ": if it is null then the test case fails. The assertNull() method means "a passed parameter must be null ": if it is not null then the test case fails.

Under what circumstances would you place an assert () into your code?

Use an assert when your program meets a situation that does not allow to continue.

Why do we use assert statements in code?

An assertion is a statement in the Java programming language that enables you to test your assumptions about your program. For example, if you write a method that calculates the speed of a particle, you might assert that the calculated speed is less than the speed of light.

Should assertions be in production code?

Normally, you don't want users to see assertion messages in production code; assertions are primarily for use during development and maintenance. Assertions are normally compiled into the code at development time and compiled out of the code for production. However, later in the same section, this advice is given:

Is it possible to return Null with assert?

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.

When should assertions be compiled?

Assertions are normally compiled into the code at development time and compiled out of the code for production. However, later in the same section, this advice is given: For highly robust code, assert and then handle the error anyway.

Why doesn't my company put assert statements outside of the code?

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.


2 Answers

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.

like image 142
akuzminykh Avatar answered Sep 28 '22 07:09

akuzminykh


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.

like image 34
jeprubio Avatar answered Sep 28 '22 09:09

jeprubio