Null references redux
Steven Schveighoffer
schveiguy at yahoo.com
Sun Sep 27 08:32:17 PDT 2009
On Sat, 26 Sep 2009 17:08:32 -0400, Walter Bright
<newshound1 at digitalmars.com> wrote:
> Denis Koroskin wrote:
> > On Sat, 26 Sep 2009 22:30:58 +0400, Walter Bright
> > <newshound1 at digitalmars.com> wrote:
> >> D has borrowed ideas from many different languages. The trick is to
> >> take the good stuff and avoid their mistakes <g>.
> >
> > How about this one:
> >
> http://sadekdrobi.com/2008/12/22/null-references-the-billion-dollar-mistake/
> >
> >
> > :)
>
> I think he's wrong.
>
Analogies aside, we have 2 distinct problems here, with several solutions
for each. I jotted down what I think are the solutions being discussed
and the Pros and Cons of each are.
Problem 1. Developer of a function wants to ensure non-null values are
passed into his function.
Solution 1:
Rely on the hardware feature to do the checking for you.
Pros: Easy to do, simple to implement, optimal performance (hardware's
going to do this anyways).
Cons: Runtime error instead of compile-time, Error doesn't always occur
close to the problem, not always easy to get a stack trace.
Solution 2:
Check for null once the values come into the function, throw an
exception.
Pros: Works with the exception system.
Cons: Manual implementation required, performance hit for every function
call, Runtime error instead of compile-time, Error doesn't always occur
close to the problem.
Solution 3:
Build the non-null requirement into the function signature (note, the
requirement is optional, it's still possible to use null references if you
want).
Pros: Easy to implement, Compile-time error, hard to "work around" by
putting a dummy value, sometimes no performance hit, most times very
little performance hit, allows solution 1 and 2 if you want, runtime
errors occur AT THE POINT things went wrong not later.
Cons: Non-zero performance hit (you have to check for null sometimes
before assignment!)
Solution 4:
Perform a null check for every dereference (The Java/C# solution).
Pros: Works with the exception system, easy to implement.
Cons: Huge performance hit (except in OS where segfault can be hooked),
Error doesn't always occur close to the problem.
-----------------------
Problem 2. Developer forgets to initialize a declared reference type, but
uses it.
Solution 1:
Assign a default value of null. Rely on hardware to tell you when you
use it later that you screwed up.
Pros: Easy to do, simple to implement, optimal performance (hardware's
going to do this anyways).
Cons: Runtime error instead of compile-time, Error doesn't always occur
close to the problem, not always easy to get a stack trace.
Solution 2:
Require assignment, even if assignment to null. (The "simple" solution)
Pros: Easy to implement, forces the developer to clarify his
requirements -- reminding him that there may be a problem.
Cons: May be unnecessary, forces the developer to make a decision, may
result in a dummy value being assigned reducing to solution 1.
Solution 3:
Build into the type the requirement that it can't be null, therefore
checking for non-null on assignment. A default value isn't allowed. A
nullable type is still allowed, which reduces to solution 1.
Pros: Easy to implement, solution 1 is still possible, compile-time
error on misuse, error occurs at the point things went wrong, no
performance hit (except when you convert a nullable type to a non-nullable
type), allows solution 3 for first problem.
Cons: Non-zero performance hit when assigning nullable to non nullable
type.
Solution 4:
Compiler performs flow analysis, giving an error when an unassigned
variable is used. (The C# solution)
Pros: Compile-time error, with good flow analysis allows correct code
even when assignment isn't done on declaration.
Cons: Difficult to implement, sometimes can incorrectly require
assignment if flow is too complex, can force developer to manually assign
null or dummy value.
*NOTE* for solution 3 I purposely did NOT include the con that it makes
people assign a dummy value. I believe this argument to be invalid, since
it's much easier to just declare the variable as a nullable equivalent
type (as other people have pointed out). That problem is more a factor of
solutions 2 and 4.
----------------------
Anything I missed?
After looking at all the arguments, and brainstorming myself, I think I
prefer the non-nullable defaults (I didn't have a position on this concept
before this thread, and I had given it some thought).
I completely agree with Ary and some others who say "use C# for a while,
and see how much it helps." I wrote C# code for a while, and I got those
errors frequently, usually it was something I forgot to initialize or
return. It definitely does not cause the "assign dummy value" syndrome as
Walter has suggested. Experience with languages that do a good job of
letting the programmer know when he made an actual mistake makes a huge
difference.
I think the non-nullable default will result in even less of a temptation
to assign a dummy value.
-Steve
More information about the Digitalmars-d
mailing list