Billion-dollar mistake(s)!

In the Javascript world & how to deal with them

Jagadeesh Rampam
7 min readDec 9, 2020

What are the billion-dollar mistakes in the software world?

  • Y2K bug, a class of bugs related to the storage and formatting calendar data, was estimated to cost a little less than 4 billion dollars according to Tony Hoare.
  • CodeRed Virus, a computer worm that infiltrated world-wide companies, brought down all the networks. The interruption to business and all the ordinary banking, other business was estimated to cost the world economy 4 billion dollars.
  • Null is the misguided invention of British computer scientist Tony Hoare (most famous for his Quicksort algorithm) in 1964, who coined his invention of null references as his “billion-dollar mistake”.

Who coined “null” a billion-dollar mistake & why?

Sir Charles Antony Richard Hoare FRS FREng is a British computer scientist. Famous for his invention of Quicksort algorithm

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. — Tony Hoare

Courtesy: Maximiliano Contieri

A null pointer reference could be a bad idea. Comparing a null pointer reference to a promiscuous adulterer he noted that the null assignment for every bachelor represented in an object structure “will seem to be married polyamorously to the same person Null. — Edsgar Djikstra

What is/are billion-dollar mistake(s) in the context with Javascript world?

We have two candidates in Javascript world falls under this category:

1⃣️ Null

The value null is written with a literal: null. null is not an identifier for a property of the global object, like undefined can be. Instead, null expresses a lack of identification, indicating that a variable points to no object. In APIs, null is often retrieved in a place where an object can be expected but no object is relevant.

2⃣️ Undefined

undefined is a property of the global object. That is, it is a variable in global scope. The initial value of undefined is the primitive value undefined.

Javascript’s primitive datatypes(ES2020),

  1. Boolean
  2. Null
  3. Undefined
  4. Number
  5. String
  6. BigInt
  7. Symbol

Null and Undefined in Javascript called “Nullish”(falsy) values.

Falsy Values: Undefined, null, 0, NaN, empty string‘’, false

Null vs Undefined

Despite the behaviour for both being falsy values, if one is thinking Null vs Undefined as Declared vs Undeclared, not really!

Undefined can be for both declared and undeclared.

What about Null?

Null has it’s own issues to deal with.. great! Let’s look at that,

Well, typeof null == “object” is a 25 year old bug, since the first version of Javascript.

In the first version of JavaScript, values were stored in 32 bit units, which consisted of a small type tag (1–3 bits) and the actual data of the value. The type tags were stored in the lower bits of the units. There were five of them:

  • 000: object. The data is a reference to an object.
  • 001: int. The data is a 31 bit signed integer.
  • 010: double. The data is a reference to a double floating point number.
  • 100: string. The data is a reference to a string.
  • 110: boolean. The data is a boolean.

From the original source code jsapi.h, (link)

#define JSVAL_OBJECT      0x0     /* untagged reference to object */
#define JSVAL_INT 0x1 /* tagged 31-bit integer value */
#define JSVAL_DOUBLE 0x2 /* tagged reference to double */
#define JSVAL_STRING 0x4 /* tagged reference to string */
#define JSVAL_BOOLEAN 0x6 /* tagged boolean value */

Two values were special:

  • undefined(JSVAL_VOID), is int minus(-) JSVAL_INT_POW2(30), that is, a number outside the integer range
  • null(JSVAL_NULL), is the machine code NULL pointer, an object type tag plus a reference that is zero(OBJECT_TO_JSVAL(0)).
#define JSVAL_VOID              INT_TO_JSVAL(0 - JSVAL_INT_POW2(30))
#define JSVAL_NULL OBJECT_TO_JSVAL(0)
#define JSVAL_ZERO INT_TO_JSVAL(0)
#define JSVAL_ONE INT_TO_JSVAL(1)
#define JSVAL_FALSE BOOLEAN_TO_JSVAL(JS_FALSE)
#define JSVAL_TRUE BOOLEAN_TO_JSVAL(JS_TRUE)

Now, when examined its type tag and the type tag said “object”. (source)

Source code for “typeof”
  1. Line# 10, first checks whether the value v is undefined(VOID).
  2. Next check at line# 12, checks for is object JSVAL_IS_OBJECT,
  3. Additionally, calls for Function Class (line# 18, 19)
  4. And hence evaluates to Object
  5. Subsequently have checks for number, string, and boolean, not even a check for Null

Might be one of the reason, where the first version of JavaScript completed in 10 days. Later on, continued to live with this issue rather than fixing due to its tightly coupled logic in the original source code. Fixing would lead to breaking lot of things in the code.

Dealing with Null & Undefined

From ES2020, we have better way of handling “Nullish” values in Javascript. For current projects, the same can be achieved with the support of Babel.js and/or Typescript.

  • Optional Chaining (?.)

Also known as Safe evaluation or Safety operator

Long chains of property accesses in Javascript are lead to errors causing crashes as one might yield null or undefined (“nullish” values). Checking for property existence in a deeply-nested structure is a tedious task, for e.g., consider a weather api response,

In order to fetch the value “Thunderstorm” details, the three approaches,

Now, from ES2020 or TypeScript 3.7 or @babel/plugin-proposal-optional-chaining supports optional chaining, where one can write like this,

  • Nullish coalescing (??)

The Nullish Coalescing operator(??) acts very similar to the || operator except that we don’t use falsy values but nullish, meaning is the value strictly equal to null or undefined

Supported with ES2020, Typescript 3.7 and @babel/plugin-proposal-nullish-coalescing-operator

Avoid Null in all possible ways

NullObject Pattern

❌ WRONG

✅ RIGHT, NullObject Pattern

Courtesy: Maximiliano Contieri

Final Words

(courtesy: Maxmilliano Contieri)

Programmer use Null as different flags. It can hint absence, an undefined, a value, an error, or a falsy value (“Nullish” value). Multiple semantics lead to coupling errors.

Problems

  • Coupling among the callers and senders
  • Mismatch among the callers and senders
  • If/Switch/case polluting
  • Null is not polymorphic with real objects, hence NullPointerException (TypeError: null or undefined has no properties)
  • Null does not exist on real world. Thus it violates Bijection principle

Solutions

  • Avoid Null
  • Use Null Object Pattern
  • Use optionals

Exceptions

  • APIs, Databases, external systems where NULL does exist

Linter support

Add no-null and no-undef to your .eslintrc

Sound Null Safety

The Modern languages introducing Sound Null Safety or otherwise known as Void Safety for safer and maintainable code, meaning by default the language assumes the variables are non-null values unless explicitly specified otherwise.

When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be null unless you say they can be. With null safety, your runtime null-dereference errors turn into edit-time analysis errors.

For e.g., Dart, Swift to name a few follow Sound Null Safety

References

--

--