ColdFusion 9 - What We Know (so far)
Since I got the
obligatory pricing rant out of the way (well, ok, it was more
complicated than that), I figured it was time to focus on the features
we have already heard about regarding ColdFusion 9 (codenamed Centaur).
Most of what we know so far was revealed during this year's CFUnited
Adobe Keynote, though a couple items were made public during the
extremely brief cf.Objective() Adobe Keynote. Let me start by saying
that I think everything we have learned leads me to believe that the
ColdFusion team is on the right track. Of course a lot rides on the
actual implementation of the features, but all signs are pointing in a
very positive direction. Also, keep in mind that, as they say, these
are only plans and plans can change (as in, while these features are
likely there are no guarantees).
CFML Advisory Board
This was briefly introduced at cf.Objective(), though the actual details were released at CFUnited (and Ben Forta wrote about it
at length). Though it isn't a "feature" of CF9 per se, it is an
important driver of the product's development and a sign that Adobe
continues its trend towards more openness and cooperation. Members
include Sean Corfield, Ben Forta, Sanjeev Kumar, Gert Franz, Ray Camden
and Rob Brooks-Bilson among others. As you may notice, only two of
these names directly represent Adobe and one even represents an
alternative CFML engine. In my opinion, this shows a level of long-term
commitment to the langauge (as opposed to simply the
product) that we have not seen previously and I applaud Adobe and the
ColdFusion team for it (given that Adobe has the most to potentially
lose by such openness, particularly with competitors).
Free for Educational Use
I
don't really have to say more than, "Its about time!" This is another
one that isn't exactly a feature but will still play a large part in
the future viability of ColdFusion/CFML. We probably won't see the
positive effects from this for years but we need to start somewhere
bringing new talent to language, and this is the right place to start.
ORM via Hibernate
It slightly shocked me to hear via Adam's post
that this feature wasn't a big hit in early SyncDev meetings (though
not totally surprised which relates to why I am hesitant about
over-weighting non-coding manager opinions). Personally, I think this
is a no-brainer for ColdFusion. Hibernate is the de facto standard for
ORM and has become more prevalant over the years, so utilizing it in
ColdFusion simply makes sense for a product that bills itself for rapid
application development.
Thankfully, despite the initial low ratings, Jason Delmore and the team
didn't remove the feature. In fact, according to Jason, over the course
of SyncDev, the feedback changed whereby this became the most important
feature. He says it was simply a matter of expanding upon the total
solution built around this.
CFC Enhancements
Adobe
has announced a number of excellent CFC enhancements so far, and I
assume there are more tome. Those we already know include:
Local Scope
Finally
we can rid ourselves of the needless and mistake prone var scoping.
ColdFusion 9 plans to default to local scoping your unscoped variables
within CFC methods.
Default Scope Setting
Don't
want ColdFusion to default unscoped variables to local? Well, the
intent is to allow you to override this behavior and specify what scope
variables will default to.
Implicit Getters/Setters
If
you use ActionScript, you are already used to this concept whereby the
getter/setter for class variables is implied without needing to be
coded (though it can be coded overriding the implied getter/setter).
Well, from what we know so far, ColdFusion 9's implicit getters and
setters will function much the same way and will be defined by a
components cfproperty tags.
CFScript Enhancements
Up
to now we have heard signals that CFScript will get what may possibly
amount to an overhaul. At cf.Objective() some of us wanted this to go
as far as ActionScript on the server support. Nonetheless, there seemed
to be some push to make cfscript complete (i.e. support for all
functionality available in tags - if possible) and to clean up
cfscript's syntax. Now, we haven't received definitive confirmation of
the previous but what we have heard is:
UDF's and CFC's written entirely in CFScript
This
was teased in a slide at cf.Objective() but formally discussed at
CFUnited. The idea here is that you can write everything you need for a
component, including function definitions, properties and so on, fully
in script. Obviously this would require some form of expanded
functionality support as discussed above.
Language Enhancements
Much
of what discussed above could be classified as language enhancements
but some of the additional items we have heard about are:
CFContinue
Again
this is already something someone form ActionScript (or other
languages) may already be familiar with. CFContinue will allow you to
jump back to the beginning of a loop from a specified point within the
loop rather than have to wrap the remaining code in some form of
if/else block.
CFFinally
Also
common in other languages like ActionScript, CFFinally is for try/catch
blocks and is a block of code that always runs after an exception is
caught. This helps you not have to duplicate code within each element
of a try/catch block.
New and Import keyword support for creating CFC instances
You
will be able to import components much like they are imported in other
languages like Java and ActionScript at the top of a template using a
syntax like "import com.user.User;" and then instantiate this component
anywhere in the template by stating "user = new User()". There have
been some hints that you will be able to define a constructor for a
component (like the common init()) and it will run when you call "new
User()". These code improvements should help eliminate some of the
tedious and redundant CreateObject() calls throughout many
templates/components.
Server Component
In
ColdFusion 9 you will be able to define a Server.cfc per server
instance that will give you access to some additional utility methods (OnServerStart/OnServerEnd) that can be used for a couple of useful functions such as cleanup and/or synchonization.
AIR Integration Improvements
Not
surprisingly, a lot of time at CFUnited was focused on AIR integration
improvements much of which focused on a new library that would be
available ot AIR applications:
com.adobe.coldfusion.*
This
library would give you access to, for example, a ColdFusion datasource
which would allow you to perform ColdFusion queries directly within AIR
via MXML (Ray's post
has some of the example syntax that was used). While I am not sure of
the merits of allowing direct querying within the MXML, I think that
better and easier AIR/Flex integration will be a huge driver of
language/product adoption going forward. Other tags mentioned as
potentially being exposed to AIR this way could include CFMail.
Tooling
By tooling I
mean an IDE. I only use the term tooling because that is about all we
know from Adobe so far - that one of the focuses of ColdFusion 9 is
"tooling." Do they mean an IDE? I hope so. This is
probably the single most important item in my opinion, yet also the one
we know the least about. There have been hints/promises of more details
on this topic to come at MAX.
Further Reading
Centaur (ColdFusion 9) User Research Complete by Adam Lehman
cf.Objective() Keynote: News on Centaur (CF9) by Raymond Camden
CFUnited 08 Opening Keynote by Raymond Camden
The Future of ColdFusion series by Dan Vega:
Part 1
Part 2
Part 3
ColdFusion 9 Details by David Tucker
ColdFusion 9 + Hibernate == Transfer Killer? by Mark Mandel
Ready, set, CFUnited is a go - ColdFusion 9 Sneak Peaks! by Mark Mazelin
ColdFusion 9 (AKA Centaur) to have impressive new features by Marcos Placona
CFML Advisory Committee Update by Sean Corfield
I tend to agree with that assessment.
While most CF applications aren't particularly sophisticated when it comes to the database and typically don't use any kind of ORM (a few Transfer / Reactor / etc. apps notwithstanding) I really don't feel there's anything lacking in CF's current db access features (aside from allowing nested cftransaction tags and improving the cfdbinfo tag that I'd suggested during the Scorpio alpha).
On the other hand, particularly with now the ability to duplicate() CFCs and the fact that cfthread tags do that automatically when they're passed in creates a new, hidden threat of *MAJOR* disaster when pushing an application into production.
Nearly every application does perform some kind of caching, although most of them not nearly as sophisticated as say ColdBox. And I'd expect with these new features that make it so easy to accidentally consume huge amounts of memory, that we're likely to see more Toys-R-Us stories in the future.
While dealing with the database is already well established and none-too dangerous, memory management is a time-bomb waiting to happen. That's why I think memcached would be a far better plan than hibernate support.
On the up side, in spite of the fact that I'm totally nonplussed by the idea of writing entire CFC's in script, I do feel many of the other items are headed in a great direction. My two favorites are local scope and the sever component... speaking of which, the server component may be very useful for the project I'm planning right now. My hope is to publish a combination of what are currently the best caching algorithms available in the ColdFusion Open Source community as a plugable caching service called CacheBox which can then be leveraged in all the frameworks where that effort is currently being duplicated (ColdBox, MachII, ColdSpring, Lightwire, Transfer, DataFaucet, the onTap framework and I'm sure others).
The idea is to have an onDuplicate() method in CFCs like the onMissingMethod() method that would allow the component author to declare how a given component responds to a request for a deep-clone from the duplicate() function.
I just submitted an enhancement request and blogged about it here:
http://ontap.riaforge.org/blog/index.cfm/2008/7/23/onDuplicate-for-ColdFusion-9
Thanks
I, also question the inclusion Hibernate, but for a different reason. I just don't like the idea of using an ORM. I am very picky about my database design, and I frankly don't trust a library/framework to do all that work for me, and do it correctly. So I'll likely never use this stuff in CF 9.
Also, at CFUnited Hal Helms said in one of his presos that he really dislikes ORMs, and he sorely wishes people wouldn't use them. But he doesn't like them because an ORM doesn't fit into his conceptual vision for OO applications. I'm a little more down to earth than that...I just plain like building databases, and setting up the interactions with them in my code. :)
I spoke with Hal a bit on this topic at CFUnited and while I have and still do share some of his concerns with ORMs, they are quickly becoming a standard tool (Hibernate specifically). So ORMs aren't going anywhere...in part because of the huge amount of time, effort and complexity they can help remove from an application.
My boss (the technical one) at my new job here in Boston however said what Jake is saying to me in a private meeting... He said "I like doing something and seeing it work"... and I have to think "GREAT! Go instantiate a J2EE class for SMTP transfer to send that next email from CF!" :)
I actually like designing databases tho, and my ORM (DataFaucet) handles the DDL to create the tables and such from an XML dialect. Transfer has only tools for going the other direction, using an XML config to map classes to tables the way Hibernate works.
As far as using ORMs in general (I know it's off topic, sorry), and I can't speak from experience. But when I have looked at them, it seems like a LOT of work, for little gain. I can spend 20 hours building my database in a properly normalized design, or I can spend 20 hours building the XML definitions for my ORM (wondering if it creates the DB with a good level of normalization).
On top of that, I seriously doubt any ORM will handle the complex queries I often have to write, so I'd be stepping around the ORM to access the DB directly in those cases. I guess I just don't get it. I have to continually tell myself, though, that I shouldn't knock if I haven't tried it. But I do wonder if my high level observations are correct...
And for those in the audience that don't know what database normalization is, check out the Wikipedia article:
http://en.wikipedia.org/wiki/Database_normalization
Valid point. I don't think that OO is bad, I just haven't made the leap yet. But even when I do make the leap, I'll still eye ORMs with skepticism. Unless someone can tell me that their ORM would allow me to create a normalized database, using the level of normalization that is appropriate for the type of application I build, then I'd be more inclined to give it a try. And if it would allow me to use left, right, and inner joins, and all the other standard SQL query tools.
Relational SQL has been around for a LONG time, with millions of developers giving feedback and helping refine the standard over the last 30+ years. Thus why I am skeptical that an ORM developer can duplicate all of that functionality and wisdom overnight, relatively speaking. I mean, look at SQL Server. The core DB engine has been around for a long time as well, but Microsoft is just barely "catching up" with the ANSI SQL standard with their most recent releases (which admittedly is partially their own fault).
Boy that was longer than I expected... the point I was getting to before I got so long-winded is that in spite of the fact that normalization is very important to me, I don't think the word normalization actually appears anywhere in the DataFaucet documentation currently. But that's a good point and I'll probably try and see where I can fit in a short document that explains normalization, what it is and how it relates to the way DataFaucet works. But I mostly wanted to make the case (devil's advocate) that not having used the word doesn't necessarily indicate that they feel the subject is superfluous or unimportant.
re: complex queries - I can't speak to Transfer or any of the other ORMs, but the DataFaucet tools evolved out of a desire on my part to have a way to write SQL across all the major database platforms. I started doing this on CF5 before there even were CFCs believe it or not, and although it certainly wouldn't have supported all the things you mentioned then, it supports most of them now. I haven't ever added support for right-joins, probably because I've never run into a situation where I actually needed one and on top of that, I personally find the semantic of inner/outer, left/right joins to be overcomplicated, so I simplified it to "required" versus "optional" joins. But beyond that, everything else you mentioned is supported. There's an article about my reasons for the semantic change on the DataFaucet blog under the title "filtering on left join" where it also explains how the system does a "complex" filtered left-join that's the sort of thing that a lot of junior developers get stumped by, including myself many years ago when I was green.
re: OO and its use -- well, just because you personally haven't "made the leap" or "drunk the kool-aid" (take your pick), doesn't by any stretch of the imagination mean that you can't take advantage of tools that are designed ultimately for people who have. Many years ago I had a brief stint at an ASP company (your condolences are appreciated), where the code was certainly very procedural. Yet we used a shopping cart from Microsoft (Commerce Server?) that was all COM objects. The difference with something like either Transfer or DataFaucet is that, whereas Microsoft's tool has a complicated API to integrate, some of these ColdFusion ORMs can actually make certain things a lot simpler. Understanding that you enjoy working with SQL, you may find that being able to rely on a system for standard insert/update/delete statements (typical CRUD) and in some cases maybe even common "search" features, gives you more time to focus your attention on the complex queries that really need your attention. So while you might insert/update a record in your CRUD admin area with Transfer.save(product) or in the case of DataFaucet Product.update(data), that just removes the tedious parts from the work that you actually enjoy.
Anyway ... if you're interested in checking up on my wild claims of SQL language support, it's on RIAForge. http://datafaucet.riaforge.org -- These were recently removed from the onTap MVC framework and I'm still working on the next release of that to support its separation.
On a similar note, I have heard/read comments from ORM users like, "I have never been good at nor liked working with SQL, which is why I love my ORM." This sends chills down my spine. I know I'm probably a little (or maybe a lot) snobbish in this respect, but in my opinion, if any web developer is not good at SQL, they should let someone else write their DB stuff for them. And they most certainly shouldn't be using an ORM, if they don't first understand the dangers of a poorly designed database (missing data, duplication, performance, etc.). But that's just my snotty opinion. :)
As far as Right joins...I can (and usually do) live without them. It's easy enough to switch things around and use a left join, when you think you need a right join.
On the other front, I absolutely, wholeheartedly agree -- imo a good, solid fundamental understanding of db fundamentals is really important in being able to properly leverage an ORM. You don't have to be the Mozart of the relational world, but you do need a good foundation in normalization, basic performance concepts and be able to analyze questions like "when might you not want to use a foreign key constraint" (because imo, using them should be the default). Orphaned and duplicated data have a real way of wrenching up your projects if you're careless about your data integrity.
re: right join -- ahh okay... well I'll take that basically as a confirmation of my strategy then. Thanks. :)
@Brain, I too have had trouble getting the CAPTCHA text right on the first try.
<cfqueryparam value="#...#"> (but the datatype can increase performance) and that is a simple copy/paste for all variables. But I can see how having the ORM do that for me would be very nice.
ds.query_from_tblCategories_where_parentid_is_null()
or
ds.query_from_tblProducts_where_price_lte_50()
I actually haven't really decided what my opinion is on this syntax yet myself.
Sorry if it sounds like I'm "hawking my wares" at you. ;) I'm just very passionate about my projects.
I hope it makes it into CF9!
http://blogs.sun.com/alanb/entry/heap_dumps_are_back_with

