Adventures in Monkey Code

I did a little experiment this weekend.  I needed (well, wanted) to build a really simple little photo viewer application.  Create a gallery, add some photos, view the photos as a slideshow.  Really basic.  The catch is that I build it using no framework at all, aside from Application.cfm.  Note the 'm'.  And no IDE: everything was done with text-mode Emacs and the MySQL command line client.

Each "page" of the app was actually a real page (a CFM).  Data access at the top, then a CFOUTPUT block below for the "view" pages, and just simple processing with a CFLOCATION for the action pages.  I built the forms so the same page would accept both create and edit requests, switching on the presence of an ID in the request parameters, so I got a little reuse that way, but nothing else.

For initial development, this worked swimmingly.  Each page was totally separate, pick a page, build it, move on to the next.   In a couple hours I was done, and most of that was spent on getting all the JS interactions tuned for inline editing, sorting, the slideshow, etc.  The app was simple enough that I didn't even do much copy and paste.  Maybe five or six blocks total, and two of those were form skeletons so I didn't have to start from scratch (i.e. not candidates for "real" reuse).

So then I wanted to add zip upload to streamline a bit.  Make a zip, upload it, and have individual items created for all the contained jpegs.  Sounds simple, right?  Except that all the logic was inside savePhoto.cfm.  I briefly considered setting up the attributes scope for each photo and then CFINCLUDEing that file for each jpeg in the zip, but it wouldn't have worked with the CFFILE ACTION="UPLOAD" in there, so that was out.  Time to refactor.

Still wanting to avoid any sort of framework-ish-ness, I opted for a UDF library instead of a CFC.  Mostly to resist the temptation to slap ColdSpring on it so I could stop thinking about those fu$@*ng CFTRANSACTION tags.  I split the logic from savePhoto.cfm into four UDFs, sliced appropriately for either "uploading" with CFFILE or sourcing from the local filesystem.  This actually worked pretty well, and I didn't have to duplicate any logic anywhere to support zip upload, create new photo, and replace existing photo.

So here I am at the end of my journey.  I actually had a pretty good time not thinking about the infrastructure and just diving right into the code.  No messing with getting ColdSpring and FB3Lite into the project, setting up mappings for them, etc.  That said, I do NOT recommend the shortcut to anyone unless they have a similar experimental interest.

As of right now, I'm probably slightly ahead in terms of time expended compared to doing the FB3Lite-on-ColdSpring way, but only slightly.  And I have manually managed transactions, no good way to apply security, layouts managed with Application.cfm and OnRequestEnd.cfm, no ability to reuse view code other than more UDFs, and a fair amount of duplicated SQL and error handling.  In short, a mess.

I'd imagine that the next enhancement made will push me over the brink to reduced productivity from the initial decision to monkey-code it, and it's downhill from there.  Fortunately the app is small enough that doing a wholesale conversion won't be too much work (and yes, that was one of the considerations for undertaking the experiment).   So that'll probably happen at the same time for the cost of an hour or so.

All in all, a good experiement, I'd say.  Completely confirmed my beliefs that spending half an hour setting up a good project framework is worth every second, and the "lost" time is made up within the first few hours of development.   And this was a very small project with a single developer, the rewards only get more significant as projects grow in size.

2 responses to “Adventures in Monkey Code”

  1. Ben Nadel

    Barney,

    Personally, I think that this project is small enough that duplicating the logic in the "save" page for the zip-processing page would have been fine. If you know that your project is going to be and *remain* small by intent, then I don't even think code duplication is an issue. I know this might be heresy, but a little copy-paste-modify does a great job on such small projects.

    Also, another way to think about this type of a project is as a "proof of concept". Maybe, while building this, you gather ideas that you never had initially. Once you have complete and see the "future" of the application, I think it is perfectly fine to almost start from scratch, this time with a real framework in place.

  2. JAlpino

    You have to admit though, sometimes it's nice to just build without the use of frameworks. Your app ends up being a dozen or so templates and ridiculously simple to follow, no thinking, just code and go. A perfect holiday weekend project that gets knocked out in a few short hours.