Friday, July 8, 2011

DPHP 16 - OOP: Object Organizing Pandemonium

For once, I'm going to talk about something current: my move to code base version 3.0.

I decided a while back my code running on the UI controller was a mess and in serious need of an overhaul.  I'm making some minor changes and structure modifications as I do the recode from scratch, but mostly it's about one thing: moving to object oriented programming (OOP).

For those that don't know, OOP is changing the base metaphor of writing computer code.  Normally when you think of code, you think of variables, if statements, for loops, all combined to make functions and eventually whatever code you're trying to write.  It's a pretty straightforward concept and something that plenty of people could probably figure out in a weekend.  OOP is quite different but leveraging the same base tools.

In 'regular' programming you have two type of 'stuff' in your code that's pretty easy to understand: data, and structureData is all variables you calculate, predefine, and so on.  It's hard numbers stored somewhere on the device while it 'does the math.'  Data typically has a specific format depending on the variable you're trying to express.  There are integers for when you only need store and process whole numbers.  There are floats for when you more accuracy and the use of decimal points, but on microcontrollers float processing tends to be rather slow.  There are smaller and bigger versions of these two main types, depending on how big (or accurate in the case of floats) you need your numbers to be.  There are arrays which are just a specific way of defining a big set of variables you want to group together.  Ok, that's fair enough to understand.

Structure is all the stuff you're telling the computer to do with those bits of data.  There's the 'ifs', the 'fors' and also the math you put together to write your code.  The functions you write and the 'main' statement are all structure.  They have a specific format, often known as the 'syntax,' depending on the language you are using (c++, java, etc).  This formatting is critical to the 'compiler' to understand you code; the compiler that makes your code run on your microcontroller or computer.  It's a common, poor mans comparison, but computer code much like the human language can mean different things with minor differences.  For instance "that's a sweet-ass car" means something quite different from "that's a sweet ass-car."  And Yes, that was an XKCD reference.

Ok, I've been babbling on about that stuff for a while, back to the interesting stuff.  So if data is basically just numbers and structure is what you wrap data in to make it do stuff, then what does OOP do differently?  here we introduce objects.  Objects blur the line between where data ends and structure begins.  Objects in code can be like objects in life as well, with numbers and parameters that define and describe them.  Maybe not so clear as life is what else you can put in an object: bits of structure.  Specifically, it's like adding the tools you need to change that object or make it do something.  You're 'baseball' object might have a 'bat' function that makes it fly through the air, for instance.

Where I find Objects useful is in a concept of 'abstraction.'  Most people will tell you a lot of written code is a 'black box' that you put stuff into (inputs) and then it churns for a while and gives you the stuff you want (outputs).  A lot of the time, you don't need to know what happens in the black box, only that it works and it gives you what you want.  That's abstraction: making the stuff you don't really need to know more hidden from you so it doesn't get in your way.

In my UI code, I have tons of what I can 'tracking' variables, variables that are used to keep track of what's running, when it's running, how, etc.  If you want to pass those variables between different functions, those have to be 'global' and visible to all of your functions to work.  But they often have a narrow set of uses to specific bits of code, but they still end up floating around getting in the way of your code when your trying to add other features or debug other problems.  And when you make changes you have to go back and double check that you didn't break a bunch of things you didn't mean to change in the process.

How about a visual example.  On the left is my new code, and on the right is the old code, both starting with setup() at the top:

code comparison

Just looking at them, you wouldn't know that the left example is actually doing a lot more things, with a lot more new features, and doing it a lot more efficiently and directly. Heck, the new code base takes up fewer lines for the setup() and loop() functions than the old setup() had.

It's true, you can generally do the same thing both with and without OOP code.  In fact, I'm hardly using any of the true power of OOP, as you can probably tell from the depth of my description.  But moving to an OOP code base does have generally have an advantage even when you aren't using it's full potential, besides abstraction and tidying things up.  You won't know it until you try it, but OOP tends to suffer less from bugs and problems as you decide to 'upgrade' your code and add new features.  Because you generally have to take the time to lay out you objects and what/where/how they do things, you generally end up with better 'black boxes.'  Other parts of your code don't care about what happens in the box, just the inputs and outputs.  And because that is the case, you can change what's inside the box to your hearts content, because you can only break what's inside the box, not the inputs and outputs that your other code relies on.  Yes, you can make those numbers wrong and irrelevant, but you can't really break the structure of one object with broken structure in another object.  With non-OOP coding, you're probably ending up with big, all encompassing bits of structure that when part of it breaks, all of if breaks.  Eventually you want to stab out your eyes rather than debug something like that.

Long term, the move to OOP has a key advantage in the arduino language: per arduino specs, all libraries are essentially objects, and more commonly/specifically: pre-initialized objects.  I'm not in a rush to release all my code to the public, but I'm pretty sure I will have created some libraries and tools that people will want to have access to for their own projects.  We shall see, but for now I need to make sure that my black boxes work in the first place.

No comments:

Post a Comment