Object-Oriented Blog Process - VIII

Inheritance code example.

To be honest I thought I would do this post much sooner. But life's been busy lately, and even though the code was already finished, I did not find the time to post and explain it.

Download here

As last time, unzip into a directory in your wwwroot and open index.cfm. One important thing to note: You need to be running the last updated version of CF (7.0.1) to be able to run the example code. Not because of the OO code, but because I choose to use a flash form to post the products into the "webshop". The reason is simply that this was the easiest way to make a form allowing me to insert two different product types. Sure it could have been done with some dhtml code, or just using multiple forms. But I choose to use flash forms (first time you open the page it takes a while to open). If you for some reason is not on the latest version on your develoment machine you could always rewrite the form code a bit your self.

I wont explain the form code here, as flash forms is not the subject of these posts (and there are many great resources on flash forms out there already).

The first thing to note is that where we do the createObject() method, we use a value from the form to deceide what kind of object we are creating. Then we are passing all the values from the form in as an argumentcollection.

The second thing to note is that when we loop over the products in the "webshop" there's now two different kinds of products with different attributes. So I'm using the getMetaData() method in each iteration of the loop to find out what kind of product I need to output.

The code in the cfc files are almost identical to the explanation I did for the inheritance post itself.

If there's any questions regarding this code, please feel free to contact me.

Object-Oriented Blog Process - VII

Inheritance.

The web shop example we've looked at so far is very simple, to put it lightly. Don't worry, I'll still keep it simple. But let us for a moment imagine a more realistic situation.

In our imagination a product class will have far more properties, like producer, supplier, cost price, product number, etc. Let's imagine we end up with at least 15 properties in our product class. Then let us agree that different types off products needs different properties as well. Golf ball objects need properties for radius, weight and number of dimples. Golf pants objects need properties for waist width, length, fabric and color.

What are our choises now? Do we add all properties we need to the product class. Then we'll have a bunch of unused properties on each object. And what if some product types have similar properties, but that have different methods and units of measurement. Sounds like this might grow into a monster of a class, with confusing logic for figuring out conflicting properties. Definitely  not a good option.

Then how about creating a class for each product type? Then we need to have all the 15 properties in all the classes. So if we need to add, change or delete a general property we have to do this in all different product classes. Not a good solution either, huh?

Inheritance to the rescue!

One of the key principles in Object-Oriented programing is inheritance, and it addresses exactly the kind of problem described above. The idea is that one class can have several child classes. In our case that means that we can keep our product class with all the (imagined) 15 properties in one place, and then have one child class called golfBalls and one child class called golfPants. These child classes will then inherit all the properties and methods from the parent class, and need just to worry about the properties and methods that are particularly for that product type. We can visualise this relationship in the following way:

You see that for simplicitys sake I've only kept the original two properties and associated methods for the product class. And I'm only dealing with two product types. One thing to note is that inheritance can go several levels deep (as many as you would need/wish). In our example we could have made a child class of products called cloths, with the fabric property, and then child classes of that one again for pants, shorts, shirts, skirts and caps. But for now we'll keep it simple and stick with to child classes with the product parent class.

Let's take a look at how our two new child classes look in ColdFusion code. As you'll see it's not much difference from the product class we created earlier. (I'm not including the setter and getter methods here, as they follow the same pattern as before - you can see the full code in the updated example application I'll post shortly)

<cfcomponent displayname="Golf Ball" extends="product" output="false">

 

 <!--- PROPERTIES --->
 <cfset variables.instance = StructNew() />

 <!--- INITIALIZATION / CONFIGURATION --->
 <cffunction name="init" access="public" returntype="golfball" output="false">
  <cfargument name="productName" type="string" required="false" default="" />
  <cfargument name="productPrice" type="numeric" required="false" default="" />
  <cfargument name="radius" type="numeric" required="false" default="" />
  <cfargument name="weight" type="numeric" required="false" default="" />
  <cfargument name="dimples" type="numeric" required="false" default="" />
  <cfscript>
   // run setters
   setRadius(arguments.radius);
   setWeight(arguments.weight);
   setDimples(arguments.dimples);
   super.init(argumentcollection=arguments);
   return this;
  </cfscript>
  </cffunction>

 <!--- METHODS --->

**** setter and getter methods go here ****

</cfcomponent>

 
<cfcomponent displayname="Golf Pants" extends="product" output="false">

 

 <!--- PROPERTIES --->
 <cfset variables.instance = StructNew() />

 <!--- INITIALIZATION / CONFIGURATION --->
 <cffunction name="init" access="public" returntype="golfpants" output="false">
  <cfargument name="productName" type="string" required="false" default="" />
  <cfargument name="productPrice" type="numeric" required="false" default="" />
  <cfargument name="waistWidth" type="numeric" required="false" default="" />
  <cfargument name="length" type="numeric" required="false" default="" />
  <cfargument name="fabric" type="string" required="false" default="" />
  <cfargument name="color" type="string" required="false" default="" />
  <cfscript>
   // run setters
   setWaistWidth(arguments.waistWidth);
   setLength(arguments.length);
   setFabric(arguments.fabric);
   setColor(arguments.color);
   super.init(argumentcollection=arguments);
   return this;
  </cfscript>
  </cffunction>

 <!--- METHODS --->

**** setter and getter methods go here ****

</cfcomponent>

The things to notice are the following. In the opening cfcomponent tag we're adding extends="product" to establish the inheritance. In the init() method we also have the cfarguments for the parent class. And lastly, still within the init method, we're calling a super.init() method. The super.init() method call the init() method of the parent class (also called super class). You also see that we are passing the arguments as a argumentcollection, rater than one and one as we did in earlier examples.So when creating a new object we now do something like this:

<cfset golfBall = createObject("component","golfball").init("Boyzoid Custom High-Speed","12.95","3","14","222") />
<cfset golfShorts = createObject("component","golfpants").init("Frank Shortser","9.50","32","30","Cotton","Green") />

My next post will be a download of a updated version of the example app, showing a working example of what I've just explained.

Object-Oriented Blog Process - VI

Code explained.

In post IV I promised to explain some code. So here we go. Notice that in this explanation I'll use the code from the application example from post V.

I'm just going over the OO specific code here. The other parts (as the form field, the css and other html) I will asume that you know from before.

First explanation goes for the following line in index.cfm which is called if the form for creating a new product object is submited.

<cfset session.products[CreateUUID()] = createObject("component","product").init(form.productname,form.productprice) />

Here we use the createObject() function for creating a new object, telling that the object is of the type "component" (a cfc file) and the class file is product (product.cfc without the file extention). For now we are going to keep all the cfm and cfc files in the same folder, so this is all we need to conect to the class file for creating the object. Then we are calling the init() method of the newly created object, and supplying the arguments productname and productprice from the form.

We also see that the object is created as a member of the session.product structure, with a UUID as the object name.

Let us go to the product.cfc

A cfc file should always be opened and closed with a cfcomponent tag set. Next we are setting a structure for holding all the property values for the object. Then the first really interesting part - the init() method.

A method in a cfc is surrounded by starting and ending cffunction tags.

The init() method is the ColdFusion equalent of what in traditional/other OO languages are called the constructor method. This method is used to initiate the initial values of the object we create.

The cfargument tags tells us what properties that can be populated, and also if requred is set to "true" - there must be arguments passed on to populate them.

Then it takes the arguments passed on (or the default value from the cfargument tags) and calls the setter methods of the object to populate it's properties.

The init() method is present in a object by default, and is usually not counted in when we talk about the methods of an object.

Next we come to the "real" methods of the object. In our example so far we only have present so called setter and getter methods for the properties. The setters are used to set the value of the properties, first by the init() method, but if access is set to public they can also be used to update/change the value of the property later on, by being called from the outside (a cfm template or another object). The getter methods are simmply there to expose the values of the properties to the outside (as we'll see soon).

Back to index.cfm

The last part of code to look at is this:

<cfloop collection="#session.products#" item="i">
<div><strong>#session.products[i].getProductName()#</strong> - $#session.products[i].getProductPrice()#<br /></div>
</cfloop>

Here we loop over the session.products struct, which is where we created our objects. Then for each object we loop over we call the getter methods that I mentioned above to get the name and the price of each product.

That is basicaly all magic it takes to create a simple OO based application. I hope everything so far is pretty clear. If not please feel free to contact me (#coldfusion on dalnet is a good place to catch me). In the next number I plan to start talking about inheritance.

Object-Oriented Blog Process - V

I took the example code from my last post and whipped together a working example of a super-small, super-simple application.

You can download it here.

Unzip somewhere under wwwroot on your server and open index.cfm in your browser.

The code should be fairly easy to understand. I put all product objects in a structure in the session scope - and call the getProductName() and getProductPrice() on the objects to get the information about the products.

Object-Oriented Blog Process - IV

Classes and intstances

In my last post I coined the expressions class and instrance. I suspect that many of you reading this, even though you might be OO newbees like me, are familiar with these terms, and what they mean. Never the less, I'm going to have a go at explaining them in my own words. Mostly because a blog series like this would be incomplete without it, but also to root my own understanding of it.

Let's go back to the example from last time. We have a webshop, and as so it will be filled with products. So we'll have a bunch of product objects. The product class will be what deceides what attributes and what methods a product object will have.

It's kind of like writing down on a piece of paper a form with fields for product attributes. To make it easy for our self we keep the original paper clean - and each time we need another product in our catalouge we hit the "Copy" button on our copy machine. It's the same in our code. We write a class file, and for each new product we'll programatically trigger a "copy button". The cool thing in programing versus the paper version is that when you do changes to the class/original file (like adding an atribute) - these changes are reflected in all objects made from that class.

The product object we create from the product class are what we call instances. A product object is an instance of the product class.

In ColdFusion a class file would be a .cfc, but before starting to code it's usual to plan the application (kinda like an architects drawings). The way a class is planed/drawed will most often be like this:

(For planing OO application I've earlier bloged about a marvelous tool for doing this)

Here we see the class name, the attributes and the methods. So based on our plan we can now code our cfc - something like this:

<cfcomponent displayname="Product" output="false">

 <!--- PROPERTIES --->
 <cfset variables.instance = StructNew() />

 <!--- INITIALIZATION / CONFIGURATION --->
 <cffunction name="init" access="public" returntype="product" output="false">
  <cfargument name="productName" type="string" required="false" default="" />
  <cfargument name="productPrice" type="numeric" required="false" default="" />
  <cfscript>
   setProductName(arguments.productName);
   setProductPrice(arguments.productPrice);
   return this;
  </cfscript>
  </cffunction>

 <!--- METHODS --->
 
 <cffunction name="setProductName" access="public" returntype="void" output="false">
  <cfargument name="productName" type="string" required="true" />
  <cfset variables.instance.productName = arguments.productName />
 </cffunction>
 
 <cffunction name="getProductName" access="public" returntype="string" output="false">
  <cfreturn variables.instance.productName />
 </cffunction>

<cffunction name="setProductPrice" access="public" returntype="void" output="false">
  <cfargument name="productPrice" type="double" required="true" />
  <cfset variables.instance.productPrice = arguments.productPrice />
 </cffunction>
 
 <cffunction name="getProductPrice" access="public" returntype="double" output="false">
  <cfreturn variables.instance.productPrice />
 </cffunction>

</cfcomponent>

(To quickly create this code I used the Rooibos Generator by Peter J. Farrell)

Then to create instances of the product class, or product objects we do this:

<cfset golfBall = createObject("component","product").init("Boyzoid Custom High-Speed","12.95") />
<cfset golfShorts = createObject("component","product").init("Frank Shortser","9.50") />

Voila - we now have two instances, or two product objects, a golf ball and a golf shorts.

I hope that you now understand the terms class and instance. If you don't quite understand what's going on in the code above, I'll explain that further in my next post.

- - -

As before the examples and code displayed here are simplified, and just there to illustrate the consepts that I talk about. They do not show the full or correct implementation for a real world solution.

Object-Oriented Blog Process - III

It's 9:30am on a Saturday, and I'm up fully dressed, fully bathroomed (in lack of a better word) and writing a blog entry. For all of you who knows me through my blog, through #coldfusion on dalnet, through email or other cyberspace means of interactions this might not seem so significant. But if any of my work coalegues had seen me they would have been pretty close to calling 911 (actually the number here in Norway is 113). The reason for this is that I am an extreme nightowl, and at this time in the mornings on normal workdays I'm hardly awake despite of the alarm clock screaming in my ears, my wife pulling my hands and legs (that is if she is awake) and my two year old daughter jumping up and down on my head (my five year old is sleeping long, just like me). On a Saturday morning the alarm clock is shut of, my wife and five year daughter are asleep and my two year old is downstairs with the grandparents. So I would normally be passed out for a couple of hours more at the least.

Ok - what on earth does this have to do with OO you are probably asking yourself (if you are patient enough to still be reading). Well the reason I am awake and writing is this: I read the first half of the first chapter of "The Object-Oriented Thought Process" yesterday evening. And while I had no problems what so ever falling asleep when I went to bed (around 2am), my head was started working hard in the morning (I probably was slightly awaken by the two year getting out of her bed and running to grandparents).

In short, here's what got me thinking:

In Object-Oriented programing you have the data (properties) and functions (methods) all nicely gathered within the object, while in procedural programing the data and the functions working with the data are separated.

Now, I knew this from before, but somehow, based on yesterdays reading, my understanding sored to a whole new level this morning still half asleep in bed.

Consider the following situation:

You are running a webshop selling,....let's say... golf equipment (this one is for you Scott). And in this webshop one of the zillion items is a "Boyzoid Custom High-Speed Golf Ball". Now this golf ball is presented on it's own product detail page, in the golf ball category page, on the recomended product page, and on several other pages as well. On each of these pages you are using queries to the product db to get information like product name and price. So far so good.

But then you realise that the golfball need to belong to a tax group (in Norway it would be 25% VAT on a golf ball). You could of course just put the price included VAT directly on the ball. But then you realize that if the VAT would change to 26% when a new goverment is elected you have to update the price of a zillion products manually (you can not run a script adding the 1% because some products belong to other tax groups that might not get increased). So you deceide to stick a taxGroupID property on the products, and then keep the percentages of the diferent taxgroups separate in tax group table in the db. Now on all the pages our golf ball is presented we need to add a query to get the apropriate tax percentage so that we can calculate the price. It's getting a bit tedious.

Then your boss comes up with the idea that you should have different super-sale categories, so you need to ad a property on the golf ball (and all other products) what super-sale category they bellong to, and then a separate table for keeping the percentages of discount for each category. So now you need to add yet another query on the pages for our golf ball getting the propper discount (if any) for the super-sale category the ball belongs to. Are you sure you remembered to add it in all places? Now it's starting to get nightmare'ish.

And so it goes on and on. Welcome to spaghetti code maintenance hell.

The OO solution:

You make your golf ball a product type object (an instance of a product class - more about classes and instances later) with both the properties and the methods. So on all the pages you just call the getPrice() method on your golf ball object. Whenever there's a change you just edit the calculation within the getPrice() method. You don't have to worry about going into the different pages the golf ball is presented at all.

Welcome to OO code maintenance heaven.

Some final words:

The example above is just that; an example. There are many ways you could make life easier a procedural code with custom tags, and other code reuse methods. On the other side, the example above is also fairly simple. There could be several other factors that could come into play, like diferent prices for different groups of customers, different taxgroups depending on the country it is ordered from etc. And still a webshop deals with relatively few and simple kind of objects and calculations.

If there are someone who now don't see the advantage of OO programing please raise your hand (in other words leave a comment). Actually that goes for all of you - I love getting feedback of almost any kind.

Object-Oriented Blog Process - II

Introduction

In the introduction Matt Weisfeld pretty much talk about the importance of understanding OO before atemting programing with it.

He goes on to explaining that the code examples in the book will be Java, but that you need not know Java to read and understand the book (that would contradict the fact that he's telling us to read the book before learning Java or any other OO language ).

I don't know how much I'll be able to read in the weekend, since the (family) schedule is pretty tight (man it can be stressfull to relax properly ), but I'll try to keep you updated on any progress I make.

Ok - now back to work (with making custom content types for Farcry - which seems to be pretty OO to me)

Object-Oriented Blog Process - I

I just opened the package that came in the mail, with "The Object-Oriented Thought Process" by Matt Weisfeld after a recomondation from Joe Rinehart. So far I've only read the back cover so I can't really say much about it yet. However to try to understand and remember what I read I'm thinking to blog as I read through it.

As some of you might know, I have been doing some Mach-ii development, and I have been looking at Model-Glue. I've also read pretty much what there is to read about OO in the CF blogsphere by the likes of Matt Woodward, Joe Rinehart, Jared Rypka-Hauer and many other bright minds.

While I do understand a lot of the OO stuff, I still feel that among the pieces that I've gotten, there might be pretty some important pieces lacking in the necasarry foundation for being a "real" OO programer. So here I go - starting with the introduction on page 1.