Object auto-mutilation and duck typing in CF

I’ve mentioned that I’m working on some multi-site-aware code at work, and that it’s for the massive upgrade that I am doing. (From Fusebox 4 to a framework-less collection of hand-tailored CFCs.) I’m also using it to "stretch my legs", as it were, to screw around and see what kind of fun and interesting stuff I can do now that I’ve got MX7 to play with. I’ve been stuck with CF4/CF5 for so long, I figure I could use the fresh air.

Since everyone and their mother has been talking about duck-typing lately, I figured I’d throw some of that in. Nothing ultra-loosely-coupled or anything, just a bit of pseudo-reflection to make objects a bit more flexible.

I have a vanilla object model: a siteManager instantiates a collection of site-extending objects and passes back the correct one according to which URL the user is looking at. The base site object isn’t just an interface, it’s a fully-functional object that acts as a default site when none of the other sites own up to the current URL.

A site has two methods that allow it to interact with the resultant content: BrandPage and BrandContent. The former allows a site to do things like add its own CSS and JavaScript files to the header. The latter is a catch-all that allows a site to filter the static content that the application-level contentManager throws at it. All sites will override the BrandPage method, but not every site needs to do content-level branding.

  1. For the sites that don’t need the content-level branding, why bother calling BrandContent in the first place?
  2. Given a bit of reflection, I could check for the existence of a BrandContent function and only call it if the site supports it.
  3. I don’t want to remove BrandContent from the default site object, as it uses it.
  4. Since all of the branded sites extend the default site object, they automatically inherit its BrandContent.
  5. Having an empty BrandContent in each branded site seems wasteful — pass in a potentially-large string; return it right back.
  6. I don’t want to pollute the object by adding a wantsToBrandContent member or anything silly like that.
  7. Can I remove the member function from the branded site objects?
    <cffunction name="init" displayname="init" output="false" description="Initialize our object" returntype="ricko">
    	<cfset super.init()>
    	<cfset ArrayAppend(this.Hostnames,"rickosborne[.]org")>
    	<cfset ArrayAppend(this.Hostnames,"rixsoft[.]com")>
    	<cfset StructDelete(this,"BrandContent")>
    	<cfreturn this>
    </cffunction>
  8. Run … see if it crashes … nope!
  9. Check the debug log for a call to BrandContent() … nope!
  10. Profit!

I know the object purists are already looking for the "Comment" button to flame me a new one. I don’t have a good and witty defense to prevent such a thing, but nor do I feel bad about doing it. It works.