In a colorful little piece of partisanship, Dean Michael Berris takes issue with a recent Programming and Development article of mine at TechRepublic. He seems to think I "hate" C++ with an intense passion, but the truth of the matter is that I have no passion in relation to the language at all. His error of presumption here seems to quite simply be a result of taking offense at my skepticism about its greatness, and my belief that it suffers some nontrivial design flaws and overuse in areas where other languages might be better suited.
My article under assault is A skeptic's history of C++, which attempts to give a bit of an overview of some of the aspects of the language's history that are often ignored elsewhere. It is surely no comprehensive history, and ignores a lot of the kind of history of the language you might find elsewhere -- but it does so specifically because that is information you might find elsewhere, and bears little relevance to the subject at hand: some of the reasons it might be better replaced, and some of the reasons it has not been effectively replaced.
Berris' soapbox is a Weblog called C++ Soup!, and the particular bit of writing that targets my article is titled C++ Hating (page requires JavaScript). I feel like commenting on it, a bit.
C++ Hating is filled with "ha ha only serious" insults, and bears little of any concrete value in its assault on my article, but I will attempt to avoid commenting on all of that. It would be something of a waste of time, beyond simply pointing out that the problem exists. Let us focus instead on the concrete failings of Berris' response.
The first sentence does not say anything substantive (though it is a bit denigrating), but the second sentence gets something specific, provable, and clear quite horribly wrong:
The article -- like countless articles on the web already -- try to predict the demise of C++, this time in favor of other programming languages that are not as powerful.
I'm not talking about the grammar. I'm not even talking about the claim that all the other languages mentioned in my article as potential alternatives to C++ are "less powerful". I'm talking about the basic premise of the sentence -- that my skeptic's history suggests the imminent demise of C++. It does not. In fact, it says quite the opposite. My article's words:
I am inclined to believe that C++ will have a long, stable tenure in its niche for some time to come.
He goes on to reinforce the error after a lengthy quote from the article:
If you read through the article it is littered with anecdotes from which the author tries to make a case for the demise of C++.
He does make some good points about what would be needed to replace C++ as the implementation language for applications (and application suites) such as the Chromium browser (represented by the Google Chrome distribution in his list), Adobe Creative Suite, Microsoft Office, and World of Warcraft. I would not necessarily agree with everything qualitative he says about his software examples, but I do agree with his basic statements about what kind of capabilities an implementation language should offer to replace C++ in developing such applications. None of what he says about these applications directly challenges the statements in my article, but . . .
He then goes on to say this:
I challenge you to name one programming language other than C++ to which to write applications similar to these, and be able to deliver the same level of functionality, stability, extensibility, portability, and ubiquity that these applications are written in.
Okay, fair enough.
functionality: That's easy. Write code, get functionality. Note that he is talking about whether a language can be used to produce the functionality in these applications -- not what functionality the language itself (and its implementations) may provide. Any Turing complete language can provide the indicated functionality, some more easily than others (and that ease is what many would call a language's "power"). Perhaps he overlooked my reference to Objective Caml, wherein I said (and he quoted) that it offers "more succinct and well-organized source code" and provides "far cleaner and more interesting development models", thus directly addressing the provision of such functionality with relative ease. Proponents of D (another language I mentioned in my article) would argue similarly, though for reasons of different technical advantages of the language than in the OCaml example.
The jury is still out on the other major non-C language I mentioned, Go, as developers are still sorting out the appropriate niches and major advantages of the language; it demands some different approaches to software development to make use of its most compelling functionality, so it offers fertile ground for debates over the trade-offs it offers for the next couple years or so.
Another option, of course, is Haskell. It is sometimes derided by those who do not understand it as impractical, but it is every bit as capable as C++, and developers who work with it regularly commonly churn out nontrivial code in fractions of the time and linecount required for equivalent functionality. Haskell code, for an equivalently skilled developer, also tends to be more easily maintained thanks to its greater visual clarity and succinctness.
Regarding C++ itself, as concurrency becomes increasingly important, the lack of standard threading functionality is a growing source of frustration and criticism for C++ programmers. The C++0x standard may eventually serve as the basis for addressing this problem in a portable, widely applicable manner, but for now this is still a bit of a worrisome failing of the language's capabilities.
stability: Right away, I wonder where Berris gets his ideas about C++. Stability is not really a feature for which C++ is known. In fact, people like Linus Torvalds refuse to let any C++ creep into their projects built primarily in C precisely because of stability concerns. This is above and beyond the stability concerns it shares in common with C, such as the ease and frequency of buffer overflow with unsafe core and standard library functions that are not meticulously checked and rechecked by painstakingly careful coding, and the fun of occasional programmer errors when pointer arithmetic enters the picture.
Leaving C++ itself alone for the moment, I have yet to see any credible suggestions that Objective Caml, D, or Haskell produce unstable applications as a result of some feature of the language, Objective-C only shares the same shortcomings in this area that exist in both C++ and (because it is a true superset of the parent language, unlike C++) C itself. What criticisms I have seen regarding Go's contributions to software instability issues seem primarily to be similar to, but less egregious than, the example of C and C++ core functions that require special handling to avoid issues.
extensibility: I'm not sure what he's trying to say here. Surely Haskell is far more extensible in many ways than C++, Objective Caml's module system is incredibly flexible and easy to use, and both allow much less painful cost:benefit ratios for metaprogramming. I am intentionally holding off on mentioning Common Lisp here. My point is simply that bringing up "extensibility" seems like a losing play from the perspective of his position.
portability: It's true that Go is still in the process of achieving widespread portability, though it is already available for Linux-based systems, MacOS X, MS Windows, and the various BSD Unix systems. I am not quite well-versed enough in D lore to be able to offer useful insights in this realm. Objective Caml, Objective-C, and Haskell are available basically everywhere except certain fringe platforms, and binary compilation for such platforms would likely not be far behind the moment a demand arose.
The most important factor for portability, given that all that is needed for binary compatibility is market penetration, is the ease with which code generic to many platforms can be written -- which is certainly easier at least in most cases using languages like OCaml and Haskell than for the C family of languages. It is this factor of portability that ensured C's early and enduring successes, and some of the lessons learned there have been utilized (and improved upon) in the design of these other languages.
ubiquity: What is this? Is he suggesting that a language's popularity is a purely winning factor? I disagree strenuously with such a positive assertion that language popularity is a key factor, as do a number of much more august and famed programmers than me. We might as well write our browsers in Java and PHP if language popularity is such a big deal. If that is what he means, he should explain why this is so important so I can enlighten myself. If that is not what he means, he should explain what he does mean when making such vague, hand-wavy statements.
C, by the way, is not a strict subset of C++. Parts of C have been replaced in the form that C++ takes, so that some working C code will actually not work for a C++ compiler -- and I speak of more than mere boilerplate. Objective-C is a true superset of C in that sense (or, in the terms in which Berris puts it, C is a true subset of Objective-C), on the other hand. This is one of the reasons that some wish Objective-C had enjoyed the successes that have instead been granted to C++.
Meanwhile, using different development philosophies than those that best suit C++ -- some would say far superior development philosophies, such as the Unix philosophy -- can suit C as an excellent development language where C++ might otherwise be used. Take for example the uzbl browser, written in C, with extended functionality provided by additional software written in a number of languages including Python where the near-metal performance of a C-family language's compiled binary executables is not needed. In fact, the C code in something like uzbl is much cleaner and more easily maintained than the equivalent C++ code in projects such as Mozilla Firefox.
I said above that I was intentionally not mentioning Common Lisp at that point. Some implementations of Common Lisp are quite performant, and its proponents can tell you that functionality, stability, extensibility, portability, and ubiquity are all quite well represented in that language. On the other hand, it attracts flame wars, so maybe we should just ignore it for now.
Let's move on to Berris' next major complaint:
Have you really thought about what C++ offers in reality before you corner it as simply an object-oriented programming language?
Have you stopped beating your wife, yet?
The reason I have not "really thought about what C++ offers in reality" before I "corner it as simply an object-oriented programming language" is that I never actually pigeonholed C++ as "simply" an OOP language.
C++'s strength is not its object oriented programming support -- it's the fact that you can write in many different paradigms in C++ that makes it its strength.
Objective Caml offers much more complete cross-paradigm capability than C++.
Also, if you're doing benchmarks, then everyone knows that micro-benchmarks are meant to highlight one aspect of the system/solution you're benchmarking. A true benchmark is one that accounts for real-life conditions and usage patterns.
I'm not "doing benchmarks". I don't know that "everybody" knows this, but Berris' statement about the proper use of micro-benchmarks is effectively true. It does not disprove anything I have said, nor does it prove anything he said, however.
He continues on in that vein for a bit, and finishes up with an attempt to discredit OCaml claims of performance:
If you're comparing a bubble sort in C++ with a radix sort in OCaml, then maybe the OCaml will have a better performance profile depending on the inputs.
Ultimately, however, all he manages to do (if we take him at his word) is eliminate the performance argumet that many offer in favor of C++.
He addresses the matter of readability -- sort of:
Also, when you talk about aesthetics, this is a matter of taste and familiarity.
There is a big difference between subjective taste and practical readability issues, however. Greater succinctness without sacrificing clarity improves readability. Greater power in semantic constructs improves readability. Judicious use of language "punctuation" improves readability. These things are, for your average human, largely independent of personal taste and familiarity. Subjective taste and familiarity come into play with issues like preferring significant whitespace in Python, braces in Perl, and do/end blocks in Ruby -- and not so much issues like less significant support for composable source code organization, greater requirement for boilerplate code littering your source files, and cluttered semantic models.
He makes an excellent point here:
A large part of efficiency and proficiency is mainly attributed to familiarity with not only the technical matters, but also the idioms and shared understanding between/among a group of practitioners.
Of all the languages I have used, and whose communities I have encountered, Perl, Python, and Ruby do this the best. PHP mostly fails, Scheme's "community" is too fractious and provincial to achieve that level of idiomatic communion, and Java too bureaucratic for its otherwise strong culture to offer as much benefit as it should. C and C++ have legendary flame-wars between partisans for different cultures of idiomatic code, but if you pick a partisan ghetto and stick with it, you can surely achieve what Berris describes.
Unfortunately for his argument, it is largely irrelevant to any of the points I raised in my "skeptic's history".
Borrowing from the great John Dvorak, I'd say "this is baloney!". If you think being proprietary may hinder its widespread adoption, take a look at Java which the enterprise world is treating as the new Cobol.
If you note the word "may" in the statement of mine to which Berris objects so strenuously, you will surely see that his objection is baseless. I did not say it would necessarily hinder its adoption. I said it might. Standardized languages (like C++) and those with open reference implementations (like Ruby) tend to get much more friendly receptions, when lacking the massive marketing power of Sun Microsystems.
Think the x86 assembly language, that's proprietary.
It is well-documented and not proprietary in any way that matters. It has been reimplemented many times, in non-proprietary forms, not only without its originators' interference, but with their blessing and encouragement. In any case, x86 assembly language's widespread use is a product of its ties to hardware that achieved strong market success -- a benefit not enjoyed by languages that aspire to great portability like Java, C++, and D, so its inclusion here is a bit of a red herring.
He evidently believes that technical quality trumps all. I wish it were true, in practice, but I find I have difficulty swallowing this statement:
Unlike in the world of social interactions where investing in politics has an effect, this is not so true when it comes to hackers choosing the tools they use. If you're trying to sell a better mousetrap, your mousetrap better be a lot better than what I have for me to even start considering buying it.
Why then, I wonder, did he bring up Java? What about PHP? These are languages that, to a significant degree, enjoy continued success despite their technical characteristics and hacker-friendly capabilities (or the lack thereof).
Much as Microsoft does, Berris blames users for the failings of the tools he wants them to use:
As far as concurrency is concerned, the real problem is that the general population of programmers don't know how to write effective concurrent programs.
That is rarely more true than in C++. Meanwhile, Erlang provides safer, easier, and more performant concurrency than C++, at least the vast majority of the time. The fact he brings up Erlang (and Go) here with a sentence that begins "Even if" suggests that even he realizes C++ lies well behind Erlang (and, to a lesser extent, Go) in terms of its facility for concurrent development.
Let's revisit Common Lisp again, this time at Berris' insistence:
I will be the first to admit that C++ is not as powerful as Lisp when it comes to the things you can do with Lisp, but if you know your Lisp you can approximate these with modern C++ -- and some even might say "voodoo" with C++ template metaprogramming.
Greenspun's Tenth Rule comes to mind:
Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
The concept is more generalizable, in that it applies equally well to most programming languages, with only some of the more interesting -- and less widely used -- cutting through a lot of what that implies. Examples include languages like Haskell, Smalltalk, and Lisp spin-offs.
Stating that you can effectively reimplement significant portions of Common Lisp in C++ to achieve the same capabilities, as Berris essentially did here, is hardly a point in favor of C++. The fact you can effectively reimplement significant portions of C++ in any contenders for the same development niches comes to mind as an interesting counter-point, too, I think.
He endeavors to address the performance benefits of C++ more directly, at last, in an argument against (presumably Common) Lisp:
Also, Lisp is a non-starter when it comes to performance, at least unless you're prepared to tune your Lisp implementation for the specific workload you're encountering.
One must wonder what implementations of Common Lisp he has used to make this statement so categorically, and why it seems to disagree so directly with his arguments about OCaml above.
His wrap-up ends thusly:
Admittedly, there aren't a lot of well-written books about C++ programming for beginners -- the one I can point to is Programming: Principles and Practice using C++. Before you knock on C++ again, read this book first then tell me how not powerful C++ is -- it's alright, you can thank me afterward.
(Just to get this out of the way: I did not say C++ is not powerful.)
I must admit I have not read that book. I wonder if he has devoted similar effort to reading about the other languages he claims fall so short of C++ in so many ways. Regardless, I will make a point of checking out Programming: Principles and Practice using C++, though for now I'm a little more wrapped up in reading books about C, Clojure, Erlang, Haskell, Io, Prolog, Ruby, Scala, and Scheme. I think SQL (yes, I know it's not exactly a programming language), JavaScript, UCBLogo, and Common Lisp books are in the queue ahead of C++ at this point, and a book or two about Perl, and maybe some Objective-C, might sneak in there as well. I'll likely do some more C++ work before I get around to investigating Python, PHP, or Java any further, though.
You may gather that I'm a bit of a programming linguaphile. I am by no means an expert in all these languages, but I am at least minimally competent in several, and in fact C++ was the third (or fourth, if I'm forgetting one) language I have used, after BASIC and Logo in the '80s, roughly concurrently with my first encounter with C. Still, I would like to revisit C++ after mostly not using it for years and refresh my skills in that area. Maybe his book recommendation will prove valuable for me. I suppose it is always possible the book might even change my mind about the relative merits and flaws of C++ -- that is to say: my opinion of it, as a skeptic of the language's greatness [0].
Dean Michael Berris' screed certainly did not.
0: The purpose of my opinion piece on the subject at TechRepublic was, in fact, to express the opinion that I hold as a skeptic of the language's greatness -- rather than journalism as he suggests when he refers to it as "yellow bloggerism".