Join the Cult: Object-Oriented Programming

Last week, my wife decided to start learning PHP.  And no, she’s not just trying to humor me–pssh, like she’d do that.  She’s burning to code some roleplay generators.  It’s a bit of a blast, sitting and coding side-by-side.  (And not just because I get to work on Escher without feeling guilty!) She’s doing a great job, picking it up like lint, and it’s fun to see her sense of accomplishment.  I miss that sort of instant gratification that came in old days, before PHP became a paying gig and I started counting lines of code by the tens of thousands.  Say what you will about rapid development frameworks…  Nothing beats the efficiency of a single-file script running linear or functional code and inline HTML.

For a small project, at least.  Since she’s been doing so incredibly well, I thought I’d try and show her a thing or two about PHP classes so she can get her code more compartmentalized and portable.  After all, in the past week, this endeavor has grown from a simple desire for a few one-off scripts to the possibility to create our own RPG system and an accompanying website.  So we might as well start thinking ahead, and no better way than OOP, right?

Oh, wait…

OOPs.  (Yeah, I went there.)

In my arrogance, I’d forgotten something significant about object-oriented programming.  Nevermind that OOP is a godsend, that for large projects it makes things exponentially more manageable, or that we proabably all use a lot of OOP whether we know it or not, thanks to all the libraries and database wrappers and even a lot of built-in PHP5 functionality.  There’s something off-putting about OOP when you aren’t already coding it.  It seems unnecessarily complicated, and there are really no great & simple ways to describe its advantages.

Heck…  I hated OOP.  With a passion. I avoided it for years, and managed to build a pretty respectable website without it.  OOP was just a cult, and they were never gonna suck me in.  Well, now look at me.  I’ve joined the cult, I’m sporting the weird haircut, and I’m sippin’ the koolaid daily.

So, how can I explain OOP to my wife in a way that makes sense?  (Not makes-sense makes-sense, but makes-sense why-should-she-bother?)  The real-world analogies never worked for me.  (“You’ve got a building object, and a door object, and maybe we want to extend a door object to have a lock…  yadda yadda…”)  Even still, I find that those analogies actually screw up my perspective on a project, I think because physical hierarchy and structure is just plain different from programmatic hierarchy and structure.

I think, perhaps, the best analogy for OOP programming might actually be non-OOP programming.  Functional programming, at least.  The automation and portability provided by writing our own functions is not difficult to see first-hand.  OOP actually behaves in a very similar manner, and takes our portability to the next level.

Let’s say we want to create a character name generator…  say, for rednecks.  It’s pretty simple to do just using linear code:

<?php

$firstnames = array('Joe','Bob','Roy','Bubba');
$lastnames = array('Jones','Briggs','Hill','Foxworthy');
echo $firstnames[array_rand($firstnames)].'-'.$firstnames[array_rand($firstnames)].' '.
  $lastnames[array_rand($lastnames)];

?>

Like I said, doesn’t get much simpler.  What if we wanted to generate 10 names at once?

<?php

$firstnames = array('Joe','Bob','Roy','Bubba');
$lastnames = array('Jones','Briggs','Hill','Foxworthy');

for ($i=0; $i<10; $i++) {
  echo $firstnames[array_rand($firstnames)].'-'.$firstnames[array_rand($firstnames)].' '.
    $lastnames[array_rand($lastnames)].'<br>';
}

?>

No problem.  But hmm, we can see a pattern.  We’re starting to run that one line of code an awful lot.  And what if we wanted to do something different with the name we generate, such as use it in a sentence?  Perhaps we should make this into a function:

<?php

$firstnames = array('Joe','Bob','Roy','Bubba');
$lastnames = array('Jones','Briggs','Hill','Foxworthy');

function redneck_name() {
  global $firstnames,$lastnames;
  return $firstnames[array_rand($firstnames)].'-'.$firstnames[array_rand($firstnames)].' '.
    $lastnames[array_rand($lastnames)];
}

$my_name = redneck_name();

echo "Howdy!  I'm $my_name.  Let me introduce you to some of my friends:<br>";
// Outputs: Howdy!  I'm Joe-Bob Briggs.  Let me introduce you to some of my friends:

for ($i=0; $i<10; $i++) {
  echo redneck_name().'<br>';
}

?>

There we go.  Our code has gotten more complicated, but we can use it in different ways.  We had to include $firstnames and $lastnames as global variables to use them in our function.  Also, note that we return our results rather than directly echoing them.  This allows us to capture the resulting redneck name as a variable and use it elsewhere.

What if we wanted to use our redneck name generator in other scripts?  We could simply define the variables and function in a standalone script, redneck.php, and include this file in our other scripts.  But what if those scripts also have the $firstnames and $lastnames variables?  Our redneck script would conflict, and probably break its functionality.  We could simply define our variables inside the function, but perhaps that’s not optimal…  Perhaps we want to keep them publicly accessible for down the road.

This is where object-oriented programming becomes truly useful.  Objects operate in their own little world, so as long as you name your class something unique, there’s no chance for conflicting with other code.  Let’s see an object-oriented version of the above code:

<?php

class Redneck_Name_Generator {
  var $firstnames = array('Joe','Bob','Roy','Bubba');
  var $lastnames = array('Jones','Briggs','Hill','Foxworthy');

  function redneck_name() {
    $firstnames = $this->firstnames;
    $lastnames = $this->lastnames;
    return $firstnames[array_rand($firstnames)].'-'.$firstnames[array_rand($firstnames)].' '.
      $lastnames[array_rand($lastnames)];
  }
}

$generator = new Redneck_Name_Generator();
$my_name = $generator->redneck_name();

echo "Howdy!  I'm $my_name.  Let me introduce you to some of my friends:<br>";
// Outputs: Howdy!  I'm Joe-Bob Briggs.  Let me introduce you to some of my friends:

for ($i=0; $i<10; $i++) {
  echo $generator->redneck_name().'<br>';
}

echo "Have you met ".implode('-',$generator->firstnames)."?";
// Outputs: Have you met Joe-Bob-Roy-Bubba?

?>

It doesn’t look that different, does it?  Notice where we defined our variables, though?  Inside the object class. As we can see with Joe-Bob-Roy-Bubba, we can still access the variables directly; but they will never cause a conflict on the global namespace.  What’s nice is that we can actually manipulate these object variables, or create new ones, inside our functions.  So we could extend this class into a general-purpose Redneck_Generator that generates a name, grade level, belt buckle, family tree (more like a fork or a spoon?) and more, and keep track of these values so we can use them later, i.e. $redneck->name.  What’s even nicer is that every new Redneck_Generator() is a new set of variables, so $redneck->name might be Joe-Bob Briggs, but $redneck2->name might be Bubba-Roy Hill.

There’s so, soooo much more to like about object-oriented programming, but like I said, I think they’re hard to appreciate until you’re to that point.  I just hope that anyone reading this article will see that (1) it’s not really any more difficult to code in classes than it is to code in functions, and (2) the most basic advantage to OOP is code portability, so if you see yourself using the same code later on, if you want it to last forever and save your future self the effort of re-coding, please just go ahead and start coding OOP now.  :)

Now, as for my wife, I think she’s starting to get it.  And her code is really clean, seriously…  So when & if we do need to convert her code over to classes and objects, it won’t be much work.  I’m not terribly concerned…  It took me years to find the value in OOP, I don’t expect her to come to the same understanding in a week.  She probably will though…  She’s a faster learner than me.

This entry was posted in Programming. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *