|
YOUR FEEDBACK Did you read today's front page stories & breaking news?
SYS-CON.TV SYS-CON.TV WEBCASTS |
TOP COLDFUSION LINKS Frameworks Features Without Fixtures
onTap framework can save huge amounts of development time
By: Isaac Dealey
Apr. 13, 2004 12:00 AM
If you've ever worked on a licensed application you know how prepackaged applications rarely meet enough of the client's needs to be implemented without modification. Whether the application is intended for your own use or someone else's, there's usually a feature or two missing, keeping the tools from being exactly what you need. Most scripted applications can't even be configured without manually editing an existing configuration file. Although intolerable to desktop customers, this has become the de facto standard with Web applications. So you trudge along, laboriously configuring the application and making your modifications by manually editing another developer's original templates. Several months pass, and the original software author publishes a new version. You're excited to see new features that will make your life easier, and you're even entitled to a free upgrade as a part of your licensing. You want to upgrade, and you would... if only you had the time. In the intervening months you've edited quite a few of the author's original templates and as a result, upgrading to the latest release will involve days or weeks of tedious examination to determine what you've changed, how you've changed it, and how to ensure that your changes will integrate with the new version without causing problems. Although this may seem unavoidable, there is another way. In August 2003 I published a new open source ColdFusion project called the onTap framework. Rather than belabor the merits of frameworks, I'm going to show you what makes the onTap framework unique. Specifically, I'm going to show you how to use the onTap framework to save hours, weeks, even months of development time by automating the integration of separate, often unrelated applications and components. To use a publishing analogy, most scripted applications are like hardback books: if you want to add pages you have to strip the binding and rebind the book. That's a lot of work. In this article I show you how to design applications that resemble three-ring binders, wherein adding pages in the middle is the assumed norm. A Brief Demonstration /_components/cfdj/_htmlhead/ In the cfdj directory, add a template named index.cfm with only the following line of code: <cfinclude template="#request.tapi.process()#"> Don't worry if this looks strange; it will all make sense very shortly. Open a browser and navigate to http://[your domain]/ontap/cfdj/, where you just placed the index template. You'll see a generic message from the framework indicating that it couldn't find any content for the index page in this directory and providing a link to the framework documentation. Now, to create content for this page we're going to create two new templates. The first template, /_components/cfdj/_local/100_defaults.cfm, will contain the code shown in Listing 1. What these lines do is to create several ColdFusion native structure variables that represent certain HTML elements on a Web page. What they haven't done is to display any html content. To display the content, create another template called /_components/cfdj/index/_process.cfm. In this template add only the following two lines of code: <cfoutput>#htlib.show(view.main)#</cfoutput> Refresh the browser and you'll see that now the page displays a menu and a few lines of text. Below the text you'll also see a ColdFusion dump of your content for debugging. You'll notice how all the content is sorted into structures and arrays. At first glance this may seem rather complicated. However, I'll show you how the onTap framework's architecture and the HTML library make using these structures easy and alleviate the problems with customization I mentioned earlier. Unfortunately, the menu isn't very pretty (all the links run together) and the title text for the magazine doesn't look any different from the content. Let's fix that. Create a style sheet template in /_components/cfdj/_htmlhead/100_default.css with the following code: #title { font-size: 20pt; margin: 10px; } Refresh your browser. You'll notice that while you needed to create the style template, you didn't write any HTML to apply the style sheet to your document; the framework did this for you. Here's where it starts to get sticky. Our imaginary client sees this draft and decides they like how it's looking, but they don't want to display the home link on the home page. So now you need another page for testing purposes, to confirm that the menu is different on the home page. Copy the template /cfdj/index.cfm to /cfdj/members/index.cfm and duplicate the directory /_components/cfdj/index/ to the location /_components/cfdj/members/index/. Now you can view the page at http://[your domain]/ontap/cfdj/members and you can see that it has the same content. To remove the home link from the home page, create a new template named /_components/cfdj/index/_local/100_menu.cfm and include this code: <cfset htlib.childRemove(view.menu,1)> Refresh the home page, and you'll see that the home link is gone. To ensure this meets the client's requirements, however, we have to be sure that the link remains on other pages, so refresh the members page as well. If the home link is still visible on the members page, congratulations! You've just made a discrete and complex modification to a page with one line of code in a completely separate template. The members link appears on the members page, however, and since the client didn't want the home link on the home page, they probably don't want the members link on the members page either. Add another template in /_components/cfdj/members/_local/100_display.cfm with the following code: <cfset htlib.childRemove(view.menu,2)> Refresh the members page. You'll notice that in addition to removing the members link you've also changed the title of this page. Looking at the ColdFusion dump below the content, you'll notice that the function htlib.replace() takes the outermost structure as its first argument, followed by the string to replace and the new string. In this case I know the string "CF Dev Journal" appears only once in the content, although if I wanted to be more efficient and precise, I could instead pass only the title object to the first argument of the htlib.replace() function. Establishing a Brand In most cases a client with such a request would be told either that it's simply not possible or that the change will require a lot of time and money. I'm going to show you how to make this change quickly and discretely, using all the same code as the rest of the clients, without editing any existing templates and without affecting any of the other ASP clients. Using much the same architecture, which allows individual pages to be discretely modified, the framework allows sites to be branded by domain. A branded domain may display different style sheets, images, and even content for each client. The framework maps each domain to a directory, where it looks to find custom code for branding. Custom templates for the www.widgets.com domain, for instance, would be stored in /_components/_brand/www_widgets_com. If your domain name includes a hyphen it will also be converted to an underscore in addition to the dots. Using this convention, create a new template in /_components/_brand/[your domain]/cfdj/_local/100_menu.cfm with the following code: <cfscript> Refresh the page again. You'll see now that the menu is almost magically transported to the right side of the page. Again, to ensure the clients' requirements are met, you need to view the same page from a different domain (or IP address). Declare this project a success if the menu remains centered across the top for all other domains. Especially as the size of a site or application grows, the ability to make wide-sweeping, yet discrete changes to the content and layout in this manner can save your sanity - as well as allow you to accommodate a lot of client requests that otherwise would not be reasonable. If your clients are anything like mine, I recommend becoming as familiar as possible with the Cascading Style Sheets (CSS) standard as well. Using style sheets for as much of the display as possible will not only reduce the load on the ColdFusion Server but also greatly reduce the amount of code required to achieve clients' desired look and feel. Under the Hood The onTap framework's principles were generated from the simple idea that most of us weren't getting as much out of the cfinclude tag as we could. Usually it's just a static relative path to a template containing static HTML for a header or a footer template for layout. Though this approach is a bit better than having all static templates, it doesn't take advantage of all the power a dynamic content server like ColdFusion has to offer. Knowing that variables can be used in the template attribute of a cfinclude tag, I then connected this idea of dynamic inclusion of templates with the query returned from the cfdirectory tag's list action. If you could get a list of all the templates in a given directory, then you could include all those templates without necessarily worrying what might be in the directory. There would have to be a pattern for determining which files should be included and in what order. Obviously, you don't want to attempt to include a PDF document in the middle of a ColdFusion page if someone happened to put one in the same directory, so by default the onTap framework includes only files beginning with two or more digits and an underscore and ending with the .cfm extension. The files are included in alphabetic order so that the number at the beginning of the file works like an old-fashioned line number. Two additional breakthroughs turned this quirky idea into a real framework. First is the idea that any given page request can be divided into several logical stages such as beginning, middle, and end. The onTap framework divides each request into seven stages, including _application, _htmlhead, _local, _layout (header), [content], _layout (footer), and _onrequestend. The templates for any given stage are placed in a separate subdirectory, and the names of the directories begin with an underscore to separate framework-stage directories from other subdirectories. The remaining breakthrough involved the realization that most developers already handle most of the work of structuring an application. They do this by creating logical directory structures. For example, a site containing a members directory logically separates content available only to members from content available to the general public (see Figure 1). A members/forum directory then separates forum content from other members-only content. Each subdirectory is a logical child of its parent directories, so with this in mind the onTap framework is designed to use your existing site or application structure instead of forcing you into a new set of conventions regarding site structure (see Figure 2). This is accomplished by placing the set of related stage directories within the directories for your logical site or application areas. So, for instance, if your members forum needs its own style sheet, that template would be located in the directory /members/forum/_htmlhead. Because it's theoretically possible for a malicious visitor to execute an individual template within a directory, there must be a way to protect your code. For instance, if any visitor can execute the template /members/forum/post/100_db_insert.cfm without first executing /members/_htmlhead/100_authenticateuser.cfm, a malicious user might be able to insert content into your forum without signing in or even registering as a member. This is the reason for the _components directory. All of your site's or application's publicly accessible templates and directories are placed in the application root directory, and all of your code is placed in mirrored templates and directories in the _components directory. Code in the _components directory is protected by an Application.cfm template that prevents any template in these directories from being accessed directly within a browser. Templates in the _components directory are then accessed by the include tag: <cfinclude template="#request.tapi.process()#"> The function request.tapi.process() returns a relative path to a custom tag that handles all the particulars of determining which content is included and in what order (with the exception of _application and _onrequestend stage code, which are executed in the application's corresponding Application.cfm or OnRequestEnd.cfm template). For example, when visiting the page http://[your domain]/ontap/members/forum/index.cfm, the onTap framework will automatically include all the serialized templates in these _component subdirectories in the order shown in Listing 2. Branded subdirectories for a specific domain are interleaved with these directories, so to take the _application stage, for example, if you've added templates and directories to brand this stage, they will execute in the order shown in Listing 3. This structure provides many advantages over writing contiguous ColdFusion base templates. When using a code versioning system you're much less likely to experience conflicts or bottlenecks involving the checking in or checking out of templates because each template is so small and controls a discrete portion of the application. By using the branding framework it's possible to simultaneously develop and test multiple displays or multiple approaches to the same technical problem using a consolidated code base (no more copy-and-paste development). Most important, if you develop large or "enterprise" applications, other developers or other companies can develop extensions for your applications that can be installed without editing any of your templates. Currently a Plugin Manager module and a Login module are available for download from the onTap framework site. By the time this article is published I hope to see an additional security module on the site. These are the beginnings of a collection of common tools that can be easily combined in new projects without the need for any programming to install and configure them. Final Thoughts For more information about the onTap framework, visit the Web site at www.turnkey.to/ontap and join the onTap framework mailing list at www.houseoffusion.com/cf_lists. CFDJ LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||