I thought of entitling this post “Object-oriented programming is the pesto of programming paradigms,” to paraphrase the philosopher Costanza. Since I was in middle school, I’ve been hearing people say “object-oriented” with a strange air in their voices as though they were discussing Camus or Beckett; they also often have the annoying habit of throwing in “modern” when talking about their favorite languages.
When I really started programming a few years ago, it came up right away when I was looking for reading material. I studied quite a bit of Python, but since Python is a multi-paradigm language (in a way), I wasn’t forced to learn how to program in an object-oriented style. This past week I decided that since I’m doing real work in Python, I should give real object-oriented programming a try to see what it’s benefits are. Here I report my conclusions.
Table of Contents
1 My Programming Background
A couple things you should understand about me and my programming projects are that (a) I’m a Unix guy and (b) my “programs” are typically along the lines of “input some values and spit out some different values.” I’m not building large programs with complex user interfaces; I have made somewhat complex interfaces in the form of command-line arguments are runtime configuration, but they are still batch-oriented, non-interactive programs. I get the impression that nowadays these are no longer typical. Although my impression is that most programming books only include batch-oriented programs as examples, most people I encounter on the web, and most programming reference guides seem oriented towards either web programming (where the user interface is a browser), or GUI programs.
As for (a) I don’t like limits and labels, but nine-hundred and ninety-nine times out of a thousand, the solution I end up using follows Unix philosophy and GNU standards. I don’t think this is a concerted effort on my part, but pretty often when I think I need to use a language like Python, I end up writing a shell script or make target that gets the job done, often in less than twenty minutes.
2 What is Object-oriented Programming?
No one has given me a satisfactory answer. Alan Kay should know. I certainly don’t know. You will not get a good definition from someone who goes around saying “object” and “object-oriented” with his nose in the air. Nor will you get a good definition from someone who has done nothing but object-oriented programming. No one who understands both procedural and object-oriented programming has ever given me a consistent idea of what an object-oriented program actually does. If you’re reading this, please comment!
The usual definition goes something like this:
OO Zealot: objects have attributes and methods.
Me: Wait, I asked what object-oriented programming is, not what objects are; I know what objects are, every programming language has pieces of data that procedures operate on
OO Zealot: Yeah, but in an object-oriented language, you can define your own data types
Me: I define new data types in C all the time, they’re called structures
OO Zealot: Yeah, but in Java these data types have attributes that they carry with them, that are like procedures, but they’re called methods
OO Zealot: Yeah, but in C you can’t tie a function to a piece of data like you can with object-oriented programming
Me: Sure you can; you can define a structure with a pointer to a function, whose other fields are the arguments of that function. Then you can create a function that takes the structure as an argument and evaluates the function pointed to. In Scheme you can also create what’s called a closure where you basically return a procedure that encapsulates the environment at the time the definition is called. You can use these closures to evaluate the same argument in many different encapsulated environments; you can make whole lists of closures fairly easily. In Scheme you can also travel backward in program execution by capturing the continuation of an evaluation, kinda like a throw-catch.
OO Zealot: Oh.
I don’t mean to alienate people who really know what object-oriented programming is, but that is based on real conversations I’ve had. The people who advocate object-oriented programming at me have seemed at times to just be really narrow-minded and totally ignorant ofother kinds of programming. They think object-oriented programming is the only way, and seem like they’d have trouble learning any other kind of programming. That does not mean I think that anybody who advocates object-oriented programming is a bad programmer, but the people who have advocated it to me have sounded less knowledgeable about programming to me than they thought they did. Is the reason lots of languages phrase their documentation in terms of object-oriented programming because there are a bunch of people out there who can’t do anything else?
Furthermore, none of the definitions of object-oriented programming given by these devotees, or that I have found go beyond defining what “object” means in the phrase “object-oriented.” Some of them also say that “objects pass messages to each other” or “the program is a set of interacting objects,” but that doesn’t really say what goes into the program text of an object-oriented program.
I had a little Eureka! moment when I realized that sure, you could define a program, with “endowed objects” just by instantiating a certain set of such objects, and maybe calling one or two methods. I headed over to my favorite programming showcase, 99 Bottles of Beer, to get some examples of object-oriented programs in languages that are the biggest sellers of the object-oriented lifestyle. Sure enough, what I found was exactly what I refer to above, however it looked an awful lot like a plain old imperative program. What I see in both the C++ and Python versions said to “object-oriented” is that the programmer defines a data type and within that data type he defines some procedures (called “methods”) and then he calls those methods on an instance of that data type. Read that again: defines a variable and calls procedures with that variable. That is no bloody different from imperative programming.
So on a cycling trip across Durham I closed the intellectual book on object-oriented programming again, thinking that I personally have no need for it. Maybe it comes in handy for really huge, really complex programs, but as I said, I try to avoid that at all costs, and I’m not designing a new web browser for anybody. Maybe it has some applications, like in video games, where these “objects” will interact in unpredictable ways, but that’s not what I’m doing either.
And maybe it makes somebody a lot of money, but I’m in it to learn, not to make money.
3 I gave it a try
I still had this challenge of using object-oriented programming languages, especially their libraries. Pythonis an excellent multi-paradigm language, but its libraries work within the object-oriented paradigm. This makes perfect sense because one of the advantages of object-oriented programming is that the datatypes from the library come with their procedures pre-defined. That’s cool. You still have to look up what those procedures are and what they do, and every library that comes with custom data types comes with functions that take advantage of them. Therefore this isn’t unique to object-oriented programming either: think about how useless a library would be if it didn’t work this way. I would like to build some more complex programs in Python, and use its web, XML-processing, and database libraries, so I really should learn how to use some object-oriented programming techniques.
What I had already was a functional program, in Python, which executed a population genetic simulation. For iterating equations, functional programming makes the most sense, and so far Python is the best functional (multiparadigm) language that works in a Unix-like environment. Basically I had a function that did the iteration, that took a function and its argument as arguments. Nice, clean and simple.
What I tried to do in Python was to define a class that did the iteration, and a derived class that defined a specific function to do the iteration. Here’s what I ended up with:
#============begin satire============ self.self.self.self.self.self.self.self.self.self.bungle () #=============end satire============
I’m not an experienced Python programmer, but I felt like this wasn’t really capturing the essence of the problem like OO advocates said it would. Well, a program can only be as good as the programmer. But here’s a more critical question: can you take a mediocre programmer, and give her a C++ or Java project and say “Here, use object-oriented programming” and have the program come out better?
4 Ask the experts
After that half-hearted (is that the right body part?) attempt at object-oriented programming, I thought I should see what some of my favorite hackers had to say.
Paul Graham said this:
Object-oriented programming is exciting if you have a statically-typed language without lexical closures or macros. To some degree, it offers a way around these limitations.
Immediately I thought “Oh yeah, that’s true, I’ve never had that problem.” In other words, I’ve done a lot of programming in Lisp, Scheme and using Python in a functional style. You can even program C in a somewhat functional style, as long as you keep track of the scope of allocated versus stack objects. In C you have to remember to think about things the way the computer does, whereas in Lisp you have a huge pile of abstractions already there. However, it’s pretty easy to build up abstractions in C without moving to C++ or Objective-C.
Graham writes more:
Object-oriented programming is popular in big companies, because it suits the way they write software. At big companies, software tends to be written by large (and frequently changing) teams of mediocre programmers.
So this answers my question from above. Giving a mediocre programmer a confining paradigm to work within will not produce better code, but it may produce a better-behaved programmer. In my case, it won’t do me any good whether I’m good or mediocre. Graham’s point is supported by evidence collected by Eric Raymond:
… inspection of open-source archives (in which choice of language reflects developers’ judgments rather than corporate mandates) reveals that C++ usage is still heavily concentrated in GUIs, multimedia toolkits and games (the major success areas for OO design), and little used elsewhere.
Richard Stallman had this to say:
Emacs Lisp is powerful enough. Adding OOP to Emacs is not clearly an improvement; I used OOP when working on the Lisp Machine window systems, and I disagree with the usual view that it is a superior way to program.
Emacs does, by the way, have an object-oriented programming framework called eieio.
As it stands, I cannot justify learning an object-oriented programming style. I may want to learn C++, since it seems to have a lot of interesting standard library datatypes that might be useful in my research. However, anyone I’ve asked whether I should learn C++ has said “Don’t bother,” for one reason or another.
I would really like to know what you all think: it’s been at least four years that I’ve been trying to understand the value of object-oriented programming when functional programming and imperative programming seem so simple and obviously useful to me. A critical piece of my own story is that I have made all my decisions about what to learn on my own: no one told me to learn C++ for a job. I decided to learn Scheme, C, Python, Perl and many other languages because I did research and found out they were right for one reason or another. The one programming language I learned for my job was Stata, which is a special purpose language (incidentally it does have a class system). On the other hand, most of the people advocating object-oriented programming at me have been either given the task of using an object-oriented language (e.g. Java), or learned it as the pinnacle of a programming class. I’ve never taken a programming class.
I was having some trouble today with Autoconf: the m4 macro
AC_CHECK_LIB wasn’t finding my haploid genetics library even though the function I specified was definitely there. I read about how this test works and was still dumbfounded. I read a whole bunch of blog posts with people complaining and talking about switching to CMake and SCons because the autotools are just so old-fashioned (like, they’ve been around since the late nineties!).
But only five minutes after sending a message to the autoconf mailing list, I got a reply from a RedHat employee with the very simple message: look in config.log! He was nice about it, and very helpful, but he had every right to act like an elitist jerk: I looked in config.log and what I found was that I hadn’t properly linked my library with libgomp (OpenMP). Duh!
I added the following check to configure.ac in both the library and application directories:
in the proper places. Everything works now. Another coup duh etat for GNU Tools.