June 9, 2008 |
What I Like About Object-Oriented Programming
This is the text for a lightning talk in-progress.
|
The question: "what do I like about object-oriented programming" | As you might gather from the fact that this is a lightning talk, the real answer is "not very much". There's a lot to dislike about OOP: in the mid-80s it was sold as yet-another silver bullet that was going to save the world; and it was going to do that by encouraging code-reuse through the new mechanism of inheritance! These days, one of the first things an OOP advocate will tell you is that you should avoid using inheritance in favor of aggregation (which is to say you should go back to building things up out of sub-components just the way we always have). OOP advocates have always liked to say lots of mysterious things about the right way of using Objects (these days, they normally invoke "Design Patterns"), but it always looks like a lot of jargon chasing a small number of ideas (it might be compared to other 80's intellectual fads like "postmodernism"...). |
But Objects are intuitive! |
But then, object-oriented code is bound to be more intuitive
because it models the real world, which is also full of objects.
For example: Hold up a piece of paper put it on one side of the table, hold up a pair of scissors, put it on the other side of the table. "Scissors, cut!" (pointing at scissors), "Scissors cut!" (point at scissors, point at paper.). Shake head, and bang on the scissors, pause expectantly. "It's not returning an error object!" The notion that Objects are a "metaphor" doesn't really work: if you start off with a rule of thumb like "identify the nouns", you're likely to end up with something that's over-designed and that under-performs. My opinion (at the moment at least) is that it's best to just think about classes as bundles of routines that need access to the same data -- and it's perfectly okay to invent new abstractions that have no analog to some physical object (typically you need to come-up with bogo-nouns to convince people these are really "objects": "This is the Wangifier Handler Manager class"). |
Namespaces |
The name of the game is namespaces and the goal of the
game is to get the size of the namespace to be small enough
to grasp, but not so small that it leaves you feeling trapped.
The one thing I really like about oop: OOP is a widely accepted compromise between the wide-open style of using globals all over the place, and the tight, purely functional style of passing everything in and out explicitly. |
historical digression: Structured Programming in Pascal |
When I was getting started in this business, the latest silver
bullet was "Structured Programming", and we were all going to
save the world by carefully drawing flow charts and implementing
them in Pascal, writing pure functions with no side-effects.
We'd all gotten disgusted with spaghetti code and
action-at-a-distance, and we had sworn off global variables.
Examples of pure-functional programming (like every other programming methodology demo I've ever seen) always picked the really easy cases, e.g. something that takes a just few arguments and returns one piece of information. In actually trying to write code like this, I kept getting the funny feeling that I must not be designing it correctly, because I always had functions that needed something like a dozen ordered parameters passed in, and eight of them might be the same for nearly every routine. |
avoiding globals in perl |
Much later, while getting into perl programming I was still
trying to follow the doctrine of avoiding global variables,
but I was running into similar problems involving passing a
bunch of stuff around. At one point I hit on a simple
solution for this: I could write routines that would accept
a hash (I liked to call it the %bag) as an argument,
and return a modified version of it, so any number of named
arguments could be passed around that way... but is that any
better than just having a global name space? What's the
difference?
Actually, there is at least a small difference: rather than just letting everything talk to everything, it takes a conscious decision to bundle a piece of data into that %bag, and you don't have to have just one "bag", you can maintain multiple different hashes, appropriate for different sets of routines. Recognize where that's going? I was "inventing" perl objects. |
Summary |
So in summary:
I don't claim it's the only way, but at this point it is a familiar way that a lot of people understand (or at least think that they do), which makes it a good way of doing it. |
A close competitor: procedural with package globals |
problems with procedural modules |
But what about the good, old-fashioned procedural module?
Perl's "global" variables are really just package globals,
so modules with procedural routines using some shared package
globals would seem to provide much the same benefits
I claim for perl OOP modules.
I have a few objections to the package global approach:
|
Clumsiness of perl oop can be fixed |
Some of the objections to perl-OOP (even in the traditional href-based style that I still favor) can be easily fixed using a few tricks of the language, and a system of code-generation via templates and so on. |
Perl tricks |
|
Emacs tricks: |
|
But why not use Class::Std or Class::InsideOut or Object::InsideOut or Moose or ... |
There's an embarrassment of riches in the field of alternative
ways of doing OOP in perl. I'm intentionally a late-adopter;
hype and reality have very little connection where software is
concerned. Each one of these approaches might be a better
solution, but I won't believe it until I get around to
experimenting with them personally.
My first impression: these new techniques are falling into the trap of not letting perl be perl. If I wanted to switch to a different language, it would be easy enough to do so... They go through a lot of work to make perl's encapsulation bullet-proof rather than just advisory, but I suspect you could get 90% of the way there with a test that looked for improper accesses ( $obj->{ ). |