As a programmer who spend a good portion of his times developing web
applications I'm always on the lookout for new frameworks or
approaches. This is especially true for web application frameworks, as
there is plenty of room for improvement in the web world. In production
settings I have rolled my and used struts. In a demo environment I've
played with PLT's web server and similar packages.
It was with that background that I saw the announcement for SISCweb. As
the name suggests, it's a web application framework built on top of the
SISC Scheme implementation. I downloaded the samples and played with
them, and hit me -- this could be really special. Why? Using SISCweb
you get access to any Java library, hosting by any standard J2EE servlet
container, access to a full Scheme implementation, and a powerful
approach to developing web applications. This seemed like a very
impressive combination, but I wanted to more than think that -- I wanted
to know that. So I decided to write a significant web application using
SISCweb as a proof of concept. I figured this would give me an
opportunity to see if my hunch about SISCweb and its advantages, was
correct.
Choosing an application as an example turned out to be pretty easy,
mostly because it had already had been done. That's exactly what SUN
did when they published the Java Pet Store. They wanted to demonstrate
Java's viability as a web applicatio platform, and I wanted to do the
same thing for Scheme. Others have followed this tradition, leading to
a .net, ColdFusion, Flash versions of the Pet Store.
It turned out that having a running version of the Pet Store was a
significant help during the development of the application. I didn't
need to figure out the requirements of my test application, or guess at
how a certain function worked -- I could just play with a pre-existing
application.
The Pet Store is also a nice application to use as an example because of
it's realative complexity. It requires the programmer to do things such
as manage server side state and execute transactions. These details
regularly go into a real life web application, while samples can easily
forgo them.
So, with a fresh emacs buffer and a browser window pointing to a version
of the Pet Store, I began.
There are two overriding principals that I hoped to meet with
development of a Scheme Pet Store. The first is that I wanted to
develop a web application that looked as little like a web application
as possible, and second, I wanted to support the concept of seperation
of concerns.
Developing a web application in a new framework is always a little
tricky. I have found that it is easiest to spend some time focusing on
what the shape of the application will be more so than any of the
details. For example, in struts, the shape of the application consists
of Action and Form objects, JSP views and a configuration file to tie it
all together. It was hardly this clear to me when I started developing
the pet store in SISCweb.
My first plan was to develop SISCweb as a series of small web programs,
connected together by URIs. For example, the section of the site that
allows you to view pets by category would be a simple program that would
be invoked by a URI that had as a single argument the category name. In
this world view, a web application is a collection of small web scripts
and the URIs that hook them together. I discussed this with the SISC
user community and in the end they steered me to a different approach.
The approach suggested, and the one I finally settled on was
ridiculously simple: a web application is just a collection of
functions. These functions can invoke each other using the standard
function call mechanism. The fact that these function calls are spread
across multiple HTML pages is pretty much irrelevant. After focusing on
this approach, I realized that I could develop a web application that
had a relatively small amount of web'ness associated with it. For
example, the only URI the Scheme Pet Store concerns itself with is the
top level one which kicks off the main function. After this initial
function is invoked, the control proceeds as normal.
This behavior of calling a main function is very similar to how any C or
Java program would be called. As a programmer you define a special
function typically named \scm{main} which is magically invoked by the
operating system. The same is true for the Scheme Pet Store, there is a
top level function named \scm{store} which is invoked as a servlet,
however, after this point, all functions are called in a normal fashion.
The shape of the Scheme Pet Store goes beyond simply specifying that
functions invoke each through a normal process. A second component of
the chosen approach is the type of values that a function returns. In
general, functios return SXML. This SXML is convereted through a
seperate process into HTML and rendered to the user. However, the SXML
value from these functions may just as easily be converted to another
format, or used in other compuations.
For example, the view shopping cart function may return a value such as
described below.
\scm{
(cart (item (price 3.45) (description "Foo") (quantity 3))
(item (price 9.99) (description "Bar") (quantity 1)))
}
I have frequently referred to the above approach as a Single Web
Application methodology. This is because an entire website, such as the
pet store, is thought of as a single application. This application is
no different than MS-Word or Emacs, in that it is a complex application
providing a variety of services.
The main benefit that of this single application approach is that many
issues relating to the complexity web applications simply go away.
For example, you don't need to worry about storing state in a user's
session, or if a value stored in a request paremeter will be lost during
an HTTP 302 redirect, simply because that's not part of the vocabulary
of the system. A value is available if it is passed in as a function
argument or if it is visible in lexical scope.
Developing a web application in a new framework is always a little
tricky. I have found that it is easiest to spend some time focusing on
what the shape of the application will be more so than any of the
details. For example, in struts, the shape of the application consists
of Action and Form objects, JSP views and a configuration file to tie it
all together. It was hardly this clear to me when I started developing
the pet store in SISCweb.
My first plan was to develop SISCweb as a series of small web programs,
connected together by URIs. For example, the section of the site that
allows you to view pets by category would be a simple program that would
be invoked by a URI that had as a single argument the category name. In
this world view, a web application is a collection of small web scripts
and the URIs that hook them together. I discussed this with the SISC
user community and in the end they steered me to a different approach.
The approach suggested, and the one I finally settled on was
ridiculously simple: a web application is just a collection of
functions. These functions can invoke each other using the standard
function call mechanism. The fact that these function calls are spread
across multiple HTML pages is pretty much irrelevant. After focusing on
this approach, I realized that I could develop a web application that
had a relatively small amount of web'ness associated with it. For
example, the only URI the Scheme Pet Store concerns itself with is the
top level one which kicks off the main function. After this initial
function is invoked, the control proceeds as normal.
This behavior of calling a main function is very similar to how any C or
Java program would be called. As a programmer you define a special
function typically named \scm{main} which is magically invoked by the
operating system. The same is true for the Scheme Pet Store, there is a
top level function named \scm{store} which is invoked as a servlet,
however, after this point, all functions are called in a normal fashion.
The shape of the Scheme Pet Store goes beyond simply specifying that
functions invoke each through a normal process. A second component of
the chosen approach is the type of values that a function returns. In
general, functios return SXML. This SXML is convereted through a
seperate process into HTML and rendered to the user. However, the SXML
value from these functions may just as easily be converted to another
format, or used in other compuations.
For example, the view shopping cart function may return a value such as
described below.
\scm{
(cart (item (price 3.45) (description "Foo") (quantity 3))
(item (price 9.99) (description "Bar") (quantity 1)))
}
I have frequently referred to the above approach as a Single Web
Application methodology. This is because an entire website, such as the
pet store, is thought of as a single application. This application is
no different than MS-Word or Emacs, in that it is a complex application
providing a variety of services.
The main benefit that of this single application approach is that many
issues relating to the complexity web applications simply go away.
For example, you don't need to worry about storing state in a user's
session, or if a value stored in a request paremeter will be lost during
an HTTP 302 redirect, simply because that's not part of the vocabulary
of the system. A value is available if it is passed in as a function
argument or if it is visible in lexical scope.
A second key goal I had for the Pet Store application was demonstrating
Scheme's ability to build well abstracted systems. From my experience,
this abstraction is most benenficial when isolating parts of the system
from each other. I wanted to show that a DBA could develop database
queries, which an application programmer could use and the graphic
designer of the system should be able to give the application a facelift
without bothering the application programmers or DBA.
I accomplished this goal by viewing key parts of the system as being
split into proceducer concerns and consumer concerns. For example, a
producer concern for the query system may be the actual SQL statement
used, while a consumer concern may simply be the ability to execute that
query and review the results. I provided this seperation of concerns
for all of the following areas, including: database queries, layout,
forms and navigation. The seperation of concerns always revolves around
some resource, be it a specific query, form, layout or other entity.
The sections below describe some of the specific features of the ways
that I seperated concerns. In general, the goal is always to try to
give the producer flexibility and the consumer simplicity.
Take the query system as an example. The producer can provide
arbitrarily complex queries that take in any number of arguments and
return any number of rows. The consumer however, needs to only know the
name of the query, what arguments it expects and what the return values
will be. The consumer can remain ignorant in the details of the query
and the producer can remain obliviously to where the query is used.
While developing the Scheme Pet Store I played the role of the
application programmer, DBA and designer. However, I still found the
separation of concerns mechanism to be quite useful. I could put a
simple query in place, make use of it in the application and then go
back and improve it without disturbing the application. SISCweb
provides a mechanism whereby Scheme definitions can be updated on the
fly, which meant that I could play all of the above roles without ever
needing to restart the server.
\XXX{I don't think I talk enough about SISCweb and I'm using it. Where
should that go?}
- Examples of scheme modules
In this section I describe some specific modules used in the Scheme Pet
Store. I hope this section will serve to demonstrate some of the key
decisions I made, as well as give some valuable clues to those who are
interested in reading the Scheme Pet Store source code.
One common theme that will quickly become clear is the role
pre-exisiting 3rd party libraries played in the development of the
Scheme Pet Store. Quite a bit of the difficult work of developing a web
application had already been done. For example, Java provides JDBC as a
method for accessing a database, and SXML provides a standard for
representing XML in Scheme. In many cases these technologies were
simply wrapped up in a module to expose them in a such a way that the
goals outlined above could be met. This has the additional benefit of
making a large amount of the the code in the Scheme Pet Store
non-controversial and well tested.
I have noted how SISCweb gives programmers the opportunity to develop
web applications without having to worry about many of the details of
the web. While that is true, one issue that must always be kept in mind
is that in the end, a browser needs to render the output of our
functions. In this section I describe how I developed a seperations of
concerns framework for handling the layout of the Scheme Pet Store.
Scheme's ability to support XML is remarkable. In fact, the ability to
easily generate and manipulate XML and HTML is just as impressive as
SISCweb's magic handling of function calls. There has been quite a bit
of work done in the Scheme community to map XML to Scheme and vice
versa. SISCweb made use of the SXML representation which is one of the
more common approaches out there. Consider how the following is
represented in both XML and Scheme.
\verb{
}
\scm{
(cart (@ (count "1"))
(item
(name "Cat")
(price "3.94")
(quantity "3")))
}
SISCweb extends the standard SXML format by allowing numbers to appear
in the structure, as well as strings. In the Scheme Pet Store this
approach has been extended even further, allowing arbitrary Scheme
values to appear in the XML tree. Consider how a form might be
represented in Scheme versus XML.
\verb{
}
\scm{
`(form (@ (action ,(lambda () ...)))
(field (@ (name "q") (size 20)))
(submit))
}
In the above case, rather than naming an action assocaited with the form
one simply provides the implementation of the action itself.
Comments (0)
You don't have permission to comment on this page.