0

Head First Design Patterns SimUDuck in ColdFusion

ColdFusion
As I make my way through Head First Design Patterns, which I am starting to agree is a "must" on a developer's bookshelf, I decided I would work out some of the exercises in ColdFusion code.  It is geared towards Java, but the principles carry over into OOP practices in ColdFusion as well.

The opening chapter deals with an imaginary SimUDuck application,which gives a great example of the Strategy Pattern.  I am not going to go into great detail on the chapter, but it deals with not only the benefits of object inheritance, but the problems as well.   I have produced ColdFusion versions of 4 stages of the SimUDuck application which follow along with the chapter.  This might make a nice companion for someone reading that would like to see how this implemented in ColdFusion.

Even if you haven't read the book (which surely means you are waiting on your shipment of it), the code is fairly straight forward, and you hopefully will see how the solutions are implemented.

Step 1: Starting the SimUDuck App
First, the simple SimUDuck app contains only 2 types of ducks which are subclasses of the Duck class.  Each duck subclass implements its own version of the display() method.

Step 2: New requirement!  Ducks need to be able to fly.
No problem!  Since the ducks inherit the methods of the Duck class, we can solve this problem by just adding a fly() method.  Whoops!  Someone just added a Rubber Duck to our system.  Rubber Ducks can't fly! 

Step 3: Fixing our flying Rubber Duck problem
We solved our flying Rubber Duck problem by just adding a fly() method within the RubberDuck class that did nothing.  This overrides the fly() in the Duck superclass.  We also added a quack() to the application.  Since Rubber Ducks don't quack, we implemented a separate quack() that squeaks in the RubberDuck class.  So problem solved... but now we have added a Decoy Duck to our application.  This duck doesn't fly or make a sound.  Again we overrode the Duck methods, but we are beginning to see what a maintenance nightmare we are creating.

Step 4: Encapsulating the Behaviors
We have now encapsulated the fly() and quack() behaviors into their own groups of classes or "families of algorithms". Then each instance of the duck object can have their own instance or whichever behavior is appropriate to them and are contained in their FlyBehavior and QuackBehavior properties. By doing this, a duck class is not locked into a specific type of behavior and these behaviors can easily be altered at runtime. Additionally, if we suddenly add a new type of flying behavior, it is as simple as adding a new subclass to the FlyBehavior group.

tags:
ColdFusion
Ali said:
 
Dave,

Thanks for putting all the work into presenting a CF Example of these Design Patterns.

Everything works great for me up until the Solution Example.

I can't get the solution to work unless I change the returntypes and argument types of the subclasses to "Any".

I have tried a relative dot-path, and an absolute dot-path for the returntypes of the subclasses and I keep getting errors.

If you have run into this problem or know of a workaround, I'd be very appreciative.

Other than that, thanks again, and I look forward to more CF examples as you dig deeper in the land of OO.

cheers,
-AA
 
posted 1122 days ago
Add Comment Reply to: this comment OR this thread
 
 
Ali,

Make sure that your dot-path is relative to the web root. I had to alter it slightly when I placed it on www.worldwildweb.biz. From the web root, the application lies in /exercises/simuduck/solution/, and my actual return type for getFlyBehavior() for instance had to be changed to returntype="exercises.simuduck.solution.com.Behavior.Fly.FlyBehavior". You could maybe try placing all the CFCs in a single folder and just calling "FlyBehavior", but I personally like the idea of organizing it a bit. Hope this helps.

~Dave
 
posted 1122 days ago
Add Comment Reply to: this comment OR this thread
 
Ali said:
 
Thanks for the quick reply dave.

Yeah, the solution files are under my webroot:
wwwroot/Ali/Solution/

And what I was trying was in getFlyBehavior
returntype="Ali.Solution.com.Behavior.Fly.FlyBehavior"

But it keeps erroring out :(

 
posted 1122 days ago
Add Comment Reply to: this comment OR this thread
 
 
Is is possibly a case issue? Are you on a *nix server? I would be interested to hear what you come up with.
 
posted 1122 days ago
Add Comment Reply to: this comment OR this thread
 
Ali said:
 
Nah I'm on a Windoze server.
The exact case of my folder names are
wwwroot/Ali/Solution/com/Behavior/Fly/FlyBehavior

The only way I can get it to work at the moment is
by removing the "type" attribute to the "flyBehavior" argument in the "setFlyBehavior" method.

And by setting the returntype to "any" in the getFlyBehavior method.

I really wanted to get it working by using the classnames for the types though.
 
posted 1122 days ago
Add Comment Reply to: this comment OR this thread
 
Neil said:
 
Yeah, doesnt work for me either - fails on the Solution example but not all of the rest. Exact error is "Could not find the ColdFusion Component com.Behavior.Fly.FlyBehavior." The Duck CFC is in the com folder so maybe it cannot legitimally find it.
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
 
That is really interesting. Maybe try putting all of the CFCs in a single folder and just saying type="FlyBehavior". If either of you guys figure it out, please let me know. I had it running both on my laptop and on the server you guys see it on.

Neil, in your case is it possible that com has a mapping to something other place on the server? I ran into this recently with something I was working on. Maybe try renaming to "cfc" or something and then altering the path.

Also, for what it is worth, I found a goofy copy/paste thing I did. You will notice that in the setFlyBehavior() method I put displayname="com.Behavior.Fly.setFlyBehavior". That should have been displayname="setFlyBehavior". Not that it really matters, but I am going to put up the fixed version in a minute.

~Dave
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
Neil said:
 
hey Dave,

My Directory Structure is how I unzipped it.

C:\Inetpub\wwwroot\cfmx\oop
C:\Inetpub\wwwroot\cfmx\oop\Solution
C:\Inetpub\wwwroot\cfmx\oop\Solution\com
C:\Inetpub\wwwroot\cfmx\oop\Solution\com\behaviour
C:\Inetpub\wwwroot\cfmx\oop\Solution\com\behaviour\fly

Duck.cfc (which is in C:\Inetpub\wwwroot\cfmx\oop\Solution\com) on line 12 references "com.Behavior.Fly.FlyBehavior" but it probably wont work on this as the file is already in the com dir. I changed this to drop the com. and when i run the code again it states: The argument FLYBEHAVIOR passed to function setFlyBehavior() is not of type com.Behavior.Fly.FlyBehavior.

Something it defo not correct here.

N

 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
Neil said:
 
sorry, I just typed behaviour like how we spell it ;-) it is behavior!
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
 
LOL, well we can rule that out.

If you are calling that page by http://whateverdomain.com/cfmx/oop/Solution/simudu..., then I would set that type = "cfmx.oop.Solution.com.Behavior.Fly.FlyBehavior" since the path is from the web root. Have you tried that?

~Dave
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
 
Oops, that should have been:

If you are calling that page by http://whateverdomain.com/cfmx/oop/Solution/simudu...
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
Neil said:
 
Yep, cfmx is not in the path as the home directory is pointing to that folder...I did change it to oop.com.Behavior.Fly.FlyBehavior and I get the same error of "The argument FLYBEHAVIOR passed to function setFlyBehavior() is not of type oop.com.Behavior.Fly.FlyBehavior" which is the same error I get if I remove the com from the path...it could be something to do with paths to com.x...will need to try again later.
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
 
Well, if you don't mind, please post back your solution. It seems to not be an entirely unique problem.

~Dave
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
Neil said:
 
Well, I am not sure what it is at present. What is your folder structure? I am stumped as to why it is not working yet the others are - it is a path problem for sure...will need to see if a mapping resolves it.
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
 
My physical path to the application is:

D:\Inetpub\Customers\MyCrappyHostingCompany\
dshuck\worldwildweb.biz\www\exercises\simuduck\Solution\
where 'www' is the webroot of the site. The code for the getFlyBevahior is pasted here:

   <cffunction name="getFlyBehavior" displayname="getFlyBehavior" returntype="exercises.simuduck.solution.com.Behavior.Fly.FlyBehavior" output="false" access="public">
      <cfreturn variables.flyBehavior />
   </cffunction>

      
   


The code in the sample zip file was for setting the site was set up where "solution" was actually the webroot. On my laptop I had a seperate site set up for each one. Does that make sense?

~Dave
 
posted 1121 days ago
Add Comment Reply to: this comment OR this thread
 
Jason Daiger said:
 
For starters, thanks for putting this example together. It definitely helps to view examples in CF instead of Java. I've been on the fence about getting the Head First Design Patterns book b/c I've been using the Core J2EE Patterns book but I think I'll revisit the Head First book to use as an alternate resource as it seems to get rave reviews.

I had the same issues regarding error the at first until I changed the CFC paths in the Duck.cfc class to the full dot qualified path from my CFMX7 webroot. For my dev machine I did a simply Find & Replace of the 'com.' w/ 'DevZone.SimUDuck.Solution.com.'. The files physically exist in the C:\CFusionMX7\wwwroot\DevZone\SimUDuck\Solution\ directory.

Thanks again for the post and sample files.

-Jason
 
posted 1120 days ago
Add Comment Reply to: this comment OR this thread
 
Ali said:
 
I did exactly what Jason did, but I still get the same error as before:

The argument FLYBEHAVIOR passed to function setFlyBehavior() is not of type Ali.Solution.com.Behavior.Fly.FlyBehavior.
If the component name is specified as a type of this argument, the reason for this error might be that a definition file for such component cannot be found or is not accessible.

The error occurred in D:\Inetpub\wwwroot\Ali\Solution\com\Duck.cfc: line 33

31 :       
32 :       
33 :    
34 :    
35 :       


 
posted 1120 days ago
Add Comment Reply to: this comment OR this thread
 
Ali said:
 
You know what.
It took a new year, a new outlook, for me to arrive at the conclusion that this isn't an error at all.

I can and should leave the returntype as Any, as the code works perfectly fine like that. Because, you know what, ColdFusion is NOT a strongly typed language. We don't need to specify the types.

Anyway, great code! Great Examples!
Thanks for this post to help us understand the concepts and patterns.

Happy New Year!
Cheers!
 
posted 1094 days ago
Add Comment Reply to: this comment OR this thread
 
Bruce said:
 
Dave:

Thanks for writing up the Strategy pattern in CF. I'm continously going back to the Head First design patterns book as I develop applications in Java and CF.

As you know the book's explanation of the Strategy pattern emphasizes encapsulating the fly and quack behaviors as interfaces that other classes can implement.

The duck parent class is then composed of the generic interface types. This gives the duck's child classes the freedom to any specific behavior object as long as it implements the correct interface.

Since CF doesn't have interfaces (or strict typing) was it more difficult to implement this design pattern in CF or simpler?
 
posted 1093 days ago
Add Comment Reply to: this comment OR this thread
 
 
Bruce, since I have never written a single line of Java code, I have nothing to compare it to! :) My gut feel on it however, is that it is probably not much different. The generic type interface in the CF version is nothing more than an abstract class CFC. I can't imagine that doing it in Java could be terribly different. I sure would like to learn and find out though! I keep picking up little bits and pieces of Java and understand quite a few of the concepts, but I don't know where to begin when it comes to actually sitting down and writing code, where to place files, how to physically set up an application, etc. Most of the Java references I find assume you have that knowledge already.
 
posted 1092 days ago
Add Comment Reply to: this comment OR this thread
 
Michael White said:
 
I just received my copy of HFDP along with the poster... Thanks for doing some coldfusion versions, now I won't be so terrified to crack the cover! Are there any more CF exercises from the book on the horizon?
 
posted 1091 days ago
Add Comment Reply to: this comment OR this thread
 
 
Yup! Stay tuned. As soon as I get some of the giant load of projects off my lap I am going to finish doing the next chapter. I began, but I got buried in client work (which wins in the battle of priorities!) If you are interested, you can subscribe via email to this blog and watch for it.
 
posted 1091 days ago
Add Comment Reply to: this comment OR this thread
 
Clint Willard said:
 
Hey Dave, guess what. I couldn't wait so I created a Coldfusion tutorial from one of the chapters and put it on my blog. I also linked back to you for more tutorials. I wouldn't be affended at all if you blogged my new tutorial if you find it useful. Isn't this stuff great?! Visit my http://www.cfcdeveloper.com/index.cfm/2006/1/22/Co..." target="_blank">Coldfusion OOP tutorial here.
 
posted 1081 days ago
Add Comment Reply to: this comment OR this thread
 
Wesley Clarkson said:
 
We had a very similar issue with objects erroring out. We had some objects that were created back several months ago and started getting an error several months later. (Seemed like it was after we updated our coldfusion server with some 7 patches but that could be coincidence.) We ended up just removing the type on the passed in variables when they were object types. On one server it would only work if we had only the cfc name as the type and on another it would only work if we fully qualified the path. Was very odd and we never really figured out why it stopped working.
 
posted 1079 days ago
Add Comment Reply to: this comment OR this thread
 
Dan said:
 
Dave,
I am finally reading this book and what a great book it is. Do you have these files available for download? I would like to compare yours with mine.
 
posted 705 days ago
Add Comment Reply to: this comment OR this thread
 
 
Dan, I moved my site over here to InstantSpot since I first posted this (2005?!?! how can that be!). I will dig those files up, edit this post and comment back so you get notified.
 
posted 705 days ago
Add Comment Reply to: this comment OR this thread
 
 
Dan the links are fixed. Thanks for pointing it out.

~Dave
 
posted 705 days ago
Add Comment Reply to: this comment OR this thread
 

Search