Thoughts on the OOP and abstraction “crap”
I used to believe firmly in Object Oriented Programming methedology, not because I’ve had any experience with it, but because the professor who taught my class about it sounded like he really knows what he’s taking about (I’m sure he does, and I still have a lot of respect for him).
However, judging from my own experience, OOP is not always the answer. Hell, it’s the thing to avoid most of the time!
Let me first explain what’s the OOP crap I’m talking about, because there are many definitions of what OOP is, so to make sure you’re on the same page as I am, OOP means:
- High cohesion: every class should be responsible for a single task only, and it should do it well.
- Low coupling: different parts of the application should not be highly coupled/interwined together.
Now, in principle, this is all well, but in practice, if you apply high cohesion, you end up with high coupling.
Think about it, if every class is so simple and so small, then every class is utterly useless by itself, because it doesn’t do anything! Therefore, to do anything useful, many objects must interact together. Even simple tasks become very complex.
Think about reading a file in Java, I’ve done it several times but I keep forgetting how to do it. What was it? First you create an object that reads chunks of a file as raw bytes, then you wrap it in a buffer, then a buffer reader, then a text buffer reader? or some nonsense like that.
That, my friends, is a Horrible Way To Program!
This is related to my previous rant about Django.
With everything chopped down into tiny simple classes, the task of adding new functionality becomes immensely complex, and also the act of changing an existing functionality. Because the interactions between objects are so complicated.
I’m not saying that you shouldn’t use abstraction, no, do it, but do it sanely. Do make classes/function simple, but don’t make them dumb and useless. Make them simple to use, simple to read, to interface to, but don’t make them stupid.
Linus made a comment about micro-kernels, in which he describes why they are so damn difficult to implement: you don’t have a single thing that is a kernel, you just have many tiny components that do simple things, which results in a system that needs many complex interactions between these components, and that’s something that’s very hard to get right and very difficult to debug. (every wonder why the Hurd kernel is taking so damn long??)
That’s exactly what it is: if you simplify the individual components too much, you’ll get a very complex system that’s unmaintainable.
It’s better to start with something that “just works” even if it looks like spaghetti at first, as long as you keep refactoring, you can end up with a reasonable abstraction, where functions and/or objects are simple, but not too simple to the point of being utterly useless.