Wednesday, May 15, 2013

A Different Kind Of Lego

     I'm going to talk a bit about Object Oriented Programming, and why it's a great tool for you to use to solve a problem.

     It is far from the only tool, and there are plenty of circumstances where it isn't appropriate. You'll notice this is a theme in programming. Sometimes, a decent OOP hierarchy is just Too. Damn. Slow. The "Introduction to Data Structures and Algorithms" class at my university is an example of this -- I designed ALL of my projects with SOME semblance of "objects" (I can't call it OOP and look myself in the mirror) -- and the speed of my program took a noticable hit. That class was speed-based, so my grade took a hit as well.

     I'm a very big fan of the following mantra:

     "Make it work, make it pretty, make it fast."

     The last two, as mentioned above, are fairly interchangable, based on the needs of the program. And your program is useless without the first. Functionality above all, but there's no need making things harder on yourself when you do the eventual code restructuring for (pretty | speed), which is where the subject of this post comes in.

     Let's talk about abstraction. CS (and CE, lets be honest -- I'll cover it in a bit) is all about abstraction. People throw around the "pillars of OOP", and a common "weed out the ones who didn't pay attention in CS 102" interview question is "Explain (inheiritance | polymorphism | encapsulation)" (Source: I was asked it, and the interviewer was surprised that I had an immediate answer. I was surprised other canidates did not).

     I would argue that an understanding of what abstraction /is/, and why we use it, is fundamental for a good programmer.

     See, abstraction lets you modularize your code. Think of it as (*gasp*) turning your code into a Lego model. Each component of your code is an individual Brick. If you're anything like me, you've had those Bricks for 10, 15 years, and your little brother chewed on some of them, making them not click in as well; making the model not be built easily or successfully. Some are even (ick) MegaBloks. Every once in a while you find a K'nex.  
     Such is your code when designed in a decent OOP manner. Each object is a Brick. They click together REALLY nicely -- in fact the only reason they exist at all is to click together with each other. Private/public properties exist to force things to click only in certain manners -- if you're using superglue instead of the studs of a Brick, you are Doing It Wrong.

     Every once in a while you get a chewed-upon Brick, or a MegaBlok, or a K'Nex. OOP allows you to say "this isn't the end of the world, I'll just get a new Brick," and be on your merry way.

     Or you could have no modularity, no abstraction whatsoever to your code. You have a superglued conglomerate mess, and if you have a bug (hint, you do. You might not know it yet, but you do.) then it will be HELLA difficult to detect (see: Knowing You're a Tool), and even worse, HELLA difficult to fix. See, you have to bash open your scale-model of the Statue of Liberty with a hammer, pull out the broken section, patch together a fix with ducktape and prayer (we call this a "hack" and they're frowned upon. Hacking the Matrix is cool. Hacking your codebase is not.), throw it in there, and superglue it all up together again.

Not OOP.
     Everything in CS/CE has abstraction. Consider: transistors->logic gates->combinational/sequential circuits->basic mathematical circuits (timers, combinators, ALU's, etc)->....->processor. That's CE for you, and the idea is you can make something VERY complicated VERY elegantly out of VERY tiny components.

     CS is no different, and that elegance, alongside knowing how to apply it, is more key than I feel is being taught. Industry thrives on it. Especially in projects that are being simultaneously developed by non-trivially large teams. I talked about Revision Control before. Well, consider: what do you think is easier, 10 programmers all working on the same 4 files that collectively do something very large and complicated, or each programmer "owning" their own task, and related sets of files. You trade off a small number of files, but who cares? If you throw a 1.5 KLOC file at me, my eyes will glaze over anyway. Which do you think Git plays nicer with (if you know how to merge nicely, this is admittedly a non-issue)?

    Each programmer owns* their own Brick. They can click into their team, and have it pulled out and replaced if need be, when it's discovered you are trying to use a MegaBlok when the team really needs a Lego.

    It works, and it's pretty. It might not be the fastest, but that's okay. I'll willingly make that trade, and so will every part of industry I've experienced to date.

    That's not even getting into the discussions of the benefits of "code contracts" and RAII (Though I intend to). This is purely based on "look how easy it is to refactor your code and find/fix bugs".

    And here's a little secret: even the code I wrote that was supposed to be blazing fast (the NDIS driver) had abstraction, had some semblance of object-orientedness.

    So for the love of all that is holy, please stop saying "I have the following, and it works for 7 out of 12 test cases, but I can't find the bug..." and show me a 200 line function that has seven or eight STL containers all being indexed into simultaneously. I will want to strangle you.


*The concept of ownership is under some debate from senior developers. If you "own" some code, and that code is wrong, should you really own it? Or should they take it away from you?

For Friday: (Introduction to) Introduction to Object Oriented Programming Week, Part 2

No comments:

Post a Comment