Brian's Waste of Time

Sat, 27 Aug 2005

Leo's Blogging Again!

I'm glad Leo has returned from his "escape geekery" sabbatical! In particular I'd like to point out a post on changing how we write jarvar =)

Leo gives us some code:

iterate(
      over( pairs(coll) ) )
    .skipIf(  keyIsInstanceOf(UnprocessableObject.class)  )
    .returning(  arrayOf(Pair.class)  )
    .exec(
      new Object(){Object process(Pair pair){
        print(  "%s -> %s", pair.getKey(), pair.getValue()  );
      }}  );  

What caught my eye is that it looks like a bunch of stuff I've been doing lately when building API's:

handle.inTransaction(new TransactionCallback() {
    public void inTransaction(Handle handle) throws Exception {
        handle.prepareBatch("insert into something (id, name) values (:id, :name)")
            .add(new Something(1, "one"))
            .add(new Something(2, "two"))
            .add(new Something(3, "three"))
            .add(Args.with("id", new Long(4)).and("name", "four"))
            .add(Args.with("id", new Long(5)).and("name", "five"))
            .execute();
    }
});
assertEquals(new Integer("5"),
             handle.first("select count(*) num from something")
                   .get("num"));

or

AsyncHelper.tryUntilNotInterrupted(new AsyncHelper.Helper() {
    public void cycle() throws InterruptedException {
        pendingWriteFrames.put(new FrameBuilder(Stomp.Responses.ERROR)
                        .addHeader(Stomp.Headers.Error.MESSAGE, message)
                        .toFrame());
    }});
}

which a popular couple libraries with reasonably well respected client api tends to do

return (Thing) getHibernateTemplate().execute(new HibernateCallback() {
    public Object doInHibernate(Session session) throws HibernateException {
        return session.createQuery("select s from Thing s where " +
                                   "s.wombat = :wombat and " +
                                   "s.mouse = :mouse")
                .setString("wombat", wombat)
                .setString("mouse", mouse)
                .uniqueResult();
    }
});

All of these examples use a common idiom from Ruby, Objective-C, and (I am told) Smalltalk -- message chaining. It leads to some really natural feeling and expressive code (which can look awfully funny at first, but you get used to it really fast, and then get frustrated when you cannot use it.

Next time you write a method with no return (a void method) consider having it return this instead. It breaks JavaBeans, sadly, which explicitely say a setter returns void, which limits its usability as the JavaBean naming convention is one of Java's serious strong points. It works nicely for chaining action style things though!

I blame Ruby. Leo blames Python. Gavin has blamed Smalltalk (he doesn't look old enough to be a Smalltalker, who'd have thunk). I don't know who gets blamed for the callbacks and templates in Spring, or to what they attribute the practice =)

2 writebacks [/src] permanent link