Sunday, October 23, 2011

アリエル・ネットワークを退職しました

私事ですが、先週でアリエル・ネットワーク(以下アリエル)を退職しました。正確には最終出社を終え、今はまだ有給消化期間です。

"美しいプログラムを書けるプログラマ"の言葉に共感し入社したのが2007年2月、そこから4年9ヶ月をアリエルで過ごしてきました。その間いろいろな変化がありました。20名だった社員は100名に増え、オフィスは2回移転、初期から関わってきた製品は成長して大きくなり、そして僕の立場はマネージャになっていました。

マネージャにならないかと打診されたのは1年ちょっと前でした。不安はありましたが、プロジェクトやチームを動かせる機会なんてそうそうないですし、エンジニアと兼務してもいいと言われたのでやらせてもらうことにしました。一応誤解のないように補足しておくと、アリエルではエンジニアの先にマネージャがあるわけではありません。いようと思えばずっとエンジニアでいれます。

マネージャになってからは、開発プロセスの改善や、チーム作りなど、望んでいたとおりそこでしか得られない貴重な体験ができました。しかしマネージメント上の課題や問題(半分くらいは開発とは直接関係のないこと)が頭の中を占める割合が増え、エンジニアの方に思うように力を入れらなくなると、果たしてこれが今自分がやりたいことなのだろうか、という疑問が出始めました。仕事だからと割り切り、生きがいを個人でのエンジニア活動に限定することもできなくなはいでしょうが、日々の大半は仕事です。僕はマネージャを辞め1エンジニアとして再出発することを決断しました。

再出発には別の道を進むことを条件に付け加えました。"不得手なことをする"と言い換えてもいいです。入社以来1つの製品をひたすら開発し続ける中、得意とするフィールドができあがり、そこでしか勝負しない自分に嫌気がさしていました。その思いはプロジェクトに余裕がない状態でマネージャが考えることではない、と自分に言い訳しながら無視してきましましたが、こうなればそんな言い訳はできません。

当初、アリエルに残る道も考えましたが、選んだのは退職でした。しがらみを乗り越えるより、不便になること覚悟で何もかも捨てて身軽になる方に魅力を感じました。とにかくシンプルにしたかった。

アリエルではほんとにいろんな人にお世話になりました。特に開発の3アミーゴスである、井上さん大谷さん中山さん、そしてチームの皆には最後まで迷惑をかけ、いろいろと助けてもらいました。この場を借りて改めて感謝の言葉を伝えてたいと思います。本当にありがとうございました。

11月からは新しい場所で出直しです。これからもよろしくお願いします。

Thursday, October 13, 2011

Groovy の AST を楽に書く方法

AST を書くのは大変

Groovy は AST 変換の実装用に AST を生成する DSL を提供しています。ところがこの DSL は複雑で習得が困難です。次のような GString の AST を生成したいとします:
"Hi, $name."
その場合、DSL はこうなります。こんなもの構文と同じ数覚えられません:
gString 'Hi, $name.', {
    strings {
        constant 'Hi, '
        constant '.'
    }
    values {
        variable 'name'
    }
}

ソースコードから直接生成することもできますが、コンパイラによるチェックの恩恵を受けられないですし (これについては Joachim Baumann が説明しています)、DSL よりパフォーマンスが悪いです。次のベンチマークを見てください:
@Grab('com.googlecode.gbench:gbench:0.2.2')
import gbench.BenchmarkBuilder
import org.codehaus.groovy.ast.builder.AstBuilder

def benchmarks = new BenchmarkBuilder().run {
    'DSL to AST' {
        new AstBuilder().buildFromSpec {
            gString 'Hi, $name.', {
                strings {
                    constant 'Hi, '
                    constant '.'
                }
                values {
                    variable 'name'
                }
            }
        }
    }
    'Code to AST' {
        new AstBuilder().buildFromString('"Hi, $name"')
    }
}
benchmarks.prettyPrint()

            user system cpu    real

DSL to AST     0      0   0  339918
Code to AST    0      0   0 2076590
というわけで、DSL を実装コードやテストコードを見ながら書く羽目になるのですが、これが大変な作業になることは簡単に想像してもらえるはずです。

どうすれば楽に書けるのか

この問題を解決する為に DSL をコードから自動生成してくれるライブラリを作りました。 AstSpecBuilder と名付けたこのライブラリはここで公開しています。使い方はとても簡単、build メソッドに馴染みのあるコードを文字列で渡すだけです:
import astspecbuilder.*

def spec = new AstSpecBuilder().build('"Hi, $name."')

def expectedSpec =  '''\
block {
    returnStatement {
        gString 'Hi, $name.', {
            strings {
                constant 'Hi, '
                constant '.'
            }
            values {
                variable 'name'
            }
        }
    }
}
'''
assert expectedSpec == spec
AST からも生成できます。というより実は上のメソッドは次のコードのショートカットに過ぎません:
import astspecbuilder.*

def ast = new AstBuilder.buildFromString('"Hi, $name."')
def spec = new AstSpecBuilder().build(ast)

インデントはデフォルトではスペース4つですが、変更するオプションが付いてます。次のようにすると DSL がタブ1つでインデントされます:
def spec = new AstSpecBuilder(indent: '\t').build('"foo"')

def expectedSpec = '''\
block {
\treturnStatement {
\t\tconstant 'foo'
\t}
}
'''
assert expectedSpec == spec