Thursday, July 10, 2008

Objects are NOT the Answer

I remember my first brush with Object-Oriented Programming. I had mostly a C background (with some Basic and Assembler) and C++ almost seems silly at the time. I asked multiple people "What's an object?" and received many smart-ass answers. What I walked away with was the idea that someone could treat objects like groups of values with functions attached. I understood assembler so it didn't take me long to understand that an object was a list of data types. This was good until I realized the vtable (list of functions) was not just attached in front of the object's data. It instead kept a pointer to the vtable. Ok, well that made sense until I thought about inheritance. Well, that wasn't hard, just add a new vtable with the additional types and then more data. Simple, right?


The new object could reuse (override) a function's name. Well, just use the new one right? No. You must know in your parent class that you might override this function! Something never made sense about it but it took me a while to understand what. Whenever I needed to reuse a class, I had to modify the original class! Isn't that against the whole idea of objects with hidden data and code reuse by default? To be fair, using the same name works fine unless you access the object as its base class. Then instead of using the new function, it will use the old. I understand why someone would want this but isn't this still a decision that should be made by the child object? Isn't it possible I want this for one child object and not another?

To get around this, people came up with interfaces. Classes with data and function names described, but not implemented. Then your child classes can use whatever function you want, but you have to put them into the classes each time. Wow, so much for code reuse, but at least you can reuse it as long as you just copy it. Never mind the compiler is making a binary file for each of these classes so you can multiply your code size. Never mind that people always forget to change the code in both (or multiple) places. Never mind it makes your project directory look like word salad. Add the fact you have to make a header file and a code file only makes this worse. Adding a new class becomes like pulling teeth and programmers start making whole programs in a single object. Code reuse goes out the window and gets written again and again because who knows which one I should be using? People like me start just using the C subset of C++.

Then I learned about Design Patterns. Ok, I thought, now I have a way of telling when I should use objects and when I shouldn't. Not only that, but it suggested what kind of solution I could use for different types of projects. My design process was to take the whole project and divide it into pieces using a know pattern. Then I would subdivide it until the abstraction wasn't useful anymore or when I was writing more code for my classes' frameworks rather than working code. This worked fairly well, allowing me to deliver working, but inflexible solutions. CASE (Computer Aided Software Engineering) Tools seems like the answer until I realized this was generally ineffective because I end up changing the software after the tool is done. It provides a starting point but it can't make radical changes to the code base without much manual effort. Templates looked to be a possible solution but their complexity and cryptic error messages made it like learning a new language in itself. Don't believe me, look at the Boost library. It's a Turing complete language written in C++ Templates that runs at compile time! I can't argue with the functionality but I can't really understand it well either. And just wait until you try to debug it.

Then I started learning Lisp. While learning it I came across a sentence that ended my object-oriented career:

"If you need to use design patterns, you need to use a more powerful language." - unknown

And Lisp is the most powerful because, as Paul Graham put it, "Lisp is a programmable programming language."

After that I read as much as I could about Lisp. I was amazed at the abilities I found. I was soon getting stuck with my programming because I wasn't used to continuous coding. I had become so used to doing repetitive work that I relied on it for time to think. I ended up sitting at my desk staring into the screen blankly then suddenly banging out a few lines before staring some more. For Christmas I got a copy of "Lisp in Small Pieces". From it I learned how to implement a lisp, or lisp-like elements, in C. I no longer worry about using STL correctly, when I get to something I need to do, I just use some bastardized C-Lisp. If anyone complains, I just use an XML library instead of S-Expressions. I am no longer an object-oriented programmer, but I am a better programmer.

No comments:

Post a Comment