The central problem of NULL is that it makes system unreliable.
In 1980 Tony Hoare in the paper dedicated to his Turing Award wrote:
And so, the best of my advice to the originators and designers of ADA has been ignored. …. Do not allow this language in its present
state to be used in applications where reliability is critical, i.e.,
nuclear power stations, cruise missiles, early warning systems,
antiballistic missile defense systems. The next rocket to go astray as
a result of a programming language error may not be an exploratory
space rocket on a harmless trip to Venus: It may be a nuclear warhead
exploding over one of our own cities. An unreliable programming
language generating unreliable programs constitutes a far greater risk
to our environment and to our society than unsafe cars, toxic
pesticides, or accidents at nuclear power stations. Be vigilant to
reduce the risk, not to increase it.
ADA language has changed a lot since that, however such problems still exist in Java, C# and many other popular languages.
It is developer's duty to create contracts between a client and a supplier. For example, in C#, as in Java, you can use Generics
to minimise the impact of Null
reference by creating readonly NullableClass<T>
(two Options):
class NullableClass<T>
{
public HasValue {get;}
public T Value {get;}
}
and then use it as
NullableClass<Customer> customer = dbRepository.GetCustomer('Mr. Smith');
if(customer.HasValue){
// one logic with customer.Value
}else{
// another logic
}
or use two options style with C# extension methods:
customer.Do(
// code with normal behaviour
,
// what to do in case of null
)
The difference is significant. As a client of a method you know what to expect. A team can have the rule:
If a class is not of type NullableClass then it's instance must be not null.
The team can strengthen this idea by using Design by Contract and static checking at compilation time, e.g with precondition:
function SaveCustomer([NotNullAttribute]Customer customer){
// there is no need to check whether customer is null
// it is a client problem, not this supplier
}
or for a string
function GetCustomer([NotNullAndNotEmptyAttribute]String customerName){
// there is no need to check whether customerName is null or empty
// it is a client problem, not this supplier
}
These approach can drastically increase application reliability and software quality. Design by Contract is a case of Hoare logic, which was populated by Bertrand Meyer in his famous Object-Oriented Software Construction book and Eiffel language in 1988, but it is not in use invalidly in modern software crafting.