380 likes | 532 Views
Prelude to Fusebox. The Basics: <cfinclude> <cfmodule> <cfswitch> - <cfcase> <cfapplication> Variable scopes: session/client/application/request/attributes/caller Custom Tags URLToken. Fusebox Changes The World!. How lazy coders make big bucks By Nat Papovich
E N D
Prelude to Fusebox The Basics: • <cfinclude> • <cfmodule> • <cfswitch> - <cfcase> • <cfapplication> • Variable scopes: session/client/application/request/attributes/caller • Custom Tags • URLToken
Fusebox Changes The World! How lazy coders make big bucks By Nat Papovich With help from Hal Helms and Steve Nelson
The situation with web application development these days... • Skilled craftspeople are needed to create the product. • Each product is a unique work of its creator. • There is a shortage of skilled workers. • There is a wide variation in the quality of finished goods. • Maintenance of our products require the user to go back to the creator or to employ the skills of a highly-paid master craftsperson. • There is no ability to interchange parts from one product to another. • There is very limited division of labor. • There is no efficiency of scale: it takes 10 times as long to produce 10 products.
A CF Programmer’s Dream World... Imagine if…. • You could work in a team of developers and have all the code look like it was written by single person. • You could understand the structure of your co-workers code in 5 minutes, without asking questions. • You could concentrate on solving the problem instead of thinking about how to write the application. Nice, huh?
Why use a Structured Architecture? • File based applications get messy. A structured architecture helps to clean this up. • Multiple person development is more easily facilitated – without stepping on toes. • If your structure is clearly defined, your application documents itself. • You only focus on the client’s problem instead of the application’s architecture.
What is Fusebox? Fusebox is: • A structured application architecture for building web applications, primarily using ColdFusion. • A methodology of coding so you can use others’ labors without feeling guilty - as if you ever did. • An open-source project, created by the ColdFusion community for the ColdFusion community. • Quick to learn. Adopt as much or as little as you want. • Flexible and extensible. There is no Fusebox Gestapo to make sure you followed all the rules. • Free.
Before You Write Any Code • Talk to the client about general ideas, business requirements and specifications. • With the client on-hand, write down these ideas into a loose specification. Better yet, have him/her do it. • Create a tight specification from the loose specification. Figure out all the sections of the application and all the actions required to do everything the client wants the application to do. • Repeat this process until every action in the application is understood by everyone involved. • Write a Fusedoc for the application from these use-case scenarios.
Create the Directory Structures • Use the tight specification to figure out all the sections of the application. • Each section is given its own directory; these sections are known as “Circuit Applications”. • A circuit application is a section of the overall home application. • Examples: • www.ebags.com/search • www.autobytel.com/customerlogin • www.ecommerce.com/cart
Create the Index.cfm Files • Every directory (circuit application) has one index.cfm file. • Index.cfm controls all the Fuseactions of that circuit application. • It is the Fusebox. • All links and form submissions go to the index.cfm. • It is a single <CFSWITCH> statement with multiple <CFCASE> statements. • Each <CFCASE> is a different Fuseaction.
Fusebox Anatomy: the Fusebox (index.cfm) <!--index.cfm--> <cf_formURL2attributes> <cfinclude template=“app_globals.cfm”> <cfparam name=“fuseaction” Default=“login”> <cfswitch expression=“#attributes.fuseaction#”> <cfcase value=“login”> <cf_do_logic> <cfinclude template=“dsp_UserLogin.cfm”> </cfcase> .... </cfswitch> Fusebox
The Fusebox Architecture http://index.cfm?fuseaction=login This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. dsp_UserLogin.cfm Fusebox
The Fusebox Architecture http://index.cfm?fuseaction=login This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. http://index.cfm?fuseaction=validateUser Fusebox
Create the Fuseactions • A Fuseaction is made up of one or more .cfm files. • Determine what types of files (display/action/query) are needed to create each Fuseaction. • Create a CFCASE statement for each Fuseaction and CFINCLUDE each necessary file.
Conventions, Extensions, and Rules • File Naming Conventions • Fusedocs • <cf_formurl2attributes>
File Naming Convention (Fuses) • app_globals.cfm - Global variables, one per Home application • app_locals.cfm - Local variables, one per Circuit application • dsp_filename.cfm - Display files • act_filename.cfm - Action files • qry_filename.cfm - Query files
Fusedoc: A Documentation Standard • A Fusedoc outlines responsibilities, customizations, and expectations. • A Fusedoc is a collection of Fusecards which are granular to the actions and steps of the application. • A Fusecard contains the following elements: • Fusename • Responsibilities (hopefully non-technical, in plain English) • Author / Coder • Variables list (incoming, outgoing, and persistent)
Fusedoc Legend • --> explicitly passed incoming parameter • <-- explicitly passed outgoing parameter • <-> pass-thru parameter (unchanged) • ++> existing persistent parameter • (session, client, etc.) • <++ created persistent parameter • +++ included file • [parameter] indicates optional • Examples: • --> CurrentUser: a WDDX STRUCTURE • <-- [badLogin]: a STRING • <++ Session.ColorChoice: a STRING (Red|Blue) • <-> UserID: an INTEGER • +++ myGlobals.cfm
Sample Fusecard / Fusestub • <!-- dsp_UserLogin.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC • || Responsibilities: I make sure that the UserName and Password match what’s • in the TableName table. If so, I let the person pass with a parameter of • UserAuth set to “yes”. If not, I send the user back to the Fusebox with • BadLogin set to “yes”. • || • FuseStub: hal.helms@TeamAllaire.com • Approved: hal.helms@TeamAllaire.com • Edits: • || <-- [BadLogin]: variable sent if user tried to login unsuccessfully • <-- [UserAuth]: on success, a STRING value set to “yes” • --> UserName: a STRING indicating the user’s name --> Password: a STRING indicating the user’s password --> DSN: a STRING of the ODBC datasource name to use to verify --> TableName: a STRING of the table name to use to verify • END FUSEDOC--->
What’s in a Fuse? • Fusedoc • [HTML] • Code • The perfect fuse is small and has a very narrow focus.
Create the Necessary Files (Fuses) • All links and forms in the display files should point to one of the index.cfm files in the application, never to the specific dsp or act files. • All links and forms must specify which Fuseaction they point to. • A hint now, for advanced Fusebox techniques: Use the “attributes” scope instead of form/url scope. This allows you to call the index.cfm file as a custom tag.
Fusebox Anatomy: a fuse • <!-- dsp_UserLogin.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC – blah blah blah (Hal likes his Fusedocs) • END FUSEDOC---> • <form action=“index.cfm” method=“post”> • <input type=“hidden” name=“fuseaction” • value=“FormAction1”> • Name: <input type=“text” name=“userName”><br> • Password:<input type=“password” name=“password”><br> • <input type = “submit” value=“OK”> • </form> I am a fuse… A Fuse
Putting it all Together • One home application is made up of many smaller circuit applications. • One circuit application is made up of a directory of files. • Each circuit must contain an app_locals.cfm and index.cfm file plus other display/action/query files as Fuses. • One index.cfm file is made up of one or more Fuseactions. • One Fuseaction includes one or more display/action/query files plus any necessary CFML logic.
Extending Fusebox This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. UserManager ? This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. ? ? ShoppingCart This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. Fusebox ? CompanyInfo This is Meant to Be Just text That isn’t Clear. I hope It works the Way I want It to. Circuits
Display Fuses showCartSummary showCatalog showItem Action Fuses addItemToCart removeItemFromCart clearCart Building A Fusebox Shopping Cart
The Shopping Cart Array • Implement shopping cart as 2d array
The Cart Summary page • <!-- dsp_CartSummary.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC • || Responsibilities: I show the contents of the user’s • shopping Cart. • || • Edits: • || • ++> session.shoppingCart: a 2D ARRAY with columns • of itemID, quantity, description, price • <-- [itemID]: a PK from Items table • END FUSEDOC--->
The Catalog page • <!-- dsp_Catalog.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC • || Responsibilities: I show the contents of the Items table • to the customer, letting them examine an item or buy it. • || • Edits: • || • --> request.DSN: a valid ODBC DATASOURCE • <-- [itemID]: a PK from Items table • <-- quantity: an INTEGER • END FUSEDOC--->
The Item page • <!-- dsp_Item.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC • || Responsibilities: I show the details of a particular • item to the customer hoping they’ll buy it. • || • Edits: • || • --> request.DSN: a valid ODBC DATASOURCE • --> itemID: a valid PK from Items table • <-- [itemID]: a PK from Items table • <-- [quantity]: an INTEGER • END FUSEDOC--->
Adding an item to the cart • <!-- act_addItem.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC • || Responsibilities: I add an item to the cart. If I • already have one of these items in my cart, I’ll just • increment the value. • || • Edits: • || • --> itemID: a valid PK from Items table • --> quantity: an INTEGER • --> request.dsn: a valid ODBC DATASOURCE • ++> session.shoppingCart: a 2D ARRAY with columns • of itemID, quantity, description, price • END FUSEDOC--->
Removing an item from cart • <!-- act_removeItem.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC • || Responsibilities: I remove an item from the cart. If I • have more than one of these items in my cart, I will just • decrement the value. • || • Edits: • || • --> itemID: a valid PK from Items table • ++> session.shoppingCart: a 2D ARRAY with columns • of itemID, quantity, description, price • END FUSEDOC--->
Clearing the cart • <!-- act_clearCart.cfm • Author: hal.helms@TeamAllaire.com --> • <!---FUSEDOC • || Responsibilities: I remove all items from the cart • || • Edits: • || • ++> session.shoppingCart: a 2D ARRAY with columns • of itemID, quantity, description, price • END FUSEDOC--->
The Fusebox – index.cfm <!--index.cfm--> <cfinclude template=“app_locals.cfm”> <cfswitch expression=“#attributes.fuseaction#”> <cfcase value=“main”> <cfinclude template=“qry_GetShoppingCart.cfm”> <cfset UserShoppingCart=session.UserShoppingCart> <cflocation url=“index.cfm?fuseaction=Catalog”> </cfcase> <cfcase value=“addItem”> <cfinclude template=“act_AddItem.cfm”> <cflocation url=“index.cfm?fuseaction=cartSummary.cfm” </cfcase> <cfcase value=“ClearCart”> <cfinclude template=“act_ClearCart.cfm”> <cflocation=“index.cfm?fuseaction=Catalogue”> </cfcase> </cfswitch>
App_Locals.cfm <!—app_locals.cfm--> <cfinclude template=“app_globals.cfm”> <cfparam name=“fuseaction” default=“main”> <cfif not IsDefined(“application.statelist”)> <cfset application.statelist=“AK,AL,AR,(etc,etc)”> </cfif> <cfparam name=“session.UserAuth” default=“no”> <cfif not session.UserAuth> <cflocation url=“../index.cfm?fuseaction=login”> </cfif>
App_Globals.cfm <!—app_globals.cfm--> <cf_formurl2attribues> <cfparam name=“fuseaction” default=“main”> <cfapplication Name=“NatsFuseboxApp" SessionManagement="Yes">
Congratulations! That’s all there is to Fusebox. Not too scary, eh?
Current Enhancements to Vanilla Fusebox • <cf_bodycontent> • Application.cfm <cfif ListLast(GetTemplatePath(),'\') is not “index.cfm”> <cflocation url="/index.cfm?fuseaction=logoff2"> </cfif> • Return fuseactions • Exploded Benchmarking for 4.01 HKEY_LOCAL_MACHINE\SOFTWARE\Allaire\ColdFusion\CurrentVersion\Debug String Value: WriteExplodedBenchmarkingInfo=1
Conclusion: Why use Fusebox • Fusebox is (most likely) very similar to how you may already build an application, thus it will be easy to learn. • It is a well thought out process, and will continue to be improved by the CF community. • It’ll save you time, which will save you money. • Cut-n-paste your way into completed applications. (No, really. I’m serious!) • Most importantly it will prevent hair loss.
Fusebox Resources • http://www.fusebox.org • Somewhat dated white paper • http://www.houseoffusion.com • Fusebox mailing list • http://www.teamAllaire.com/hal/ • Fusebox primers • http://home.san.rr.com/natp/fuseboxnframes.zip • Source code for using Fusebox and frames happily