Thursday 13 June 2013

What do I want to see in ColdFusion 11?

G'day:
I'm suffering a bit from motivation paralysis at the moment... I'm not suffering writer's block: if anything the opposite, I've got about a dozen articles on the go at the moment. Or maybe that means I've got writer's block a dozen times over? Dunno.

Anyway, this is just an easy article to bang out: listing a bunch of stuff.


I've been to a coupla conferences recently - cf.Objective() & Scotch on the Rocks - where at both Adobe has done a presentation hinting at what they're looking to do in ColdFusion 11. What they've been demonstrating had been the ability to use CFML as a wizard to write the client-side Javascript for mobile applications. It seems like there might be a couple of interesting facets to this, but I'm afraid that on the whole it all seems to be be to mobile app development what <cfform> is to HTML forms: a bloated, badly-written solution to a problem that only exists in Adobe's marketing mind. I guess Adobe could deal with the "bloated, badly-written" bits, but that's always the way they implement this sort of crap, so I think that might be the level at which their capabilities for this sort of thing lie, so that's what we'll get again. This sounds harsh perhaps, but equally I think it isn't unfair, based on what they've delivered in the past.

I'm sure there'll be more stuff in ColdFusion 11 (and stuff that doesn't sound rubbish), but as this is what they're choosing to promote, I guess it's one of the main features. Oh dear.


So, anyway, I clearly don't want any of that crap in ColdFusion 11, but what do I want to see. Here are some random ideas / thoughts I've had. Some of this stuff I've touched on in the past, and most of them come from tickets I've raised in the bug tracker over time.


Package Manager

I've been looking at Ruby recently, and one of the best things about it is the RubyGems system. It just makes installing modules / extensions / apps / whatever as easy as an easy thing. There's example code in the article I link to above, but here it is again. From a command line, one just does this:

gem install rails

And this installs Ruby on Rails. Bang. Just like that. It handles everything to do with installing Rails, including dependencies, version management, installing local or remote gems, do it programmatically, etc.  Here's the docs for Ruby Gems.

This is brilliant.

Adam Tuttle has a project on github, Ramen, which is a package manager for ColdFusion. I have never used it, but it looks like a step in the right direction, and good on Adam for donating his time to the community. However I think Ramen misses the simplicity a package manager ought to have. Here's some sample code (from the readme):

<cfset ramen.namespace("taffy") />
<cfset userLocation = ramen.getParams().location />

<cfoutput>
    <strong>Install location:</strong> #userLocation#<br/>
</cfoutput>

<cfset ramen.download("https://github.com/downloads/atuttle/Taffy/taffy-v1.1.zip", "taffy-1.1.zip") />
<cfset ramen.unzip("taffy-1.1.zip", userLocation) />
<cfset ramen.cleanup() />

<p>Taffy install complete.</p>

I get why Adam has to do it this way, but one oughtn't need to have to piss around with all that code. It'd be getting closer to the mark if it was simply:

<cfset ramen.install("https://github.com/downloads/atuttle/Taffy/taffy-v1.1.zip", "taffy-1.1.zip")>

(maybe it'd need some other params, I'm just hacking around with the example code).

One doesn't want to (or should have to) go "here it is", "get it", "unzip it", "clean up". RubyGem demonstrates what one wants to do "This thing? Make it work for me please".

I think Adobe are best placed to do this, as to work best, it requires (or greatly benefits) a centralised repository of registered Gems, and one defined approach do doing things (as opposed to Adam doing it one way, someone else doing it another way, etc), and to make things as slick as a slick thing probably takes more effort than a (ColdFusion ~) community-driven project will ever achieve.

Having a package manager like this would also improve the uptake of third-party projects, because people won't need to hunt around for them, and if Adobe have "approved" a project, then it removes some of the uncertainty as to whether the project is any good, too. But just the ease of use will make people use more third-party stuff. 

I've raised an E/R for this: 3576112.

Code coverage tooling

During a presentation @ SotR, I started thinking about code coverage, and how it'd be great if ColdFusion baked-in the tools to perform code-coverage testing on a ColdFusion app. Again, there is an OSS project that addresses this: Rancho, however reading the blog for it, it's only really proof-of-concept quality, as it has these caveats:

Limitations
  • Supports only tags not script, so any CFML code inside will be uncovered.
  • Multiple level of folders is not supported yet. Instrument and generate report for single folder level at a time.
  •  Instrumentation of single file is not supported. Only folders can be instrumented.
  • Only line coverage is provided.


However - again - I think Adobe are the best people to provide the tooling for this: they've got the code parsers / compilers etc needed to do the job thoroughly, and have a far better knowledge of how to analyse CFML than anyone outside of the Railo dev team. Cough.

There's an old E/R for this: 3037290.

Note that the E/R requests an API for this, not a CFB plug-in like Rancho. I agree strongly. If there's an API then one can do a CFB plug-in if one wants, or a CFAdmin UI, or just some code in unit tests / CI build processes, etc.

Expose ColdFusion types as classes with methods

This is something else fairly obvious that Railo has started to do, but ColdFusion hasn't yet. One gripe I have with how Adobe has developed CFML is that it's given us - the CFML developer - the ability to write object-oriented code, but CFML itself remains firmly procedural. This is a bit of an uncomfortable paradox, and dilutes the credibility of the language, I think.

Railo's addressed this by treating variables of its internal types as objects, and calling methods (or member functions as they put it) on the objects rather than passing the object to a stand-alone function. Being able to do this makes code look more uniform, and less of a mishmash of OO and procedural code. I also think in this day and age, it'll make code easier to read and write for people arriving in CFML from other languages.

I wrote a dedicated article about improving ColdFusion's OO-ness, a coupla weeks ago, and raised an enhancement request at the same time: 3559652.

First class functions

Likewise, I would like ColdFusion's own functions to be promoted to be "first class", so they can be used as objects. I cover this in a separate blog article about using built-in functions as callbacks (or: not being able to), so I won't repeat myself too much here. There's an E/R for this too: 3434441.

Self-executing anonymous functionsImmediately invoked function expressions

Update:
Cheers to Josh for giving me the appropriate jargon above. I'm always useless with that stuff.
 
I've already covered anonymous functions in another article. We're familiar with these in Javascript, wherein we can do this:

(
    function(message){
        var uppered = message.toUpperCase();
        document.write("Inside: "+ uppered + "<br />");
    }
)("Hello World");

The chief benefit to me here is that the code within the function block is isolated from the code around it, so the variables don't over with the calling code, and are cleaned up as soon as the block exits. Plus it just makes code self-contained, which is nice. There's an E/R for this: 3346435.

Delegates

ColdFusion 10 added function expressions and closures, and promoted the idea of callbacks in CFML code (by referring to the concept as closures, which gets people's buzzword propellors spinning). ColdFusion's had the ability to use functions as callbacks since CF5, but not many people were aware of it. One thing that CFML has never done to further the implementation of callbacks is to be able to "type" them (as in "data type", not as in "with a keyboard ;-). In C# one has the concept of a delegate, which defines a type that the callback needs to be. Initially this seems odd, but if you think about it, when passing a callback it cannot simply be any old function, just like when passing an object, it's seldom the case it can be any old object. One needs the function to conform to certain expectations and behaviours. A delegate defines the function prototype for the callback's requirements, eg: what arguments it will be passed, and what type it returns. I discuss delegates in the same article I linked to above, and there's an E/R for them: 3346444.

CFScript coverage

This is something Adobe are actually going to do (so they claim) in CF11: finally get 100% functionality coverage in CFScript. This is essential these days, I think. It'll be interesting to see what they do with this, as they've promised the same think in CF9 and CF10 too. And never managed it (due to getting bored with it as a concept during development, I think).

queryExecute()

It's contradictory perhaps that I advocate improving CFML's OOness above, now suggest this. The current CFScript-friendly approach to running DB queries is an abomination, and whoever wrote it (and spec'ed it, and passed it through QA, and - basically - everyone involved with it) should be shot. Or put in a sack with a dog, a snake, and an ape, and thrown in the nearest river. Adobe's solution to this very real requirement was to ship a CFC which simply wraps-up a call to <cfquery>. This is incredibly lazy and amateurish of them. It's also completely at odds with the rest of the CFML language. The same can be said about http.cfc, mail.cfc and their ilk hiding away in [instance]/CustomTags/com/adobe/coldfusion/.

To run a query in CFScript one needs to create a transient object, init() it, call a bunch of setters to configure the thing, then call execute(), then call getResult() to get the actual record set. Talk about making easy things hard.

All Adobe needed to do here is to implement a single function, queryExecute() (executeQuery() would be better, but they have this habit of calling their functions noun-verb, rather than verb-noun):

public query function queryExecute(required string SQL, string datasource, string dbtype, [etc...], array params)

(the function ought to be implemented like how some functions are in CFML to allow named arguments to be specified, rather than just positional ones).

The only non-obvious thing here is that one will need to pass params into the function too (ie: as per <cfqueryparam>), which is the last argument I mention above.  This could be populated either just directly as an array of structs, or using a queryParam() function, eg:

params = [
    {type="CF_SQL_INTEGER", value=1},
    queryparam("CF_SQL_INTEGER", 2)
]

I would like to see all of those CFCs deprecated, and the work done properly in a way that fits with the rest of CFML, and is written in Java, not CFML.

Express "Install"

Both Railo and OpenBD have a version which is "installed" by unzipping a ZIP file, and... err... that's it. All settings are "best guess", or not set. For example when one first goes into the Admin, one is asked for a password. This is slick, sensible, and fine for almost all developers. I've written a dedicated write-up of this express install idea, and have raised a ticket for it: 3370889.

Make the core language free

This is always a contentious issue, but I'm sticking with it. I discussed modularisation of CFML ages ago, and that remains the way I'd like the pricing / bundling / licensing model to work.

Built-in framework

The thing that made Ruby really popular seems to be Ruby on Rails. I think ColdFusion ought to bake this sort of thing into the product. I realise RoR is not part of Ruby nor written by the guy who created Ruby, but this doesn't mean Adobe can't bake it in itself. I realise there are a lot of frameworks out there already, and indeed there ColdFusion on Wheels which is conceptually similar to RoR, but is - from what I hear (I've never used RoR or CFoW) - not a complete implementation, so "doesn't count". We don't need something that vaguely mimics Rails; we need something that does everything it does, as slick as it does, and does more besides. I really think Adobe are the only organisation with the resources to do this properly. I say this because it's a large undertaking, and I don't think the ColdFusion open-source community has the resources, motivation and direction to DIY.

I'd also consider whether MXUnit ought to be baked into a ColdFusion install, and have a plug-in for CFB such that when I create a CFC or a method, the plug-in goes "I'll create the unit test for that", and that sort of nice icing. I'm aghast at how many people in the ColdFusion community don't unit test, and having it baked-in my help people get their heads out of their arses in regards to this.

Language clean-up

Remove anything that's already deprecated. Deprecate all the UI stuff, for removal in ColdFusion 12. If needs must make the UI stuff something that can be added back in as a patch or something (for whoever actually uses that crap, and wants to continue upgrading CF).

Bugs

Fix 'em. Really really assault the bugbase and make a concerted effort to clear out as many of the valid issues as possible. Adobe are actually pretty good at chipping away at these, but it's good to observe that featuers are lovely, but we've got by without any given feature so far, so it's not like there's any burning urgency to add them. However bugs hinder our day-to-day work every day, so have a bigger impact on the community. This is an over-simplification, but I think it holds water.

Docs

Wikify them so we can go in and fix a lot of the crap that's wrong, and improve a lot of the poorly written stuff. This is already in the pipeline. It's been in that pipeline for quite a while though.

Important omission: Query on Query

How could I forget! QoQ is one of those "not a bad proof of concept, but not quite production ready". QoQ is almost really good, and it would be good if it wasn't so flaky. There are plenty of small bugs or shortcomings with it - too many to list - and if they were all sorted out, it'd be a handy tool.

Things I'd like to see:
  • its type handling to be made stable. It just gets confused too often;
  • JOIN syntax rather than only be able to join tables in the WHERE clause;
  • OUTER JOINS;
  • Support for joining more than two queries;
  • more function support (eg, left(), right(), etc)
  • possibly INSERT / UPDATE / DELETE support



I've filed a bunch of other enhancement requests, but they're bitty sort of things, so not worth dredging up here.

What stuff do you want to see in ColdFusion 11?

--
Adam