The Weekly Source Code 20 - A Web Framework for Every Language
We just keep oscillating back and forth between thin clients and chubby clients. We started with basic terminals receiving text from the server and displaying it, then added control codes and more smarts until we got into things like VT102 and beyond. We pushed all the User Interface over to the client for rendering.
Now that the Web is squarely here to stay, we've got islands of activeness in the form of browser plugins like Flash and Silverlight, some of which are cross platform and some less-so, but for now my quad-processor machine spends a lot of time either:
- Waiting for markup to show up
- Rendering markup
There's a thousand different ways to generate your UIs and send them down to the browser/client for rendering. Turns out there are as many ways as there are languages. If you've got a programming language, there's a web framework for it.
I don't know why this surprises me. Folks love their programming language, whatever it is, and it makes sense that the "ultimate" proof of their language's awesomeness would be the "ultimate web framework."
That said, it still seems funny to me that the greatest (er, most overtly visible) example of a language's superiority is how well it works as a Web Framework angle-bracket generator.
For example, Arc is Paul Graham's new LISP dialect that a number of people are talking about (with varying degrees of enthusiasm). A tutorial on Arc is available here and there's an "Arc Challenge" being discussed here as folks try to this slightly more complex Hello World example:
"First generate a page with an input field and a submit button. If the user clicks on submit, he gets a second page with a link saying "click here." If he clicks on that, he gets a third page saying "you said: ..." where ... was whatever he put in the input field. This has to happen without the value being passed in the url; it should not be possible to change the behavior of the third page by editing the url in the second."
In Arc/LISP it looks like this:
(defop said req (aform [w/link (pr "you said: " (arg _ "foo")) (pr "click here")] (input "foo") (submit)))
It's pretty terse to look at if you're used to doing things in more conventional languages. There's a lot of fun solutions like this entirely client-side one in JQuery:
$('body').append('<input id = "myInput" /><input type = "submit" />') .find('input[@type=submit]').click(function() { val = $('#myInput').val(); $('body').html('<a href = '#'>click here</a>').find('a').click(function() { $('body').html('You said: ' + val); }); });
Other examples include:
#!/usr/bin/env ruby require "ramaze" class MainController < Ramaze::Controller def index if f = session['foo'] then "you said #{f}" elsif session['foo'] = request['foo'] then A("click Here", :href => '/') else '<form><input name="foo" /><input type="submit"></form>' end end end Ramaze.start :port => 7001 __END__
Then Rails:
def said if request.method == :post session[:said] = params[:said] render :action => "clickhere" else render :action => "result" if session[:said] end end default template said.rhtml: <% form_tag do %><%= text_field_tag "said", "" %><%= submit_tag %><% end %> clickhere.rhtml: <%= link_to "click here", "" %> result.rhtml: You said <%= session[:said] %>
- Continuity and Catalyst on Perl
- Pylons and CherryPy on Python
- UnCommon Web, Lisp On Lines, and ABCL-web on Common LISP
- Seaside on SmallTalk
| something | something := self request: 'Say something'. self inform: 'Click here'. self inform: something
serveAs "said" $ hasIndex $ \x -> "click me" `linksTo` (text ("You said " ++ x))
- the PLT continuation-based web server on Scheme
- JQuery (client-side) and Helma (server-side) on JavaScript
- ASP.NET and C#
<%@ Page Language="C#" ClassName="WebApplication1._Default" %> <script runat="server"> // C# and ASP.NET protected void SubmitButton_Click(object sender, EventArgs e) { MultiView1.ActiveViewIndex = 1; } protected void ClickHereButton_Click(object sender, EventArgs e) { SaidLabel.Text = string.Concat("You said: ", SayTextBox.Text); MultiView1.ActiveViewIndex = 2; } </script> <html> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0"> <asp:View runat="server"> <asp:TextBox ID="SayTextBox" runat="server" /> <asp:Button ID="SubmitButton" runat="server" Text="Submit" OnClick="SubmitButton_Click" /> </asp:View> <asp:View runat="server"> <asp:LinkButton ID="ClickHereButton" runat="server" Text="Click Here" OnClick="ClickHereButton_Click" /> </asp:View> <asp:View runat="server"> <asp:Label ID="SaidLabel" runat="server" /> </asp:View> </asp:MultiView> </form> </body> </html>
Shorter but not-typical ASP.NET:
Shorter but non-idiomatic C#/ASP.NET: <%@ Page Language="C#" %> <html> <head> <title>Said</title> </head> <body> <form id="form" runat="server"> <% if (!IsPostBack) { %> <input name="foo" /> <input type="submit" /> <% } else if (Request.Form["foo"] != null) { Session["foo"] = Request.Form["foo"]; %> <a href="javascript:form.submit()">click here</a> <% } else { %> you said: <%=Session["foo"]%> <% } %> </form> </body> </html>
There are so many ways to generate the same result. Big thanks to Ted Glaza for his indirect help on this post.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
For example
said.haml:
- form_tag do
= text_field_tag "said", ""
= submit_tag
clickhere.haml:
= link_to "click here", ""
result.haml:
You said
= session[:said]
Seriously though, why does the web still draw in such attention? Why is HTML still king? Why not use WF XBAP clients, or Click-Once apps on the web? Should I redo my app in Silverlight or stick to HTML?
I wonder what the advantage of HTML and JavaScript is over Silverlight and Flash. People have already mentioned the SEO problems with Flash, but for applications, that's not usually a big deal.
I think it has more to do with user experience and immediacy. If you alway send down a definition of everything the user will see, format plus data, the page is displayed quickly. If the user has to install something or even wait to download a flash app, it puts them off, and they quickly go elsewhere.
If that is the case, HTML and angle-bracket generators are going to be here for a long, long time still.
Will we ever see XAML-frameworks for generating XAML for Silverlight?
that's brilliant scott. best half-line summary of the 'web framework' movement i've ever seen.
- You are absolutely right on client side runtime issues with Flash, etc. If Silverlight, etc. has to install something, has to install something in different browsers (some people use more than one) and has to install something with each new version, that's just more work for the user.
- Markup-based apps, although they can be done poorly, have inherent consistency within a given browser. Control consistency, some behavioral consistency. Flash-based apps are more open to variance, which hits up against the average user's learning curve. I'm sure this can be minimized or it's over-stated, but it's valuable to consider.
- Markup approaches are open standards. Flash and Silverlight are proprietary to some extent.
- There is a glut of people who can build markup-based web apps (poorly or not) so it's pragmatic from a staffing, retention and turnover standpoint for many organizations.
- View source. Yup. View source. Think about it :-)
ColdFusion gets no love.
Comments are closed.