This Saturday afternoon, I was tidying my bookshelf and come across this gem, Best Software Writing I which is a compilation of interesting software related articles, published in 2005. In this book, there is this article, C++ The Forgotten Trojan Horse written by Eric Johnson in his now abandoned blog. I reproduce here the article with the conclusion from the book.
I know programmers who started using C++ solely to get the ability to use “//” as a comment delimiter. C++ definitely owes a lot of its popularity to the fact that any legal ANSI-C program was also a C++ program that pretty much did the same thing. -Ed
I find C++ interesting. No, not because my compiler can spit out an incoherent set of errors if I fail to include all of the right headers to appease the angry STL gods. And, no, not because its population of practioners has reached a steady state and is now beginning a slow decline.
I find it interesting because there’s a lesson to be learned about how it conquered an existing community. The tactic it took was deceptively simple yet its one that technologists, especially the “system architects”, rarely learn.
To understand what happened, we need to fire up the way back machine. Before P2P, before spam, before the web, before the Internet was even close to being mainstream, we need to go back to a time when the Macintosh was still running on those old school 68k Motorola chips.
C++ was born in a world that was clearly on its way to being dominated by C. In the late 1980’s, C had become the language of choice for many CS graduates. It was just respectable enough to be taught, and fast enough to be useable for that degrading domain of problems known as “the real world”.
The only real competition that C had faced was from such powerful threats as Pascal, Basic, Fortran, and Cobol. Pascal briefly flirted with fame but flamed out. Basic won its market share, but could never shake the stink of its backwater roots, undeserved as it may be.
With that, we’re left with the only two real contenders. Fortran was for the slide ruler crowd and Cobol was, well, it was Cobol. C found the then perfect balance between respectable programming language and reasonable business tool. From there, it took over the development scene.
Now yes, of course I’m aware that there are many other languages out there. There was Ada, but it had all the sex appeal of a 800 page requirements document from the US Department of Defense. Nothing was as entrenched as Fortran, Cobol, and Basic across such a large swath of development arenas.
In any given system that used any of these classic programming languages, one could achieve a semi-plausible detente between most of them. Interoperability between any of them was never perfect, but it was certainly doable. Depending upon your operating system, Fortran could call into Cobol or even Basic into Fortran. Link level compatibility was possible
Let’s not forget that the Mac had an early love affair with the Pascal community that resulted in its Pascal calling convention and prediliction towards Pascal strings. Fortunately, the Mac was cured of that silliness.
The C programming language fit very naturally into this tranquil world. On most systems, C functions could call into Fortran and vice versa.
Why is this so important? Because for any new technology to take root, it must successful leverage existing legacy into which the contender wants to take over. That’s just a fancy way of saying that it has to not require an organization to rewrite everything from scratch. Leverage what’s already there, and you’re a helpful contributor.
So C come as a helper. What makes C++ so fascinating is that it first emerges as a helper, but with enough encouragement, its transformed into the conqueror and eventually the new master to which all must yield.
The C++ language was purposefully designed to subsume as much of the existing C language as possible. Only the most observant C++ language lawyer can articulate the areas in which C compatibility was not kept.
So what does such subsumption get you?
Existing C developers could be dropped, almost entirely unaware, into a C++ compiler. Yes, there were performance differences in those early days, and yes C++ compiler’s have a cranky streak to them.
Most C developers could be guilted into accepting such stringency. Even the high falutin talk of the wonderous powers of object oriented programming shamed them into using the compiler.
But in reality, all of this meant was that existing C developers would continue to write C and merely append a few more letters to their compiler invocations and their world wasn’t different. Not yet. The trap was set.
C++ made the switching easier since it easily consumed all of the functionality in an existing C domain. There was nothing to rewrite. The only real code change to make was to declare those old school functions with their “extern C” magic and C++ could easily consume them.
In years before, interoperability between a C function and a Fortran function required a little bit of thought and some understanding of how the two worlds work. C++ worked differently. Heck, it just worked.
This gave considerable power to the C++ advocates who would arrive into an existing C organization. They could easily develop new functionality by leveraging the existing code base. They could co-opt the system.
On top of this, C++ at least made it feasible to declare functions such that the old school C geezers could still consume them. Granted, the old C school couldn’t get access to the new fangled classes or templates, but that was ok by both parties.
The geezers weren’t entirely threatened by the C++ upstarts. And if the organization was growing, the geezers were headed for management real soon anyway, so it was just a matter of time.
Its at this point in the infection process that C++ takes over. Not only does it leverage the features of the existing code base. But it offers a potpourri, a smorgasboard, a veritable endless supply of doodads and useful features that the willing and intelligent developeris able to use.
The C++ language never rammed any features down your throat. Let’s not confuse the languages stance with that of the zealots in that community. You never had to use those OO features if you didn’t want to.
But they were so tempting weren’t they? They glistened like gold and were so much fun to use. You were young. You didn’t know any better. You needed the money.
At first, the changes start in small ways. The comment style changes. /* */ evolves into //. Shortly thereafter variable declarations are sprinkled liberally in the middle of functions.
Then the inevitable happens. References find their way into function declarations and structs turn into classes with multiple inheritance. Classes pick up non-trivial constructors, and critical high level functions start throwing exceptions.
By the time the sickness has fully set in, its too late. There’s no turning back. The beauty of the transformation process is that as the code base becomes more entrenched into C++ specific features, it becomes harder to get out. The code begets further C++ addiction.
Given the difficulties created by the linkers on most modern operating systems, C++ has to go through extraordinary silliness to make its function overloading available to mere mortals. But its the same silliness that serves as its defense. Once you have mangled function names, there’s no hope for the rest of the classic languages like Fortran or Cobol to feel like equals.
The trap has finally triggered. There’s no going home anymore. C++ took a classic maneuever. Embrace, extend, extinguish. A trojan horse.
C++ used a time tested technique for conquering a community and setting it off on a new course. Why do battle with a community when you can co-opt them into your mission?
Too often we developers think of great change as requiring discrete, atomic, massive events that stand out as a fork in the road. We envision corporate mandates, industry initiatives, an onslaught of PR releases, and carefully staged PowerPoint presentations as the only tools of change.
But like plate tectonics and evolution, great and enduring changes are also possible through purposefully directed actions in a small sequence of steps. It’s even more powerful when your developers can use the legs they already have.