2007-11-29

Why not C++?

This was originally posted on iDevGames, but since people are constantly asking me why I hate C++ so much, I thought it should be posted here too.

My philosophy is that at any given time, there are three things that you may care about when programming. From least common to most common:

  1. You want to write fast code.
  2. You want to write correct code.
  3. You want it to be easy to write code.

Unfortunately, these tend to work against each other.

If you want to write fast code, you need a language which takes you close to the hardware. It needs to provide a fairly direct mapping between the "high-level" source and the assembly, so that you can pinpoint problems in the assembly and know exactly what needs to change in the high-level code to fix them. The only language I've ever used which does this is C. With C++, as soon as you get into references, copy constructors, operator overloading, etc. there is too much going on for that direct correlation between source and assembly to exist.

If you want to write correct code, you need a language which prevents you from making as many errors as possible. That implies a strict static type system, array bounds checking, an inability to poke around directly at bits and bytes in memory, etc. Obviously, C++ doesn't fit that bill; the closest language I've found is Haskell. Java's unchecked exceptions rule it out, though there are tools that can help with that.

If you want it to be easy to write code, you need a language that allows you to express what you want; that doesn't tie you down to rigid typing structures, or keep you fiddling with minutiae like memory management. This tends to mean a highly dynamic object-oriented language. Unsurprisingly, since this is the most common category for code to be in, this is the category with the most appropriate languages in it. Ruby and Python are two obvious ones. C++ is far too static, and keeps you far too immersed in low-level details to be useful here.

Of course, any given project is likely to consist of parts which fall into each of these three categories, which leads many people to seek a "compromise language" — one which is "fast enough", "safe enough" and "easy enough". Ultimately, I believe such languages are always a waste of time. You will spend more time optimizing the bits that need optimizing, more time fixing bugs in the critical sections of the code, and much, much more time trying to design your software in such a way that you can actually build it, than if you were using the appropriate language for each part.

These languages are not difficult to tie together. All have easy ways to interact with C, which can be used as a thin layer of glue to stick them all together. The boundaries between the sections of code with different requirements tend to be reasonably well-defined, and you can therefore avoid crossing your language boundaries too often.

If you're using the right language for the job, your code will be as clear, concise, and well-designed as it's possible for it to be. To use the favorite vehicle analogy, you wouldn't try to use a Ford Ka as a personnel carrier in a war zone, and you wouldn't drive to the shops to get the groceries in an APC. Either might "work", but you'd be better off with two separate vehicles.

And please, don't try the argument that "it's easy for me to write C++" or "I don't waste time fighting C++'s memory management and lack of dynamicity" or "I don't make bugs these days"; it's well known that people are notoriously bad at analyzing their own productivity. There are simple studies and metrics that prove that programmers are more productive in more dynamic languages, and write safer code in safer languages.

0 comments: