In mid-1999, Tennessee rivers were low, but the Ocoee River was flowing well. As I approached a rapid called Hell Hole, I could see the other tourists shudder with fear, but I wasn't worried. In this massive raft, we had nothing to worry about. In fact, up ahead, a kayaker was playing in the hole, and his body slowly slid down, as if he were on an elevator. We passed over, and he came right back up, still surfing the hole. Strange and wonderful.
My raft might be bigger and safer, but there were things it just couldn't do. In his tiny kayak (called a playboat) he could surf the waters beneath the surface to do things seeming alien to those of us in the raft. The Seaside framework is like that. You wouldn't use it for all Web development, but under these circumstances, you might give it a try:
- You have sophisticated work flow and want to manage flow from one simple program.
- You don't want to stay with a safe, conservative language, like the Java™ programming language.
- You like Smalltalk or one of the Smalltalk dialects.
- You have a start-up company in which picking a productive technology is much more important than picking a fast one.
This article gives a high-level tour of Seaside. If you like what you see, you'll have enough information to dive deeper.
Avi Bryant had created a continuations-based server in the Ruby programming language, but left for the Squeak dialect of Smalltalk -- a pure, object-oriented language invented in the early 1970s, when Ruby continuations proved to be a little too unstable. (They've since been fixed.) He then built the Seaside framework on the Squeak dialect of Smalltalk and has never looked back. He now uses Seaside to quickly build Web applications for his customers. They're willing to put up with a niche language like Squeak because the framework is so productive, lowering the total cost of development dramatically, and improving time to market.
I'm not suggesting that we'll all be programming in Smalltalk in the next 10 years. That train rusted at the station. But I will say that language issues go away when there's compelling economic justification. Give me an application written in an obscure language that's five times as fast as an application written in a popular language, make it easy to maintain, and charge me one-third of what I'm spending today, and I likely won't care what language you pick.
Before I go too far, you should know a little Squeak syntax. If you want to follow along, download the Squeak integrated development platform (IDE) (see Resources). Smalltalk dialects like Squeak use an image, which is a copy of all running applications, including the classes you were coding the last time you saved your Smalltalk image. Start Squeak, click Tools, then drag a workspace and transcript window onto your desktop. Use your workspace window for input and look to the transcript window for output.
Squeak syntax is quite simple. Type an object name first, the method second, and any parameters third. For example, in your workspace, type:
Transcript show: 'Hello'
Right-click the text, then select Do it (you can also press Alt+d to evaluate the line). You should see the word
Hello in your
Transcript is the object,
show: is the method (Squeak calls methods messages), and
Hello is a parameter.
Squeak supports closures -- that is, using blocks of code as parameters -- like this:
1 to: 5 do: [:i | Transcript show: i]
The open and close brackets (
]) mark the beginning and end of the code block, respectively. The
i parameter marks the code block. Finally, try a ternary message in which one message has two possible outcomes:
age := 4. (age > 16) ifFalse: [Transcript show: 'Youngster.'] ifTrue: [Transcript show: 'Old timer.']
This message prints Youngster. That's all the Squeak you'll see for now. You should know enough to get started.
Now download the Seaside image from seaside.st and store it where Squeak can find it (put it in the directory with other .image files). Follow the directions to install the image, then start the Web server. Remember: Seaside is a development framework, including a continuations-based Web server. The Seaside image has a running version of the Web server and the code for the continuations framework.
Follow the directions provided by your version of Seaside and enter the pathway to the administration page in your browser. For my image, I point my browser to http://localhost:9090/seaside/config. Type
admin for the user ID and password, respectively, into the provided data entry fields, and click Submit.
To use continuations, you need a Web applications server that supports them. If you're familiar with the Java™ technology implementation of Apache Tomcat (which processes Java servlets), you'll understand that Seaside is a Tomcat implementation for Squeak with continuations support.
When the Seaside administration page appears, you'll see a couple of applications already running (see Figure 1).
Figure 1. The Seaside administration page
On the administration page, click the Counter application. Counter is a simple application that prints a count and includes two links: + and -. It's hardly a groundbreaking application, but it shows some of Seaside's capabilities nicely. Click + until the count is 5. Then, click Back twice. The count is now 3. Here's where things get interesting. You might expect the application to have a session with a current count of 5. After all, 5 was the last value of Count before you clicked Back. Click +: You'll see a count of 4, not 6!
So, Seaside is predictable for users, not programmers. As you've learned, the magic is in a dictionary of continuations. Each time Seaside captures a continuation, it stores it in a dictionary until a certain period of time passes and the session expires. Seaside stores the continuation with an ID and places the continuation ID in the URL. My URL looked like this:
The funny-looking string after the question mark is the ID for the continuation. When you clicked Back twice and + once, Seaside loaded the state of the application given the continuation tag and simply resumed operation from that point. You're literally going back to a previous call stack. (Unlike the Java language, Squeak uses a dynamic data structure instead of a call stack, but the concept is the same.)
Let's see what the code for this application looks like. You can see it from the browser. A few useful links appear at the bottom of the page (see Figure 2), including a link to help you determine memory use, a profiler, and one to manage user sessions. Click the Toggle Halos link.
Figure 2. Links in the Counter application
Notice that a box with three pictures surrounds every component. The first picture is a code editor, the second picture is an inspector (so you can see the values of the objects in your system), and the third is a style editor (so you can edit the style sheet for the component).
Right-click the first picture and open the link in a new window. A Squeak class browser appears. In the first box, click Seaside > Examples > Test. That's the module, like the Java package. In the second box, click WACounter. That's the class. WA stands for Web application. In the fourth box, you'll see the methods.
Four are clear enough. The
count method returns the current count, and the
initialize method asks for Back button support (sometimes you might not want Back button support) and initializes the value of
increase method adds one to
decrease subtracts one from
count. Click increase and change it to:
increase count _ count + 5
The underscore means assign. Click Accept and type your initials (for version control). Go back to the Counter application and click the + link. It will now count by 5. You don't have to reload the application: Just keep right on going. You can even encounter a bug, click Back (restoring the state), fix the bug, and keep typing.
Now, let's see how the control is rendered. Go back to the code window and click the
RenderContentOn: method. This code appears:
renderContentOn: html html heading: count. html anchorWithAction: [self increase] text: '++'. html space. html anchorWithAction: [self decrease] text: '--'
Think of the
html parameter as your canvas. Rather than using a template, Seaside gives you helper classes to render the different parts of the HTML page. You can see helpers for links, too. For each case, you pass a code block that fires a Squeak method. You don't have to manage those details yourself. It's not like the Java language, but it is very productive. Think of components as the Seaside view.
Seaside components stand alone, which is nice. You can easily print a component or an array of components. On the administration page, click the Config application, then click the link for the example called Multi. Notice the five counters. Click Show Halos, select the browser picture on the outer halo, click Seaside > Examples > Test, then click WAMulti to view the code, as shown in Figure 3. There are only three methods:
initialize sets up an array of counters,
children returns the list of children, and
renderContentOn: calls the
render methods on each of the five counters. How many Java Web development frameworks can do that?
Figure 3. The three methods in the Multi application
In Seaside, each component must handle its own state, action, and view. As in the Java language, most of the business logic is in Squeak objects, and Seaside stores any presentation-specific state in component instance variables.
So far, you've seen only simple tasks. Seaside also provides tasks for creating more complex code. For fun, go back to the code browser (if it's not active, go to an example; click the Toggle Halos link and click on the first of three images in any halo). Now, use the code browser. Select the the Seaside-Examples-Store module in the first list, the
WAStoreTask class from the second list, and the
Go method from the fourth list. This Seaside task handles the shopping cart checkout. You'll see this code:
go | shipping billing creditCard | cart _ WAStoreCart new. self isolate: [[self fillCart. self confirmContentsOfCart] whileFalse]. self isolate: [shipping _ self getShippingAddress. billing _ (self useAsBillingAddress: shipping) ifFalse: [self getBillingAddress] ifTrue: [shipping]. creditCard _ self getPaymentInfo. self shipTo: shipping billTo: billing payWith: creditCard]. self displayConfirmation.
isolate method lets you isolate a transaction. Notice three blocks of code. The first block performs some initialization, then retrieves the contents from the cart, asking the user to confirm the contents. The second block retrieves the shipping and billing addresses, and the credit card information, then ships the order. The third block displays a confirmation message. Think of the tasks as your controller.
Notice the lack of state management. You never had to store the application state to a session or restore it when you were done. You were able to look at a whole application, instead of coding many smaller requests. The framework handles all of it for you in the form of continuations -- a very powerful concept.
Finally, Seaside handles your model in plain old Squeak objects. You can see the model for this application by selecting the module Seaside > Examples > Store > Model from the first list. You'll see many classes that represent the domain model for the store. There's nothing special there -- just the code to hold the state of the application and a few business methods having nothing to do with the views. You get only pure objects, just as you should.
There you have it. In Seaside, you've got incredible debugging and management tools built right into the application. The framework handles links, HTML display details, state, and difficult issues, such as the Back button. I hope this article series has shown you some strategies for lightweight development, in the Java language and beyond. You'll be able to read more about both in my new book, Beyond Java, and in my previous books, especially Better, Faster, Lighter Java. I hope you get the chance to try some of these techniques, and your friends and peers will think of them as strange and wonderful, just as I judged the kayakers on the Ocoee River.
Lightweight development is a huge topic, and developers throw the term around so often that it's hard to tell what it means. "Secrets of lightweight development success, Part 1: Core principles and philosophies" introduces the core principles and philosophies behind the movement.
Heavyweight architectures, such as Enterprise JavaBeans, can be overkill for everyday problems. "Secrets of lightweight development success, Part 2: How to lighten up your containers" introduces lightweight containers and explains how they can provide the services your business needs without tying you to a given programming model.
Learn the basics of lightweight containers in "Secrets of lightweight development success, Part 3: The emergence of Spring."
In "Secrets of lightweight development success, Part 4," three popular containers are compared: Spring, HiveMind, and PicoContainer.
Lightweight development works best with a lightweight process, but it can be tough to get a conservative company to adopt agile methodologies. Learn how you can propose and promote lightweight processes in your organization in "Secrets of lightweight development success, Part 5."
In "Secrets of lightweight development success, Part 6," we compare and contrast Enterprise JavaBeans, Hibernate, Kodo JDO, and iBATIS to help choose the best persistence framework.
"Secrets of lightweight development success, Part 7: Java alternatives" shows what's important for productivity in an application's language.
Beyond Java, by Bruce Tate, is available now.
Better, Faster, Lighter Java, by Bruce Tate and Justin Gehtland, provides a good overview of lightweight development.
Programming Ruby, by Dave Thomas, is the best Ruby book out there.
Continuations Made Simple and Illustrated is a good resource for information about continuations in the Python programming language.
Read Martin Fowler's excellent article about Closure.
Learn about the Smalltalk Squeak dialect.
Seaside is an amazing framework based on the Smalltalk language and continuations.
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
Get products and technologies
Download the Squeak integrated development platform to follow the examples in this article.
Check out the Java frameworks Apache Cocoon 2, RIFE, and Spring Web flow.
Innovate your next open source development project with
IBM trial software, available for download or on DVD.
Get involved in the developerWorks community by participating in developerWorks blogs.
Bruce Tate is a father, mountain biker, and kayaker in Austin, Texas. He's the author of three best-selling Java books, including the Jolt winner Better, Faster, Lighter Java. He recently released Spring: A Developer's Notebook. He spent 13 years at IBM and is now the founder of the J2Life, LLC, consultancy, where he specializes in lightweight development strategies and architectures based on Java technology and Ruby.