Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud.
We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
If reusability is so desirable, why is it so difficult?
Everybody wants reusability, but nobody does it well, it seems. And that's frustrating. We know as coders that we end up writing software that's virtually identical over and over again. So why can't/don't we simply reuse what we rewrote? It's not for lack of effort, certainly. One of the great attractions to object-oriented development methodologies is their promise of creating reusable code. But it turns out that there's nothing about OO that automatically produces reusable software. I think it's time to ask "why not?"
It seems one major problem is that while different applications share functions that are very similar, they are seldom exact duplicates of each other. And that's where are our trials begin. Code isn't usually made to easily be massaged into a different shape. More often, even the simplest code changes introduce bugs. And those bug fixes introduce more bugs—it's no wonder that many coders' least favorite task is trying to work with someone else's code.
But does this need to be? Look at the electronics industry: the great majority of electronic components are entirely generic. The same transistor is used in a great variety of electronic gizmos. There aren't "radio transistors" that are different from "CD player transistors". Somehow, they've worked the problem out—and how they worked it out might give us some important clues about how to proceed.
First, most electronic devices are single-use devices. A CD-player does just that—play CDs. If you want to hear Howard Stern, you'll need to use another single-use device: the radio. In contrast, most software applications are multi-use devices. In fact, most software applications are massively complex devices. We know something about dealing with complex systems, thanks to a new branch of science that deals with such things. Its apt name, "chaos theory", indicates the difficulty in dealing with such systems. An important step in achieving reusability is not to underestimate the scope of the problem.
Second, most reusability within electronic devices occurs not at the level of specified application functionality ("play a CD") but at the much lower level of components. These components have two features: they have extremely limited functionality and they have a clearly defined interface—that is, a way to interact with them.
If we take our cue from these devices, then we can begin to see that a goal of reusability at the macroscopic level of application functionality may be misguided. Instead, we may want to look at the multi-use devices known as software applications and factor out the common low-level components. One of the great successes of this approach is the category of software code called "functions" which are nothing more than low-level reusable components. The challenge is how to extend this approach to the larger-scale problems we encounter when writing applications.
One approach is known as "application severability"—the ability to cut a complex application into small, discrete components. If this can be done, an application architecture can be developed prior to coding that identifies common components. Part of creating the architecture for an application involves consciously looking to reuse items from a repository of previously built and tested components.
A component interface provides the system designer with the necessary information on how to communicate with it. It does so by specifying the requests it understands and the information it needs (if any) to fulfill these requests. This is the idea behind object-oriented methodologies. And it is the idea behind a different methodology developed specifically for ColdFusion application called Fusebox (www.fusebox.org) that I described in the last issue of CF Advisor.
How does Fusebox promote reusability? One of the notable elements of Fusebox is the insistence that all action be handled through a central file called a fusebox. This fusebox is passed a single request called a fuseaction. The effect of this architecture is to create a single "application object" (the fusebox) that has a well-defined interface (the fuseactions). In order to fulfill the fuseaction, the fusebox calls on low-level components called fuses that are discrete in function and small in scope.
Fuses define the variables they require to fulfill their functions and set about their work. The internal workings of the fuse should not be of concern to the system designer. Fuses do their job and then, in compliance with the Fusebox specification, return to the fusebox.
But, of course, things are seldom so simple as we would wish them to be. In fact, even fairly simple fuses may find that there are several different conditions under which they return to the fusebox. For example, a fuse called "validateUser", with a job of validating user logins, has at least two conditions: failed validation and successful validation. Our Fusebox specification tells us that the fuse should return to the fusebox, but should the fusebox next show a user menu or ask the user to log in again? For this decision, the fusebox needs to know which of the two conditions was in effect when the fuse returned.
One way to handle this is to send a name/value pair back to the fusebox—something like "validated=yes". This certainly works, but when extended throughout an application it tends to create code that is messy and difficult to read. Code that is difficult to read is almost impossible to maintain. And while reusability may well be the Holy Grail of programming, maintainability may be even more important.
I suggest another approach that I find more in keeping with the programming principle of encapsulating functionality within a black box. I prefer to have each fuse define its own "exit states"—those conditions under which the fuse may return to the fusebox. These exit states then become part of the interface specification, so that a system designer that wishes to reuse a "validateUser" fuse knows that s/he must provide "return fuseactions" (or RFAs) for both "successfulValidation" and "failedValidation". When the fuse returns to the fusebox, it sends with it the appropriate RFA as a fuseaction. This is quite simple in practice—and practice is just what I recommend we do to make this more clear.
What if you were to be asked to write a small program that would allow the editors at CF Advisor to see their American subscribers that lived in a certain state? Obviously, we wouldn't want to write 50 separate programs, each handling a single state. It would make more sense to write a single fuse that would accept a state abbreviation as a parameter and would then use this to generate an SQL statement and display that result.
You might begin by defining the name and the format of the data to be passed in—something like "stateCode: a valid US state abbreviation". Using the concept of return fuseactions, you might also specify something like "membersFound" and "membersNotFound". This would tell any other users that your fuse, "getStateMembers", requires a return fuseaction for each exit state. We know that your fuse must return to the fusebox—and when it does, it will return the appropriate fuseaction corresponding to its exit state.
Here's what our fuse might look like: (If you're unfamiliar with reading Fusedoc headers, you can get more information at www.TeamAllaire.com/hal)
<!-- getStateMembers -->
<!--- BEGIN FUSEDOC
Responsibilities I query the Members table to find out all the members who live in the state passed to me as "stateCode". If my query returns one or more user, I'll display them and return to the fusebox with an exit state of "membersFound". Otherwise, I return to the fusebox with an exit state of "membersNotFound".
--> stateCode: a valid state abbreviation as a STRING
--> DSN: a registered DATASOURCE
--> RFA.membersFound: a FUSEACTION to return to the
fusebox if members are found
--> RFA.membersNotFound: a FUSEACTION to return to the
fusebox if members are NOT found
<-- [noMembersFound]: a STRING set to "yes" if no members
are found
END FUSEDOC --->
<!--- I've got to get the members who belong to the
stateCode state. --->
<cfquery name = "getMembers" datasource
="#attributes.DSN#">
SELECT
memberID, memberName, status
FROM
Members
WHERE
memberState = ‘#attributes.stateCode#'
</cfquery>
<--- Now, if I got some members, I'll display them and
return to the fusebox as "membersFound"... --->
<cfif getMembers.recordcount>
<table border=0>
<tr>
<td>Name</td>
<td>Member Status</td>
</tr>
<cfoutput query="getMembers">
<tr>
<td>#memberName#</td>
<td>#status#</td>
</tr>
</cfoutput>
</table>
<cflocation url = "index.cfm?fuseaction=#attributes.RFA.membersFound#">
<!--- ... otherwise, I'll just return to the fusebox as
"membersNotFound". --->
<cfelse>
<cflocation url = "index.cfm?fuseaction=#attributes.RFA.membersNotFound#">
</cfif>
This arrangement allows us to reuse the fuse without ever changing the fuse code. All we need to do is change the RFAs—and these are declared in the fusebox itself. Remember that fuseboxes are made to handle a single request at a time, called a fuseaction. The bulk of a fusebox is a large CFSWITCH/CFCASE statement that interprets the value of the fuseaction sent to it and shuttles the action off to various fuses as needed. We're concerned with the case where the fuseaction calls our "getStateMembers" fuse.
The use of return fuseactions thus lets us reuse our component-fuses without ever opening up the fuses themselves while providing us with a single point (the fusebox) from which we can gain a vantage point on our entire application's logic.
About Hal Helms Hal Helms is a well-known speaker/writer/strategist on software development issues. He holds training sessions on Java, ColdFusion, and software development processes. He authors a popular monthly newsletter series. For more information, contact him at hal (at) halhelms.com or see his website, www.halhelms.com.
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!
Click to Add our RSS Feeds to the Service of Your Choice: