kなんとかの日記 このページをアンテナに追加

2009-06-25

Web アプリのボトルネックはテンプレートシステムにあり

| 02:18 |  Web アプリのボトルネックはテンプレートシステムにあり - kなんとかの日記 を含むブックマーク

Ruby のネタがないので Python でお茶をにごす。

Python の速度を 5 倍速くするという目標を掲げている unladen-swallow というプロジェクトがあるんだけど (日本語はこちら)、その中に次のような一節があった。

Unladen Swallow's benchmark suite is focused on the hot spots in major Python applications, in particular web applications. The major web applications we have surveyed have indicated that they bottleneck primarily on template systems, and hence our initial benchmark suite focuses on them:

Unladen Swallowのベンチマーク集は、主要なPythonアプリケーション、特にウェブアプリケーションホットスポットにフォーカスしている。我々が調査した主要なウェブアプリケーションでは、主にテンプレートシステムがボトルネックであると分かった

Google Code Archive - Long-term storage for Google Code Project Hosting.

(翻訳は日本語訳より引用、強調は筆者)


もちろんこれはデータベースアクセスを除いたベンチマークだろうけど、それでもこのことを言い切ったのは注目に値する。

これは Python のプロジェクトだから調査対象には当然 Django が入っている。そして Djangoテンプレートエンジンがボトルネックになっていることに気づいたのだろう。

Djangoテンプレートエンジンはむちゃ遅いんだよね。機能も、テンプレート継承以外は見るべきものもないし。正直、Google が AppEngine でなぜあれを採用したのかわからん。スピードにこだわる Google だからこそ、Django はやめてほしかった。


で、何がいいたいかというと・・・

テンプレートエンジンは重要だからマイナーなセッションにも参加しましょうね

2008-08-02

XMLC の紹介

| 09:47 |  XMLC の紹介 - kなんとかの日記 を含むブックマーク

実は私もxmlcのメリットってよく分かってないです..orz

よかったら教えてください。

2008-07-20 - kなんとかの日記

XMLC (XML Compiler) は、Java製のテンプレートシステムのひとつ。


仕組み:

  1. HTMLテンプレートを「コンパイル」し、DOMを生成するようなJavaクラスを自動生成する。
  2. Javaクラスが生成したDOMを操作して、変更したい箇所の要素やテキストを変更する。
  3. 変更したDOMHTMLに変換し、出力する。

特徴:


欠点:

  • DOM操作が複雑
    • 特にループは超面倒
    • テキストの置換だけなら簡単 (XMLCがそれ用のメソッドを生成してくれるので)
  • XML/HTMLしか生成できない
    • Webアプリが対象なら気にする必要はない
  • 知名度が低い

XMLCは、仕組みが非常に単純でわかりやすく、動作も高速、おまけにテンプレートHTMLデザインがまったく崩れないという、なかなか優れたテンプレートシステム。

ただし、ループ時のDOM操作がほんとに面倒であり、この欠点が他の長所を打ち消してあまりあるほど。


興味が湧いた人はどうぞ。

http://xmlc.enhydra.org/

2008-07-22

デザイナに eRuby を書かせるべきか否か

| 01:11 |  デザイナに eRuby を書かせるべきか否か - kなんとかの日記 を含むブックマーク

masayang氏に、わざわざ回答をいただいた。ありがとうございます。

  • eRubyでXHTMLの大枠を記述するのはRubyエンジニア
  • そのeRubyの編集をデザイナにも解放せよ
  • デザイナがeRuby構造を壊したとしても、テストで検知できるし、最悪リポジトリから戻せるではないか
技術が変われば分業体制も変わる - サンフランシスコ出羽守手記(masayangの日記

これは同意できる。

  • リポジトリの概念はCSSの階層構造を理解できるデザイナなら、すぐに習得できる
技術が変われば分業体制も変わる - サンフランシスコ出羽守手記(masayangの日記

これはよくわからない。リポジトリと、CSSの階層構造は、似ているとは思えない。

  • デザイナが先にHTMLテンプレートを作成し、プログラマがそれを参照にeRubyを書くという古典的手法では、「先に画面デザインを確定させる必要がある」ということになり、Agileの持ち味をぶち壊すことになる。
技術が変われば分業体制も変わる - サンフランシスコ出羽守手記(masayangの日記

eRuby や Smarty のようにテンプレート中にロジックを埋め込むタイプだと、主に 2 つのアプローチがある。

masayang氏は、(a)のやり方は古典的であり、Agile の持ち味をぶち壊すといっており、37signals がとっているような (b) のやり方を勧めている。

(ここまではあってるよね?)


自分としては、(a) も (b) も間違いだと確信している。こういう問題が発生するのは、そもそも HTML の中にロジックを埋め込んでしまう eRuby や Smarty の仕様が原因である。HTML と Presentationg logic をちゃんと分離するようなツールを選べば、このような問題は発生しないし、デザイナが eRuby を書く必要もない。

eRuby や Smarty のようなタイプのものは、プログラマが HTML も書く場合は手軽な方法でありお勧めできるが、デザイナを入れて協業するようなプロジェクトには向かない。


で、id:kwatch さんの指摘

> いやー、超ありそう。つーか、SmartyとかJSPとかでもありそう。デザイナ涙目。

が成立するかどうかってのは、デザイナ作業によるデグレードをテストで検知できるか否かにかかっているのではないかと。つまり、テストフレームワークの選択と、それをチームが正しく使っているかどうか。

技術が変われば分業体制も変わる - サンフランシスコ出羽守手記(masayangの日記

違うと思うなあ。デザイナと協業しようという工夫と熱意がプログラマにあれば、協業するためのライブラリを持ってくる(あるいは作ってしまう)なんて難しいことではない。でも現実にはそんなプログラマがいないから、デザイナが苦労しているだけ。

正直、デザイナに eRuby を書かせるなんてのは、プログラマの都合をデザイナに押し付けているだけだと思う。

Ruby on Rails でいえば、DHH が eRuby で満足しちゃっているのが元凶。


進化した技術を習得した技術者が集まる現場では、当然分業体制も変わってくるよね、という当たり前といえば当たり前の結論。だけど、わかってない人達は、わかってないこともわかってくれない。COBOL屋の話と同じだ。

技術が変われば分業体制も変わる - サンフランシスコ出羽守手記(masayangの日記

まあ、これはその通りだと思う。デザイナが (JavaScript も含めて) プログラムを書くようになるんだから、プログラマもデザインに限らず要件定義や営業もできるようになるべき。


参考:米国における「Web Designer」求人一例

...(snip)...

もちろん、プログラマとデザイナの分業を維持している会社もまだまだ残っているよ。でも、ちょっと検索しただけでも、そういう分業体制が破壊された会社が見つかる、という意味をこめて上記3事例を載せてみた。

技術が変われば分業体制も変わる - サンフランシスコ出羽守手記(masayangの日記

これはすごい。デザイナの募集のはずなのに、まるでプログラマを求めているかのような条件ではないか。参考になるなあ。

この条件をクリアできるデザイナだと、給料はどのくらいになるのかな。これが平均レベルとかだったらやばいね。

2008-07-20

デザイナに eRuby を書かせるのは、あくまで次善策

| 23:07 |  デザイナに eRuby を書かせるのは、あくまで次善策 - kなんとかの日記 を含むブックマーク

Ruby on Rails の開発元である 37signals では、デザイナが eRuby ファイルを編集するだけでなく、ヘルパーとかも書くらしい。

UI Design on Rails

  • 37signalsにおけるデザイナとプログラマ連携の事例紹介
  • デザイナにも積極的にviewファイル(.erb/.rhtml)を触らせろ、そしてリポジトリを使わせろ、というお話
  • 最初はちょんぼもあるかもしれない。でも、そこで壁を高くしては駄目。ちゃんと対話し、一緒にイタレーションを回せるようになれば、開発はとてもうまくいく。
  • 目から鱗が落ちた
RailsConf 2008まとめ(簡易版) - サンフランシスコ出羽守手記(masayangの日記

こういうのはやめてほしいなあ。理想的だというのはわかるんだけど。

37signalsのやり方は、自社に専属のデザイナを用意できて、かつそのデザイナがHTMLをエディタで書いてくれるような心の広いデザイナである場合にのみ有効だよな。

でもふつうは、専属のデザイナなんていやしないし、テキストエディタじゃなくてDreamweaverを使ってる。

もし、仮に、37signalsのやり方が広まったとしたら、そして今の Ruby on Rails 人気を考えたら、デザイナが eRuby を書くのが当たり前だと思うバカプログラマが増えそう。

そしてデザイナが文句をいったら、「これが正しいやり方なんだ、37signalsもそうしている」とか言いそう。

それでも37signalsではデザイナにRailsの流儀を一つひとつ丁寧に教えるけど、こういうバカプログラマはそういうことは面倒くさがってしない。めんどくさいことはせずに、eRuby を押し付けることだけ真似しそう。


いやー、超ありそう。つーか、SmartyとかJSPとかでもありそう。デザイナ涙目。

masayangmasayang 2008/07/20 23:46 トラックバックありがとうございます。

eRubyを最初に書くのはプログラマですよ。

それをデザイナに触らせることを恐れるな、ということを37signalsの人は言ってたのです。取り返しのつかないことをされても、リポジトリから戻せれば問題なし。ちゃんとテスト書いてればデサイナがまずいことをしても検知可能でしょ。

日本の現場ってDreamweaverなんか使ってるのですか??

hitachitac 2008/07/21 00:31 デザインのロジックの完全な分離って、本当に実現できるのでしょうか?

いろんなテンプレートエンジンとか、覗いても、結局、プログラマ側か、
デザイナ側が、ある程度「余計な仕事」を行うことで成り立っていると思うのですが。
(少なくともどちらかに、デザイン、プログラムの両方に精通した人材がいる場合に
 効率よく作業が回ることが多いように思われます)

37signalsのやり方ってのは、デザイナにプログラム側への歩み寄りをさせる試みだってことでしょう。
(もちろん、プログラマ側にもデザイナ側の作業が分かる人間がいたほうが、よりいいはずです。)

アジャイル型の開発プロセスには、そういうやり方の方が相性がいいと思います。

kwatchkwatch 2008/07/21 08:20 masayangさん:
RailsConf2008のレポートは参考になりました。ありがとうございます。

> eRubyを最初に書くのはプログラマですよ。

はい、それは構わないと思います。

> それをデザイナに触らせることを恐れるな、ということを37signalsの人は言ってたのです。取り返しのつかないことをされても、リポジトリから戻せれば問題なし。ちゃんとテスト書いてればデサイナがまずいことをしても検知可能でしょ。

そのためには前提条件があるんじゃないでしょうか、ということを本文で書いています。まず専属のデザイナを雇うところから、条件として厳しいように思います。
また37signalsの場合は、デザイナに対してきちんと教育をしたうえでeRubyを使わせたりリポジトリを使わせたりしていますが、バカプログラマはそういうことをせずに、eRubyを強要するところだけ真似しそうなのを心配しています。これも本文に書いてますけど。

> 日本の現場ってDreamweaverなんか使ってるのですか??

Dreamweaver*なんか*ですか。Dreamweaverはよくできてると思いますが、だめですか?
GoLiveはともかく、世界的にはDreamweaverは使われてないんでしょうか。

kwatchkwatch 2008/07/21 08:28 hitacさん:

> デザインのロジックの完全な分離って、本当に実現できるのでしょうか?

できます。XMC, Mayaa, Tapestry, Amrita, CGIKit, Kwartz あたりを調べてみてください。
#Tapestryあたりはまだ甘いところもありますが。

> いろんなテンプレートエンジンとか、覗いても、結局、プログラマ側か、
> デザイナ側が、ある程度「余計な仕事」を行うことで成り立っていると思うのですが。

なにをもって「余計な仕事」とおっしゃっているのか分かりませんが、その余計な仕事も、許容範囲であればいいんじゃないでしょうか。そのおかげでちゃんと分業できるなら、大きな利益ですよ。

> (少なくともどちらかに、デザイン、プログラムの両方に精通した人材がいる場合に
>  効率よく作業が回ることが多いように思われます)

これはその通りなんですけど、知識があるからといってデザイナにeRubyを書かせるのが本当に効率的かというと、そうは思いません。
デザイナにRailsの知識があったとしても、<% %>だらけのファイルより、純粋なHTMLだけのファイルのほうが、デザイナにとっての作業効率は高いですよね。

> 37signalsのやり方ってのは、デザイナにプログラム側への歩み寄りをさせる試みだってことでしょう。
> (もちろん、プログラマ側にもデザイナ側の作業が分かる人間がいたほうが、よりいいはずです。)
>
> アジャイル型の開発プロセスには、そういうやり方の方が相性がいいと思います。

別に歩み寄りに反対しているんじゃなくて、自分は歩み寄りをしないくせに相手(デザイナ)の歩み寄りを強要するようなバカプログラマが増えることを懸念しています。

タイトルに書いてますけど、デザイナがeRuby(やSmartyやJSP)を書くのはあくまで次善策であって、最善策ではありません。
それを分からず、デザイナもeRubyを書くのが正しいやり方だ、37signalsもそう言っている、というような風潮にはなってほしくないです。

chunchun 2008/07/22 01:22 >XMC
XMLCではないでしょうか。

kwatchkwatch 2008/07/24 09:02 その通りです。間違えました。ご指摘ありがとうございます。
# XMLCはまったく流行りませんでしたねー。

chunchun 2008/07/26 21:21 実は私もxmlcのメリットってよく分かってないです..orz
よかったら教えてください。

2008-06-02

eRubyを35行で実装してみる

| 21:06 |  eRubyを35行で実装してみる - kなんとかの日記 を含むブックマーク

以前のエントリで「eRubyは50行もあれば実装可能」と書いたけど、eRuby の実装は正規表現を使えば極めて簡単。Erubisには約50行で実装されたtiny.rbが含まれているけど、これをさらに小さくしてみたら、35行で実装できた。code golfみたいなことは一切せず、空行を省いたりもしていない。


class TinyEruby

  def initialize(input=nil)
    @src = convert(input) if input
  end

  attr_reader :src

  def result(_binding=TOPLEVEL_BINDING)
    eval @src, _binding
  end

  def convert(input)
    src = "_buf = '';"       # preamble
    input.scan(/(.*?)<%(=)?(.*?)%>/m) do |text, ch, code|
      src << " _buf << '#{escape_text(text)}';" unless text.empty?
      if ch == '='           # expression
        src << " _buf << (#{code}).to_s;"
      else                   # statement
        src << code << ';'
      end
    end
    rest = $' || input
    src << " _buf << '#{escape_text(rest)}';" unless rest.empty?
    src << "\n_buf.to_s\n"   # postamble
    return src
  end

  private

  def escape_text(text)
    return text.gsub!(/['\\]/, '\\\\\&') || text
  end

end

expressionとstatementの部分をまとめて

        src << (ch == '=' ? " _buf << (#{code}).to_s" : code ) << ";"

とかにすれば30行を切ることもできるだろうけど、そこまではしない。

ただ、これだと正規表現でのグルーピングのせいで極めて遅くなる場合があるので、ここでやっているように正規表現から遅いグルーピングを取り除く。これで40行。

class TinyEruby

  def initialize(input=nil)
    @src = convert(input) if input
  end

  attr_reader :src

  def result(_binding=TOPLEVEL_BINDING)
    eval @src, _binding
  end

  def convert(input)
    src = "_buf = '';"       # preamble
    pos = 0
    input.scan(/<%(=)?(.*?)%>/m) do |ch, code|
      match = Regexp.last_match
      len   = match.begin(0) - pos
      text  = input[pos, len]
      pos   = match.end(0)
      src << " _buf << '#{escape_text(text)}';" unless text.empty?
      if ch == '='           # expression
        src << " _buf << (#{code}).to_s;"
      else                   # statement
        src << code << ';'
      end
    end
    rest = $' || input
    src << " _buf << '#{escape_text(rest)}';" unless rest.empty?
    src << "\n_buf.to_s\n"   # postamble
    return src
  end

  private

  def escape_text(text)
    return text.gsub!(/['\\]/, '\\\\\&') || text
  end

end

またコメント (<%# %>) にも対応してみる。ついでにSmart Trim対応、つまり文の場合は前後の空白を取り除くようにしてみる (式の場合は何もしない)。こうすると、出力に余計な空行が含まれないようになる。これで52行。

class TinyEruby

  def initialize(input=nil)
    @src = convert(input) if input
  end

  attr_reader :src

  def result(_binding=TOPLEVEL_BINDING)
    eval @src, _binding
  end

  def convert(input)
    src = "_buf = '';"       # preamble
    pos = 0
    input.scan(/(^[ \t]*)?<%([=\#])?(.*?)%>([ \t]*\r?\n)?/m) do |lspace, ch, code, rspace|
      match = Regexp.last_match
      len   = match.begin(0) - pos
      text  = input[pos, len]
      pos   = match.end(0)
      src << build_text(text)
      if ch == '='           # expression
        src << t(lspace) << " _buf << (#{code}).to_s;" << t(rspace)
      elsif ch == '#'        # comment
        src << t(lspace) << ("\n" * code.count("\n")) << t(rspace)
      else                   # statement
        if lspace && rspace
          src << "#{lspace}#{code}#{rspace};"
        else
          src << t(lspace) << code << ';' << t(rspace)
        end
      end
    end
    rest = $' || input
    src << build_text(rest)
    src << "\n_buf.to_s\n"   # postamble
    return src
  end

  private

  def build_text(text)
    return text && !text.empty? ? " _buf << '#{escape_text(text)}';" : ''
  end
  alias t build_text

  def escape_text(text)
    return text.gsub!(/['\\]/, '\\\\\&') || text
  end

end

このくらい簡単だと、他の言語で実装するのも簡単 (Pythonは除く)。興味のある人は移植してみるべし。


しかし、はてなのpre記法は中に<strong>相当のものは入れられないのかな。強調したい箇所が強調できないから、すごく不満なんだけど。