On November 19th, 2004 I converted this site from Mach II 1.0.10 for ColdFusion to Fusebox 4.1 Beta for ColdFusion. A lot of people immediately started asking why a staunch advocate of the Mach II project (and project contributor!) would switch to the other framework. I'll address my reasons (and they are many) at the end of this article (hey, don't just scroll to the bottom!) but first I want to talk about the actual experience of the conversion.
This isn't the first conversion I've gone through with this site. As noted on my blog, I've gone through all these:
- from ad hoc PHP to Fusebox 3 for PHP
- from Fusebox 3 for PHP to Mach II for PHP
- from Mach II for PHP to Mach II for ColdFusion
- from Mach II for ColdFusion to Fusebox 4.1 for ColdFusion
Each conversion seems to be getting less and less painful which I attribute to streamlining the code and the URL structure during each conversion rather than any particular aspects of the frameworks involved.
No display fuse changes
Since the site was once a Fusebox 3 site, it should not be too surprising that I did not need to change any display fuse code this time around. When I moved from Fusebox 3 to Mach II, I kept the changes display fuse changes to an absolute minimum - each display fuse became a view in Mach II and I just added a couple of layout views to replace the nested layouts I was already using. Mach II has the notion of content variables (contentkey=
) so I planned to use the same machinery in Fusebox 4.1 (contentvariable=
).
A couple of my views had started to use the Mach II event
object so they contained code like this:
<cfset section = event.getArg("section","0")/> <cfif event.isArgDefined("archive")> ... </cfif>
I had a choice here to either change the views or to provide an equivalent mechanism. In order to increase 'portability' of my view code between Mach II and Fusebox 4.1, I decided to provide event
object compatibility within Fusebox. In the fusebox.init.cfm
file, which is automatically executed at the beginning of every request, I added the following code:
<!--- fake attribute lookup for compatibility with mach ii views: --->
<cffunction name="machii_getarg">
<cfargument name="arg" type="string" required="true"/>
<cfargument name="def" type="string" default=""/>
<cfif structKeyExists(attributes,arguments.arg)>
<cfreturn attributes[arguments.arg] />
</cfif>
<cfreturn arguments.def />
</cffunction>
<cffunction name="machii_isargdefined">
<cfargument name="arg" type="string" required="yes"/>
<cfreturn structKeyExists(attributes,arguments.arg) />
</cffunction>
<cfset event = structNew() />
<cfset event.getArg = machii_getarg />
<cfset event.isArgDefined = machii_isargdefined />
Mach II moves all the URL and form scope variables into a single event
object; Fusebox moves all the URL and form scope variables into a single attributes
struct. These UDFs provide a general level of Mach II compatibility within Fusebox 4.
Circuit definitions
Again, since the site was once a Fusebox 3 site, most of my URLs were already in the form of circuit.fuseaction - which I had preserved when I converted from Fusebox 3 to Mach II. In fact, as I'd added new events to the Mach II version of the site, I'd tended to stick to the circuit.fuseaction style of event name. Of course a few single word event names had also crept in (montana, machiirewrite, php2cf). I created circuit.xml.cfm
files for every implicit circuit in the various event names in my mach-ii.xml
file (actually my mach-ii-cf.xml
file) - a total of fifteen circuits. Some of them were artificial sub-divisions so I just created a sub-directory whose circuit.xml.cfm
file that included display fuses from the directory above - one of Fusebox 4's key strengths is being able to define circuits that have a name independent of its directory (and being able to define parent-child circuit relationships).
Mach II's single monolithic mach-ii.xml
file becomes a series of small circuit.xml.cfm
files. Common event handler code can sometimes be moved to <prefuseaction>
/ <postfuseaction>
within a circuit (see Pros & cons below for more discussion of this).
Private viewing
Mach II requires that you declare every view, Fusebox lets you simply include a view file into a fuseaction. That means that where a Mach II event handler invokes a named view and requires a definition for that view, Fusebox lets you omit the definition part:
<!-- Mach II: --> <event-handler event="foo.bar"> <view-page name="foobar"/> </event-handler> ... <page-view name="foobar" page="/views/foobar.cfm"/>
becomes:
<!-- Fusebox 4: --> <fuseaction name="bar"> <!-- in circuit foo --> <include template="foobar"/> </fuseaction>
The location of the view is specified differently in Mach II and Fusebox (this was mostly a non-issue). The other difference is that Fusebox does not require the file extension to be specified (so that, in theory, a Fusebox application's XML files can be used with both ColdFusion and PHP).
Who's listening?
My site only used two Mach II listeners, neither of which really took advantage of the framework.
The email listener was a simple service CFC that had one method - which sent an email. Just remove the extends=
attribute from the component and use the <invoke class="mailer" methodcall="..."/>
verb (new in Fusebox 4.1).
The bookstore listener had a non-standard method which acted as the constructor and then provided a number of accessor methods used by the bookstore view to display various lists of books and authors. Again, I was able to remove the extends=
attribute and simple instantiate the object:
<instantiate object="bookstore" class="bookstore"/>
<invoke object="bookstore" returnvariable="attributes.bookstore" methodcall="parseBookList()"/>
I think I had to add an empty init()
method to both CFCs. If I'd had a configure()
method (as I should have done) then I could simply have specified constructor="configure"
instead. In other words, if I'd followed best practice, this would have been slightly cleaner.
Pros & cons
I guess this is going to be the controversial part. I'm a strong advocate of Mach II and I've also become an advocate of Fusebox. They have a lot of similarities and a lot of differences. Each framework has its own strengths and weaknesses. My site doesn't have much of a model behind it, very little logic, so Mach II doesn't bring much benefit to a site like mine - my site is mostly about simple views. Fusebox lets you include a view file directly in a fuseaction, Mach II requires that you define a view and then render it which means the XML is somewhat redundant.
Comparing the size of the XML files might be unfair but it represents a measure of maintainability. The Mach II version of the site had 425 lines of XML (nearly 16k of data). The Fusebox version of the site has 270 lines of XML (nearly 12k of data). Instead of one monolithic XML file, I have 16 separate files - that is both a pro and a con. One file is easier to manage in some ways but the size is a problem. Sixteen files is more of a maintenance problem overall but each file is easier to work with.
Code reuse: Mach II has no way to refactor event handler code for related groups. Fusebox allows you to group 'events' into circuits and then refactor code using <prefuseaction>
and <postfuseaction>
to simplify code. Both frameworks provide a variety of plugin points but they don't match - Mach II has pre-/post-view plugin points that have no Fusebox equivalent; Fusebox has a wide variety of plugin points that have no Mach II equivalent.
The areas where Mach II really shines are not highlighted by my site. My site's logic does not need filters or dynamic event queuing.
Why change?
There are several reasons why I changed my site from Mach II to Fusebox 4.1.
- I'm writing a talk comparing the two frameworks so I need side-by-side comparisons.
- I'm a member of Team Fusebox so it makes sense that my personal site is built with Fusebox 4.1.
- I think a simple, view-centric site like corfield.org is better suited to Fusebox 4.1 than Mach II.
- I just plain like fiddling with technology and will probably continue to switch my site between frameworks.
I switched my blog to Ray Camden's fine Blog CFC and then built a Fusebox 4.1 front end for it. Now that I've switched the rest of my site from Mach II to Fusebox 4.1, I'll probably build out a Mach II front end for Blog CFC. All of this informs the first point above - my talk comparing frameworks.