Javier Casas

A random walk through computer science

The Tyranny of the new keyword (I)

Every modern programming language has a way to construct new values, because every minimally complex program is designed to process basic values into more complex results. The usual operation to summon creating a new value is the new keyword, at least in Java-like languages, such as Java, C++, C#, TypeScript and others.

But I think this new keyword is based on wrong assumptions, and has done significantly more harm than good. Allow me to explain my points:

What does new do under the hood?

new is a keyword to instantiate a class into an object. It receives as parameters the class to instantiate, and the parameters to the constructor. A bit of digging under the hood reveals that new works by doing:

  • Allocate enough memory to hold the object. A call to malloc, jealloc or whatever other memory allocator (even implicit in a GC environment) happens.
  • Initialize the memory to default values. Local variables are initialized to null or zeroes. The vtable is initialized with pointers to specific methods depending on the specific class instantiated.
  • Summon the constructor with the specified parameters on a pointer to the object being created. The constructor does whatever needs to construct (user defined).
  • Return a pointer to the newly created object.

Well, none of these steps actually require special support by the programming language. The C guys would just do the four steps in succession and get over it. But having nicer syntax helps, doesn't it?

The results of having the new keyword

new is used to instantiate a class. Which means it lives somewhere between compile-time and run-time. Depending on the programming language, if types are erased during compilation, the class dissappears. If types are kept during compilation, the class is likely to live in some kind of limbo, not being a class anymore but something different. But this is not the main effect. The main effects happens on the mind of the programmer.

The first short-circuit

  • The way to instantiate a class is by using the new keyword.
  • Therefore I have to use the new keyword to bring new objects to live.

This is the first short circuit that happens on the mind of the programmer. It's effects are insidious, and will be multiplied later when we add more short-circuits on top of it. Bear in mind that every OO programming language that claims the previous, in fact, is violating it for many cases. After all, you don't do:

  • var mynumber = new 3; - 3 is not the name of a class, so you can't really put it here.
  • var mynumber = new Number(3); - Good, Number is a class, but how do you get a 3 to put it as a parameter?

As soon as the programming language designer accepts this transgression, he happily throws in more transgressions. Here comes some C# where we create a new Tuple without invoking new:

  • var mytuple = Tuple.Create<int, string>(3, "asdf");

Obviously, neither of the parameters have been created with new as well. Why bother at this point?

The second short-circuit

  • The way to call constructors in objects is by using the new keyword so indirectly the constructor is called.
  • Therefore, I need special effort to initialize an object, as I need to somehow call new on it.

So initialization of an object is something that can be done only as the result of new. Which means we have a single chance at initializing the object properly, and we have to use that chance properly. Soon, all kinds of design patterns arise to be able to use this incredibly valuable single opportunity, such as the Builder design pattern.

The third short-circuit

  • I can't swap a class name in an instantiation, because the class name is constant and exists at compile-time only.
  • Therefore I have to construct something that allows me to swap the class name at runtime.

You won't find a programming language with the new keyword that accepts the obvious code below:


var myclass;
switch(someSetting) {
  case development:
    myclass = MyClassForDevelopment;
    break;
  case testing:
    myclass = MyClassMockForTesting;
    break;
  case production:
    myclass = MyClassUsingTheProductionDatabase;
    break;
}

var myobject = new myclass();

The reason for rejecting the code above is that classes are not something that can be assigned to a variable, and the only way to call new is by supplying a class, which means you can't swap a class with another at runtime, even though the OO-is-classes guys claim that you should be able to replace a class with a subclass.

With this inability to switch classes easily, the programmer evolves to Your Highness the Architect, and invents the Abstract Factory.

The fourth short-circuit

  • There is a single constructor (or maybe some constructors if you are in C#) and it receives a fixed list of parameters.
  • (Optional) I shouldn't create many constructors because then it will be hard to figure out which one to use.
  • Therefore I need a helper thinguie to help me instantiate my complex class.

And now we have another reason for the Builder pattern. We have a complex class (which is a problem on its own), and we fix that complexity by creating another class so we can hide the complexity of constructing my complex object under a blanket of more complexity intended to reduce the complexity of constructing a complex object with complex parameters. Before it, we had a problem. Now we have two. What a great improvement.

Conclusion of the first part

This is only the tip of the iceberg. On the next chapters we will explore in deep how this minor detail has shaped the mind of a whole generation of programmers in order to make them significantly less strong than they could be.

Back to index
Copyright © 2018-2023 Javier Casas - All rights reserved.