Saturday, September 08, 2007

The right tool for the job: C++ vs Objective-C

I read Alexei's blog entry about C++ vs Objective-C. I agree fully with his statement that:

The argument (which you can go and read yourself) boils down to “C++ can do everything Objective-C can” versus “sure it can, but not easily, usably or understandibly.” The usual argument comes down to object models: With Objective-C, you can send any object any message, and if it understands it, it will respond. C++ is restricted by its compile-time type system, so that even if you have arbitrary objects that all implement the member function foo, there is no way to call that method on a set of them unless they all inherit from the same base class. Except that you can, as exemplified boost::any and boost::variant.

Actually I pretty much agrees with everything Alexei says and the comments put forth by different people. C++ templates is a wonderful thing while often complicated to understand and use. My major issue with them is that they can't be extended into runtime.

So anyway what I want to emphasis is that templates is not substitute for Objective-C's dynamic features. I work daily on a C++ application with +4 million lines of code. The application have a natural fit with OO design because it has a number of data objects which can be inspected, manipulated and visualized in many different sorts of views at the same time. E.g. one view can show the object in 3D while another can show an intersection in 2D. So Model-View-Controller is a natural fit for it.

The more I work on it the clearer Greenspuns Tenth Rule of programming becomes to me:

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

Bottom line is that the kind of structure a large application like this would typically have is what Objective-C was designed for. And thus when I look at the app, all we do in C++ is making a bug-ridden slow implementation of Objective-C.

Creation of views for data objects has to be abstracted because we might create new views we never thought about when the data objects were designed. Thus construction of views has to be abstracted. In Objective-C this is easy. Classes can be passed around like objects and instantiated. C++ on the other hand provides no abstraction of object creation so we ended up making this elaborate scheme with Class ids and factory classes.

We created reference counting, a system for sending messages between object for notifications etc. All stuff that Objective-C was designed for. We end up with huge amount of code for the overall architecture. And it is not even working that well.

But we are not the only ones. Every time I look at a large C++ framework or toolkit I realize that they are just re-implementing Objective-C features in a non standard and buggy way. When I say non-standard I mean that every toolkit has those features but they are done differently in each one and thus not compatible.

E.g. VTK (Visual Toolkit) has reference counting, message passing and abstraction of object creation. Open Inventor has their own reference counting etc. The Qt GUI toolkit has basically gone around the limitations of the C++ language for dynamic behavior and essentially created a library that allows for object introspection and runtime and dynamic dispatch. Essentially they have reimplemented Objective-C in C++. While they have don't quite a good job and I love the Qt toolkit it is still a kludge and non-standard.

So what exactly is my point? My point is that while people can argue from a theoretical foundation that C++ really is the better language due to all its features the power of templates etc, reality speaks for itself. In practice C++ very frequently fails as a language. It seems quite plain to me that when any large C++ toolkit seem to make a half bad implementation of Objective-C then something is wrong with the language.

Does this mean that I think Objective-C is a better language? No, far from it. I just think that one should use the best tool for the job. Frequently it seems like Objective-C would have been the best tool but C++ was selected instead. While C++ has an obvious advantage in implementing algorithms and high performance code, it doesn't seem like the mistake has been done as frequently at the Objective-C camp.

My speculation would be that this is because Objective-C's deficiencies are so obvious. While C++ deficiencies are not as clear. One can more easily kid oneself into thinking C++ will solve the problem without any hassle. And not at least because C++ is better known, a Objective-C developer will more likely consider using C++ for specific parts of the program than the other way around.

C++ and Objective-C complements each other very well in my opinion and they have different enough syntax from each other that it should be easy to keep the two apart in a program. But too often people think C++ is the silver bullet that can be used equally well for any task.


Dav said...

Thank you for a great post! I am just now attempting to hack together some code using Objective-C for the first time and you've explained all the weirdness very efficiently. You anticipated my thoughts perfectly and addressed them well. Seriously, great post.

Adam Smith said...

Thanks for the encouraging comment. It is very nice to get some comments, it also gives some ideas of what to write about later or changes to make.

Did you read the "Why Objective-C" is cool post? It should give some better understanding of ObjC wierdness.

Anyway it is a great language but it takes some time to get into. But once you do it is fun how much you can do with all the powerful toolkits apple provides: Bindings, Core Data, Interface builder, Core Image, Core Animation etc.

HCN said...

Well, at least, you *can* implement dynamic behaviors of Objective-C in C++, but can you implement templates in Objective-C? Note that we are not talking about design here. If you tell me you don't need templates of C++ to implement whatever you want, I would say also I don't need runtime dynamism of Objective-C to do whatever I want in C++.

But I think you guys miss a very important point here: Outside the context of Mac OS X, Objective-C is almost useless. That is to say, unless you think you will never port your application to other platform, Objective-C should never be a choice.

Beside that, if I my design need absolutely runtime dynamic behaviors, I would consider Python as first choice and not a language that is just a mix of C and Smalltalk.