In his Web Framework Manifesto, David Pollak identifies a number of features that he believes web frameworks should have, and I think he’s right on the money. He starts out with what you’d expect to find from one of the newer frameworks.
- A quick and easy way to map between a relational database and the target application.
- Easy, “right by default,†HTTP request mapping.
- Automatic “view†selection and composition.
So far, so good. In Rails, Django, and other similar frameworks that emerged about the same time with the same values, this is largely accomplished by staying DRY, by favoring convention over configuration, and by being focused and limited in scope. DHH makes much of his having no interest in Rails as a one-size-fits-all framework, and this is a Good Thing. Yes, it means that Rails isn’t a good fit for every app. Get over it. It also means that although Rails et al changed a lot in their emphasis on radical simplicity, they didn’t change enough. I don’t see Rails as the future of web development so much as I see it as representative of a final stage of MVC web frameworks, wrapping up up a lot of good ideas and giving us something to work with as we get over the hump into the next stage. Whatever that will be.
I’ll put my money on a few ideas: component-based architectures, addressing how Ajax shifts how and where state is managed, and better state/scope/workflow management with continuations.
Pollak gets into some of that in his next criteria, which is quite a list. He starts with a discussion of components. (I won’t quote everything here. I really suggest you go read the full piece.)
- Pages must be composed of arbitrary components that manage their own state.
- The rendering of components must be asynchronous based on user-based and external event-based state change.
- Components should be live (or seamlessly persisted) at all times, ready to respond to events.
Right away we’re getting into an area where older-style MVC frameworks like Struts, which is still alive and kicking thankyouverymuch, completely fall down. I’ve been dancing around this for years without getting into it too deeply here, but I just don’t think that MVC is a perfect match for web applications. It is useful as a separation of concerns, but the action-based controllers that we’ve been used to in MVC web programming are becoming inadequate with the rising use of Ajax. We are hitting a wall and should be able to do so much more.Both the Java and the .NET worlds seem to be moving toward components, albeit with slower adoption than either Sun or Microsoft would like. (I don’t know what I’m basing that on, by the way: I freely admit that it’s just a gut feeling. I also admit that I don’t deeply understand the shift to components and what it entails. I just haven’t taken the time.)
- The browser should be honored and feared. That means the back button should “do the right thingâ€
- There should exist a simple, unified way to describe modal user behavior (e.g., filling out a multi-page form.)
- Sessions should be tied to a browser window/tab, not to a browser session.
I am interested in Seam and RIFE in part because of how they manage state — especially using continuations in RIFE. Seaside has demonstrated what that can be like, done well. Not only do we have continued usability problems with managing state across multiple HTTP requests, but considering that it’s still in the OWASP Top 10, I’d say it’s fair to say it’s a significant security problem, as well.
- Mapping between object fields and HTML (or whatever the presentation layer is) should be “right by defaultâ€
We spend far, far too much time messing around with this at a low level, and it offers far too many opportunities for niggling little bugs to introduce themselves. I won’t trouble you with details about how I just spent two days doing something that should have taken twenty minutes. I’m still too angry about it.
It should come as little surprise that I am delighted by Pollak’s emphasis on security. Web frameworks do not do enough for security, period. I believe that developers can and must understand the range of attacks to which their software is likely to be subjected, even if they don’t become security experts, but frameworks should also make it easier to do the right thing than not to. Input validation should be centralized, simple, and a default. Output encoding should be handled properly by default. Access control should be more transparent and pluggable. And so on. Pollak has good suggestions.
- input from the browser should never be trusted, but should always be tested, validated, and destroyed if it is unexpected
- There should be a single way of describing input validation.
- There should exist an orthogonal security layer such that objects that are not accessible to a user should never be returned in a query for the user and fields on an object that are not accessible should not be visible.
- Code should be impervious to a replay attack. That means that fields in forms should have random names that change for each request.
- The framework and runtime should correctly and gracefully deal with non-ASCII characters.
The last one is not just a security issue, but I lumped it in there because it does fit.
I love the idea of random names for form fields. So simple, yet we’re so caught up in the annoying low-level mapping of field names to back-end objects, that it gets overlooked. And as valuable as the Commons Validator framework can be, calcifying field names in even more config files is tiresome, error-prone, and constricting.
Finally, deployment. I’ve written before how as much as I like Rails, Capistrano, and Mongrel, and as confident as I am that a Rails apps can be deployed so they perform, scale, and can be well managed, I’d still feel sheepish suggesting deployment scenarios that change as often as Rails’s “proven practices” seem to. Maybe I should just get over it. Regardless, it’s clearly something to take into account when considering a development platform.
- Deploying the web application should be as simple as putting a file in a known location (e.g., a WAR file on a J2EE server) or by executing a single command (e.g., Capistrano.)
- Deployments should contain all dependencies.
- The production environment should support modern technology including executing multiple threads in a single process and allowing for many “live†objects to be corresident
- The production environment should support hot code replacement
- The development environment should support hot code replacement such that once a file is saved, it becomes live at the next HTTP request.
The last is so very, very important. Shortening the feedback is vital, one of the much-touted features of Rails and other dynamic language frameworks. It can be done with Java and a decent IDE, but not always. And although I think it’s obvious, this is far from universally understood or believed. Not long ago, because of a really slow database load and a design error, a developer I know had to wait 15 minutes for a Java web app to deploy and load. Unacceptable. I don’t know how she or her supervisor tolerated it, because it meant that she could make and test at most four changes an hour. Or, more likely, make more changes than were really safe, which is what a long feedback cycle encourages.
The benefits of frequent and automated testing should be well known by now, or at least I think they should be, so I won’t write ano more about that now.Where does all this lead? Shortly after he wrote this manifesto, David Pollak responded to it by releasing Scala with Sails, now known as the lift web framework. You can get a feel for some of it in the recent announcement on his blog. Lift is written in Scala, a functional/object-oriented language (yes, both) that compiles to Java bytecode, so it runs on the JVM and has access to the Java API. Scala is my next language, if only so I can work with (and on?) lift. Much as I have high hopes for JRuby on Rails, I think that lift is something to watch, especially if the development team can do half of what they set out to do. As is clear from the Pollak’s essay, we need to push web frameworks more than we have done.