Late last week Dan Fredericks emailed an interesting question. I honestly had no idea how to even begin to answer it, so I thought I'd share it here and get advice from my incredibly intelligent (and good looking) readers. His question was:
I have read over the last couple of days Ben's post and Dan's post about tag vs script for components. I am more comfortable with tags, and so are most of my coworkers. However, the application we work on (CF 8 app), is written in coldbox and the previous developers did a lot of their handler work in script. So, we have developers now that don't work in script, but the code is in script...you can see the mess we are making :)
so, my question for you, or for the community as a whole, how best to transition from tags for cfc's to script? me personally, when i was converting a foxpro app to CF, i was able to grab some foxpro code and just copy it into a cfscript block and change a bit of it and it worked, but i am still no expert in script, and nobody here is. I was thinking it might be a good think at my job to try to run a small demo on the basics of scripting for CF (obviously cf8 scripting), but I really don't have a good idea about how to go about it.
are there any demos that you know of already, or do you have any suggestions? or do you think the community would have some?
So this is definitely a fascinating question. I began my web development career with both HTML and JavaScript. When I began doing server side work, it was in Perl. So I had scripting experience from a very early age. Scripting feels very natural to me, even with most of my development career being in a tag based language. Dan's question then threw me for a loop. If your only experience with code was tag-based HTML and ColdFusion, how do you get into scripting?
You can - of course - make use of the docs that specifically cover scripting in ColdFusion: Extending ColdFusion Pages with CFML Scripting. These docs walk you through the process of using cfscript. I find that people ignore the official docs far too often, or complain that they have too many errors and omissions in them. As a technical writer, let me just say that I've yet to see any technical book ship without errors. The official docs for ColdFusion are huge and are a resource too rarely utilized.
Obviously learning another scripting language, especially JavaScript, would be incredibly helpful. Not only would it give you another language to add to your tool chest, it would give you more experience in working within a script based environment.
Ok readers - what would you suggest?
Archived Comments
I was in the same boat - all tag-based coding early on, but I found a number of resources to help me get started, and now I really can't imagine live without script.
Eloquent JavaScript dot net is a great resource for learning JS.
O'Reilly books also has a JavaScript Pocket Reference (by David Flanagan) that I always carry with me.
Amazing how powerful JS makes your pages. Once you have a foundation for JS, cfscript is a no-brainer!
Hi Ray,
The blog-title is a little mis-leading. A "Scripting Language" is defined on WikiPedia as:
"A scripting language is usually interpreted from source code or bytecode.[2] By contrast, the software environment the scripts are written for is typically written in a compiled language and distributed in machine code form; the user may not have access to its source code, let alone be able to modify it."
For clairty, I wouldn't confuse CFScript with a Scripting language. While CF is a scripting-language, the two definitions are very different things.
[1] http://en.wikipedia.org/wik...
I have to admit I have no idea what you are talking about David. I find it totally confusing to see "wouldn't confuse cfscript with a scripting language" and then "while CF is a scripting-language".
I think Dan is asking about learning CFScript. I read the title of the post, thinking the article was about learning a scripting language.
David, well, I think it still applies. We can get picky about ECMAScript and all that - but for all intents and purposes - I think there is enough similarities between JS, CF Script, even PHP, that the "feel" of it is pretty analogous. Wouldn't you?
I have a whole shelf of JavaScript and jQuery books. It has been a very hard language for me to learn. If someone were to write a book on just the Good Parts of JavaScript, it would be a very thin book. Even thinner if they left out Appendix A and Appendix B.
I use the CFWheels framework, and one of the main reasons I use it vs just Ruby on Rails is CFscript. I was overwhelmed with it at first, but now I do my views in CFML and controllers in CFscript. That way CFML is to HTML as CFscript is to Javascript.
That probably didn't add much to the conversation but I thought I'd chime in.
P.S. I just used CFWACK to learn CFscript. There is a section on common tags converted to CFscript and then I went from there.
I agree with Phillip. I think a lot of my love for script came from JavaScript. For me I was tired of writing so much code for functions and arguments in tag based components. I also have a little bit of a Java background so writing components in script just came natural. If there is anything specific you guys want to see I could start writing a new series on moving over to script. I have been looking for something to blog about anyways :) Just let me know.
I think ColdFusion draws a lot of its inspiration from JavaScript, doesn't it? Closures are the Johnny come lately to ColdFusion. Coming up with a valid example would be helpful.
Not that I want to encourage just writing about the latest tag/technique.
I toyed with some sort of rating system a while back: which tags were considered essential down to "do not use". In my cfmeetup talk, someone offered the idea of crowd sourcing which tags were used the most in an effort to prioritize their learning. We all have precious few minutes per day to learn something new, so if you're new to a topic, it would be nice to see what the community has found to be essential, advanced, and not useful.
Doesn't ColdFusion Koans have cfscript lessons? I believe it does. You can find it here: http://bittersweetryan.gith...
I prefer to write in cfscript. I recommend moving to CF9 not only because cfcript has gotten a lot better, but also because CFCs are easier to write in CF9 due to the enhancements in how to declare variables.
I've written a few CFCs entirely in cfscript, but sometimes I end up getting stuck wanting to call a module or do something that can't be done in cfscript, in which case I write my cfc as a hybrid of cfscript and cftags, which seems to work fine. The cfc shell is in cftag, and then inside the component, I create a cfscript block that has methods written in cfscript.
As a side note in working with javascript/cfscript: When I go back and forth between the two languages, the one thing that I always mess up is the difference between javascript operators (> < <= >= !=) and CF operators (GT LT LTE GTE NEQ), as well as the lack of ++ and --. I really hope CF handles these operators in cfscript someday!
John, you're in luck, Coldfusion handles those operators right now. Otherwise I agree with what you're saying. My suggestions for learning cfscript are to find some tag based code that you've written and understand really well and translate it to cfscript. At first keep the overall structure of the cfcs in tags and use cfscript tags to wrap the code within each function. There are certain tags like cfquery where the current implementation is problematatic and you want to be able to avoid frustration with them at first.
Hey Everyone,
thanks for your initial posts, and Ray thanks for blogging about this.
Dan Vega, if you are looking for stuff to blog about, a couple post about the best way to transition from tag based CFC's to script based would be awesome...Finding out the Koans have cfscript is helpful as well.
I am not really sure how to approach showing my coworkers that cfscript is becoming more of a standard for cfc work, plus a lot of our cfc's are already in script so we are mixing both tags and script. Not saying this is bad, but i'd like to educate everyone so they at least can see the benefits of cfscript, and maybe we can even get our code more consistent.
So, I'll be checking the Koans, looking to see if we have a CFWACK book, and waiting to read some blogs from Dan about cfscript and the cleveland sports scene :)
thanks everyone and any more suggestions about how to teach cfscripting to people would be very helpful.
dan
I went from all tags to script.
I found this early on, helped a bunch: http://www.petefreitag.com/...
Started with flow control. Repeatedly hit Google with search terms like "cfquery in cfscript" and "cfc in cfscript".
I use script for almost everything now, and love it. Some things are still easier in tags for me though, like queries with a lot of variables in them, and anything on the output side more than a quick status or dump sort of thing.
You definitely want to work very hard at eliminating tags from your programming "vocabulary" and transition into script. It's really an important key into having a continuous career without being tagged or labeled (scarred??) as a CFML developer. The tags do you know good other than to increase the number of keys you have to type when programming. Plus, it reduces the amount of time it will take you to get up to speed on another language like PHP or Java, which is very important.
Jorgen - I'm not sure I'd agree with eliminating tags. Have you done layout in script? It's a pain in the rear. Heck, even in JavaScript you have multiple templating options. I think tags work GREAT for layout and html and I'll always use them. For business logic though scripting is a lot more efficient.
No one tool fits all!
I'm really sorry but you are WILDLY incorrect. Scripting is the only way to go. If you need the advantage of tags to ease the pain of layout, then you've got too much logic in your view. Scripting or bust. I. am. correct.
"Scripting is the only way to go." If you truly believe that there is no alternative than that is your opinion. So to be clear,you like to render HTML in script? You enjoy using multiple writeOutputs to create HTML?
"I. am. correct"
You. Have. An. Opinion.
I render HTML using HTML. What do you use? In all of these frameworks that have become so popular, don't any of them separate concerns? Yes, I have an opinion. So do A LOT of other developers. And when those opinions are gelled by an entire community, they form what are called "standards."
So force yourself to do more script, Ray. You might be inspired to put less business logic in your views.
I guess the JavaScript template libraries are for people who don't like scripting. I'm not sure what to tell Jorgen. I use script 100% of the time now for my business logic. For generating dynamic views, I use tags, because it makes me more productive. My HTML isn't static. Even with business logic in the model layer, you still have to build HTML dynamically at times and tags work best for me there.
Again, see the _multiple_ JavaScript frameworks that support this. Obviously the "entire community" does not agree with you Jorgen.
I am not sure I agree with Jorgen either, considering I have worked as a federal government contractor for 8-10 years now and most of that doing CF work, and my current job is the first one I have seen any cfscript work. To say using cfscript is the only way to go would be telling all the contractors in the fed gov't they are doing great work all wrong. If you said it would be totally more efficient to use script and everyone should look into using script, then great that is a better statement...plus that is why I asked Ray to create this blog post. I hope you have some ideas about how I should help my team move to using cfscript?
thanks for everyones feedback...
dan
No Ray, the _ColdFusion community_ doesn't agree with me because the de facto standard for them is to agree with you. Like the sheep above.
"To say using cfscript is the only way to go would be telling all the contractors in the fed gov't they are doing great work all wrong."
How do I break this to you Dan... well... good luck in your career.
Wow, what a completely dick thing to say Jorgen. I tried to be respectful to you. We obviously do not agree, but I thought we were discussing this nicely. I'm truly sorry you felt the need to resort to this level of discussion.
Jorgen - First, anyone who makes absolute claims like you do is most likely suffering from cranial rectitis. Only a Sith thinks in absolutes.
How do you take your wonderful scripty logic and put it into you view? Can you post a code sample so we can better understand where you are coming from?
How is this putting 'logic' in the view?
(assume I used scripty magic to get an array of user objects and named it 'users')
<ul>
<cfoutput>
<cfloop array="#users#" index="user">
<li>#user.getName()#</li>
</cfloop>
</cfoutput>
</ul>
I see NO business logic there. None. At. All.
Sorry to not agree with you jorgen, but I asked Ray to post this so I could get some actual Help on how to train up my team on cfscript, not being told that I should use cfscript. If I did not want us to use cfscript, i would not have asked him to post it. As as for being a sheep, i think a lot of people would be offended by that comment, there are many developers out there in this and all programming communities that have their own ideas and do things differently, no matter what Ray says :)
So, if you are not going to offer me any assistance, please let others do so...
thanks
Dan
Now before you resort to name calling, just know that this conversation simply got out of hand. Truth be told, I idolize you for all your work in the community because, let's face it, it's _AWESOME_. Note the underscores.
But I've worked for NASA, JPL and contracted for several government agencies and can safely say those CF projects are the worst things I've ever looked at, and they even take nicely designed applications and bastardize them into clumps of CF crap, hence my reply to Dan.
@Phil there is a Good Parts of Javascript book. In fact, it's even called Javascript: The Good Parts. http://www.amazon.com/JavaS... (Nonreferral amazon link)
"All your work is awesome"*
*its just wrong.
Nice backhanded compliment there, Jorgen
First off - Jorgen - I think you may have a point here. I want to listen to your point. If we can keep things civil and back off a bit - then awesome. Let's discuss!
Jorgen: I've no doubt you've seen bad code. But do you honestly think it is a tag versus script problem or rather an architecture problem - perhaps one where the user did BLOT (Business Logic on Top) as opposed to MVC?
(I have more to say, but want to hear what you have to say to that.)
Maybe Jorgen has a different definition of 'business logic', hence the conviction on his part, and the confusion on ours.
Jorgen, do you see an 'business logic' in this bit of code?
<ul>
<cfoutput>
<cfloop array="#users#" index="user">
<li>#user.getName()#</li>
</cfloop>
</cfoutput>
</ul>
I can see where having the ability to use tags in business objects, controllers & views can lead to a bleeding of business logic into the views. Simple templating like handlerbars in Javascript keep you from even attempting to put logic in the view
Marlon: I agree completely. But looking at Handlebars - it supports basic conditionals - basic looping - etc. That to me is where tags work great. That's display logic, not business logic.
@Scott Stroz: I know a few people who argue that your view shouldn't reach into your user model and shouldn't have to know that there's even a getName() method on it.
I'm slowly becoming one of those types ;)
@Marlon: I would call getName part of the public API of the user object, and therefore fair game to be called by the view. Yes - you could use a Controller to generate a string of LIs and pass the string to the View, but to me, that's abstraction for abstraction sake. You could take it to the extremete and say you shouldn't use dateFormat() in a View.
@Marlon - this may be semantics, but the view isn't actually reaching into the model. The controller is reaching into the model, and putting data into the view.
I do understand the concern tho. You're exposing methods on the object. But unless there's a compelling reason to hide the getters, I think I agree with Ray. As part of the normal routine, I don't know that it's worth the extra abstraction in the controller.
... but now you've got me thinking. Dammit.
@Raymond: dateFormat() should be used in the Presenter Object :)
You're right though...it all depends on how far you want to abstract things out. I'd rather have plain ol variables sent to my views. If an API changes, I'd rather not have to go into each view to make changes either. This is especially evident with the different representations, e.g. xml, json, html....If we want to change the way a name is displayed, it would require each view be changed. If we define that in the controller or a presenter object, it's only 1 place we need to change it.
marlon - I am all about separation of view and logic, but I fail to see how you could display a list of usernames any other way - except using controllers/services to create the HTML you you, which, to me, just seems...well...in the interest of keeping it civil I won't say what it seems like.
Regardless, even if you used a controller/service method to generate the HTML, using tags to do so is not 'wrong' :D
Marlon - One could argue that even with a Presenter Object, if the 'API' changes you would have to make the changes in the same number of places - assuming of course you reuse view code whenever you can (which I happen to do - with custom tags whenever possible). :D
Scott: You'd have one presenter object with multiple views that attach to it.
Can someone explain to me how you can output _anything_ in a view without tags?
Even if you had your HTML stored in a variable, you still need, at the very least, <cfoutput> or <cfscript> to actualyl put it on the page. Unless of course we are talking about using output=true in these presenter objects (but I am going to assume that is NOT the case - because, well, that is bad...very baaaaad)
Marlon - not sure I follow.
Can you show us, in pseudo code, how that would work? A 'presenter object with multiple views that attach to it' can still mean having to change the code in the same number of places. Not sure your are saving anything by having a cfc that generates HTML.
Scott: In essence instead of your User object being passed to the view, a UserPresenter object would be passed. The UserPresenter object would have variables/methods like formatted_username which would respond back with "lastname, firstname" or user_categories which would give you a list of categories that a user belongs to (2 different objects being referenced), or even user_categories_as_select which would return an html select tag.
Your views would only refer to objects inside the presenter object. The presenter object only cares about how stuff is displayed. The model never has to worry about how it's being displayed.
Now, don't get me wrong....I don't do this all the time. I have been starting down this road. I'm really trying to decouple my views from my models all together as I go forward.
To me, that seems like abstraction for the sake of abstraction.
All you are doing is taking chunks of CF and HTML and putting them into a CFC. It also does not seem like a separation of view/model, rather it seems to me like the model is doing so of the views work.
I am not sure how the model is 'worrying' about how its being displayed in my example - its simply returning the name of the user.
I think the problem is the original example was too trivial. How do you handle a form where a user can have multiple categories assigned to them? Do you send both the user & categories to the view and construct the select list there with logic to highlight the categories they already belong to?
Also, does a formatted_name method belong in your user object? Or should it be done in the view? This is where I find Presenters to be helpful.
All abstraction is only for the sake of abstraction until that abstraction is truly needed. There are times when a cfquery on the top of the page is perfectly fine. As the app grows bigger, that query may have to be moved to a business object. Some people start by putting it in a business object to begin with. Other people would think it's "abstraction for abstractions sake"
I would likely have 'categories' as a property of user, so I could call user.getCategories() to get the categories. As for creating form for them, yes, I would need to send a list of available categories to the view and work some kind of logic to determine which ones are selected or checked in the form.
But, that is not 'business logic' so much as it is 'view logic' - two entirely different beasts.
I kind of see your point about about formattedName (sorry, I loathe _ in variable/function names - it reminds me of PHP or, worse, Oracle). However, I tend look at objects as if they are real. I would expect that if I asked a user their full name, they would be able to put their first and last name together and respond accordingly. If I was using a presenter object, I would need to ask the presenter for the user's full name, the presenter would need to ask the user for its first and last name, the user would need to tell the presenter their first and last name and then the presenter would put them together and then respond accordingly.
Presenter objects seem intriguing to me, but they seem like more of an extension of the view (or of the model) and is doing work that the model should be (or the view should be if you see the presentation object as an extension of the model). Can't seem to wrap my brain around the advantage they bring to the table.
Lastly, even using a presentation object, you still need tags to output anything you may retrieve form it - pretty much nullifying Jorgen's 'If you use tags, you are wrong' comment earlier.
Trying to chew on this a bit more:
Would the presenter object (PO) have methods you would call? Like po.getUserFullname()?
I guess the PO would need properties for all the stuff it would need to handle? In your user/category example, can I assume that the PO has a user property and a categories property (and properties for every other object it would need to display items for)?
Is there one PO per app? Or do you have different POs depending on what needs to be displayed?
You mentioned using the PO for a select box, would you do the same for every type of form field, or just ones that could be more complex?
Can you tell you really got me thinking here?
One thing that I'm not a fan of when it comes to CFScript is database queries/stored procedures. I work with humongous queries, and stored procedures that take a lot of parameters.
Also, is there even an equivalent to <cfpdfform> in CFScript? I know you can use the pdf service component for general pdf manipulation, but what about working with forms?
@Travis: A year or so ago I was converting a tag based CFC to script and about 200 lines was a massive query. I made the decision that it was ugly enough to keep that portion in tags. I just moved it to an include. Elegant? No. Practical? I thought so.
As for pdfform - no - not yet. Keep in mind that stuff like queries, mail, http, etc are built in CFML. You can look at the source of them. You can also write your own version.
Wow, I did not know this simple question to the community about what resources were out there about training up coworkers on cfscript and moving away from tags in cfc's would cause so many different comments...some totally on point, and some slightly off point, and some about farm animals :)
If others have any info about how to train my coworkers great...if not, keep up the comments, i am learning on just about every comment :)
Tacking on to what Ray said - be careful not to name any cfc you write something like mail.cfc, query.cfc, http.cfc, etc, or you will overwrite the expected behavior within cfscript. I work in a place where it WAS pretty common to bundle up all the utility email calls into one cfc called - you guessed it- mail.cfc. I started getting errors saying no method named setFrom in mail.cfc because coldfusion was not finding the "built-in" mail.cfc but the one my boss had written.
Interesting. You could get around that by removing the core custom tag folder from the CF Admin. I don't mean to delete it physically, but remove it from the list of default custom tags.
You could then add it back in via mapping and create your instances using the mapping.
Someone just needs to write a converter that lets you once-click translate an entire file or directory to or from script. Preferably from ;)
Just thought I'd jump in on this discussion and add my $.02 (probably not actually worth that, however.)
I did not take CS or MIS classes in college. While I have always been a techy computer nerd kind of person (I wrote programs in Apple Integer BASIC in the early 80's,) I was put off by the hard core, full blown programming languages, and wanted nothing to do with a career where I would spend hours wrestling with hard to read, arcane code.
My introduction to CF came as a result of my familiarity with HTML and JavaScript circa about the year 2000. Having seen and avoided the tangle of syntactical crap that was PERL, CF was absolutely "the right answer" to me. The transition was very easy as a result of the tag based syntax, and despite what the haters said, rarely was (or is) there anything I needed to that I couldn't using CF.
Fast forward to today. I am a CF application developer. Even though I write plenty of JavaScript and jQuery, I still prefer using tag based CF for most of my day-to-day CF work. (I think it is easier to read, and for other folks who follow behind me to understand.) That said, I think this debate about using tags versus CFSCRIPT is like arguing over which color hammer works the best, and is ultimately pointless and unnecessary.
Despite their lack of ability to aggressively market CF, Adobe has gone to great lengths to make the product incredibly flexible and usable by almost anyone from ANY programming background (from literally NO programming experience whatsoever, to uber geeks that can do trigonometric math in octal in their head.)
The introduction of CFSCRIPT, CFCs, ORM,, etc., are all wonderful ways to bring in folks who ALREADY think and program that way (based on whatever "best practice" is the flavor of the month,) and can help expand the horizons of folks (like me) whose experience has been pretty much limited to HTML, JS, jQuery, CSS, XML, and CF.
The many different ways you can program in CF are not inherently "right" or "wrong". To be Zen, they simply "are." Granted there is good code and bad code, but let's try to keep our eye on the bigger picture: CF is a fantastic tool, and the fact that it is so incredibly flexible is an absolute plus! We should be collectively celebrating that and spreading the word, and not getting preachy, pedantic or self-righteous about any one way to use it over another.
We had almost the same problem here. Millions of tag-based code and a new small project I developed 100% in script to learn and understand it. Awesome. Except for queries (script-based querying in CF is somewhat weird) the rest of the code was easy to learn, type, debug and visualize. After breaking this first barrier, the entire team started to love scripting. Now we do maintenance in tags, but everything that's new we're using scripts because we believe its the future, its similar to other languages we use like JS and its better. But we only started to use it when we've found good color-coding in Eclipse.
@Jim, you can avoid those collisions if you specify the full component path for the built in script objects, so "new com.adobe.coldfusion.http();" instead of "new http();". A bit more to type, and less portable, but it works and makes sure it doesn't find another http.cfc.
@Sean: How would it be less portable? I've yet to see folks actually move those resources.
I mean you can't use that same construct on Railo, since they don't exist using that same package path.
Than that's a bug with Railo. You won't get much sympathy from me there. ;)