Thursday, March 02, 2006

Python Web Application Frameworks (Part 2: Guido Asks For Help)

The recent debate on application frameworks was galvanised when Python creator and Benevolent Dictator For Life Guido van Rossum (currently employed by Google) asked the community to "Please Teach Me Web Frameworks for Python". It turned out that WAFs are different things to different people, so it's likely best if I start with a bit of a definition.

But before you read that you may want to start with Part 1 of this article, so you can follow my perspective. As incentive I will say that the first part was highly entertaining. This part will not be, although I do promise one pun.

Next, put on your well-worn copy of the Arcade Fire album and sing along while reading. Ready? Then we'll begin.

What is a Web Application Framework (WAF)?

In Python terms it's a bunch of modules for building web apps, modules which may contain one or more components. In order to establish what these are, let's look from the perspective of a typical victim user. Said person is browsing a particular page served up by your application. Let's examine what components will be needed behind the scenes.

First, the user types in the URL. Many WAFs contain an URL to object mapper, which interprets a given address as a method call on a particular class. This means that the web site does not contain a pile of HTML files in a doc folder, but rather a pile of classes in a custom module. Whether you like this idea or not will determine a lot about which WAF you choose.

The request handler wraps around the URL component and provides for the proper interpretation of the HTTP spec: GET, PUT, and so on.

This needs to talk to the server, and for that you need some sort of web server connection. The classic old-school slow-but-sure way is CGI. But there's all sorts of improvements which embed the Python interpreter into the web server. The main advantage of these methods is performance, since the interpreter does not need to be loaded each time a request is made. (Examples include mod_python and FastCGI.)

Since memory space is shared between requests, these methods allow database connection pooling and other enhancements. The downside to embedding the interpreter is that you have to be careful how you code, and need special mechanisms to dynamically load code changes without restarting the server.

On the topic of databases, a WAF may have its own database interface. A special type is proving popular these days, namely an Object-Relational Mapper (ORM). This allows a more Pythonic1 mode of database access, hiding SQL, cursors and the like behind a familiar sheen of classes, methods, and iterators.

Unless the HTML is totally programme generated (generally not a good way to make friends with your designer) there will be a templating language, designed to extend HTML to allow for dynamic content. Some templates allow for embedding arbitrary Python code directly in the page (me hates). Others supply a limited but powerful menu of custom tags (me likes).

For example, Wasp had tags for including another file, expanding a simple macro, running a custom procedure to embed HTML, and also a simple conditional. I still do not see any advantage to providing more than that. As soon as you get into loops and variables and stuff you are better off in a code module2.

Some WAFs do not have their own template markup, but rather a plugin architecture to install someone else's. In this day and age that makes total sense, because this particular wheel does not need reinventing. (I will try not to use the word "interoperability" in this article but I trust you will forgive me if it slips out.)

In order to provide some state to the stateless world of web pages, WAFs might have a session mechanism in combination with, maybe, cookies. At least that's how I did it. On top of this an authentication mechanism fits well. For increased performance (especially if the framework is slow) you may need page caching. I'm betting you don't need it, but your client thinks it makes them sound like one of the big boys. Cache on the line, that's how they like it!3

It goes without saying that forms are a particular pain. You may find your WAF has a special library to make them easier. Other features may include logging, error handling, testing,... the list goes on. (Funny how people always say "the list goes on" in precisely those situations where the list does not go on.)

In fact, there are so many components that this has spawned the need for one more: an installation component to get all the others set up nicely.

To summarise, here are common WAF components:
1. URL mapper
2. request handler
3. web server connection
4. database interface
5. object-relational mapper
6. templating
7. sessions
8. cookies
9. authentication
10. caching
11. forms
12. logging
13. error handling
14. testing
15. installation

Furthermore, there are some features you may see bandied about. There's the aforementioned "connection pooling" and "multi-threading" and "object publishing" and "iron-fortified"4.

There's also lots of talk of "middleware" which, near as I can figure, just means one method calling another.

I believe we are now equipped with the domain knowledge and terminology necessary to evaluate specific WAF products. That's what I'll do in the next article. But before then you may want to look over that tall list of features and assign priorities to the items based on what you want to see and how important it is to you. That will help tailor this discussion to your needs.

See you in Part 3.

1 Pythonic means "behaving like Python", which is to say in a pragmatic object-oriented style free of fluff, fuss, and Freon. Beyond that it is in the eye of the beholder. Though you may want to type "import this" into the Python command interpreter window -- surprise!

2 How are you enjoying Arcade Fire?

3 That's my pun for this article. You can now breathe easy. The worst is over.

4 OK, I admit it. I made that last one up.


No comments:

Post a Comment