Bashing C++

It’s easy to bash C++ having Linus Torvalds on your side. But bear with me for a minute and you will see how this bashing post is more argumentative than others.

Before the flame begins, let’s speak about the following two worlds of application development: constrained software and rapid application development.

The former world includes software severily constrained in the run-time by some factor, for example by limited CPU performance or memory. Both can happen either due to cheap hardware (eg. embedded hardware, handsets, etc) or due to the sheer size of the computational task rendering any available hardware to be limited.

Typical examples are operating systems, codecs, 3D game rendering engines, or Google Search. And the top 3 priorities in this world are:

  • Run-time computational performance
    • Theoretical Big-O of used algorithms as well as ability for parallel execution
    • Practical performance of implementation (including effects of processor caching architecture, prediction, locality of data, network congestion, etc)
  • Run-time memory efficiency
    • Theoretically efficient data structures (i.e. not wasting bits for no reason)
    • Practically efficient data structures (including taking care of memory fragmentation, malloc overhead, etc)
  • White boxes instead of black boxes. In constrained situations it is almost never possible to add some new functionality as a black box module with a clearly defined inputs and outputs. Internal implementation of the module will often interfere with the whole system, therefore the black box must be stripped of its case (hence the term white box, although strictly speaking it should be transparent box).

For the lack of established term for this world I will call it CS.

The world of rapid application development (RAD) includes wide spectrum of application software, for example enterprise information systems, web sites, media players, mobile apps, office software, etc. Its top 3 priorities are

  • Productivity, defined as inverse of costs to implement a feature.
    • Money costs: how much developers will charge per feature
    • Time costs: how long we must wait until the feature hits the market
  • Flexibility, defined as inverse of costs to change some existing software
    • Money costs
    • Time costs
  • Black boxes everywhere. A great software architect will split the whole software system in such black boxes that many of them will be reused later, both inside and outside of that system. An ingenious software architect would give his black boxes such a sex-appeal that other developers would eagerly re-use them (without being forced or asked for).

These two worlds constitute by no means the complete list of software universes. There are other worlds like

  • viruses and security-related software;
  • compilers, language run-times and web browsers;
  • games and art (eg. the demoscene);
  • scientific software;
  • statistical and ah-hoc calculations;
  • and competitive programming.

But CS and RAD worlds are the biggest and primary ones, and the other worlds often overlap with one of both of them.

According to mentioned top priority lists, we can quite naturally see what are the usability requirements for the programming tools, especially for programming languages.

The CS world needs a language that is not present in run-time. Ideally, CS software should look like as if it was carefully crafted byte by byte in machine codes, to eliminate any waste possible. Programming languages higher than assembler are for CS developers an embarassing acknowledgement that their minds are not powerful enough to use assembler.

The RAD world needs a language allowing to go live before all the bugs are fixed. This language must provide a lot of information when something goes wrong, and also ideally allow to fix things without killing the process being currently executed. So RAD developers expect language to be very present at the run-time and helping them to fight the last blocker bugs under pressure of already being live with end-users stumbling upon the bugs and cursing the programmers.

The CS world needs a language that will do most its checks at compile time, and possibly check all white boxes of the system against each other, before blessing the compilation result as a whole for its first run. Whenever they can, CS developers would compile everything from OS kernel to user interface all at once, just to be sure everything is checked against everything and all sits and fits.

The RAD world needs a language allowing to replace black boxes without affecting other black boxes; and being able to do it directly in the running system without stopping it (ideally, in a running system being actively used without affecting its performance or letting its users know about the change).

Enter static vs. dynamic languages.

Enter debugging by core dump vs. RAD debugger user experience.

The CS world can only find white boxes useful, and so its libraries reflect that. For example, for a single data structure concept (a mapping between key and value) the standard library might provide an implementation based on hashes and another implementation based on lists, and might be yet another implementation for a special case of key type, as well as basic building blocks to be able to write your own custom implementation.

The RAD world needs a language one can easily (as in: quickly and cheaply) read and understand, so that a data structure concept must be directly reflected in the data structure name, and therefore there will be exactly one data type, preferrably built-in into the language, and its name will be Dictionary (or map).

Enter white box data structures vs. black box data structures.

I could go on, giving more and more detailed examples of how different these worlds are. But that should be enough for us to agree it is impossible to cover both worlds with a single programming language.

And now, it is time to bash C++, as it is guilty.

According to Stroustrup, the initial idea for starting C++ was combining Simula with C. From C, he has used its run-time efficiency (a core CS feature). From Simula, strict static type-checking (another fine CS feature) as well as its concepts of classes and inheritance,  that is, the ability to define black boxes (RAD feature). Wait, a RAD feature in CS world?..

Later on, other RAD features were added to C++, like exceptions,  RTTI, generic programming, and, lately, garbage collection. Stroustrup himself states that C++ is a general purpose programming language with bias to systems programming.

So, what has happened to C++? Stroustrup started with a CS language, added some CS improvements that were bitterly needed (improved static type checking for example, or inlines), but then started to clutter a CS language with RAD features. As a result, we can see all kinds of mess:

1) Some naive people who work in CS world would use a RAD feature (because they don’t know better) and would shoot themselves in the leg. For example, using exceptions inside of a library or system-level tool. And we all wait for the first codec or driver using garbage collection.

2) Some naive people who work in RAD world would use C++ because “it looks so native, pretty guy” and would shoot themselves in the head, because you can’t be productive in RAD without black boxed data structures, and without more powerful reflection, and without dynamic type checking, and without useful error messages when your templates went wront, and with such a convoluted and unlogical syntax, and so on.

3) People who work in a mixed world, like game development, would use C++ both for CS part (i.e. scene rendering) and RAD part (i.e. game objects, AI), with the result that a) their RAD part will suffer from less productivity and flexibility because of poor C++ standings from RAD part of view and b) their CS and RAD parts would tend to uncontrollably diffuse in each other, for example, game objects would have some render support or physics logic.

4) Poor students whose first programming language is C++ won’t understand, what really OOP is, what really systems development is, and what really generic programming is, because all that is so horribly mixed together that you can barely find a teaching book cleanly and concisely separating the CS from RAD in this language.

C++ is an MFU. It can somehow print, and a more or less scan, and sometimes even fax a little. But none of its functions is truly user friendly.

I wonder how Objective C is designed.

One response to “Bashing C++

  1. Pingback: On TypeScript | Maxim Fridental

Leave a Reply