Tuesday, April 24, 2007

C++ is a psycho hose beast

C++, you and I go a ways back. We've been together since before I finished my degree. Since before I got married. I had great times with C++ in college, and we were hanging out pretty much exclusively during my first 3 years as a professional, and I thought things were just great the whole time since we'd met, 12 years ago. That's a pretty freaking long time to be deluding myself into enjoying a dysfunctional relationship.

I've had enough. You suck, C++. We're getting a divorce.

I'll be civil about the whole thing, and we'll still deal with one another to support the kids (legacy projects). Maybe you'll still have a happy life in low-level systems code, but I just don't love you any more, and I've got to move on with my life. But before we split, it's only fair that you know why I'm taking such drastic measures.

How do I hate thee? Let me count the ways...

1) You can't decide who you are.

Any time we're with our other compiler friends, you are maddeningly inconsistent in your behavior. It's seriously creeping me out when I hear about the multiple lives you're going on with. I talk to one buddy and he says that you've adopted the standard namespace and no longer want to deal with your old friend and all her friends. Another says you told her you've never heard of the standard namespace, and you're as close to the old ".h" gang as ever. And now I heard that you actually acknowledged the existince of the "export" keyword with that one pedantic friend, and now that's all he'll talk about when we meet. It's like you brainwashed him into thinking it's commonplace.

I'm tired of trying to remember which compiler we're hanging out with, and having to walk on eggshells with the preprocessor so you don't blow up. No more. My next significant other will be somebody that not only has standards, but sticks to them.

2) You live in a constant state of self-denial

The other day I wanted to ask you about an enumerated type, to see if you'd defined a particular name. Of course, you would have covered your ears and done your "I don't know what you're talking about" routine. Just once, it would be nice if I could give you a string, and you could tell me if a class had that particular method, attribute, whatever. Instead, you basically tell me screw off and do it myself. Introspection opens up all kinds of amazing framework and metaprogramming possibilities, but you're utterly incapable of doing this without help from clunky libraries.

3) You don't know what strings are.

Speaking of strings, what the heck is your problem? Every time I want to use one, I have to use a null-terminated pile of garbage, or a
std::string with a horribly bloated interface, or any number of nonstandard third-party solutions with different interfaces and conventions. I shouldn't have to put up with this every time I want to do some high-level string manipulation.

4) You barely know what arrays are.

Arrays are just pointers to the data with no comprehension of the length of said data? Seriously, do you know how crappy that is? You make two-dimensional arrays needlessly cumbersome and obtuse. How tough would it be for a minimal, non-resizeable version of std::vector to be a first-class citizen? Heck, just making them objects that are aware of their own size would make "ProcessArray(int data[], unsigned int length)" a thing of the past.

5) Your templates are uglier than Sam the dog

Sure, at least you have templates, which is more than Java could say before generics. But holy crap, do they have to be so freaking nasty? And I'm just talking about usage, not implementation. I hope I never again have to type "for(std::map>::iterator ix = data.begin(); ix != data.end(); ix++)"(note: The fact that I forgot to use the preincrement operator instead of the postincrement is yet another stupid detail I have to devote brain cells to) just to set up a loop. Frankly, I'm amazed that people have produced compilers that can make sense of your nonsense.

6) Crappy dependency resolution

I could just #include everything I need, but then every time I make a change half of the project gets recompiled. Admittedly, this isn't a problem until I, oh, get out of school and enter real life, and have to work on sizeable projects, and then it takes 15, 30, 60 minutes, or even hours if you've got a really gnarly program. Way to kill productivity, jerk. And even with #include peppered all over the place, if I get a circular dependency loop, I still have to throw forward declarations in there to get by. Then I have to keep track of when to give you a forward declaration or an inclusion. When I'm subjected to this kind of micromanagement, how does this help me?

7) The neccesity for design patterns

Let me make this clear: I don't hate "Design Patterns", neither the book or the concept. What I do hate is that these are even neccesary in C++. A lot of these patterns are simple to use and don't require a cookbook if implemented in another, more capable language, unlike you, you decrepit heap of ineptitude. I guess this is nitpicking, but I'm at the limits of my attention span on this blog post, and I felt I just had to throw one more reason in there. I could probably go on all day, but then I'd get all weird and incoherent on my imaginary audience, so I'll just take a deep breath and move on to my conclusion. Let's get this rant, er, break-up over with.

(deep breath)

Programming language monagamy considered harmful

Ruby looks like a really cool language, and I'm going to start playing with it more, and hopefully use it on some lightweight applications. Yet, as great as Ruby looks, I'm promising myself that I won't ever get married to another language. I need to broaden my skillset some more, wrap my mind around different paradigms, that kind of thing.

I've heard it said many times, in various forms, that I don't neccesarily need to use Lisp for real work, but I need to learn about it, get comfortable with it, really explore what makes it different from the C family of languages, and it will make me a better programmer. That's next on my list, after I try building a few decent-sized apps in Ruby. Maybe I'll try Haskell or OCaml next.

It's hard to get away from the safe languages, like C, C++, Java, Perl, etc. That's what employers want, because they're popular, and they can pick up just about anybody that can read some C, and have a vauge idea of what's going on. It's hard to use some of these more different languages at many companies, which is understandable, because for all of it's groundbreaking amazingness, who has real world work experience with OCaml? Speak up. Anybody? That's what I thought.

But if we had fewer language monagamists out there, more die-hard language bachelors of the kind I'd like to become, this wouldn't be as much of an issue. We might just find ourselves asking each other why the heck we're still using Perl, when Ruby does everything Perl does with practically none of the downside. And then some of us start using these new languages on some low profile, internal projects, and it works, and we start using them more and more, and suddenly it reaches some sort of critical mass and a language like Ruby completely supplants an inferior cousin like Perl.

It could happen, and I hope it does.

9 comments:

Masklinn said...

Since you look like you've got a lot of C++ experience, maybe you should check D? I don't know it very well but it looks like C++ done right, and one of my friends swears by it.

Will McGugan said...

I was seeing C++ on the side. And although she put out like crazy, I found her difficult and temperamental. I did the slightest thing wrong and she would just go ballistic, often refusing to do anything till I fixed the dozens of things that were bothering her. Her tantrums lead me to the arms of Python, who just 'gets me' in a way that C++ never could.

Serpent said...

std::string isn't bloated.

Use typedefs to make types easier to work with - you don't have to type out the full name of every type every time you use it.

Introspection is nice, but there's a hefty runtime hit that C++ didn't want to take. The design decisions for the language are a good read in "The Design and Evolution of C++".

C++ isn't a good choice for some programming tasks, but it also isn't a bad choice for many. Any powerful tool takes care and maintenance, just like any good relationship.

Anonymous said...

OCaml and other languages are most certainly used in the real world. Here's a job ad which Google put up for me when I searched for "ocaml": http://www.janestcapital.com/tech.html

Anonymous said...

"who has real world work experience with OCaml? Speak up. Anybody? That's what I thought."

I saw a craigslist ad for an OCaml-heavy startup in the Bay Area the other day.

C++ sucks balls.

I recommend having a look at the D programming langugae, it's really freakin' fast and it fixes a lot of the stupidity in C++.

Anonymous said...

Ruby has downsides too

http://blog.cbcg.net/articles/2007/04/22/python-up-ruby-down-if-that-runtime-dont-work-then-its-bound-to-drizzown

I definitely recommend reading one article about Lisp before you dive into Ruby. The postscript article here

http://paulgraham.com/rootsoflisp.html

Then of course there are the recent posts all over the place about "Lisp is not a good Lisp". Start with steve yegg's blog.

Max Bolingbroke said...

I was at a talk by Bjarne Stroustrup this week, and he showed some new syntax for C++0x that solves at least one of your problems. Specifically, you can now do something like:

for (auto foo : fooVector)
{ /* Work with foo */ }

Basically it's syntactically like Javas for comprehension, but works with iterators behind the scenes.

Rafael said...

I don't think you should get divorced with C++. Or even C.

I gotta agree with you, C++ can be sometimes cumbersome. Unlike C (which I consider a K.I.S.S. compliant language), it can be very useful sometimes.
Like every language, C++ has its own idioms and programming practices.
You must follow a pattern. I.e., Java programmers love threads. They spawn threads for everything that must be done paralelly. This is nice with Java because Java has good support for threads and concurrency. On the other hands, you should see C and C++ programmers getting away of threads (and if they are into Unix world, getting really away), and instead using the C idiom for asynchronous tasks: the I/O multiplexing model (say, the select function). This way they don't have to deal with concurrency and many bugs will never turn up.
Of course you can also take on very nice helper tookits. Glib and QtCore are nice examples. Qt has a very good API for dealing with strings, mutexes, threads and so forth.

Well my conclusion is: Each programming language has its advantages and disadvantages. Perl is really good for writing neat automation scripts and other lightwait applications. Java has become the de-facto enterprise programming language, altogether with the .NET platform. But, IMHO, Java sucks for desktop applications.
So, basically, what I mean is: You will not want to write a web application using C, C++ or Perl. You'd prefer Ruby on Rails, or Java (or whatever) depending on some other external factors.
But you will not write a real time traffic tolling system in .NET. Prefer C.

Choose your language carefully. There is no silver bullet.

Anonymous said...

"Can you rewrite the article on this one and compare it towards the major source? Awesome way of pondering about it, but perhaps I don't believe of it that way."

--------------------------------------------
my website is
http://6stringbass.net

Also welcome you!