ISITE Design

ISITE Design
is a big-money web dev firm in Portland, OR.  They recently
expanded to Boston, MA as well, judging by their web site. 
However, what's interesting to me is that for a while they had a
reasonably nice all-Flash site.  Definitely one of the better
Flash sites I'd run across.  That's now gone in favor of an
XHTML-based one.  They also have a Breeze presentation linked on
their homepage about measuring ROI on a Flash content.  Obviously
they did the math and decided that Flash wasn't appropriate.

I'm sure that I'm the only one this caught the eye of, but I think it's
a good sign that people (including high profile companies) are actually
taking the time to consider the ramifications of Flash, rather than
just jumping on the RIA bandwagon because is the "hot new thing." 
I've been saying for quite a while that RIAs are just simply not ready
for prime time, and pretty much been scoffed at.  They definitely
have their users, but they're still pretty narrow in scope.  And
yes, this is coming from a guy who's company's corporate web site
(which I built) is entirely Flash based.  Believe me that I went
kicking and screaming, and only acquiesced because they sign my
paychecks.

Whitespace Suppression

Christian Cantrell posted a blog entry about expanding CFML whitespace suppression by leveraging CFMX's J2EE underpinnings. There seems to be a fair amount of happiness that this solution was made known (especially such a simple one). Two things I see here:

  1. people need to stop thinking about CFMX and a CF server and start thinking about it as the J2EE application it really is. You're getting a hell of a lot of power, basically for free, and the vast majority (or so it seems) totally ignore it.
  2. this looks like a good product feature for CFMX to have natively, maybe even in Blackstone, though it might be too late in the dev cycle for that.

What makes this more interesting to me is that I had a private discussion with Vince from New Atlanta about BlueDragon's whitespace suppression capabilities last week. CFMX's definition of whitespace suppression (both the CF admin option, and CFPROCESSINGDIRECTIVE's behaviour) is that all whitespace between CFML tokens (tags or hash-wrapped expressions) is consolidated into a single space. All other whitespace is left alone. BlueDragon's definition (same scope) is that after the whitespace-suppressed block is fully generated, all runs of whitespace are replaced with a space.

These sound pretty similar, until you realize that BD is drastically modifying your page's generated content, which has great consequences for inlined javascript (try using a // comment), PRE-formated text, and content for TEXTAREA tags.  Unfortunately, BD doesn't provide CFMX-compatible whitespace suppression in addition to this built-in overall whitespace suppression, so your in-code whitespace suppression mechanisms are pretty much incompatible with one or the other. BD's mechanism, however, is of nearly identical scope to the servlet filter solution Christian blogged about.

I'm happy to say that in the next version of BD (partly as a result of my discussion with Vince), the whitespace suppression mechanism will compress whitespace in a slightly more conservative manner, being more aware of newlines and such. This should remove the problems with inlined javascript, but will not solve the PRE and TEXTAREA issues. I also suggested that rather than trying to do it all with one option, they should split the function into CFMX-compatible suppression and then separately generated-content whitespace removal, so that you can just do the CFMX-compatible part. We'll see if that happens.

Also, just to throw this into the mix, using things like mod_deflate will generally give you an enomrous savings over simple whitespace suppression, especially if you're using CFML's built-in suppression facilities effectively already.

Beans, Transfer Objects, and Other Mumbo Jumbo

There was a series of interesting threads on CFCDev today about
different types of objects, and how they play together to form a
complete OO system.  Couple that with a pretty active week in the
CF blogosphere regarding objects, and I think it's pretty safe to say
that CF development is growing up.  Definitely no longer just the
quick-fix dev tool for little apps, CF developers are starting to think
about pretty hard core development techniques, and with enough numbers
to warrant widespread discussion.  That's really cool in my view,
and should bode well for the community as a whole.

I want to
sum up a few things with quick definitions/discussions as kind of a one
stop shop, rather than having to look all over, so here goes:

Objects
- A collection of state (instance data) and behaviour (methods). 
A struct has state.  A UDF has behaviour.  An object has
both.  The state should be inaccessible to the outside world; it
can only be retrieved and manipulated via methods of the object. 
Some objects are very thin, with almost no behaviour, some objects are
very thick.

Business Objects (BOs) / Beans – These are
the heart of any object model.  They represent the entities within
the model, and hold not only the entity state, but also entity
behaviour. 

Transfer Objects (TOs) – These are
snapshots of the state of a BO, without any of the business
logic.  Their purpose is twofold: 1) to make passing the data
around easier (one object, versus a bunch of individual fields), and 2)
maintain the integrity of the BO's state, without requiring the BO
itself (the TO's state is immutable, and only accessible via
getters).  This should be a CFC with getters for each property of
the BO, but you can use simple "read-only" structs with similar effect.

Data Access Objects (DAOs)

- These objects provide a way for a business object's state to be
stored and retrieved from some "persistant store".  Usually this
means a database, but it might be a collection of XML files, or any
number of other things.  The idea is to isolate the BO from the
method in which it is stored, so you can transparently switch out
persistance mechanisms without affecting it.

Data Gateways
- These provide a related function to DAOs, but they aren't for a
specific BO (or entity), but rather for collections of entities. 
So where you might have a User BO and a corresponding DAO for it's
persistance operations, you'd have a gateway object for getting lists
of users, or other such multi-entity operations.

is-a, has-a
- These are the two core types of relationships between objects. 
Is-a relationships are inheritance, where you say "a Corvette is a Car
is a Vehicle".  Has-a relationhips are composition, where you say
"a User has a Role which has some Responsibilities".  Wherever
there is ambiguity between which type of relationship to use, the
natural instinct is usually to go with is-a, but the proper solution is
usually to go with has-a.  ; )

Object Modelling
-
The process by which you define and create the set of objects needed
implement a given set of business logic.  This is a VERY
complicated process, and is damn near impossible to get right on the
first try (or the third, or the tenth …).  It usually starts by
identifying the entities in the model, and then identifying the
relationships, and then identifying the types of objects needed to
represent them.  Once that's done, you go back and revise them,
checking for cohesion, loose coupling, appropriate use of patters, and
all kinds of stuff.   Then you revise again.  And
again.  Simple on paper, difficult in actuality; very
much an iterative process, no matter your level of expertise.

If you're interested in using OO with CFML, I'd highly recommend the CFCDev list
It's not particularly high-traffic (much, much less than CF-Talk), and usually
stays remarkably on-topic.  You might also check out An Architects View (Sean Corfield's blog), ClearSoftware.net (Joe Rinehart's blog), and Matt Woodward's blog.  Finally, I'd also recommend the ColdFusion news feed on FullAsAGoog.com, which includes all of these blogs (along with mine), plus with many others to numerous to mention here.

I'm Back

After a gloriously long holiday break (nearly two full weeks), I'm
finally back to real life.  I won't say that I've missed it, but
it is kind of nice to be back into a routine.  And now, the
obligatory quick recap.

Aside from a botched trip to Victoria, BC (things are closed on New
Years Day, imagine that ;), the holidays were quite nice.  It's
the first length time I've really gotten to spend with Lindsay, which
was very enjoyable.  She's almost a year old now. 
Amazing.  Got the mandatory Legos for Christmas, a very cool pneumatic truck
I managed to make an air-powered catapult with that set alone, but now
that I'm back home, I can mix it up with all my old sets, and I'm sure
something really cool will come of it.  Also while I was gone,
another check came in from Fusium, so I'm up to $450 in the Free Barney fund.

The app I've been working on (and the source of my BlueDragon woes) is
done.  It's a new backend for this site, including online image
editing and management.  Nothing complex, but enough to occupy my
evenings for a couple weeks, especially with the troubleshooting. 
As a Christmas present to my sister and sister-in-law, I set up a site
for each of them (Hawaii Boisverts and The Whisler Life, respectively) on the system, in addition to this site and The Boisvert Life.  They're now happily blogging away, photo galleries and all.

That's about it for the past two weeks.  Once I get a little more settled, the normal posts will resume.

ColdFusion for Christmas?

I got an interesting email from Tim Buntel (Macromedia's Senior Product Manager for ColdFusion) yesterday.

"We would like to hear more about your BlueDragon experience. If
you could write up a document detailing your experience, frustrations,
and the like, we could help you out with your request for a shiny new
license of ColdFusion MX 7 Standard."

So I might well get a
license of CFMX for myself without actually having to earn all the cash
and send it off to Macromedia.  Nice for me (less work), nice for
Heather (maybe a late christmas present for her), and nice for
Macromedia as well (potentially some free – as in beer – advertising).

Merry Christmas to all, and to all a good night!

TinyMCE

With cross-platform inline HTML editors all the rage these days, I
though it appropriate to share my experiences with a couple of them
this evening.  I use soEditor and HTMLArea
extensively in my professional work, and like them both.  Neither
is perfect by any measure, but they get the job done, though soEditor's
IE-only stance is becoming more and more cumbersome.  However, I
went a totally different track from the known and into the
unknown.  My requirements were very minimal.  Has to work in
IE and FireFox (on Windows, OSX, and Linux).  It needs to easily
allow for custom link and image dialogs.  It needs to load hella
fast, and turning off pretty much everything on the toolbar needs to be
simple too.

First stop was FCKEditor
It's gotten a lot of time on CF-Talk of late, so I thought I'd give it
a whirl.  It's definitely a full-featured editor with all kinds of
features and customizability.  However, I was unable to get it to
do anything except load it's initial blank document in the
IFRAME.  Since I had no issues running the demos on the FCKEditor
site, I suspect that the problem arose from running on BlueDragon's
internal web server.  Unfortunately, until New Atlanta gets around
to releasing an Apache 2 connector for OSX, that makes the issue a deal
breaker for FCKEditor.

The next one I tried was TinyMCE,
which seems to be a lightweight version of a more elaborate editor that
Moxiecode sells.  I'd run across it in the past and was impressed,
particuarly with how lightweight it was, because that's exactly what I
needed.  Threw the directory in my web root, and it fired right
up.  Firefox refused to use the stylesheets because BD was serving
them up with the wrong MIME type, but other than that, it worked like a
charm.  Customization was straightforward, and in less than two
hours, I'd gone from Google to fully implemented, with custom dialogs
and everything.

I would have liked to have played with FCKEditor a little more, as it
seems really slick (though rather slow to load), and mostly gets
glowing reviews, but unfortunately that didn't pan out.  However,
I did find a new editor that is very well suited to lightweight editing
tasks.  It's fast and simple from both user and developer
perspectives, and it looks like it can be scaled up pretty effectively
to meet pretty in-depth editing needs.  It doesn't come with all
the bells and whistles that FCKEditor or HTMLArea come with, but if you
don't need all the extras (or are going to build your own), it's
definitely a good choice.

BlueDragon: Still Breathing Fire

BlueDragon continues to give me fits. CFEXECUTE (which I'm not sure – there is conflicting evidence – is supported on the Server edition) refuses to work correctly. No big deal, since launching a Process direct from the Runtime class is straightforward (I didn't need the IO streams, in this case). However, the waitFor() method of Process refuses to do anything except throw exceptions when called, which basically means no syncronized subprocesses. So what's the solution? Write a JSP page that does the exact same thing (except it works) and then call it with CFHTTP. Hardly elegant, but it worked well enough.

Next problem was doing some simple image manipulation with the ImageIO class (from javax.imageio). Nothing complex, just a simple read-scale-write operation to generate a thumbnail. However, BD pukes on the write part. From the stack trace on the NPE, it appeared that it was having trouble selecting which of the method versions (write is overloaded) to call, even though it was pretty clear cut (the one with a RenderedImage, a String, and a File). What's the solution for this case? You guessed it. Write a JSP page that does the exact same thing (except it works), and then call it with CFHTTP. Ooof.

I do tire of such hacks, and so once again, my pursuit of the CF license is in full swing. I just finished up some more work for Fusium (awaiting the check), and lined up another little project that should just about round out the two grand I need. Now if only I could be done and have the license today….

iTerm Rules

I long ago discovered iTerm, a slick little Terminal replacement for OSX. Among other things, it lets you have tabbed windows, just like any decent browser, which is handy for managing the swarm of SSH and MySQL sessions I usually have open. What I just noticed today was that you can tear a tab off into it's own new window, which is way slick. Only problem: you can't move tabs between windows at will. Regardless, it's a handy feature to a very functional piece of software that no OSX user should be without.

Architecting FB4.1

Architecting with Fusebox 4.1 is a very wide arena. There are lots of ways to do it, but I think I found one that is particularly well suited to the framework, especially when combined with CFCs for a backend. My presentation at the 2004 Fusebox Conference hinted at much of the principles, but I can say that after having written a couple more FB4.1 apps from scratch, that they make for a very nice little package.

There's a few main points:

  1. Separate 'pages' from 'actions'
  2. Separate the UI from the application proper
  3. Separate the markup from the presentation
  4. Reuse code everywhere it makes sense, and nowhere else

For point #1, a legit question might be "what's the different between a page and an action?". My definition is that a page renders content to the user, while an action performs an action and redirects to somewhere else. The definitions are mutually exclusive, so if you're doing an action, you HAVE to redirect to a page in order to render content; you can't do both on a single request. There are a few exceptions (for instance, marking a message 'read' – an action, when you open it – a page), but they are few and far between.

I opted to have all my fuseactions that generate HTML be named as you'd expect (addEntry, viewComments, etc.). All my fuseactions that do actions start with 'do' (doInsertEntry, doDeleteComment, etc.). In my presentation at FBCon04, I'd recommended separating the pages and actions into separate circuits. Upon further reflection, I'm retracting that recommendation in favor or just separating the pages and actions in your circuit.xml file. One block has all the pages, and another block has all the actions (commented appropriately, of course).

Point #2 is accomplished by the use of a 'service' CFC. It is a singleton CFC that is instantiated into the APPLICATION scope of the app, and it contains all the business operations and data recall for you app. Each business operation has a defined method name and set of parameters. How it's implemented (inlined SQL, a mess of BOs, DAOs, and gateways, magical pixie-powered light-based storage, whatever) is irrelevant, and that's exactly the idea. You should be able to change your presentation layer without changing your service object, and you should be able to reimplement your service object (maintaining the method signatures, of course) without changing your presentation layer.

Point #3 is the standard "use (X)HTML and CSS" line. Make sure you pages are designed from a semantic perspective. Build all the pages before you ever write a single line of CSS. Not going to be pretty, but they do need to be functional in that fashion. Then whip out your CSS magic wand and make it all pretty. This really has nothing to do with FB4.1, but it does have to do with good architecture, because the more divorced your markup is from your presentation (CSS, in this case), the easier it will be to make changes (visual or functional) down the road.

And at last, number 4. Two clauses, and the latter is the more important one. I've seen a lot of people (myself being one) who try to squeeze every last drop of reuse out of a bit of code. Reuse is good, but there are definite times when it's simply a foolish goal to strive for.

In this particular app, most of my display templates (roughly analogous to views in Mach-II) are in their own fuseactions. Again, I opted to not use a separate circuit, but rather name them starting with an underscope (i.e. _entryForm) set them as access="internal", and group them all in their own section in circuit.xml. They include everything needed to render the view, except for designated parameters for reuse (such as the XFA to submit a form to). That means they might include calls to the service object for a recordset, might set their own XFAs, might do basically anything, as long as it's bound directly to rendering that specific view file.

So, in a nutshell, what do I have? A single circuit, broken down into three sections (pages, views or pagelets, and actions). An abstracted service object that encapsulates all the business and persistent operations behind a known interface. Markup that is independant of it's presentation. An app that is both enormously flexible and easy to work with.

Future updates can apply to single sections of the app without affecting other sections if they don't need to, greatly reducing the subsequent testing needed. Poorly implemented sections (of which there are a couple because of time constraints), can be transparently reimplemented without affecting the app.

What I've described isn't quite MVC, at least in the traditional sense. It's subtly different, and while only time will tell, I think those differences result in a much better end result.

Whoops

So it wasn't quite perfect. Realized that I'd botched the new entry config slightly in that comments weren't enabled by default. But that's fixed now, so anyone who happened by in the middle of the night and wondered why the previous post couldn't be commented on, that's the reason. It's fixed now though.