|
Comments
|
Today's Top SOA Links
BF on CF ColdFusion Components and Data Abstraction
CFCs provide basic object functionality to CF developers
By: Ben Forta
Jun. 22, 2004 12:00 AM
I've been discussing ColdFusion Components on and off since we first introduced them - which was in ColdFusion MX - and even dedicated my entire keynote time slot at our 2002 conference to CFCs, as well as covering them extensively in prior CFDJ columns. But, apparently, many users have yet to take advantage of these important application building blocks, or have failed to fully appreciate their necessity. So I am going to dedicate my next two columns to explaining the most important aspect of ColdFusion Components - data abstraction. The Separation of Presentation from Content <!--- Get employees ---> This is really simple code. You've seen code like this, and have likely written something much like it many times. It uses <CFQUERY> to retrieve an employee list from a database table, and then displays the names in an HTML list. Simple enough. So, what is wrong with this code? It is commented, uses case consistently, is indented, doesn't have extraneous # characters, and, best of all, it works! So, is there really anything wrong with it? Well, maybe not. After all, if the code works, then there's nothing wrong with it. The fact of the matter is that applications are written to do a specific job, and if that job gets done, then the application is doing exactly what it was intended to do. That's not wrong. If it works, there is no wrong per se. But having said that, there is no right either. There are lots of ways to write applications, with pros and cons to each (usually). And the code above has one big con going against it. Consider what would happen to your code if the table column names were changed to NameLast and NameFirst. Or if the table schema changed. Or of the user list was to be pulled from Active Directory instead of a database. These are not far-fetched scenarios, back ends do change all the time. And when this happens, what will happen to your code? Obviously the above SQL statement will break, and will need to be changed to reflect the new table information. That will likely be a tedious but not impossible task. You'll need to find all <CFQUERY> tags (a simple site-wide search will find those) and make the code changes. A pain, but doable. But that won't be enough. Look at the code again. The <CFOUTPUT> loop is referring to column names explicitly, and so those will break too. Now the change has gotten a bit more complicated. What if your database query was returning columns used in <CFIF> or <CFSET> statements, values used in calculations, or flags that somehow affected data presentation? Think about it. How many <CFQUERY> tags are used throughout your code? And how many columns are referred to within CFML code outside of <CFQUERY> tags? How much of your code will break when back-end changes occur? It's a scary thought, but it's an important one. The truth is that database changes should never be able to break HTML formatting, that makes no sense at all. And if table schemas do change, that should not be able to throw errors in client-generated output. Even if a database is replaced with directory services, employee lists should still be rendered the same way. I have explained this problem in detail previously (see CFDJ, Vol. 4, issue 10), so I'm not going to dwell on it here. Rather, I'll concentrate on how CFCs help overcome this issue. CFCs to the Rescue Don't let the word "object" scare you; CFCs are as easy to use as the rest of ColdFusion. They are plain text files made up of tags, and they are called (invoked, to be precise) from other .cfm pages. Here's a modified version of the previously seen code: <!--- Get employees ---> A tag named <CFINVOKE> invokes a component named emps (the actual file name would be emps.cfc, in the current directory), and calls a method (function) named list that returns a query named employees, which is used just like the query in the first example. So where is the actual <CFQUERY> tag? It is in the emps component. Basic CFC Abstraction <CFCOMPONENT> Everything in a .cfc file is enclosed within <CFCOMPONENT> and </CFCOMPONENT> tags. These define the component itself. The component contains one or more methods (functions), each defined with a set of <CFFUNCTION> and </CFFUNCTION> tags. The method contains the exact same <CFQUERY> as used before. But this time a <CFRETURN> tag returns that query to the calling page. So, in order:
The Value of Data Abstraction Let's go back to the scenario where something changed in the table layout. Perhaps the table columns LastName and FirstName are now named NameLast and NameFirst, respectively. You'd obviously need to change your SQL; there is no real way around that. Your updated .cfc code might look like this: <CFCOMPONENT> Notice that the SELECT statement contains aliases (defined using the SQL AS keyword) that rename NameLast to LastName and NameFirst to FirstName. The database changed, and so the SQL had to change accordingly. And what about the presentation code? It can stay the same, as far as it is concerned nothing changed; it'll continue to work as it did before. Even in an example as simple as this one, the benefits start to become apparent very quickly indeed. Not Just for Data Retrieval <!--- Update an employee ---> Now, to update an employee, .cfm code would simply need to invoke this new method and pass the required arguments (parameters) to it. One way to do this is by adding name=value pairs to the <CFINVOKE>, like this: <CFINVOKE COMPONENT="emps" Another option is to use <CFINVOKEARGUMENT> tags, like this: <CFINVOKE COMPONENT="emps" Either way, .cfm code need simply pass values, and not care about what the update operation does internally. It turns out that there is a right way to do things after all. Conclusion Reader Feedback: Page 1 of 1
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 |
|||||||||||||||||||||||||||