1

Today I (once again) dereferenced an undefined object's property causing a spectacular crashing of our server. Fixing the problem included writing one of my most disliked pieces of boilerplate code, turning

if (foo.bar.baz.id) {...

into

if (foo && foo.bar && foo.bar.baz && foo.bar.baz.id) {...

because baz happened to be null in an edge case and this raised an exception.

So my question is: why is dereferencing null/undefined such a problem? Why doesn't foo.bar.baz.something just safely return undefined when foo/bar/baz are undefined? I understand the technical why, and am interested in the language design why? Are there languages that have safe dereferencing? Is there a real CS reason for why there aren't, or is it just tradition (inherited form C and it's friends of old)?

I can think of one reason, which is that having more "type checking"-style logic in an action that is as often executed as dereferencing, can slow the language down quite a bit. But then I also think that most of the problem could be solved by having proper exception handling in assignment / if / etc. operators so the dereferencing could just keep on going as is and the "higher level" operators take care of the occasional "oopises".

Another reason I can think of is that it is simply too much of opinionated language design decision to implementing some sort of rule set for how to deal with this issue.

I would greatly appreciate any CS people shedding some light on this issue.

Timo
  • 4,246
  • 6
  • 29
  • 42
  • 1
    The first thing that comes to mind is performance issues: If accessing a member field implicitly verified that all containing objects are valid, then OOP would be inherently slow compared to non-OO programming (if one field's value is computed from two other fields, then the entire object's validity would be checked a minimum of three times). While this can be optimised (by only checking the object's validity once per operation, unless the language's `volatile` or equivalent is used, for example), not all compilers are equally skilled at optimising. – Justin Time - Reinstate Monica Dec 04 '16 at 22:39
  • *"Are there languages that have safe dereferencing?"* - Yes, [Objective-C](http://stackoverflow.com/a/2696909/1402846). – Pang Dec 07 '16 at 09:24

1 Answers1

1

What you are describing is not the soundness/safeness of deferencing, it is what I call null monadic behavior meaning that if an operation T take the null value n as input, its result is n without any computation done.

Probably you are more familiar with the term null propagation from C# or the Objective-C equivalent.
Even the SQL NULL behaves monadically with respect to operations.

Languages like C don't have null propagation for performance reasons, adding a branch before any deference is a huge slow down.
Other languages are defined differently because they have different purpose (SQL for example works with data and a NULL marked was needed) or different history (Objective-C comes from SmallTalk where objects are not deferenced but signaled, so sending a message to no-object is valid and does nothing).


The burden of null-checking is not alleviated by the null propagation though, that's even worse.
Sometimes is handy but mostly it violates the rule of "fail fast".

Is it acknowledged that null was a big mistake in CS.
The solution is the use of what is known as monads in Haskell or Optional in Java or the nullable types in C# or the boost::optional in C++.
Null is not a value, has not a type, while all the solution above are values and have types.
Combined with pattern matching, or an approximation of thereof, they are very smooth to use and great for self documenting code.
They are also safe to use (for what the Type system of the language permits)

Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124