Why Use Object Orientation?

When i first came across a few examples of objects, it seemed to me like they contained a lot of "extra" code that did a lot of extra work for no good reason. Various authors i read extolled the benefits of object orientation to no end, but it was hard for me to see those benefits by looking at examples. For instance, check these 2 code samples out:

<cfscript>
person = StructNew();
person.fName = 'George';
person.lName = 'Smith';
person.age = 35;
</cfscript>

It's nice and simple. Our structure encapsulates our data very nicely in one package. Now let's do the same except use an object. Give me a few minutes to type all this out! ;-) ...

...

<cfcomponent displayname="Person">

   <cffunction name="init" access="public" output="false">
      <cfargument name="firstName" type="string" required="true">
      <cfargument name="lastName" type="string" required="true">
      <cfargument name="age" type="numeric" required="true">
      <cfset setFirstName(arguments.firstName) />
      <cfset setLastName(arguments.lastName) />
      <cfset setAge(arguments.age) />
      <cfreturn this />
   </cffunction>
   
   <cffunction name="setFirstName" access="private" output="false">
      <cfargument name="firstName" type="string" required="true">
      <cfset variables.firstName = arguments.firstName />
   </cffunction>   
   <cffunction name="getFirstName" returntype="string" output="false">
      <cfreturn variables.firstName />
   </cffunction>
   
   <cffunction name="setLastName" access="private" output="false">
      <cfargument name="lastName" type="string" required="true">
      <cfset variables.lastName = arguments.lastName />
   </cffunction>   
   <cffunction name="getLastName" returntype="string" output="false">
      <cfreturn variables.lastName />
   </cffunction>
   
   <cffunction name="setAge" access="private" output="false">
      <cfargument name="age" type="numeric" required="true">
      <cfset variables.age = arguments.age />
   </cffunction>   
   <cffunction name="getAge" returntype="numeric" output="false">
      <cfreturn variables.age />
   </cffunction>

</cfcomponent>

Hello! Anybody home? Who in their right mind would want to take a nice, simple struct like that and convert it into the complex, confusing code calisthenics of object orientation?

When i first considered learning object orientation, i read all about the advantages of OO in a series of articles and book, and at least theoretically i could easily understand them. But as soon as i looked at code samples, it was difficult to see the point.

One of the problems i faced being self-taught (and i still face it today) is that by and large the only literature i could find on the topic was written by computer scientists, and it was all geared toward other languages like Java or C+. So not only was it often inappropriate because it was well over my head, it was also irrelevant to me as a ColdFusion programmer, to an unknown degree. ColdFusion's implementation of object oriented language features was different, i knew. It didn't support interfaces at that time, for instance, and the literature often spoke about interfaces. And of course the code samples in these books were in an unfamiliar language.

Even if i did read an article with ColdFusion examples, and there were a few - looking back, i can say for certain that part of the problem is that it's very difficult to convey the advantages of using OO with simple examples. At the same time, it's downright impossible to convey the advantages with complex examples - they're too hard to follow.

But the truth is that as your application becomes more complex, the value of using object orientation really shows itself.

In the end, i didn't see much advantage to using OO for myself until i took the time to try it out for myself. I had to take it on faith from others that there was something to this, and just try working with it.

And i suspect it might be the same for a lot of others who attempt to learn OO on their own. You won't really experience the advantages until you have a chance to try it out in a real application.

In any case, i'm going to give it a shot and see if i can explain and demonstrate the value of using OO from my perspective as a self-taught ColdFusion developer.

First off, i'd like to point something out. If you compare the structure and the CFC (class) above, you'll notice that the CFC is a blueprint. The struct seems much more simple, but the values are hard-coded to the template.

We could make the CFC nearly as simple as the struct if we wanted to:

<cfcomponent displayname="Person">
   <cfscript>
    variables.fName = 'George';
    variables.lName = 'Smith';
    variables.age = 35;
   </cfscript>
</cfcomponent>

but what's happened here is we've lost the ability to use this CFC for any person. It's not really a blueprint anymore, and in that sense it's not really a class in OO-speak, it's George Smith, a specific instance of a person.

I know in this simple example it may not be very apparent, but there's a lot of power and flexibility that comes with the ability to define a bunch of blueprints (classes) for all the various entities in your application and be able to use those blueprints to create instances of those entities anywhere you need them.

You can try do something similar with structures, creating more of an abstract, reusable container and populating it when needed, but they aren't very well suited to it. Every time you need a person somewhere in your application for instance, or need to work with the values inside person, you'll probably wind up typing out the whole structure again. Using a simple data container like a structure seems simple at first, but the more you have to work with Persons in your app using structures here and there, the more complex it gets in reality.

And if you create an abstraction of a person with a structure somewhere in your app, ready to go and populate with values, how do you get it into your code where you need it? cfinclude it in? copy and paste? ;-)

And then how do you populate it with values? Ummm, type it out again? Loop thru the keys and populate it with the values from a query?

And then what happens if you need to add an email address to your person structs scattered around your application one day? You've got some hunting to do, and more copying and pasting, and everything needs to be tested.

The advantage in creating a blueprint, a class that represents any person using a CFC is that anywhere you need a person in your application, you can simply create an instance of one. Objects are very portable in that sense. In one line of code, i can have a whole person ready to go anywhere in my app. If i have my application's objects set up nicely, in another line of code, my object is populated with data - from a form, from the database, from another source like a webservice. The same object can be populated with data from a variety of sources.

When we are talking about just a Person object as an example, it seems somewhat handy. But remember to multiply that flexibility out, because you'll also have Addresses and Supervisors and Users and Products and Subscriptions and Categories and Comments and Pages and Settings ... anywhere you need any of those things in your app, you can just create one and you're ready to go, even if your Product has 40 or 50 parameters to it.

So although it looks more complicated to begin with - because a class is a blueprint instead of a data structure - you can code a CFC class once and pull an instance of that class into your application anywhere you need one with a CreateObject() call and just use it. And if your blueprint needs to be modified, you can modify it easily in one place, in the CFC, confident that you're not forgetting to change it somewhere else or breaking something. That makes the code related to Persons in your app much more reliable. Again, remember to multiply that reliability out to Addresses and Supervisors and Users ... etc.

So far so good. In my experience, object orientation helps to make your app more flexible and reliable, even at the simplest level, without bringing in inheritance, composition, interfaces, the whole complex world of patterns and all the terminology that people use regarding OO.

Now, here's where it gets really interesting in my opinion. An object both contains data, and can work with that data as well. When you write a class, you can also give that class the ability to be intelligent. And that package is still a blueprint that can be pulled into your application anywhere you need it. And you can still modify that package of data + the ability to be intelligent in one place whenever you need.

Let's make our Person object a little more intelligent.

Instead of the setAge() and getAge() methods, let's replace them with setBirthdate() and getBirthdate(), and change getAge() to calculate the age of the person instead. This way, as a person gets older, our application will be able to calculate their age in real time, rather than using out of date values.

Just the changed portions of Person are shown below:

<cffunction name="setBirthdate" output="false">
      <cfargument name="birthdate" type="date" required="true">
      <cfset variables.birthdate = arguments.birthdate />
   </cffunction>   
   <cffunction name="getBirthdate" returntype="date" output="false">
      <cfreturn variables.birthdate />
   </cffunction>
   
   <cffunction name="getAge" returntype="numeric" output="false">
      <cfreturn DateDiff("yyyy",getBirthdate(),Now()) />
   </cffunction>

And now let's assume that this person is actually an airline passenger, and that you just found out from your boss that infants fly free and children and teenagers fly half price, but the price for teenagers might go up at some point soon, so they want you to create categories for each so the proper fares can be calculated.

Let's just add a getFareCategory() to our Person object ...

<cffunction name="getFareCategory" returntype="string" output="false">
      <cfset var fareCategory = "Adult" />
      
      <cfif getAge() LT 5>
         <cfset fareCategory = "Infant" />
      <cfelseif getAge() LT 13>
         <cfset fareCategory = "Child" />
      <cfelseif getAge() LT 18>
         <cfset fareCategory = "Teenager" />
      </cfif>
      
      <cfreturn fareCategory />
   </cffunction>

At first, using objects seems like it only adds complication, but once you start really using them, especially in situations where you need to modify your application, suddenly objects make your work so much simpler.

Now let's say your boss asks you if you can calculate how many infants and how many children are on a flight, so the ground staff can make sure to have enough infant seat belts and games on board each flight. Your Person objects already know what fare category each passenger is in. From here, it won't be difficult to simply loop through your Persons and collect the data.

And if your boss decides to change the age range for infants one day, your code changes in just one place, and it's easy to find. And everything else you've done related to the fare categories doesn't change.

Now don't forget that in your application you've got a bunch of other objects that can be intelligent with their data too, and that these objects often will work together. So it might be the Flight object that loops thru all its Passengers (Persons) and has a method that returns the number of infants and number of children.

Note that we haven't even discussed a single headline OO concept yet that you'll find highlighted in the books you can read on the topic. It's all very simple and straightforward and useful already, without touching encapsulation, polymorphism, inheritance, composition, aggregation, etc, etc, and the whole gamut of design patterns.

And i think that's the point i'm trying to make here. Object orientation is already very useful simply from these 2 simple aspects:

1. Because you code blueprints for objects (classes) rather than something more fixed and static (like a struct) to represent "things" in your app and that allows you to create objects in your code wherever you need them. That's very flexible.

2. Because objects have the ability to be intelligent with the data they contain, and that intelligence is incorporated into the blueprint, the class.

Nevertheless, it seems like the perfect moment to introduce inheritance and composition in a simple way, but we'll save that for another post. :-)

Comments and corrections are very welcome.

PS - I forgot to mention that code generators and frameworks are available today that will generate the code for many of your classes for you. It used to be time consuming to commit all the necessary verbosity to code. That's no more the case in ColdFusion, thanks to the efforts of a bunch of really talented people in the community.

Related Blog Entries

Comments
Very, very helpful...

Looking forward to more...

Josen
# Posted By Josen Ruiseco | 3/18/07 5:57 AM
Do I feel a book coming on out of these series of posts? =)

I have to point out one area in which we disagree. While I do agree that it is possible to gain better code without consciously thinking about "headline concepts", I think it might be harder to do so.

It is those concepts which give rise to other principles we have (or the other way around) and OO just helps us better realize those concepts in our application designs. In essence, it is not OO we are striving for, but those principles which OO helps in acheiving, which help in having maintainable code. As you know (and I know all too well, at least), it is entirely possible to use CFCs *thinking* you are doing OO, and then just making it a nightmare to maintain, possibly worse that just using .cfm templates as one had before.

On the whole though, I thought you did a good job of explaining some of the concepts without mentioning them by name, so good job on that!
# Posted By Sammy Larbi | 3/18/07 8:00 AM
Sammy,

Again, for me coming into object orientation completely self-taught, there were a lot of terms i encountered in the lists and literature that encapsulated concepts that i didn't understand. It was like a novel where every other sentence has a phrase written in italicized French. Eventually, i kind of picked up the meaning of some of the jargon in context, but it was difficult. Even when i thought i understood some term, there was still a shadow of doubt. What does "service" mean for instance? What's a "service layer"?

And even if one doesn't know and you ask the list, you almost always get an answer that contains other OO jargon - understandably so because everyone is busy and that's by far the most efficient way to say it.

Then some people would argue about the meaning of the terms, like gateway and data access object for instance. "Martin Fowler says ..." "Well, in this case, i have to disagree with Martin Fowler. He's not god." "Disagree if you want, but 99% of the developers ... you are clearly outside of the norm ..."

When you learn this stuff in university or with other colleagues, it seems there is plenty of time and space to assimilate the terminology and move on to the higher level concepts that are efficiently expressed through them. I'm fairly sure that by now, it's a little difficult for you to remember what it's like not to understand the terminology. I guess i still remember it because i struggled to understand each term in the context of ColdFusion.

I still struggle with some of the terms in the context of a complex argument.

So i'm leaving out the headline concepts in the beginning very intentionally. I'm leaving out the French phases, and just attempting to say it in plain, simple English.

I know very well that object orientation and CFC usage is not at all equivalent. The principles of object orientation are everything.

But i also know that when i was new to this, i had no way of discerning the difference. In fact, i had NO IDEA how to correctly implement any object oriented concept using CFCs. So if from my perspective i'm going to explain any of this to anyone in the same shoes i was in, a total OO newbie, i'm going to go a lot slower.

By going so slowly, i'm not implying that the concepts behind OO aren't necessary or important. Not at all. I'm only trying to help people learn them who don't know the jargon, and introduce the concepts and the jargon in the familiar context of ColdFusion.

At this point, i don't want anyone in my audience of OO newbies to worry a bit if they try something out, it might not be object oriented enough! Just try it. Get familiar with how CFCs work. Make a few experiments.

At the same time, i'm not university trained. So make sure to keep an eye on me and if i mis-state or misunderstand anything, please point it out! ;-)
# Posted By Nando | 3/18/07 12:07 PM
Great post Nando!

I must admit, I'm really enjoying your posts on OO and Model-Glue. I'm currently learning MG and some OO principals and your posts are so incredibly clear it's making it very easy to get to grips with things.

Thanks again and keep up the good work - your teaching style is spot on.
# Posted By James Allen | 11/15/07 6:31 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.