Blog 4 min read

John Carmack: A C++ Programming Legend

Share this article
John Carmack: A C++ Programming Legend

Have you ever seen a basketball or soccer player play a simple yet effective game, to such a point that you say: why couldn’t everybody play like him? He uses only easy techniques.

As a C++ programmer, I had the same thought when exploring John Carmack’s source code: it’s so simple that we wonder why we can’t develop like him.

Let’s explore some Doom 3 source code choices and try to understand why the code, even though it’s simple, is very efficient.

On November 23, 2011, id Software kept up the tradition and released the source code of their previous engine. This source code was reviewed by many developers; here’s an example of Doom 3 feedback from Fabien Sanglard (original source):

Doom 3 BFG is written in C++, a language so vast that it can be used to generate great code but also abominations that will make your eyes bleed. Fortunately, id Software settled for a C++ subset close to “C with Classes” which flows down the brain with little resistance:
  • No exceptions.
  • No References (use pointers).
  • Minimal usage of templates.
  • Const everywhere.
  • Classes.
  • Polymorphism.
  • Inheritance.

To sum up, only a subset of the C++98 standard is used. And here are some design choices of Doom 3:

1. Provide a common base class with useful services.

Many classes inherit from the idClass:

doom10

The idClass  provides the following services:

  1. Instance creation.
  2. Type info management.
  3. Event management.
doom11

2. Make string manipulation easy

Generally, the string is the most used type in a project; many operations are performed with strings, and we need functions to manipulate them.

Doom 3 defines the idStr class, which contains almost all the useful methods to manipulate strings — no need to define your own methods, as is the case with many string classes provided by other frameworks.

3. The source code is highly decoupled from the GUI framework (MFC)

In many projects using MFC, the code is highly coupled with its types, and you can find MFC types everywhere in the code.

In Doom 3, the code is highly decoupled from MFC; only GUI classes have a direct dependency on it, as shown by the following CQLinq query:

doom3

This choice has a big impact on productivity: indeed, only the GUI developers have to care about the MFC framework, and the other developers don’t have to waste time with MFC.

4. It provides a very good utility library (idlib)

In almost all projects, the most used types are utility classes, as shown by the result of the following query:

doom4

As we can see, the most used ones are utility classes. If C++ developers don’t use a good framework for utilities, they spend most of their development time fighting with the technical layer.

idlib provides useful classes with all the methods needed to handle strings, containers, and memory, which makes the developers’ work easier and lets them focus more on the game logic.

5. The implementation is very easy to understand

Doom 3 implements a hardcoded compiler, and as C++ developers know, developing parsers and compilers is not an easy task. However, the implementation of Doom 3 is very easy to understand, and its code is very clean.

Here’s the dependency graph of the classes used by the compiler:

doom16

And here’s a code snippet from the compiler source code:

doom15

We have already studied the source code of many parsers and compilers, but it’s the first time we’ve discovered a compiler whose source code is so easy to understand — and it’s the same for the whole Doom 3 source code. It’s magic. When exploring the Doom 3 source code, we can’t help but say: WOW, it’s beautiful!

To sum up, the Doom 3 source code is very clean, easy to understand and maintain, and uses only a subset of the standard. No advanced techniques are used, and it follows basic best practices for designing, naming and formatting code.

We can say that John Carmack’s secret was the KISS principle, as defined in Wikipedia:

KISS is an acronym for "Keep it simple, stupid" as a design principle noted by the U.S. Navy in 1960.[1][2] The KISS principle states that most systems work best if they are kept simple rather than made complicated; therefore simplicity should be a key goal in design and unnecessary complexity should be avoided. The phrase has been associated with aircraft engineer Kelly Johnson (1910–1990).[3] The term "KISS principle" was in popular use by 1970.[4] Variations on the phrase include: "Keep it simple, silly", "keep it short and simple", "keep it simple and straightforward",[5] "keep it small and simple" and "keep it stupid, simple".[6]

What's interesting about this definition is the following assertion:

The KISS principle states that most systems work best if they are kept simple rather than made complicated.What lessons should we learn when adopting the new C++ standards?

The new standards introduced many interesting new features. Thinking that using all these features will make your code very efficient is a bad idea; many new features are more useful for developing generic libraries, especially all the features related to generic programming.

Don’t force yourself to use all the new features; use a feature only if it’s absolutely needed and contributes to making your code more efficient. For example, this interesting post talks about the drawbacks of overusing the auto keyword.

Share this article