cfwheels - pragmatic, beautiful code
DESCRIPTION
This is my presentation about CFWheels at CFObjective ANZ, November 2010, Melbourne, Australia. ColdFusion on Wheels (CFWheels), is an elegant framework inspired by Ruby on Rails.TRANSCRIPT
CFWheels Pragmatic, Beautiful code
Indy Nagpal Straker Software Melbourne, November 2010
A bit about me
• CTO, Straker Software, New Zealand
• Been doing CF (and Flex) for a while
• Cloud-based CF Using Railo
• In love with Ruby (the language) & Rails
– Was in love with Groovy (still am, I think)
• nagpals.com/blog
Rapid ≠ Agile
Agile
• Early, continuous delivery of software
• Welcome changing requirements
• Deliver working software frequently
• Working software = progress
• Technical excellence and good design
• Simplicity is essential – work not done
“There comes a time in the history of every project when it becomes
necessary to shoot the engineers and begin production.”
Need
• Quickly build and deploy database-driven web apps
• Rapid iterations in a testable fashion
• Easy for multiple developers to understand
• Working app is more important than configuring the app
Search…
• Tried lots of frameworks/methodologies
• Ruby on Rails addressed most issues
• Learn another language and framework
• Defeats the whole purpose
• Enter, CFWheels…
What is CFWheels
• Framework inspired by Ruby on Rails
• Simple organization system
• Suited for typical, database-driven web applications
• A couple of years’ old – fairly mature
Convention over configuration
• Possibly the single most important thing
• Mostly convention, minor configuration
• Easy to
– turn on
– tune in
– drop out
Directory structure • webroot – models– controllers– views
– images– javascripts– stylesheets
– plugins
– tests– events– config
Intuitive Code Structure • View
– Responsible for display and user interaction – Receive data from controller
• Controller – Process requests from view – Get/process data from model – Make data available to the view
• Model – Interacts with the database layer – Responsible for validation – Other methods to process/message data
Convention - URLs
• URLs mapped to controllers/models/views
http://blog/posts/edit/1Controller: Posts
Model: Post
Action: Edit
Key: 1
View – http://blog/posts/ /views/posts/index.cfm
<cfparam name="posts"><ul><cfoutput query="posts"><li> #linkTo( text = "#posts.title#", action= "edit", key = post.id, title = "Edit #posts.name#" )#</li>
</cfoutput></ul>
Controller – http://blog/posts/ /controllers/Posts.cfc
<cfcomponent extends="Controller"><cfscript>function index(){ posts = model("post").findAll(order="createdAt")}
</cfscript></cfcomponent
Model – http://blog/posts/ /models/Post.cfc
<cfcomponent extends="Model"><cfscript>function init(){ belongsTo("author") hasMany("comments") validatesLengthOf( properties = "title", minimum = 10, maximum = 255)}
</cfscript></cfcomponent>
Convention – Files & Database
• Place in appropriate folders – MVC
• Plural database names, singular model names
– DB Table: posts– Model: Post.cfc
• Database fields: id, createdat, updatedat
Built-in ORM
• Simple and elegant
• All major databases supported
• Almost no setup required – baked in
• CRUD instantly available via models/plugin
• Finding data using “finders” – findOne(), findAll(), findByKey()…
Associations models/Post.cfc
<cfcomponent extends="Model"> <cfscript>
function init(){ belongsTo("author") }
</cfscript> </cfcomponent>
models/Author.cfc
<cfcomponent extends="Model"> <cfscript>
function init(){ hasMany("posts") }
</cfscript> </cfcomponent>
<cfscript>posts = model("post").findAll(include="author")author = model("author").findOneByKey(key=params.key,include="posts")
</cfscript>
Dynamic Finders
• Dynamic finders are magical model("user").findOne(where="username='bob' and password='pass'")
rewritten as
model("user").findOneByUsernameAndPassword("bob,pass”)
URLs and Routing
• Beautiful URLs – http://blog/a-good-url
• Powerful routing mechanism <cfset addRoute( name = "showPost",
pattern = "/[key]”, controller = "Posts", action = "show")>
• Can be turned REST-full
Multiple response formats • http://blog/posts
• http://blog/posts.xml
• http://blog/posts.json
• http://blog/posts.csv
• http://blog/posts.pdf
Common tasks done
• Adding timestamps
• Flashing messages
• Pagination
• Sending multi-part emails
• Redirecting users
Lots of helper functions • Views
selectBox()
linkTo()
timeAgoInWords()paginationLinks()
titleize()pluralize()
• Model validatePresenceOf()
findAll()
findOneByKey()afterSave()
• Controller flash()
isGet()sendMail()
Plugins
• Neat architecture to add/override functionality
• Extremely useful
– Scaffold –generate CRUD application
– DBMigrate – Add/edit database structure
– Remote Form Helpers – Ajax with forms
– Localizer – Localizing an application
Baked in testing
• Ships with RocketUnit <cfcomponent extends="tests.Test"><cfscript>
function test_1_get_timezones(){ qTimezone = model("Timezone").getTimezones() assert("isQuery(qTimezone) ") assert("qTimezone.recordcount eq 56")}
</cfscript></cfcomponent>
Environments
• Different setup for applications based on stages of development
– Design, Development, Production, Testing, Maintenance
• Differ in terms of caching, error-handling
• Switch environments via config/url
Docs/Support
• Very helpful docs at cfwheels.org
• Active and supportive mailing list
• Quite a few screencasts
• Direct knowledge transfer from Ruby on Rails books/docs (e.g., Head First Rails)
• Bunch of blogs
IDE Support
• Eclipse, CFBuilder
– Syntax Dictionary
• Textmate
– Bundle
• Coda
– Lacking, but works by adding Clips
Beauty
• Simple code organization and flow
• Easy to understand code – eyeballing code
• Common tasks done with minimal code
• Pretty URLs
• Almost zero configuration, with power to configure as much as needed
Pragmatic
• Focus on simple code that solves issues
• Trades pure OO for simplicity and structure
• Easy to not use the framework if needed
• Common web application problems already solved – why reinvent the wheel(s)!
Wrap up
• Evaluate if you need a ‘framework’
• Learn URL rewrites (Apache, IIS)
• Dabble with Ruby on Rails
• cfscript = succinct code
• Worth trying out just to see how problems can be solved in a different manner