The Fusebox Model
Fusebox applications are modeled around an electrical Fusebox in a House. For example, the electrical circuit for your kitchen is separated from your bathrooms and also separated from your living room. In the end, your house has electricity, to the common family they never notices that the electricity is really separated. When little joey decides it would be funny to put a fork in the electrical socket in the kitchen and he blows out the fuse. So the power goes out in the kitchen but it doesn't go out in the living room. This is similar to a software program, when a user does something that the developer wasn't expecting them to do the program throws an error. With Fusebox we separate each application from the other application's in the home thus allowing circuits to be blown without taking out ALL the power in the home application.
There are two types of applications in a large scale Fusebox application.
Circuit Application - If you've ever written a Fusebox application before you've probably written a Circuit application. This generally consists of a single directory of files (although it doesn't have to be limited to this). A circuit application generally does a few related tasks.
Home Application - This is the overall application, it is made up many circuit applications that are tied together with an interface. The common user does not realize they are using a circuit applications they are under the impression that they are using the Home application. The entire site is made up of many many circuit applications that do various specific tasks such as searching, information, product details, purchasing etc. Although to the common user whether they are searching, or checking they are still in the home. This is similar to a real life home. Whether a person plugs a television into an outlet in the kitchen or in the living room, they still get power, because they are in their home. (assuming they paid the power bill :). It is important to realize that circuit applications may contain bugs in them.... but if they do, it is possible to remove them from the Home application without bringing the rest of the Home application down. It is also possible to go the other direction. When a new Circuit is added to the Home application it can be added without affecting the other circuit applications.
Because web sites are no longer static it is important to be able to add new features or remove old features from the site without affecting the entire site. This method of building your large scale applications will prove to be very helpful when it comes time to upgrade the application.
How to tie Circuit Applications together with the Home Application
The Home application is made up of many Circuit applications so when writing a large scale application it's important to be able to tie everything together. The Home application is nothing more than a concept it is the result of multiple circuit applications. You can think of the Home application as a directory structure on your IIS server. By putting all of your circuit applications in the same root directory that entire directory structure could make up the Home application. The root directory of your Home application will contain the app_globals.asp and/or global.asa file. This file will be included in all app_locals.asp files which are in every circuit application.
The root directory of your Home application may contain a circuit application itself. This would handle tasks that may be not fit in any of your other circuit applications.
Once you've set up your directory structure that will be able to handle multiple circuit applications. You will eventually need to link your many circuit applications together. This can be done so by using the different types of links that is Use the universal format as much as possible (i.e. point links and forms to: index.asp). There will be cases that you cannot use the universal format such as when building menus, I recommend using the absolute format (i.e. /directoryname/index.asp) in your menus. The reason for this is that it will allow you to use the same menu on multiple circuit applications while still having the links in tact.
The Display Block Concept
A concept that is incredibly useful when building large scale applications or when working with multiple developers is the "Display Blocks" Concept. The idea behind this is that a "display block" is a special "dsp_" file that can be reused in multiple places. A display block is a section of a web page, not an entire web page. A display block does not begin and end with the standard <HTML></HTML>. The reason for this is that it will be included within another display file that does contain those tags. By keeping these in their own files we are able to develop each of the blocks one at a time while also being able to reuse the blocks on other pages. The blocks themselves are self contained, if they require a Query file generally that file is included at the top of the blocks page. One thing to note about blocks are the forms and links. When display files are reused in this format, it is very important that the links be either universal URLs ("index.asp") or absolute ("/directory/index.asp"). It is important that links and form actions not be relative URLs because this limits the reusefulness of the block. By using the block concept you can minimize rewriting a display file more than once, this is powerful. A directory named "Blocks or Interface or Whatever" will be created off of the root directory of your application, this is where global display blocks will be stored. Display blocks all begin with dsp_ just like a standard display file. If you are building an ecommerce site that may have an secured administrator section, you may want to have a second blocks directory that exists within the secured section of your site.
The Queries directory
Like the blocks concept, in a large scale Fusebox application queries can also be reused. A directory named "Queries" will be created off of the root directory of your application, this is where global query files will be stored. Global query files will begin with qry_ just like standard query files. These global queries can be called anywhere in your application, allowing the best possible reuse of queries. Instead of rewriting the QUERY statement, simply include the queryfile.
The
Fuseaction
A Fusebox application begins with the user. The user wants to do some "action" or they wouldn't be using the application in the first place. The web allows us to transfers information to the server through URL, Form and cookie variables. One page (from the user's perspective) of an application could possibly do one or more different "actions". We need to send this action to the server with each user's page request we will need to pass this "action" in either Form or URL variables, because they are the only variables that are specific to each page. Cookies are distinct between browsers not page requests so Fuseactions could not be passed very easily using cookie variables.
Saying this we will need to come up with a standard variable name so that we can use that will distinguish what the user is trying to do for each request to the server. We will name this variable "Fuseaction", because it is unique and descriptive. Every page will have an associated Fuseaction. The Fuseaction will tell the application server what to do.
We now know the variable that will be passed with each page request. Since every page request to the server will pass this variable that tells the server what to do we will need to have a file within the application that is able to process what to do for each action. We will standardize on the file name "index.asp". This file will act as the manager for the application it will decide what additional files code are needed for the specifc action.
To use these two techniques point all "href" and "action" attributes of your forms and links of your application to the index.asp file and also include the fuseaction as either a form field or as a URL variable. Be sure to also note the "Fuseaction". Here's an example:
or
<form
method="post" action="index.asp">
<input
type="hidden" name="Fuseaction" value="adduser">
</form>
In the next page
we'll introduce the "Fuse" in the name Fusebox...
The
Fuse
Adding functionality to an asp page is as easy as including an asp page and giving that page the attributes it needs. Suddenly that page has the new functionality of the added Asp file.
In an electrical
fusebox it takes many fuses to make the electricity in the House functional. If
one "Fuse" is blown it doesn't mean all the electricity in a house goes out,
only electricity related to that one fuse. In a Fusebox application, it may take
many Fusebox circuit applications to make the main Home Application work. But
these smaller ASP applications can be designed separately so that if there
is a problem in one of the smaller applications it will only affect the other
applications that are related to that one smaller application. Likewise in
these smaller applications it may take many ASP files to make one small
application. In Fusebox terminology these ASP files are known as
"Fuses".
There are four different types of "Fuses" (ASP Files) in a
Fusebox application.
By splitting an application into these 4 types of files we can understand one another applications by simply glancing at the directory structure. When adding on or modifying the application in the future it will be quick and easy to determine that when you want to change the way the application looks you don't have to touch the application,action,or query all you have to work with are the Display files. This will greatly improve efficiency of coding.
There is one more file in a Fusebox application that acts as the "Box"
In the next page
will explain putting these fuses into their "box" (Index.asp)
Intorducing The Box
Now that we know what the "Fuse" in Fusebox is, now let's take a look at what the "Box" is.
A bunch of fuses in a pile don't really help anyone, but when they are all neatly tied together in a "Fusebox" they can manage the power in an entire house or a large building for that matter. To manage our Fuses we will use a file named "Index.asp". All requests for an application will go through the "index.asp" file. This file has one task, that task is: Determine what ASP code is necessary to do the "FuseAction" the user needs to do.
When dealing with large applications we recommend having an "Index.asp" file for every directory in your application. Each of these directories will consist of essentially a different application, although in reality it's just part of a larger application.
The Index.asp file
in every Fusebox application looks pretty much the same. Here is an example
<!--#include
file="app_locals.asp"-->
<!--#include
file="dsp_header.asp"-->
<%
Select Case
fuseaction
Case
"searchform"
%> <!--#include
file="dsp_searchform.asp"--><%
Case "searching"
%> <!--#include file="act_searchform.asp"-->
<!--#include file="dsp_searchresults.asp"--> <%
Case
Else
%> <!--#include file="dsp_about.asp"-->
<%
End Select%>
<!--#include file="dsp_footer.asp"-->
The segment of
code above does a couple things. The very first line says to include the file
"app_locals.asp". This file is a little different from app_globals.asp because
it contains information that is specific to this small application, not the
overall larger application.
The app_locals file has the following section of code to convert the passed fuseaction in different scopes. To a standard fuseaction variable:
<%if len(fuseaction) = 0 then
if
len(Request.Form("fuseaction")) > 0
then
fuseaction =
Request.Form("fuseaction")
else
fuseaction
= Request.QueryString("fuseaction")
end if
end if%>
The next part is the main part of the Index.asp file. It determines what files are needed for each Fuseaction of this application. This index.asp file only has two Fuseactions. The first one is "searchform" that fuseaction includes a DSP_searchform.asp file (display file) that will have a form that the user will see. This particular index.asp file will have a single input box for entering a couple keywords for searching. The next fuseaction "search results" will run the search and display the results in the dsp_searchresults.asp page.
IIS 5
If you are running IIS 5 it is important to note that
rather than using server side includes, performance will be increased by using
server.execute("dsp_header.asp") rather than server side includes. In the next
page we will layout Basic Fusebox Techniques
Technique 1: Large applications are rarely built all at
once. This is because larger applications generally take more than one person.
It is more effective to split an application into multiple sections, assigning
different sections of the large application to different people in a team (when
multiple people are involved). By using Fusebox techniques each of these
sections are essentially small applications in themselves and can be accessed
without the other small applications. Think about the Fusebox in your house.
When the Fuse is blown in your bathroom it does not affect the kitchen because
it is on a different circuit. Each of these circuit applications will most
likely require more than one file. So each of the circuit application will be
given it's own directory.
Technique 2:
There are four main types of files for building an application's Tag
Library: Application files, Action files, Display files, and Query Files.
Application
files begin with app_. There are two application files that always
have these two names
app_globals.asp
app_locals.asp
These files contain
global and local variables that are needed for an application. app_locals.asp
will always include an app_globals.asp file.
Action files
begin with act_ Action files contain ASP and may not contain HTML or any
other display to the user. Action files change data on the server side. For
example: A act_ file will insert, delete or update a record into a database, but
will never display information anything to a user.
Example Action
Files:
act_myfirstactionfile.asp
act_mysecondactionfile.asp
act_anotheractionfile.asp
Display
files begin with dsp_ Display files contain HTML and generally simple
ASP. Display files do not change data on the server side. For example: A dsp_
file will never insert a new record into a database. A dsp_ file may
select information from a database using Cold Fusion.
Example Display
files:
dsp_myfirstdisplayfile.asp
dsp_myseconddisplayfile.asp
dsp_anotherdisplayfile.asp
Query Files begin with qry_. Query files contain queries that may be reused in multiple parts of the application.
Technique 3: Now that you understand the difference
between the four main files for creating the application's tag library. A parent
file is created named: Index.asp
Index.asp controls all the the
application's methods known as "Fuseactions". Depending on the Fuseaction
the user requests will determine what tags are called from the application's tag
library. By knowing which action, and/or display files that will be called will
also determine what additional attributes will be required.
Technique 4: Attributes.Fuseaction is a
required attribute for all Fusebox applications, in other languages this is
known as a "method". This attribute will determine what the application
is supposed to do. The Index.asp will contain a Case statements to determine
what the user wants to do. Depending on the Fuseaction will determine which
files to call through Server side includes or using
server.execute("dsp_header.asp") *this is recommended if using IIS 5
.
Example index.asp:
<!--#include
file="app_locals.asp"-->
<!--#include
file="dsp_header.asp"-->
<%
Select Case
fuseaction
Case
"searchform"
%> <!--#include
file="dsp_searchform.asp"--><%
Case "searching"
%> <!--#include file="act_searchform.asp"-->
<!--#include file="dsp_searchresults.asp"--> <%
Case
Else
%> <!--#include file="dsp_about.asp"-->
<%
End Select%>
<!--#include file="dsp_footer.asp"-->
Technique 5: An application is always called through
the Index.asp file. The Index.asp file will determine what Fuseaction is
to be taken. If no Attributes.Fuseaction variable exists then the default page
will be displayed. In the app_locals.asp file a default value will be set for
attributes.fuseaction this value is set regardless of whether it is passed by a
form or a query string. The code to do this is below:
<%if len(fuseaction) = 0 then
if
len(Request.Form("fuseaction")) > 0
then
fuseaction =
Request.Form("fuseaction")
else
fuseaction
= Request.QueryString("fuseaction")
end if
end if%>
Technique 6: All links and Form actions will point to
the Index.asp file. This can done through a few different techniques.
Universal Format
(recommended method for easy):
<a
href="index.asp?fuseaction=adduser">Add a User</a>
<form
method="post" action="index.asp">
Relative
Format:
<a
href="DIRECTORYNAME/index.asp?fuseaction=adduser">Add a
User</a>
<form method="post"
action="DIRECTORYNAME/index.asp">
Absolute
Format:
<a
href="/DIRECTORYNAME/index.asp?fuseaction=adduser">Add a
User</a>
<form method="post"
action="/DIRECTORYNAME/index.asp">
Differect Server
Absolute Format:
<a
href="http://www.domain.com/DIRECTORYNAME/index.asp?fuseaction=adduser">Add
a User</a>
<form method="post"
action="http://www.domain.com/DIRECTORYNAME/index.asp">
Technique 8: All URL Links, and Forms will pass an
attribute called: Fuseaction. As discussed above this attribute is the
name of the Action to be performed.
Example:
<a
href="index.asp?Fuseaction=DeleteUser&User_id=<%=content("user_id")%>">Delete
<%=content("firstname")%>
<%=content("lastname")%>?</a>
</cfoutput>
<form
method=post action="index.asp">
<input type=hidden name="Fuseaction"
value="AddUser">
In the next page will
explain more complex Fusebox techniques
Complex Fusebox Techniques
Technique 1: In order to use session management in
your asp applications you may include your global .asa file in your application
root.
If some of your circuit applications need their own session management
you should set thier directory as an application in IIS and include a global.asa
file that is specific to the circuit application.
Technique 2: Because of the nature of the asp
language, the only way to rout application functionality before the page is
loaded in the browser is by using the response object. response.redirect("index.asp?fuseaction=getcode"). This is fine however http headers cannot be written to the browser
in order for this to work. In other words you must process your asp code,
redirect, and then show your display. In Cold Fusion, you can simply call
cflocation and direct the application flow anywhere. The technique that I use to
avoid any problems is as follows. I include an action case,for any functionality
that is merely an action ie inserts, updates, deletes. These action files will
response.redirect("index.asp?fuseaction=getcode")
back to the index but with the proper fuseaction for display. Below is an
example of an index.asp page with an action "case" and a "display" case:
<!--#include file="../interface/adovbs.inc"-->
<!--#include file="..app_locals.asp"-->
<%
'This is the action area that executes before anything
is displayed.
'Note headers etc are included below
this area of the index.
Select Case fuseaction
Case "update_code"
%> <!--#include
file="act_update_code.asp"--><%
End Select
%>
<!--#include
file="../interface/dsp_header.asp"-->
<!--#include
file="../secure/act_secure_check.asp"-->
<%
'This is the display area.
Select Case fuseaction
Case
"welcome"
%> <!--#include
file="dsp_welcome.asp"--><%
Case "getcode"
%> <!--#include file="qry_getcode.asp"-->
<!--#include file="dsp_code.asp"-->
<%
Case "edit"
%>
<!--#include
file="dsp_editcode.asp"-->
<%
Case Else
%>
<%
End Select
%>
<!--#include
file="../interface/dsp_footer.asp"-->
Technique 6: Abstraction: Fusebox applications
are meant to simplify the process of building an asp application, not make it
more complex. By Abstracting a problem it means to seperate the problem that you
are trying to solve into many smaller problems. When designing your Fusebox
application determine how it can be abstracted into many sections. Create new
directories for each of these sections. Each of these directories will be their
own "Fusebox Object". All the directories together will be the entire
application. By doing this you can focus on solving one problem at a time
instead of all the problems at once.
I urge you to try using these
techniques as your ASP application framework. You will find that by using these
techniques you will streamline the way you build an application, along with
creating an excellent way of team programming. I feel confident that after you
try using these techniques you will notice that they are not closing the doors
on what you can do with ASP, on the contrary these techniques will be opening
the doors so that you can focus on your projects instead of on how to write
excellent, clean code.
A few final thoughts about Fusebox
Application Files
There are two application
files in a Fusebox application.
app_locals.asp
app_globals.asp
app_globals.asp contains information that is needed for every page of the application. For example if you set a variable for the datasource of a database that is used in many of your smaller applications within your larger application this variable would be set in this file.
app_locals.asp contains information that is specific to the local smaller application that is not general enough to be used globally throughout the application. Such as setting a default Fuseaction value. This file will also include the main application's app_globals.asp file. Here are examples:
<%<!--- app_globals.asp
--->
'------------dbconnection---------'
dim path,query,comment
path
= "db/mydatabase.mdb" %>
<%
<!--- newsletters/app_locals.asp --->
<!--#include
file="../app_globals.asp"-->
<!--- set some local variables
--->
dim newsletters
newsletters = 0%>
Here is an example Display file a query that fills the content object grabs the code data and is included prior to this file:
<!--- dsp_code.asp--->
<%
test = content.recordcount
if
content.recordcount > 0 then%>
<table bgcolor="" width="70%"
align="center">
<tr>
<td>Name
</td>
<td>Description
</td>
<td>Options
</td>
</tr>
<%do
until content.EOF %>
<tr>
<td
nowrap><b><%=content("productname")%></b>
</td>
<td><%=content("shortdesc")%>
</td>
<td>
<a
href="index.asp?fuseaction=edit&key=<%=content("productid")%>">Edit</a>
<a
href="index.asp?fuseaction=update_code&action=del&key=<%=content("productid")%>">Delete</a>
</td>
</tr>
<tr><td colspan=3><img
src="images/blackdot.gif" width="500" height="1" alt=""
border="0"></td></tr>
<%
content.MoveNext
loop%>
<tr><td
align="center" colspan=3><a
href="index.asp?fuseaction=edit">Insert</a></td></tr>
</table>
<%
else %>
<div align="center" class="bodytext">
Stay Tuned For
<%=Request.QueryString("codetype")%> Code!
</div>
<% end if
%>
Here is an example of an action file that performs an insert update or delete of items within a portfolio. Based on an action passed into this file the file will perform the necessary action. Once the action is performed the file redirects to the index page and displays the listing of portfolio items.
<!--- act_update port--->
<%
if len(action) > 0 then
else
if
len(Request.Form("action")) > 0 then
action =
Request.Form("action")
else
action =
Request.QueryString("action")
end if
end if
Select Case action
Case "insert"
temp
= "INSERT INTO Portfolio"
temp = temp &
"(projectname,projecttime,projectdescription,projectdate,projecturl)"
temp =
temp & "VALUES ('"& Request.Form("projectname") &"', '"&
Request.Form("projecttime") &"', '"& Request.Form("projectdescription")
&"', "& Request.Form("projectdate")& ",'"&
Request.Form("projecturl") &"')"
Case
"edit"
temp = "UPDATE
Products"
temp = temp &" SET projectname ='"&
Request.Form("projectname")&"',"
temp = temp &" projecttime
='"& Request.Form("projecttime") &"',"
temp = temp &"
projectdescription ='"& Request.Form("projectdescription")
&"',"
temp = temp &" projecturl ='"&
Request.Form("projecturl") &"',"
temp = temp &" projectdate
="& Request.Form("projectdate")
temp = temp &" WHERE
portfolioid="& Request.form("portfolioid")
Case
"del"
temp = "Delete From Portfolio"
temp = temp &" WHERE
portfolioid="& Request.QueryString("key")
End Select
'execute the query built above
Set
Connect=server.createobject("adodb.connection")
Connect.Open "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=" &
server.mappath(path)
Set cool =
connect.Execute(temp)
response.redirect("index.asp")
%>
Query files generally only have a single QUERY statement in them, but are not restricted to one query. By using query files you can reuse queries within your application rather easily
Here is an example Query file:
<!---qry_getport--->
<%
Set
Connect=server.createobject("adodb.connection")
Connect.Open "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=" & server.mappath(path)
Set content =
Server.Createobject("ADODB.Recordset")
if
request.querystring("key") > 0 then
where = " where
portfolioid=" & request.querystring("key")
end
if
Querybegin = "SELECT * FROM Portfolio"
Query =
Querybegin & where
content.Open Query, Connect,
adOpenStatic, adLockOptimistic
%>
If you try any of the Fusebox techniques you'll learn to love them. Fusebox style will make you a better programmer, because you can focus on what you're doing instead of how you're going about it.
Special Thanks to Steve Nelson and everyone that has contributed to the fusebox architecture this article was adapted directly from Steves article as it applies to Cold Fusion.
See more about
Fusebox at: http://www.fusebox.org/