What I want out of a Web framework

Haskell has a serious Not Invented Here problem where it comes to Web frameworks. Everyone is unhappy with what we have, but no honest features differ between the six or so out there.

Let’s start with what I don’t care about:

  • Speed
  • Computer Science

If I cared about these things—or if any other Web developer cared about these things—I wouldn’t write in Ruby (or PHP, Perl, PLT Scheme, etc.).

These are nice but they’re not selling points.

Overall what I—and, Rails has taughts us, other Web developers—want out of a Web framework is a strong opinion. I want to be told where to put things. I want to be told that routes go here, HTML templates go there, tests go in this other place, and so on.

To not do that is to assume that Web apps are simple, that people maintain exactly one Web app, and that Web sites are completely unique. None of those assumptions are true.

Next up I want to bring knowledge over from the rest of my career. Some of my favorite design patterns apply here: observer and MVC. Just use MVC for your Web framework. It makes sense. I mean, it doesn’t, but it approximates it so well that it’s worth it.

The view should look like HTML. I’m not writing it, afterall; the designer is. Or she and I are writing it together. Either way, it shouldn’t be validated. I don’t care if it’s valid; the designer doesn’t care; the Web browser doesn’t care (and sometimes needs it to be invalid); so just relax already. (Any Haskell in the view template needs to be valid. I understand this.)

And I don’t want to write SQL so use an abstraction layer like the active record pattern or Arel or something dead easy. Simulate OO if you need to; it makes sense some times, and invoking behavior on data is that time.

I don’t want to “pretend I’m writing desktop apps” because this isn’t a familar metaphor. I want to write HTTP apps. I want to interact with GET, PUT, POST, and the others. The Web is a very familiar metaphor: data goes in, data comes out, and it’s over. It’s like a function call but with more moving parts. Not only does this make it easy to think about, it makes it easy to test.

I test my code. At work I test-drive my code, which also implies 100% code coverage but we don’t tend to care about code coverage. But that’s the kind of code I write: code that needs to be tested. I want to use an integration test suite to describe how the application should perform, and I want to use a unit-level test suite to ensure that refactoring goes well. My Web app will talk to other Web apps so I damn well better be able to fake that part out of my tests.

Pulling knowledge in from the rest of my career, I want to use Cucumber and something better than Selenium. In Rails we use Webrat and Holy Grail and EnvJS and ShamRack and a whole slew of other tools. There’s nothing stopping me from using Cucumber to describe my behavior except I can’t back it with a Haskell equivalent of Webrat.

Oh speaking of knowledge, I need documentation. The first-pass tutorial for a Web app isn’t “hello, world”, it’s a blog. If “hello, world” requires a full tutorial then your Web framework belongs in 1995. Make a screencast, those are fun. You should say, “Look at all these things I’m not doing!” in it, and mean it. But be aware that I’m not writing a blog. Well, I am, but it’s part of the app. Clients always demand a blog (and an admin interface, statistics, copy changes, A/B testing, …).

I see an idea crossing your mind right now and let me just say that splitting the individual components into discrete divisions that know nothing of each other simply isn’t fun to maintain. And even if it were fun to maintain, you don’t know how to make such a thing in the first version of your framework.

Speaking of things you don’t know how to do at first, I want hooks. Nearly every Web site out there is slightly different from another Web site, and I want to hook into the framework to handle those differences. The part of the framework that catches exceptions and shows a 500? I want to be able to replace that or augment it. The part that maps URL paths to module and function; the part that looks for the location of the HTML templates; the part that loads configuration files—all this, and more, are things I may want to augment.

If you provide a hooks, you should have a directory for storing plugins. That’s a nice, cheap way of having people contribute to your Web framework.

I mentioned errors, and this is one spot where Haskell, as a language, falls short. Here’s what you can get from a Ruby exception: backtrace, message, class name, and anything defined on Object, Class, Module, or Kernel. On the other hand, here’s what you can get from a Haskell exception: message. So you know that somewhere, somehow, maybe in your code, `head’ got an empty list.

(I ran into this while writing a Hoptoad notification library for Haskell. It was a very “wait … what! … waaait. Oh, what!” reaction when I realized this.)

Rumor has it that ghc is working on backtraces.

As a tangent let me tell you about the first (and last) time I tried Merb. I had been a Rails developer for maybe three years by then and I had heard that Merb was a simpler Rails. “That sounds nice,” I thought to myself. “Rails is a big pile of hacks so presumably they’ve brought that pile down to a manageable level.” First thing I noticed was that ActiveSupport was missing. This meant I couldn’t #pluralize. As I wrote more I realized more and more was missing and that, really, Rails was extracted from a real, production-level, money-making Web app … and Merb simply wasn’t.

Anyway, when the Web app is ready I’m going to deploy it to staging and, when that’s ready, it’s off to production. Maybe there will be a pre-staging server, too, or a mirror of staging, or a mirror of production with forked traffic. Either way deployment needs to happen and, when it breaks, it needs to be undone.

So it sounds like Rails has what I want. Why am I still here? Haskell gives me: type checking, a friendly and small community, and threading. It’s a smart language for smart people, and I want to pretend to be a smart person.

The next step

Which Haskell Web framework is the one we should bring into this dream? There’s no need to make yet another; let’s just take an existing one and fully realize it. I can’t figure out which, though. Advice?



  1. Posted May 22, 2010 at 6:46 pm | Permalink

    So what’s your opinion then of http://snapframework.com/ or http://happstack.com/index.html

    Both opinionated. But too focused on speed or computer science, rather than time saving for the web dev?

    • Posted May 23, 2010 at 11:42 am | Permalink

      Hey dons. Snap’s selling point seems to be the speed of the program rather than the speed to develop, and Happstack’s documentation is too lacking to really understand what’s going on (every time I look into it the tutorial is down).

      That said, I’m excited that Snap has a nice name, pretty Web site, and documentation.

  2. Christopher Meiklejo
    Posted May 25, 2010 at 9:47 pm | Permalink

    I was looking at Snap, and while it looks cool, no one would ever use it in business. Ever.

    • Posted May 25, 2010 at 9:52 pm | Permalink

      Yeah but, like, what would you change about it to fix that?

      • Chris Meiklejohn
        Posted May 26, 2010 at 10:21 am | Permalink

        That’s a good question. I’m probably not the right person to answer this because I’ve only looked at Snap for about a hour or so. But, here we go…

        From a non-technical perspective, Snap doesn’t really seem to have a real compelling argument to use it. That’s where I think Ruby on Rails excels. Rails allows developers to build an application out to a certain point quickly and easily, this giving developers a reason to learn Ruby. (This could be seen as a negative since the developers who learn Ruby while programming Rails do not write solid code). Like you say in your post, Rails basically says if you do things this very specific way, things are going to be a lot easier and you’ll be able to take this to market a lot quicker.

        Snap doesn’t do that. It’s got documentation sure, but it doesn’t try to make it seem that it’s practical for widespread use. None of the examples show this, and it’s not evident through the API documentation either.

        I’m not trying to say I don’t think it’s new and interesting. I do, and I’m going to spend some time with it and see what I can build. I just believe that to get buy in to develop software in a framework such as this, there needs to be some pretty compelling arguments for the framework, and Haskell in general.

        I believe, as sad as it is, that stupid little five minute Rails blog video was instrumental in it’s adoption.

%d bloggers like this: