Framework Comparison
This is the raw feature comparison matrix that I created as the basis for my frameworks comparison talk that focuses on Mach II and Fusebox. I've recently added columns for Model-Glue which means that you need a wide screen to view the table easily. Sorry about that. I'm open to suggestions on how to make this easier to read but I'm not going to bust myself on it - it's just raw data for your information, OK? If you want, you can download the raw .xls file (created in NeoOffice/J).
Some notes about the table:
- I use abbreviations for the framework names: FB = Fusebox, M2 = Mach II, MG = Model-Glue.
- In the MG Pros / Cons columns, (M2) means "same pros / cons as Mach II" and (FB) means "same pros / cons as Fusebox". In some cases I qualify the comparison further.
- The GGCC Example? column refers to seven variants of a sample application that I use to illustrate my talk. I'll make the code available in due course (after CFUNITED) once I've tidied it up some more and added some readme files.
- These notes were originally written for my edification in preparation for writing the talk - some of the notes are a bit terse, to the point of being cryptic. If you really can't figure out what I mean, drop me a line and I'll explain (and maybe even enlarge upon the notes in this matrix).
| Feature | Same | Different | FB Pros | FB Cons | M2 Pros | M2 Cons | MG Pros | MG Cons | GGCC Example? |
|---|---|---|---|---|---|---|---|---|---|
| XML | All use XML config files | FB has multiple XML, M2/MG has one XML | Easier to manage, can reuse | Hard to see whole app at once | Easier to see whole app | Hard to manage when it gets large | (M2) | (M2) | fusebox.xml.cfm and circuit.xml.cfm, mach-ii.xml, ModelGlue.xml |
| MVC | Can use MVC | FB allows but does not enforce, M2/MG pretty much forces it | Easier to learn | Easier to write spaghetti code | Easier to stick to best practice | Harder to learn | (M2) | (M2), but not as hard as M2 | GGCC3-7 are MVC |
| MVC Structure | Model/View directories | FB typically has controller circuit directory, M2/MG has implicit controller in framework | Structure is more explicit | Multi-circuit approach can cause duplication | Simpler organization: model is CFCs, view is CFML | None | (M2) | (M2) | Show each apps directories |
| CFCs | Can use CFCs | FB allows but does not enforce, M2/MG pretty much forces it | Easier migration path from old school code | None | Easier to stick to best practice | Harder to learn | (M2) | (M2) | GGCC3-7 use CFCs |
| Plugins | All have plugin points | FB has more plugin points, M2 distinguishes events and views, MG has simple request/queue model | Finer grained control over processing | More complex | Supports pre/post-view plugins | Not very granular | Easy to learn since 'plugins' are just controllers | No real plugin concept so it isn't as powerful | GGCC4/5 have M2 plugin, no FB plugins |
| Access control | All have private / public concepts | FB has per circuit and per fuseaction as well as roles-based model, M2/MG has per event access only | Finer grained control over processing | None | None | Not very granular | (M2) | (M2) | All but GGCC1 use public/private somewhere |
| Auth / Security | None | FB has roles support builtin, M2 provides a sample filter, MG is free form | Some builtin infrastructure | If roles-based security doesn't meet your needs, you have to start from scratch | None | You have to build it all yourself | (M2) | (M2) | None |
| Install / Config | One-stop core files, basic properties in XML file | One-stop core files is brand new in FB41, FB provides finer control over framework behavior, MG has a simple framework control model | More control over framework behavior | More parameters to learn | Simple infrastructure in place for quite a while | Not as much control over framework behavior, requires both <cfinclude> and CFC-creation setup (mapping and custom tag paths) | (M2) | (M2) | The examples assume you have /fusebox4, /MachII, /ModelGlue either as mappings or in your web root |
| Modularity of Application | None | FB has circuits to partition large applications | Better modularity | None | None | No support for partitioning applications | (M2) | (M2) | FB examples use multiple circuits |
| Modularity of Site | None | M2 allows multiple sub-applications to share application scope | None | No single sign-on across multiple apps | Single sign-on across multiple apps | Sub-applications cannot share properties etc | (FB) | (FB) | N/A |
| Commonality | Can explicitly invoke fuseactions / announce events / add results to handle common functionality | FB has per-circuit pre-/post-fuseaction hooks, providing framework level support for commonality | Some builtin support for commonality | More complex, more options | None | All commonality must be explicitly programmed | (M2) | (M2) | GGCC1 uses <prefuseaction> and also reuses common fuseactions (see taskmanager circuit) |
| Views | All encourage views to contain “only HTML” (no logic) | FB/MG lets you include a view directly, M2 requires that you declare all views in XML | Simpler, less XML to write | If you move a view, you have to change every reference to it | You can move views around and only change a single declaration in the XML file | A lot more XML to write (and it's very tedious) | (FB) | (FB), although you specify the view location via a mapping which means you can move all your views to a new location and only change one XML setting | GGCC4/5 cheat a little since they use <view-page> directly rather than separate view events (which would better match the FB examples) |
| Handler Model | All declare 'handlers' for 'events' in XML | FB is a static, explicit invocation model, M2 is a dynamic, implicit invocation model, MG is somewhere in between | Simpler, more intuitive for web developers; Performance is good because static execution model can be compiled to inline code | You cannot 'do' a dynamic fuseaction, e.g., from a database, so certain dynamic applications are hard to write entirely within the framework | Implicit invocation provides looser coupling, more flexibility and more dynamic power within the framework | The event queue model is very hard for many web developers to grasp; Dynamic interpretation of the event queue has a performance overhead | (M2); Messages are processed as they are broadcast (rather than being queued); Broadcast / listener model is even more loosely coupled than M2 | The event model is essentially static (like FB) but interpreted (like M2) although the performance overhead is lower than M2 | No real example of this |
| Data bus | Can use request scope as data bus (but it's not always best practice) – MG uses event object | FB allows variables scope as data bus; M2 allows event object as data bus, MG enforces event object as data bus | Simpler – one scope (variables) can be used throughout | No encapsulation | Event object is a nice encapsulation | Framework doesn't fully support event object as a data bus | Very consistent – all data is passed via the event object which becomes the view state | None | GGCC4 needs to do a lot more work to maintain the event data bus but FB apps are inconsistent about attributes, variables and request scope |
| Global data | None | FB has fusebox.init.cfm, M2 uses either <property> tags or plugin (or both), MG has settings | Simpler – one file contains all global data setup | Application data initialization needs to be explicitly coded | Automatic management of application data | <property> is restricted to simple string data so plugins are often required | (M2) | (M2), although you use controllers instead of plugins and the event object instead of updating the settings | All the FB examples (GGCC1/2/3/6) use fusebox.init.cfm for globals, M2 (GGCC4/5) uses a combination of <property> tags and plugins, MG (GGCC7) uses a combination of <setting> tags and controllers |
| Model CFC Structure | Most CFC methods could be the same | FB uses standard init() construction controlled by explicit code in fusebox.init.cfm or circuit, M2 reserves init() and uses a managed configure() method to initialize CFCs – with no arguments – and CFCs must extend the framework, MG has base controller init() method | Simpler – CFCs can be independent of framework and follow standard best practice | Construction needs to be explicitly managed | Standardized infrastructure to manage CFC lifecycle | Complex, requires integration with the framework and non-standard CFC structure | (M2) | CFCs must extend and initialize the base controller | Compare GGCC3, GGCC4 and GGCC7 to see how the different frameworks handle this |
| Conditional logic | None | FB has some conditional logic in the XML grammar, M2 requires conditional logic placed in CFCs, MG requires controller CFCs | Simpler | XML controller can get polluted by logic | Clear delineation of declarative configuration and procedural logic | Requires more code is written | (M2) | (M2) | User identity is a good example in every variant |
| Model Actions | All have the concept of separating business model logic from presentation logic | FB allows a model action to set multiple outputs, M2 uses strict call/return semantics so each action can have only one result, MG allows a model to set multiple outputs via event object | An action can 'do' more in terms of setting up a data environment for subsequent actions, queries or displays | Risk of spaghetti code since an action can set arbitrary outputs | Simple interactions with the business model | Often requires either more roundtrips to the business model or use of complex data structures to simulate multiple results | (FB) | (FB) | Compare GGCC2 with GGCC3 to see how the single return value affects things; GGCC7 goes back to multiple results |
| Model Queries | None | FB specifically separates out persistence operations (by a naming convention on files), M2/MG draws no distinction between actions and queries | Better organization of code | None | Consistent framework interface (listeners) | Need to use design patterns to manage separation of persistence | (M2) | (M2) | Both GGCC3 and GGCC4 blend persistence into main model, as does GGCC7 |