1 2 3 4 5 6 7 8 9 10 | public class SomeClass { public void method(Something argument) { if(argument != null) { //Do stuff... } } } |
The above piece of code contains what we commonly refer to as a "verbose null check", in other words, validating that the incoming parameters exist. This is not a nice practice often because it tends to add noise to your code and also doing stuff and validating something, are different concerns and the methods in order to be clean, should be just caring about one thing.
People often wonder, what to do then to not let the null get any further. Let's have a look at some options.
Do nothing
One option is to just do nothing, the caller of the function, should be cautious and make sure not to pass a null. But if he does and this leads to a NullPointerException, this is a good way of knowing that the way that function is being used is wrong.
1 2 3 4 5 6 7 8 9 10 | public class SomeClass { public void method(Something argument) { //Do stuff... } } |
Using assertions
The java keyword 'assert' can be used in combination with a boolean expression to stop the program execution by throwing an assertion error. While this seems like an interesting alternative to the if statement, assertions are disabled by default in java. They are a nice debugging tool for those who want to use them with care. Sometimes some programmers will enable them during a bug fix, but they will always be disabled in the production environment.
1 2 3 4 5 6 7 8 9 10 | public class SomeClass { public void method(Something argument) { assert argument != null : "Can't pass a null"; //Do stuff... } } |
Null Object Pattern
The idea behind this behavioural design pattern is to use polymorphism to create null versions of an object(M.Fowler also refers to them as missing objects). This null objects will have a function called isNull(), which for the source class will always return false, but for the null object will return true. The client will be able to choose to pass a null object instead of a null, and this will avoid having to do a verbose null check in method().
public abstract class Something {
// ...
public boolean isNull() {
return true;
}
}
public class NullSomething extends Something {
public boolean isNull() {
return false;
}
}
public class SomeClass {
public void method(Something argument) {
//Do something ...
}
}
public class Client {
private Something something;
//...
// The client avoids passing a null by using a null object
if(something.isNull())
someClass.method(new NullSomething());
else
someClass.method(something);
//...
}
Optional
Latest versions of java have a class called Optional that can be used as a way of avoiding returning nulls. It is basically an implementation of the null object pattern. By using optional on the client we can avoid passing a null.
public class Client {
private Optional<Something> something;
//...
if( ! something.isEmpty())
someClass.method(something.get());
//...
}
public class SomeClass {
public void method(Something argument) {
//Do stuff ...
}
}
Validators, IllegalArgumentException and Business Exceptions
If the caller of the function is out of our control and we cannot be confident on the value that will pass to our function there are other alternatives to the null check that maybe regardless of also being defensive are probably more business friendly and perhaps more informative.
Validators
I mentioned at the beginning that methods should not have multiple responsibilities. If for whatever reason we must do that null check or some other type of validation, we could delegate it to a validator object.
public class SomeClass {
private Validator validator;
// ...
public void method(Something argument) {
if(validator.validate(argument))
//Do stuff ...
return;
}
}
Sometimes this validator is also not seen as an smooth solution and probably an unnecessary dependency into the class. It could be replaced using the Decorator pattern. Basically a wrapper around the function being called by a decorating object.
Read more about it in another article from this blog:
http://javing.blogspot.co.uk/2013/10/can-you-please-wrap-gift-it-is-for-my.html
Illegal Argument Exception
NullPointerException its not a very informative exception for the client. So if we decide that we are not going to do any kind of null check but we are still afraid of the null, perhaps we could just throw an IllegalArgumentException instead.
public class SomeClass {
// ...
public void method(Something argument) {
try {
//Do stuff ...
} catch(NullPointerException e) {
throw new IllegalArgumentException(e);
}
}
}
It is not a good practice to catch runtime exceptions(aka. Swallowing exceptions), since as you know, the program just carries on working. It is highly recommended that if you are going to do something like this, at least you add a Logger.log() statement to help the developer that will be debugging in the case there is some problem.
Bussiness Exception
As I just mentioned in the previous alternative Runtime exceptions are not a good thing to catch. Instead of that, we could use Business/Declared exceptions, which will mandate the caller function to get ready(by adding try and catch blocks..) for a potential fault.
public class SomeClass { // ... public void method(Something argument) throws YouArePassingMeNothingException { try { //Do stuff ...
} catch(NullPointerException e) {
throw new YouArePassingMeNothingException(e);
}
}
}