Wild Man's Shore

Saturday, January 21, 2006

Problems with Finnish Keyboard and Ruby's irb

I ran into a problem with Ruby's interactive shell, irb, on Windows XP: it did not accept alt-gr generated characters with the Finnish keyboard, which prevents you from typing characters such as [ or @. The solution was found here:

Basically create the following file, .inputrc, in your home directory(C:\Documents and Settings\<username>):

"\M-[": "["
"\M-]": "]"
"\M-{": "{"
"\M-}": "}"
"\M-\\": "\\"
"\M-|": "|"
"\M-@": "@"
"\M-~": "~"
"\M-$": "$"

Then add the following line to the start of <ruby-dist>\bin\irb.bat:

@echo off
set HOME=%HOMEPATH%

and it should work fine. A real showstopper, though, which I haven't seen in other tools (such as Python's shell).

Friday, January 20, 2006

Finnish elections

As a Brit living in Finland I have as much a right to vote and comment on the elections as Conan O'Brian. The election has gone to a second round as the incumbent socialist candidate Tarja Halonen did not get enough votes for a 50% majority, so now the contest is between her and Sauli Niinistö who represents the Finnish conservative party (Kookomus). He may get most of the Center Party candidate (current Prime Minister Matti Vanhanen) votes as the latter has endorsed him.

The Finnish president is expected to be something of a neutral figurehead, like a British monarch, and the post has lost much of its power since the Kekkonen "dictatorship" of the sixties and seventies. At the same time, as a politician, people feel the president should express opinions and show some kind of leadership, and Halonen has been criticized for her lack of these qualities. Her re-election looked like a shoo-in last week; now it's going to be a much closer race. Niinistö is a dry, lawyer/banker type noted for his one-time relationship with Finland's Minister of Culture, the former Miss Finland Tanja Karpela (as indeed has Prime Minister Vanhanen; one could play a game of Seven Degrees of Tanja Karpela in Finnish politics). Halonen is (or tries to make herself out to be) a motherly, kindly Moomin Mama, but often her true colours come out, with a reputation for bullying her co-workers and her husband in public.

Many Finns put down "Aku Ankka" on their ballot paper as a kind of protest. Aku Ankka is Finnish for Donald Duck, who is considered a hero by Finns for his "sisu" (rough translation: bloody minded tenacity against all the odds). Personally, I would vote for his uncle, Roope Setä (Scrooge McDuck), as I think he would run a much tighter fiscal policy and would reduce the ridiculously generous social security spending in this country.

Wednesday, January 18, 2006

TurboGears vs Rails

I first glanced at Ruby a few years ago, round about the time I first glanced at Python. The two were, at least superficically, similiar. As I was more heavily into web development at the time Python looked the better option because of Zope, WebWare and other packages; Ruby then (as far as I know) just had plain CGI.

Now Ruby has stormed the web development world with the Rails platform, leaving Pythonistas dazed and confused. Nevertheless we rallied round two excellent packages, TurboGears and Django, while the Zopeheads worked on their interesting but rather esoteric Zope 3. And Python is not short of web development platforms; I wrote a large document management application using Quixote + Durus, about which more later. But Ruby, once an obscure Japanese cousin to Python, is now the darling of the tech media.

Rails has been around now for about 15 months, 3 times longer than TurboGears (though not TG's individual components) and so I decided that as a more stable platform it would be worth a look. Plus, and this is something I forgot to mention in my last post about Java, you should always look for possibilities to beef up your resume with buzzwords. Even if I just wrote a little wiki for handling work projects in Rails I could put that on my CV. Such is the benefit of hype.

Others have written on the differences between Ruby and Python; I'll not add to that here, except that it was in a way harder to switch between Ruby and Python than between Python and Java, because the small differences in syntax keep catching you out. Anyway, on to Rails.

The immediate first impression is that TurboGears is more verbose(or explicit, if you like) than Rails. For example:

RoR:

class NewsController
@articles = Article.find_all end

end


TG:

import cherrypy
import turbogears
from turbogears import controllers
import model

class News(controllers.Controller):

@turbogears.expose(template="news.templates.index")
def index(self, **kw):
return dict(articles = model.Article.select())


One thing to note is how you have to tell TG what methods to expose to the web, which template to use, and what data goes in the template. In RoR this is decided for you; every method by default is exposed, any data in the method goes in the template, and the name of the template is the same as that of the method (in this case, index.rhtml). You can override these, but a lot of assumptions are made on your behalf.

Let's look at how each system handles the model:

RoR:

class Article < ActiveRecord::Base
end

TG:

class Article(SQLObject):

title = StringCol(length=200)
maintext = StringCol()
created = DateTimeCol(default = datetime.now)
category=ForeignKey("Category")
author = ForeignKey("User")


Again RoR's ActiveRecord works implicitly: it looks for a corresponding database table and maps rows to Article objects. With SQLObject you define the columns in Python code and then the object creates the corresponding database table as needed (in this case, Article.createTable()). You can do things the RoR way in SQLObject, but in general this is only done with legacy databases.

This is the basic difference in philosophy between the two platforms. The Pythonic way is "explicit over implicit". Everything is out for show: you know what modules are imported, you know what methods are exposed, you know what columns are defined and so on. It may take more keystrokes but the extra code let's you know what is happening when things go wrong. The Ruby way (or at least the Rails way) is the opposite: take the burden off the developer, don't bother them with the petty details that get in the way and add to the line noise.

RoR does make for more readable code. However, there is a caveat: when things go wrong, or when you want to do something different, it's a lot more work to fix the problem than if it's always obvious what's going on. In that way RoR is the anti-J2EE; it assumes everything for you. I can see the advantages, but I also find it annoying and presumptious: I want to decide upfront what methods to expose and how my data model should look. In fact, Zope has inspired such hatred amoing Pythonistas for just that reason: things like acquisition doing mysterious business behind the scenes that cannot be explained, which is lovely when it works but a source of immense frustration when it doesn't.

Finally, one should also consider features available in TG that are not in RoR and vice versa. TG has the Toolbox, an over the web admin application that comes with a set of goodies like a relational model designer and data browser, localization tool, and so on. More importantly, it has good internationalization support, including localized date formatting and the like. This is really, really important if you work in Europe: in Finland,for example, I often have to develop sites that are available in Finnish and Swedish (Swedish is Finland's second official language) as well as for example English, Estonian and Russian. I'm not sure how well RoR supports internationalization.

Both have form widgets, though in different ways: RoR just uses simple functions in templates, whereas in TG you create form and widget objects and insert them into your templates. RoR uses ASP or PHP style text-based templating, TG uses Kid, an XML-based template engine that ensures well-formed HTML or X(HT)ML. RoR has scaffolds, TG has DataControllers. Which features you need and which is the better way of doing things is again down to requirements and preference.

In summary, both are well-designed and fun to work with. Both kick Java's fat corporate ass. They have different approaches to the same problem, but that's OK:I like the Pythonic way of TurboGears but I can see that others prefer RoR's magical implicitness. RoR has better marketing which makes it easier to persuade your boss to let you use it. It is also more stable, being in existence 3 times longer than TG, but TG makes use of well-designed, mature components like CherryPy and SQLObject. Python has more libraries than Ruby, Ruby has nice features for closures and the like. As always, YMMV.

My next comparison will be TurboGears vs the various Python web development frameworks.

Tuesday, January 17, 2006

TurboGears vs Java

I have a large, upcoming project looming at work; no details can be revealed at present for confidentiality reasons, but it will be fairly high-traffic, and it will have a lot of features.

As a TurboGears contributor I immediately thought of using this platform for the task: it has everything the project will need, for example localization (must support English and Finnish), identity management, etc. However, it is still unstable (coming up to version 0.9) and in the interests of the customer I felt I should investigate other possibilities first.

I did some Java programming a couple of years ago, mainly non-web/Swing stuff but also some servlet work with Velocity and plain JDBC. One of the requirements is that the application may have to integrate with a third party tool which happens to have a Java API, so Java may be a fine contender.

Looking at the Java landscape today after years of PHP/Python it's quite clear that J2EE, in the sense of web tier + EJB, is hardly in use any more except perhaps in the largest of companies. The most popular solution (going by blog posts and discussion groups, I have no idea about real world usage) seems to be Spring + Hibernate. Digging deeper I followed an excellent Spring tutorial to get started.

Spring has an ambitious scope, but the part I was looking at, Spring MVC, is fairly straightforward: it uses the Command pattern, each command class represents an "action" such as login, checkout, do search etc. Hibernate is again a pretty straightforward way to map relational models Java objects. Spring can be used with JSP, Velocity, Tapestry or some other presentation layer.

Localization is well supported in Java, and I liked how it was taken as granted that you need localized messages, unlike in PHP or Python where (despite huge numbers of non-Anglophone developers) it seems more of an afterthought. Certainly that is the impression I got when I wrote the i18n package for TurboGears. For example, handling Unicode in Python is a real pain. GNU gettext is supported by Python but somehow the Java localization system seems a lot simpler.

One thing that came to mind however was the sheer verbosity of Java. I had forgotten just how much line noise is required to even do the simple stuff. I don't mean the core syntax as such but the tendency of Java developers to fly into a stratosphere of abstraction layers. Along with the countless number of XML files I can see why Java developers love (or need) their IDEs so much; even for a simple tutorial application the mind-boggling number of abstract classes, interfaces, XML configuration files and so on and so forth left me wondering how a single person could possibly keep track.

Nevertheless, Ant was nice once it was up and running; compiling and deploying to Tomcat and restarting Tomcat could be done with a single command. A little more work there than,say, reloading a PHP-generated page in your browser, but not oppressive. And catching compile-time errors was a time-saver.

That's the good thing about Java vs. Python or Ruby; its boring predictability. But why the love of abstraction ? In TurboGears, for example, you have a SQLObject class for your model, say Product. It may look something like this:

class Product(SQLObject):
description = StringCol()
price = CurrencyCol()
quantity = IntCol()
category = ForeignKey("Category")


That's it. 5 lines of code and your class is done. You can access it in your code for example like this:

# get all products costing less than 10 euros

cheap_products = model.Product.select(model.Product.q.price < 10.00)


The equivalent Java code may exist not in 5 lines but 5 files, for instance:

  • Product.java : plain Java object to hold data
  • ProductDao.java : interface for accessing Products
  • HibernateProductDaoImpl.java : Hibernate-specific implementation of ProductDao
  • ProductService.java : class which accesses ProductDao interface and returns Product instances
  • Product.hbn.xml : Hibernate XML mapping for Product to relational table

Now granted the added abstraction gives you greater flexibility down the line: if in the future you decide to replace Hibernate with TopLink or some other ORM, or you get your products from XML or flat files or over a web service, you don't need to gut your code across the board, just drop in the new classes, change some XML configurations, and you're done. The equivalent SQLObject code in Python works for a number of relational databases but any more significant changes (e.g. another ORM or entirely different storage layer) would require recoding parts of the app. Of course you could write a Python application with a similar degree of complexity (Zope3, I'm looking at you). But such abstractions in the Python world are uncommon.

In the real world, however, how often are you going to change your storage layer ? For example, if I'm building an online store I design the relational model to a T and go out and set up a database, say Oracle, and design the application to talk to that. That is the part of the system that is least likely to change.

Of course Java developers would accuse me of over-simplification, and they would probably be right. And Java developers earn a whole lot more than Python developers, so maybe they have a point :-)

Next post: comparing TurboGears and Ruby on Rails!