The technology behind this site

Posted by nexus prime
(1 year, 1 month ago, on Tuesday, 28th August 2007)

Since I’ve migrated this site from running Mephisto on Rails to a custom project on Django, I thought I’d explain some of the rationale behind the switch.

Framework

My choice of Django was rather arbitrary, I could easily see myself use another full-stack Python framework like TurboGears, so don’t take it as a particular endorsement. The motivating factor was using a Python framework.

I wanted to move away from Rails, as for some time I have become disenchanted with the framework. DHH did a stellar job of marketing the framework through its birth phase, but in my opinion, the very success of Rails is what makes it less than what it could be.

Being so strongly opinionated, you run the risk of dismissing issues raised with your framework out of hand because you can’t see the forest for the trees.

And now that a particular opinion has been committed to it is somewhat harder to take a step back and maybe revisit some initial design decisions.

The primary issue I have with Rails is Active Record. It is, quite simply, a rather thin layer around the database driver with some syntactic sugar for declaring relations. Behind the scenes, its all string concatenation and direct queries to the database.

Since there is no real abstraction of an entity or its identity and lifecycle in an application, or of the concept of a session in which to do some work, the following code:

first = Person.find(1)
second = Person.find(1)

Will result in two different instances of an object in memory, referring to the same row. Changes in one will not be reflected in the other (in your application, where it counts). Since second.save() simply results in UPDATE being executed, changes can be overwritten.

Simple, you say, be careful when you load and don’t load the same object twice in the same context, when this identity is important. Except that when an object is being loaded for you by Active Record (such as, say, something declared by a belongs_to statement), a completely new instance is created and loaded if it was not loaded from the database yet, since there is no tracking of identity (and how can there be, without hacks, if there is no concept of a session?).

Eager loading does nothing to address this issue either, since if you eager load at the wrong time, or in two places, you still end up with the same problem.

This is when the need for something just a little bit more intelligent becomes apparent.

To be sure, its not an easy problem to solve. You have to live and breathe relational algebra to enjoy writing something like a full-fledged ORM that compiles language expressions into SQL. So I have my doubts about whether we’d ever see something like this arise in Rails (or Ruby, for that matter). It’s simply not sexy enough to the Rails mindset.

In Python, we have the excellent SQL Alchemy.

Language

My choice of language was largely based on similar reasons (and I didn’t really find any other Ruby Web framework that piqued my interest).

  • Performance: Ruby is slow, and unfortunately, it doesn’t seem that 2.0 (with its associated VM) is going to be released any time soon. Given enough resources, anything can be made to scale (c.f. Twitter), but my resources on this Media Temple slice are quite limited, and I’m not about to shell out for an Engine Yard slice just to host my blog. Uhh, no.
  • Metaprogramming Madness: A interesting characteristic of the Ruby community is to do a lot of invention of new Domain Specific Languages. Is too many DSLs an anti-pattern? Jury still out on this one, but I’ve gotten quite tired of tracing something to end up at a method_missing for the umpteenth time. I think I prefer the somewhat more explicit style of Python. “When you have a method_missing hammer, everything looks like a DSL nail?”

Python isn’t exactly the fastest language either, but its better than Ruby in that sense, and I’m not about to drop into anything other than a dynamic language for web programming, the productivity hit is just too big. I also happen to like Python’s spare syntax. I could have chosen an obscure or functional programming language as well, but I like to have good library support, and the Python community isn’t going away any time soon.

Web Server

I heard good things about nginx, so I decided to try it out and see how it goes. So far it’s doing a stellar job of acting as a reverse proxy and SSL frontend to my Django app running under mod_python, and to my Subversion repository under mod_dav_svn. I really like its configuration syntax and the fact that you can do much more natural conditional configuration that depends on some request state. My Apache setup is pretty conventional, if stripped down. It runs only the basic modules necessary at a minimum to support Django and Subversion, nothing else.

Database

I’ve always preferred PostgreSQL over MySQL, and this is no exception. I can’t take serious a database that treated transactions and referential integrity as second class citizens for so long, even if it does now support it properly in its latest incarnation. I’m not particularly fond of MySQL’s cavalier approach to SQL standards either, their implementation decisions are reminiscent of the approach that created the X.509 field mess.

Feel free to disagree :)

Django Powered

Posted by nexus prime
(1 year, 1 month ago, on Sunday, 26th August 2007)

This blog is now powered by a custom Django application I cobbled together whenever I had a spare hour or two to work on it.

Some things are still a little rough around the edges, but I’m happy with how it’s shaping up. Since I didn’t get around to building an admin system yet, I loaded the content in a rather primitive manner:

./manage.py loaddata posts.xml 

But on the client side of things, articles, trackbacks and comments are working, everything that should have, has RSS feeds, and the layout is how I want it.

URLs from the previous system (Mephisto) should still be working, courtesy of some rewriting.

I’m hosting it at Media Temple on a nginx instance serving up static content, proxying to Apache and mod_python for dynamic Django content, using PostgreSQL as the database server.

I plan to use it as a bit of a test-bed for deployment and caching ideas I want to try out.