TopHatenarはRails並の軽さで作られている
Java好きな僕としては、TopHatenarが、Javaでも(Seasar2ファミリーを使えば特に)スピーディーなWeb開発ができることの実証例になれば良いなあと思っています。
ただし、HOT deployが使えない場合はさすがに「Javaでもスピーディー」とは言えないかも*1。S2ファミリーのフレームワーク(SAStruts, Cubby, Teeda, etc)なら基本的にHOT deploy対応なので大丈夫です。
ここで、TopHatenarのコードの一部を引っ張り出して、仮に同じことをRailsでやったらどうなるか考えてみようと思います。
結論を先に言うと、すごく似た感じになります。TopHatenarはCubbyを使ったけど、SAStrutsでも大枠は同じになるはず。
以下は、http://tophatenar.com/view/{user}にアクセスしたとき呼ばれるアクションです(説明を簡単にするため書き換えた部分あり)。
- ViewAction.java
@Path("/") public class ViewAction extends Action { // リクエストパラメータ public String user; // 画面出力用オブジェクト public String diaryTitle; public int allHatenarCount; public HatenarModel model; public Rank subscriberRank; public Rank bookmarkRank; // サービス(DIされる) public HatenarService hatenarService; public RankingService rankingService; @Path("view/{user,[A-Za-z0-9\\-_]+}") public ActionResult view() { Hatenar hatenar = hatenarService.getHatenar(user); if (hatenar == null) { HatenaDiaryAPI api = new HatenaDiaryAPI(); if (api.isUserPresent(user)) { hatenarService.addHatenar(user); return new Forward("view/queued.html"); } else { return new Forward("view/error.html"); } } diaryTitle = hatenar.diaryTitle; Rankings rankings = rankingService.getRankings(); allHatenarCount = rankings.subscriberList.size(); model = hatenarService.getHatenarModel(hatenar.id); subscriberRank = rankings.subscriberList.getRank(model); bookmarkRank = rankings.bookmarkList.getRank(model); if (subscriberRank != null && bookmarkRank != null) { return new Forward("view/index.html"); } else { return new Forward("view/queued.html"); } } }
もしTopHatenarをRailsで作っていたら、上のViewActionに相当するコントローラは次のような感じになります。
- view_controller.rb(想像)
class ViewController < ApplicationController def index hatenar = get_hatenar(params[:id]) if !hatenar api = HatenaDiaryAPI.new if api.is_user_present(user) add_hatenar(user) render :action => "queued" else render :action => "error" end return end @diary_title = hatenar.diary_title rankings = get_rankings() @all_hatenar_count = rankings.subscriber_list.size @model = get_hatenar_model(hatenar.id) @subscriber_rank = rankings.subscriber_list.get_rank(model) @bookmark_rank = rankings.bookmark_list.get_rank(model) render :action => "queued" unless @subscriber_rank && @bookmark_rank end def queued end def error end end
似てますよね。Javaの場合はpublicフィールドの宣言が必要なのでちょっと行数が多いけど、IDEの補完がバシバシ効くことを考えれば、ほとんど差はないでしょう。
ちなみに、TopHatenarのプログラム総行数は約1800行、コメントと空行を除くと1300行ぐらいです(うちグラフ描画部が350行くらい)。
ここで生産性云々の議論をするつもりは全くないですけど、JavaでもLLに近い感覚で開発できるケースがあるということは十分言えると思います。