Ruby で手抜きテンプレートを使う

by tanabe on September 08, 2009

たまに手抜きで使うコードをなんとなく載せてみる。テンプレート使いたいんだけど、ちょっとしたスクリプトだしそもそも ERB の API どんなんだったか覚えてないし、リファレンス引くのもちょっとした手間だし。てなときに使ってる。(ERB くらい覚えろよ。という話もある。覚えてもすぐ忘れるんだよなぁ。)

sample_template = Proc.new do |param1, param2|
%Q!
とまぁこんなかんじで始まったわけですが、
この辺はぜんぶテンプレートなんですね。


だから、どんな風に何を書こうが自由なんです。

パラメタについても記法に迷うことなく
いつもの形で出力することができます。
たとえば、
 #{param1}
こんな風に。

文中にあっても#{param2}なんだか見慣れた形式で安心です。

かんたんですね。
!.lstrip
end

# 使うのも簡単。API を調べたりする必要もまずありません。
puts sample_template.call(p1, p2)

こんなん。邪道? lstrip で最初の改行を消しているあたりもださい。

ちなみにコードジェネレータのテンプレートをこれで書いていて、いつのまにかコード行数が育ってきてそろそろちゃんとテンプレートエンジン導入しないといけないなーと思ってるのは内緒。

結論としては require 'erb' と ERB.new(text).result だけなんだから覚えろよ。と。

  

「ソフトウェア開発はカオスであり、かつフラクタルである」

by tanabe on April 21, 2009

ということで、戦術的ピリオダイゼーション理論(以下、PTP)に夢中な今日この頃です。先に言っておくと今日の話は強力に電波なので気をつけるように。(PTP がではなく、ソフトウェア開発の類似性を云々しているこのエントリが。)

PTP というのは要約すると、「フッボールの本質は予測不可能性にある。だから様々なレベルでの状況判断(=戦術)を強化することでフッボールが上達する。」(フッボールという表記はネタ元の村松さんブログの表記に合わせた。まぁ、サッカーです。)というコンセプトだと理解した。ポイントは状況判断が予測不可能性を押さえ込んでねじ伏せる道具ではなく、柔軟に状況に応じて自分が変化し対処していくための道具と位置づけられているところ。

つまるところ、村松尚登さんのブログを読め。と。

で、これが(というか、村松さんがというべきか)いろいろ良いこと言ってる。

  • 戦術の基本はチーム戦術
  • 「個を育てる」というコンセプトはありません。あくまでも『トレーニングはチームプレーの改善のために存在する』というコンセプト
  • フッボールの本質が“テクニック”ではなく“カオス”だとすると、フッボールにおける最重要課題はボールと友達になることはでなく“カオス”と友達になることなのではないでしょうか。
  • “カオス”は混乱です。そして、混乱の中で闇雲に戦っていては敵を倒すことはできません。その混乱の中に存在する小さな法則(=定跡)をなるべく多く見つけ出し、混乱により良い形で適応できる術を身に付けることが、混乱の中での戦い方なのではないでしょうか。
  • つまり、カオスと友達になるということは、「他人の指示の声さえもがカオスに影響を及ぼす可能性がある」ということをしっかりと認識し、他人の指示やアドバイスに耳を傾けつつも、自らの判断でその瞬間の状況に合わせてジャズピアノ的に即興演奏を続けて行くこと
  • カオスと友達になるというのは、途絶えることなく続くカオスの変化に柔軟に適応することを可能にするために武士のようにニュートラルな姿勢と心をキープすること
  • その証拠に、リフティングをしている子供の邪魔をしようとすると「邪魔をするな!」と怒られます。予期せぬ変化(=邪魔)を許容していない時点で、彼がしているリフティングは“カオス”ではないのだと思います。

言いたいことは伝わる人には伝わるだろうから、こんなもんでいいか。

あとは、この文章なんて「あれ、どっかで読んだな」とか思ってしまって、読み返してもやっぱり同じようなことを言っているとしか思えない。

だって、フッボールの原型は試合なのですから、明日の試合に直結するチーム戦術の方が1対1の間合いの取り方よりもよっぽど大切だと思うからです。

これも村松さんのブログで見つけた引用。元はここの文章らしい。

学校を代表とする教育の一般的な方法は、完全な部分を積み上げていけば、完全な全体ができ上がるというものです。極端な場合は完全な部分が出来ないうちは、次の部分を見せない、あるいは学習者が漠然とした全体も掴めないうちに、完全な部分の習得を求めるというようなこともあります。

しかし学びの自然な姿は、大まかな全体が大まかな部分の総体へ少しずつ割れていき、部分が総体的に深まっていくというものです。つまり「大まかな全体から細かな全体へ」ということです。決して「細かな部分から細かな全体へ」ではありません。

もはや何を言いたいか、解説はいらないはず。完成に至るまでの学習と理解のプロセスだという視点で見たときには、「あー、あのことか」と。

神々の開発はまた別なのかもしれないけど、普通の人が普通の人とチームを組んで働いて、結果を求めるというのは、結局そういうことなんじゃないかなぁとしか言えない。

「守備も攻撃もテクニックもフィジカルも切り離してはいけない。
 それぞれの要素を切り離してトレーニングしても各要素が上達するだけで
 サッカーは上達しない。サッカーの上達はサッカーのトレーニングからしか
 生まれない」

via フットボールはフットボールをトレーニングすることによってのみ上達する

では“戦術的ピリオダイゼーション”では「個の成長」をおろそかにしているかというと決してそうではありません。“戦術的ピリオダイゼーション”では『フッボールチームが成長する過程でこそフッボール選手個人が伸びる。なぜならば、フッボールはチームスポーツであり戦術だからだ。このような特徴を持ったフッボールの世界で活躍できる優秀なフッボール選手は、チームが成長する過程でのみ成長する』と考えているのです。

via 戦術的ピリオダイゼーション哲学の概要

あまり一般化するのも危険なので、深入りはしないけど、いろいろヒントをもらった。

勢い余って本も買ったけど、値段分以上に得たものは大きい。フラクタルの話なんて読みながらその類似にニヤニヤしたくなる。(あ、でも本は PTP に割いているページ数は少なくて純粋にサッカーのトレーニング方法に割いているページが多いから、ソフトウェア開発的視点での興味であればまずブログを読むべき。)

ジョゼ・モウリーニョ
ルイス ローレンス ジョゼ モウリーニョ 西岡 明彦
講談社
売り上げランキング: 10281

「あとで書く」と言いつつまだ感想書いていないけど、この本も同じメッセージを受け取った。個より全体。

アジャイルな見積りと計画づくり ~価値あるソフトウェアを育てる概念と技法~
Mike Cohn マイク コーン
毎日コミュニケーションズ
売り上げランキング: 5078
  

レベル1分散でも DB で JOIN させる方法

by tanabe on January 26, 2009

いわゆる mixi のレベル1分散というものがあって、「join は使わない(方がいいケースもある)」というような話も出てきたりするんですが、join で解決できる問題はアプリケーションコード書くよりも DB にやらせたかったりします。

一方でそれぞれのテーブルは別の DB 上に載っているので、ふつうに join するわけにはいきません。

てことで、無理やり join しようとやってみた手。

まず、db_a に載っている table_a の必要なレコードを取得します。

んで、そいつの1レコードにつき一つの select 句をアプリケーションで生成します。

select
  v1 as name1
, v2 as name2
, v3 as name3
, v4 as name4 

そしてできあがった select 句を union all.

ポータブルな即席 view のできあがり。

このできあがったものを一つのテーブルとみなして join の対象とし db_b に載っている table_b, ... たちとのクエリを生成します。

これで二つの DB にまたがった似非 join が使えます。アプリケーションで妙なループを連発してコードの可読性を下げるよりもマシに使えるような気がするんですが、どうでしょうか?

発行される SQL クエリのイメージはこんなかんじ。(実際はアプリケーションの中でもう少し見通しがよいようにまとめたり整理したりしますが。)

select
  *
from
  (select v1 as name1, v2 as name2, v3 as name3, v4 as name4
  union all
  select v5 as name1, v6 as name2, v7 as name3, v8 as name4
  union all
  select v9 as name1, v10 as name2, v11 as name3, v12 as name4
  union all
   ...
  ) t1
  join
  table_b t2
    on (t1.name1 = t2.name1)
  join
  table_c
    on (t1.name3 = t3.name3)
where
  ...

もちろん、uninon all で作ったほうは index も何もあったもんではないので、そちらはそれなりにレコード数が限られていないと使い物にならないと思います。

案外パフォーマンスもまともに出る(インラインで作ってる区分テーブルみたいなもんなんで)ので、下手なアプリケーション join よりも使えるんじゃないかなーなどと思ってたりします。

  

『Exceptions を扱うたった一つの冴えたやりかた』

by tanabe on January 08, 2009

...的な釣りタイトルが付けられた Michael Feathers の "Abstracting Away From Exceptions" がおもしろかった。

コメント欄も盛り上がっているし、reddit の方にも本人が出張してコメントつけている

元エントリは「Exceptions をうまくあしらうパターン見つけた気がすんだけど、どうよ?」的な内容。そこに「いやいや、そもそも例外は・・・」みたいな指摘なんかも挙がっていて楽しい。コメントまで含めて読んで、初めてバランスがよくなってる。Aaron Powell の Should you catch System.Exception? も。

exceptions とか validation とか error handling とか各箇所に工夫なく書かれると可読性が落ちるのは間違いないので、エンジンやフレームワークのようなレベルでうまいことまとめられるとうれしいんだけどな。あとはその場合もアプリケーションの仕様なのかそれともシステムの実装上の都合なのかという切り分けと、その見せ方というのはポイントだな。

エラーにしろ例外にしろけっきょく画面なりログなりで外部とのインタフェースに対して働きかけをしないといけないので、そこは状態遷移と画面遷移の話でもある。業務系ならそうなった場合の仕事というのがあるのだろうから、ワークフローなのか。あ、話が散ってしまった。本筋の流れと枝の流れは別物として管理できるとうれしいよね、という意味では賛成ということが言いたかった。

ポインタが挙がっていた Alessandro Warth and Alan Kay の Worlds: Controlling the Scope of Side Effects は読んだことないので読んでおこう。

最後に J 言語はちょっと見てみたけど、お友達になれなさそうな気がした。

  

固有 ID 問題

by tanabe on October 15, 2008

追記。5秒でわかるまとめ

この記事から。

最近、携帯の端末IDとセキュリティの話を考えていた。

そして、今まったく別のことを調べていて偶然見つけた結城浩さんの固有 ID のシンプル・シナリオがおもしろかった。特に Q&A の項はおもしろい。

日付を確認すると、2003 年に書かれたものなんですね。

あわせて読みたい。

  

ゆの in Ruby

by tanabe on July 13, 2008

元ネタは知らないんだけど、sumim さんのところで読んでおもしろかったので Ruby の別解。

#!ruby -Ku
X = []
def method_missing name, *args
  puts "ひだまりスケッチ×365 " + args.to_s if name == :<
end
X / _ / X < :来週も見てくださいね!

method_missing 万能すぎちゃってあまりおもしろくないな。

  

BDD に関するメモ。

by tanabe on June 24, 2008

で、肝心のBDDですが、これは確かに実績を上げてました。RSpecとSeleniumを使うようになって格段にバグも減ったし、「何をやってるか知りたければまずSpecを見ろ」っていう習慣も自然に浸透したし、LLに不慣れなベテランプログラマや新人プログラマを含む混成部隊でもペアプロのお陰で開発速度を維持できたし全体の技術水準も上がりました。

あと余談だけど、「Specのないコードを書くときは上長に申請書を提出させる」とか「ペアプロ時にはナビゲータはピコピコハンマー装備」とか、今回の名言「わかんないやつは黙ってろ」とか、本当にやっちゃう人ですからねyuguiさんは。実際に。そこに痺れる憧れる。

via RubyKaigi 2008に行ってきた

以上、個人的なメモ。

最近、自分でコードを書くときはよほど小さなツールでないかぎり、ほとんど BDD で開発している。BDD の体感的の感覚としては、森博嗣氏のこの話が近いと思う。

「どうしても、思いどおりに小説が書けません。どうしたら、良いでしょうか?」と尋ねられることも少なくないのだが、そういうときは、「思いどおりに書けなかった小説を見せて下さい。何作くらいあるんですか?」ときき返す。1作も書けていない人が多い。1作も書いてないのに、どうして思いどおり書けないなんて言うのだろうか? 書いてから悩めば良いではないか。書けない書けないと悩む人がいるけれど、書けないなんてことはない、なにかは必ず書ける。幼稚園児だって書ける。100時間も1000時間も悩めば、必ず書けるだろう。5作くらい書けば、自分の才能が小説に向いているか向いていないか、多少はわかるのではないか。

(略)

沢山の具体案を考えることは、無駄なようでけっして無駄ではない。採用されなかった案が、その人の将来の持ち駒になるからだ。

via MORI LOG ACADEMY

つくづく、よくできたやり方だと思う。

  

MeCab 使ってみた

by tanabe on May 27, 2008

興味があって、MeCab を使ってみた。別にたいしたことやっていないので、Wiki に書いたメモにだけリンクしておく。
sunaot's wiki: MeCab

ポイントは最後ね。

今回まとめるのに、xmpfilter のお世話になりまくりました。超便利。

るびきちさんのところと、arton さんのところで続けて名前を見たので、気になって導入してみたんだけど、これが大正解。

コード書きながらの確認に使うには、irb よりも便利ってウソじゃなかった。vim から呼んで即反映させられるのが最高。

  

(今さら) VB6 の xUnit フレームワークのチュートリアル書きました

by tanabe on May 24, 2008

VbLiteUnit

VbLiteUnit は VB6 用のテスティングフレームワーク。名前のとおり、xUnit 方式のテストが実施可能。

前職で書いて回覧したものを Hiki に転載しました。VisualBasic6.0 でユニットテストをするためのテスティングフレームワーク VBLiteUnit の紹介文です。はたして、このご時世に今さら必要とする人がいるのでしょうか。

"Working Effectively with Legacy Code" に言わせると、テストのないコードはすべて Legacy Code なんだそうなので、VB6 だろうとテストコードを書けば(そして設計を改善し続けるサイクルを回せば)レガシー脱却もできるはず!

ちなみに、これを書いたときに VBLiteUnit のコードを読んだのですが、中々おもしろいコードでした。

Working Effectively With Legacy Code
Michael C. Feathers
Prentice Hall
売り上げランキング: 1294
  

Web 開発の決定版リファレンスになるか?Google DocType

by tanabe on May 15, 2008

Google DocType というオンラインドキュメントが公開されていた。Web 開発者による、Web 開発者のための百科事典とリファレンスライブラリを目指すらしい。サイトの紹介を読むかぎり、大きな期待を寄せてしまいたくなる内容。

Google Doctype is an open encyclopedia and reference library. Written by web developers, for web developers. It includes articles on web security, JavaScript DOM manipulation, CSS tips and tricks, and more. The reference section includes a growing library of test cases for checking cross-browser and cross-platform compatibility.

Google Doctype is 100% open.

  • Open source
  • Open content
  • Open to contributions from anyone

ざっと眺めてみたところ、まだ内容はこれから詳しくしていくという様子だけれど、それでも網羅的な情報が整理された状態で閲覧できるようになるかもしれない点や Web Security が HOWTO のトップに来ている点など見ると、今後の展開に期待してしまう。

また、overview のページに "As the open web evolves, we would like to keep articles section of Google Doctype as up-to-date as possible, for as long as possible. This requires collaborative editing." と書かれているとおり、(既存の Web の情報とは違って)できるかぎり最新の情報で更新し続けていくということなので、これが実現すると Web アプリの開発入門者は「とりあえず Google DocType を見とけ」という風になるのかもしれない。overview の "Why create Yet Another Web Reference?" の項は他の内容も Google DocType の存在意義を確認する意味で必見。

ちょうどこれを書いている合間にもちょくちょくサイトの様子が変わっているので、まさに目下進行中な様子でおもしろい。

  

業務システム開発でドキュメントを作ることについて

by tanabe on May 15, 2008

職場でここ3〜4ヶ月の間、システム再構成のためのドキュメント化プロジェクトというのを進めてきた。その中で『ドキュメントを書く』ということに対する意識が随分自分の中で変化したので、メモしておく。

まずは経緯から。

そのシステムは、いわゆるレガシーなシステムで、十数年来の歴史を持つ。これまで基盤が多少変わることがあっても基本的にソフトウェアアーキテクチャ(どのような単位で機能をモジュール化するか、どのように機能を抽象化し変化に対して柔軟にするか)に変わりはなく、作った当初の設計にツギハギしてメンテナンスを続けていた。

元々は、一体何をすれば増員以外の手段で開発量を上げられるかということを議論していた。現行のアーキテクチャのままでは求められる開発期間とバージョンアップのサイクルに対して近い将来限界を迎えることが明白であったためだ。

今のアーキテクチャや設計に問題があり、メンテナンス性を大いに損ねているという点では全員の意見が一致していたが、はたしてそれをどうするべきかという話になると、「そうは言っても、全体の仕様がわからない」「正解となる姿がアプリケーション自身しかないので困る」といった意見が出て先へ進まない。

そこで、それならその全体仕様がわかるドキュメントを作ろう、ということでドキュメント化プロジェクトが始まった。

次にプロジェクト開始時点でのぼくのドキュメントに対する考え方。

けっきょくへたくそな設計書こそが諸悪の根源なんだよ。仕様を失いそうなら、失わないようなコードを書く。仕様書としてまとめて管理したいようなものはコードをまとめる。だって、それこそがメンテのネックとなるようなルールやデータなんだから。

プログラマが自分のためにやっている実践的な工夫(内部用のメモ・ドキュメント)っていうのは、まさにもっとも貴重なノウハウの塊みたいなものなんだから、それこそがコードやデータ、データ構造で表現されている必要があるんだよ。

あとは適切な名前をつけることに注力したり、コメントでサポートしたりしていくべきなんじゃない?

というようなとにかく大事なものはプログラムで表現してしまえ、というものだった。

そして、約90日間ほどコードを書く人や書かない人や書けるけど不得意な人とほぼ毎日一時間の議論をした結果、今ドキュメントについて理解していること。

  • ドキュメントを作る目的は、書くことでも読むことでもない。レビューすることを通じて、互いの理解の差を埋めることが目的である。
  • ドキュメントに必要な内容はチームの成熟度、メンバーのスキルによって異なる。
  • ドキュメントを作るというのはプロジェクトの文化を作ることの一面であり、ドキュメント作成というツールを使って、文化やスキルレベルの違う後続のチームメンバーをトレーニングしていく活動である。(その意味ではスキルが上位の人もトレーニングの対象となる。)

だから、この視点から考えると、

  • コードがドキュメントかどうかは関係ない。「コードがドキュメント」というときのコードはドキュメントの一つの形といえる。(たまたまコンパイルも可能であり、情報が DRY に管理できるというメリットを持っている)だから、コードがドキュメントと言える環境が整えば、それは真になるし、整わなければそれは単に独りよがりなドキュメント不足のプロジェクトだ。
  • ドキュメントを作るとは、標準化することではない。マニュアル化することでもない。
  • ドキュメントを書くことと人に説明すること、フィードバックを受けることはワンセット。

この考えに立ったときの難点は、「ドキュメントとはこうあるべきだ!」という絶対的な指標を示せない点。その代わりに薦める考え方は「まずは何か書いてみて、隣りの人に説明をして意見を聞いてみたら?」というもの。レビューを通じて受けたフィードバックは、「ドキュメントに盛り込む内容のスコープ(広さと深さ)」と「ドキュメント自体の内容」、さらに「システム開発に対する考え方」を常に更新し共有していく。

書いていると当たり前すぎる内容だし、もちろんこれだけで良いドキュメントが書けるかというとまったくそんなことはないのだけど、考え方の基本として自分の中で大きな転換だったのでメモしておく。

業務システムの開発の中で、ドキュメントほど一般的な問題でありながら適切な解が出ていないものはないと思うのだけど、他の人たちはどんな風に考えながら、どういうドキュメントを書いているのかなぁ。(SOX だとか、プライムからの強制フォーマットだとか、いろいろな視点があるとは思うけどさ。)

  

TDD は企画には使うなってことでいい?

by tanabe on March 31, 2008

あかさたさんの「TDD は新規性の高いサービス開発には適さない」にとても同意。

What(何を作るかっていうゴール) が決まっているかどうかに依存するってことだよね。つまり、naoya さんが言う「新しい機能を作っているときや、新しいサービスを作っているとき」は設計でも実装でもなく、本質的に企画の状態だから TDD とか関係ないと。たまたまコードで表現できる人だから企画をコードで検証している(プロトタイプ作りながら取捨選択してサービスや機能をデザインしている)だけなんでしょう。

個人的に今まで一番「BDD/TDD すばらしい!」と感じたのは、ある機能用のライブラリを書いているとき。開発時の制約で VB6.0 を使っていたんだけど、Collection にイライラしたので Ruby の Array を移植した。

まず、要素の追加とか要素へのアクセスとかの基本機能についてこつこつとテストを書いて、それだけクラスへ実装し、その後、少しずつメソッドを増やしていくという方法で書いていった。

本当にふつうの手順で順を追っただけなのだけど、最終的に完成間際の状態での開発スピードは気持ちがいいくらい速くて(当社比 5 倍くらい自分が凄腕に思えた。)、気にいらない部分のインタフェースを変更したり、実装を多少変えたりした場合にもあっという間に影響範囲の修正が終わっていく。

この時に、本当に「開発を駆動するためのテスト」なんだなぁと実感した。

最初の話から考えると、このケースもゴール(やりたいこと)は決まっていて、そこへ至る道筋がいくつかあるという場合だったからピタッとはまった。

一方、そのときには「ある機能」自体も BDD/TDD で進めたのだけど、これはあまりうまい結果にならなかった。簡易ルールエンジンのようなものを作りたくて、フレームワークのなんとなくのイメージに従って必要な機能を書いていった。

でも、あっちへ行き、こっちへ行きとふらふらした結果、全体としてあまりうまい構成ではないことに気付き、パーツをばらして再構成というようなことが何度かあり、けっきょくテスト主導での設計は諦めてトップダウンに設計をしてしまった。

Kent Beck 本はざっと読んだだけなので、根本的に誤解があるかもしれないんだけど、自分の体験からもあかさたさんの主張はとても納得が行く。上手に適材適所で使うようにしよう。(「いやいや、誤解しているよ。そういうケースもこうすれば TDD(もしくは別の何か) でうまくいくんだって!」という反論があるとうれしいなー。)

  

目的志向の要求ヒアリング

by tanabe on March 14, 2008

職場で要求のヒアリングについてのコメントをしたのでこちらにも転載。

ユーザが語る要求というのは、

  • 課題があって
  • それを解決したくて
  • 現行の仕組み(やシステム)の制約の上で実現する案が提案される というユーザの考え方のパターンを経て出てくるアウトプット
だと理解してます。

なので、ぼくがヒアリングするときは、

  • 「その機能がないために今困っていることは何ですか?」と質問して (課題の理解)
  • 「それはどうして困るんですか?」と質問して (本当の課題へのアプローチ)
  • 「つまり、こういうことですか?」(抽象化)「それはなぜですか?」(理由の掘下げ)「たとえばどういうことがありますか?」(具象化)をわからないことがなくなるまで繰り返す (課題の構造分析)
ということをします。

  

CGI から Mongrel まで、Rack で Web アプリを Web サーバから抽象化する

by tanabe on February 10, 2008

Rack ってなに?

Rack は Web サーバと Ruby プログラムや Ruby で書かれた Web アプリケーションフレームワークとの間に、最小限のインターフェースを提供します。

http://rack.rubyforge.org/

Rack のインストール

gem install rack

Rack の簡単な始め方

Rack を使うには、まず call されるアプリケーションを書きます。call メソッドを定義し、引数に env を取ります。

 # app.rb
 require 'rack'
 class TinyCaller
   def call(env)
     [200, {'Content-Type' => 'text/html'}, ["Hello, World."]]
   end
 end 

続いて、Rack を使うための DSL ファイルとなる .ru ファイルを作成します。

 # tiny_caller.ru
 require 'app'
 run TinyCaller.new

Rack を起動するには、コマンドラインから次のように入力します。-s オプションに webrick を指定すると WEBrick が Web サーバとして使用されます。

 rackup -s mongrel -p 10080 tiny_caller.ru

Rack の基本的な使い方

Request クラス

Rack では、call されたときに引数として渡される env に環境変数一式がハッシュとして入っています。Request クラスはこの env をクラスのようにアクセスできるように補助してくれ、自然な形でのリクエストパラメタの利用が可能となります。

  • Rack#GET は QUERY_STRING を parse したハッシュを返す
  • Rack#POST は FORM からのパラメタを parse したハッシュを返す
  • クエリパラメタについては、基本的には Request.new(env).params で取得可能。ハッシュとしてアクセスできる。(実は syntax sugar で、実装としては上記 GET と POST を利用している)
  • Request#[](key)
  • Request#[]=(key, value) は Request#params(key), Request#params=(key, value) へのショートカット
  • Request#env で環境変数へハッシュのようにアクセス可能
  • Request#cookies でクッキーへハッシュのようにアクセス可能
  • Request#xhr? XMLHttpRequest として call されたなら true
  • Request#url 呼び出した URL を String として返す
  • Request#fullpath ルートからの相対パスをフルパスで返す
  • Request#get?, Request#post?, Request#put?, Request#delete? HTTP Request のメソッドが何形式かを判定し、boolean を返す

Response クラス

Response は HTTP Response の構築をサポートするクラスです。なので、基本的には、

  • HTTP status
  • header
  • body
を組み立てれば任務完了となります。

Response#initialize(body=[], status=200, header={}, &block)

header には、自動的に "Content-Type" => "text/html" が追加されます。body は、文字列か文字列の集合を与えます。(厳密には to_str できれば何でもいいらしい)

Response#write と Response#finish

Response#finish を行うまで、 Response#write された内容が蓄積されます。body としたい内容を Response#write していき、最後に finish を呼び出し結果を確定させます。

その他
  • [](key), []=(key, value) は header への syntax sugar
  • Response#set_cookie(key, value)
  • Response#delete_cookie(key, value={})

Response と Request を使った簡単なサンプル

 # app.rb
 class TinyCaller
   def call(env)
     req = Rack::Request.new(env)
     res = Rack::Response.new
     res.write req.env.map {|k,v| "<li>#{k}: #{v}</li>"}.sort.join("\n")
     res.finish
   end
 end

Response をブロックで

 # app.rb
 class TinyCaller
   def call(env)
     req = Rack::Request.new(env)
     Rack::Response.new.finish do |res|
       res.write "<h2>Rack Environment Variables</h2>"
       res.write req.env.map {|k,v| "<li>#{k}: #{v}</li>"}.sort.join("\n")
     end
   end
 end

Rack でセッションを使う

Rack でセッションを使うには、

  • ru ファイルでセッションを使うことを宣言
  • アプリケーションでは、Request#env['rack.session'] を通して利用(デフォルト)
とするのが簡単です。

Rack では、下記のように use を使って ru ファイルにミドルウェアを積んでいくことで簡単に機能強化ができるようになっています。

 # tiny_caller.ru
 require 'app'
 use Rack::Session::Cookie
 run TinyCaller.new
 # app.rb
 class TinyCaller
   def call(env)
     req = Rack::Request.new(env)
     session_data = req.env['rack.session']
     session_data['counter'] ||= 0
     session_data['counter'] += 1
     Rack::Response.new.finish do |res|
       res.write "<li>count: #{session_data['counter']}</li>"
     end
   end
 end

細かい設定をしたい

ru ファイルで use する際にオプションを細かく指定することも可能です。

 use Rack::Session::Cookie, :key => 'rack.session',
                            :domain => 'foo.com',
                            :path => '/',
                            :expire_after => 2592000
 All parameters are optional.
via) http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html

よりセキュアにしたい

今のところ、Rack の Session モジュールには Cookie しかありません。今後、サーバサイドで状態を管理するものがリリースされるのを期待するか、自分で作りましょう。(永続化は Rack のプロジェクトのスコープ外である可能性はあります。そこまでやってしまうと、Web フレームワーク化していくので。)

URI によってルーティングしたい

Rack::URLMap を使えば実現できます。ru ファイルでは、URLMap へのショートカットである map が提供されています。

 # tiny_caller.ru
 require 'app'
 require 'another_app'
 map "/" do
   use Rack::Session::Cookie
   run TinyCaller.new
 end
 map "/app2" do
   run AnotherCaller.new
 end

HTML エスケープする

Rack::Utils#escape_html(string) を使います。

認証をしたい

Rack::Auth でできるんだろうけど、試していないので詳細不明。

もっと知りたい

当初、誤って「 CGI から Rails まで」としてましたが、Rails の Handler は TODO 扱いですね。現状は、対応していません。(Rails 自体の script/server で WEBrick と mongrel は簡単に切り替えられるので、あまりここは支障ないですが。)



Rack について調べながら、Rack のコードを読んでたんだけど、とても読みやすかった。全体の構造もわかりやすいし、各ファイルもコンパクトでざっと見ると内容が想像しやすい。

Rack の説明を読んでも使い方がよく分からない人は、(ぼくの説明が不十分or不適切か、)Web アプリに関する基本的なあれこれを理解したほうが早いと思うので Ruby のまじめな名著「Ruby アプリケーションプログラミング」を一度読んでみるのがおすすめ。Ruby で CGI アプリケーションを書くための解説の章で Web アプリケーションの基本的な仕組みについても丁寧に解説されていて、非常にわかりやすい。内容は少し古いけど、基本は変わらないので今でも十分使える。

Rubyアプリケーションプログラミング
前田 修吾 まつもと ゆきひろ やまだ あきら 永井 秀利
オーム社 (2002/04)
売り上げランキング: 12952
  

Mongrel 生まれの高速(らしい) Web サーバ Thin に関するメモ。

by tanabe on January 06, 2008

Ruby Inside で紹介されていた Thin に関するメモ。(なんだけど、試していないので実態は不明。)

Thin actually relies on Mongrel, but is ultimately faster than it, even against Mongrel's EventMachine-enhanced guise.

とのこと。公式サイトの about を読むと、Mongrel のパーサを使っているので、Mongrel の速さとセキュリティを受け継ぎ、EventMachine を使っているから、安定していてスケーラブル。そして、Rack 対応なので既存アプリも簡単に移行できるということらしい。

上記のブログのコメントからいくつか抜粋。

Does Thin run multiple Rails processes? Or do you still need to put it behind a load balancing proxy like you do with Mongrel? (like this config: http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/)

に答えて、

Thin is exacly like Mongrel on that side, you’ll need multiple Rails processes for a web site with some traffic.

You should probably also check out Rev (http://rev.rubyforge.org) which is a light simple binding around libev (not libevent) and works only in Ruby 1.9. Tony is building a very nice API for it that you can use, and libev is very fast and small.

これは Zed Shaw のコメント。libev はこれか。

How long, you think, before it can be used on a production server?

への回答。

A better reply would be: you tell me! If you feel like it, deploy an app using it and let me know if it works for you.

そら、そうだw

(Ruby はあんまりスケールしない(しなかった)って議論があるんだけど、その点はどうなの?って質問に答えて。)

Ruby had some problems in the past with threads, Mongrel helped fixing those bugs in Ruby’s core but still, Ruby threads are not native (don’t use OS processes, so can’t take advantage of multicore processors). And threading is not the most scalable way of handle huge loads. Event-driven I/O can handle more requests and uses only one thread.

"Event-driven I/O can handle more requests and uses only one thread." について関連情報を検索してみた。

Cool, now where’s the info on how to replace my mongrel clusters with thin clusters?

here’s a rake task to start and stop a cluster:
http://groups.google.com/group/thin-ruby/browse_thread/thread/a639d1e20a1b0d75

豆知識として、現状、Thin で検索かけてもさっぱり目的の情報は見つからないので、"gem install thin"あたりで検索するのがオススメ。

  

データフロー並列性

by tanabe on December 31, 2007

コンピュータプログラミングの概念・技法・モデル」を読んでいて、データフローという概念がおもしろかった。複数スレッドを走らせたときに、各スレッド間で変数の束縛が行われるまで互いに評価を待つというモデルのようで、シンプルな考え方で並列処理の恩恵を受けられる。関連して検索した結果をメモ。

現在のコンピュータは、大半がフォン・ノイマンモデルと呼ばれるアーキテクチャに基づいている。演算部、制御部、記憶部、出力部があり、命令を順番にフェッチし、実行していく。命令の実行順序をあらかじめ定め、各命令に必要なデータを集め、処理を行うという、命令を中心とした処理体系だ。ところが、データフローマシンでは、データの依存性に着目し、トークンをやりとりする形で演算を行っていく。トークンは、行先ノード、ポート、データからなり、行先ノードの指定のポートにデータを届ける。そのノードにおいては全てのトークンが揃ったところで発火し、次のノードに結果としてのトークンが転送されていく。データフローアーキテクチャはデータの流れに着目した、コミュニケーションベースの処理体系なのである。

超並列アーキテクチャとディペンダビリティ - プロセッサ開発の今後

コンピュータプログラミングの概念・技法・モデル」は、翻訳がちょっとアレなところはあって、明らかに何か内容が欠落しているような部分があったりするんだけど、それを差し引いても良い内容だと思う。

コンピュータプログラミングの概念・技法・モデル(IT Architect' Archiveクラシックモダン・コンピューティング6) (IT Architects’Archive CLASSIC MODER)
セイフ・ハリディ ピーター・ヴァン・ロイ Peter Van-Roy Seif Haridi 羽永 洋
翔泳社 (2007/11/08)
売り上げランキング: 25497
  

「意図と表現」

by tanabe on December 21, 2007

今日、とある人から教えてもらった言葉。ユーザからのヒアリングをするときに、「なぜそうしたいのか。」と「なにをしたいか。」を意図と表現という言葉で伝えるとよいらしい。

同じテーマについて以前、「お客さんのホントの気持ちに迫るための一言。」というエントリで書いていて、ぼくは「何に困ってますか?」(人によっては「解決したい課題は何ですか?」)と質問してきたけど、今度、意図と表現も使ってみよう。「そうそう。困ってることがあるんだよね。」という点では同じ意見だったので、それこそ、”表現”が違うだけなんだけどね。

  

ドキュメントは重要ではない。なんて言わない。

by tanabe on December 21, 2007

「(相対的に)ドキュメントは重要ではない。」と考えていたけど、改宗する。「そのドキュメントが何を表現するかを考えずに、ドキュメントを作る」という行為が無駄なのであって、「設計を文書にして残す。それをレビューする。」という行為はけして無駄じゃない。やるべきなのは、「何をドキュメントにするか、何をドキュメントにしないかを判断すること」と、「レビューして、設計での一定レベルの合意を形成すること」だ。そして、その目的は「品質の高いインターフェースを持ったコードを共有し、スケールさせることができるようにする。」という点に尽きる。

ふつうのプログラマで成り立つプロジェクトだからこそ、上記を徹底しないといけない。詳細設計として程度の悪い擬似コードを日本語で書いたようなドキュメントを受け取る必要は当然なく、その分、たとえばビジネスルール単位で、それをどのように設計するのかを検討する必要がある。これをコードに近い表現でやってもいいし(TDD のようになるだろうけど。)、文章とインターフェース定義でやってもいいけれど、ドキュメントとして受け取ることとレビューをすることは省かないようにする。

以上、Google のソフトウェア開発についての興味深いエントリ「いいアジャイルと悪いアジャイル」を再読してみて、最近の考え続けていたことに出した結論。

彼らはユニットテストや設計ドキュメントやコードレビューといったことを、私が聞いたことのあるどの会社よりも真剣にやっている。彼らは自分たちの環境が常に整理されているよう熱心に働いており、どこかのエンジニアやチームが自分勝手な方法でやらないようにする厳格なルールやガイドラインが実施されている。結果として、コードベース全体が同じように書かれ、チームを変えたりコードを共有したりすることが、他の会社でよりもずっと簡単なことになっている。

安易にまとめてしまったけれど、上記の文章はさらに深い含蓄がある気がしている。もう一度、自分の直面している課題と照らし合わせて、なぜそれをするのか(あるいは「なぜあえてそれはするのか」)を考えてみようと思う。

  

[Ruby] 二時間の仕事を一秒で片付けてくれる(かもしれない)三行スクリプト。

by tanabe on December 12, 2007

「テキストファイルの各行に一括で同じような処理をして、その結果を得たい」というようなことはよくあります。特に職場が Windows な環境だと CUI のツールが貧弱で、ついエディタでやってみたりしてしまって、半分くらいやったところで睡魔に襲われてどこまで作業したかわからなくなって全部やり直したり。

こんなコードを PATH の通ったところにおいただけで、非常に重宝しているのでご紹介します。はまったときには、笑っちゃうくらい作業効率が上がるかも。

script = ARGV.shift || ''
lines = $stdin.readlines.map {|li| li.chomp}
puts eval(script)

ファイル名に firter とでも名付けてやって呼び出してみます。

たとえば、c:\ruby\bin\rake ファイルからコメントで始まる行だけを抜き出したいときはこんなかんじ。

type c:\ruby\bin\rake | firter "lines.select {|s| s =~ /^#/}"

lines という変数名で標準入力の各行にアクセスできます。

各行に対して、前後の空白とか除去して、重複を除いて、ソートして、空行は除外した結果がほしい、なんてときも、これだけ。

type test.txt | firter "lines.map {|s| s.strip}.uniq.sort.delete_if {|s| s == ''}"

Ruby の強力な Enumerable モジュールと String クラスと正規表現で、大抵の用事は片付きます。

元々すぐコード書いちゃう人はちょっと手間が省けるくらいなんじゃ、とか、それ per(ry とか、それ aw(ry とか、ありますが、慣れると手放せません。

あと、

@ruby "c:\ruby\bin\firter" %* 

とか書いたファイルを firter.cmd として置いておくとうれしいかも。(c:\ruby\bin は適当に調整してください。)

s/firter/filter/ という指摘は受け付けませんのであしからず。  

[Ruby] 海外の「Ruby で GoF のデザパタを実装してみた」が必見

by tanabe on December 06, 2007

Ruby でデザインパターンをやってみたよ、というのはそれほどめずらしくはないと思うけど、これは GoF の元ネタに引きずられず Ruby らしいコードで書かれていて、とても勉強になった。

もちろん、そこ、method_missing でやるのはどうなの?とか、自分なら違う形にするな、とか思うところはあるわけで、そこも含めて非常にためになる&おもしろかった。
読みたい人は、The GoF patterns implemented in Ruby から。

オブジェクト指向における再利用のためのデザインパターン
エリック ガンマ ラルフ ジョンソン リチャード ヘルム ジョン ブリシディース Erich Gamma Ralph Johnson Richard Helm John Vlissides 本位田 真一 吉田 和樹
ソフトバンククリエイティブ (1999/10)
売り上げランキング: 27191
  

Exerb に D&D でパラメタ引数とするファイルを渡したいときの Tips

by tanabe on December 04, 2007

コメントで教えて頂いたとおり、ExerbRuntime の filename, filepath で対応する方が正しいです。便利!

Exerb は Ruby スクリプトを Ruby のインストールされていない環境でも実行可能な exe ファイル化することができるという、仕事で Windows 環境を避けられない Ruby ユーザにとって最高に便利で足を向けて寝られない品の一つ。

その挙動で、軽くはまったのでメモ。(考えてみれば当たり前の動作なのだけど)

Exerb で作成した exe ファイルに対して、引数にしたいファイルを D&D で指定した場合、実行時パスがユーザのホームディレクトリに設定されてしまう。そのため、File.expand_path などで期待したパスを得られなくて困ることがある。

File.expand_path(__FILE__).dirname Pathname.new($0).expand_path.dirname で期待するパスを取得したいときなどは、exe のショートカットを作成し、作業フォルダを exe ファイルのあるフォルダに設定。(デフォルトでそのようになる。)その上で、exe にファイルを D&D したい場合はショートカット経由で利用するようにすると、期待どおりの動作になる。

ついでに、もう一つの注意点として、$0 や __FILE__ で得られる値は rb ファイル時点の名称となる。仮に exe ファイルを作成した後に名称を変更したりした場合も、やっぱり Exerb によって exe 化した際の rb ファイルの名前を維持する。実行中の exe ファイル名を取得する方法は不明。

D&D はドラッグアンドドロップね。念のため。   

[Ruby] Time.parse がボトルネックになったので・・・

by tanabe on November 29, 2007

ログの解析で Ruby を使っているんだけど、二時間かかって死ねる。繰り返し呼んでいる Time.parse がボトルネックみたいなんだけど、どうにかならない?って依頼が来た。

Time.parse は柔軟性ありまくりで便利すぎるから、そりゃ、速度は諦めないとねーと思いつつ、対応案でこんなのを出してみた。

t = "2007/11/28 15:30:28.015".split(/[\/ :.]/)
Time.utc(*t)
t = "2007/11/28 15:30:28.015".split(/[\/ :.]/)
usec = t.last.to_i * 1000
t.last.replace usec.to_s
Time.utc(*t)

無事、劇的に改善。

そういえば、DateTime.strptime てのもあったなーと思い試してみると、むしろ Time.parse よりも遅かった。

ついでに、実行速度といえば VM だよね。ということで、CRuby と JRuby と YARV で比較してみたところ、CRuby と YARV だと少しだけ YARV が速い。JRuby は大体その二倍程度の時間がかかった。

さらに、おまけで JRuby のバグ(?)発見。

t = "2007/11/28 15:30:28"
DateTime.strptime(t, "%Y/%m/%d %H:%M:%S")

が、失敗する。

自分のコードもバグってたので修正。   

オライリーの JavaScript 本読んだ。

by tanabe on November 15, 2007

単に言語自体への興味から JavaScript 本を読んだ。いい塩梅に気持ち悪くて、とても好きなかんじだった。手元にあったのがなぜか今さらの第3版だったので、第5版を買ってやろうか悩み中。

ちなみに突然 JavaScript を知りたくなったのは、るびまの石塚圭樹さんの Hotlinks でメソッドがファーストオブジェクトじゃない云々のところを読んで、なんとなく。

今年は Haskell, Smalltalk, JavaScript と浅いところでは色々読んだので、このまま勢いだけで年末までに On Lisp を読もうと企み中。

  

業務システム開発の世界だってコードの力で変えられる

by tanabe on November 07, 2007

これ、必読。

業界の重鎮とやらに惑わされるヒマがあったら、一歩でも前に進むために何をするかを考えたい。

山ほどあるサブセットから, どうやって適切な妥協点を選べばいいのだろう. 絡まりあったプラクティスをときほぐして本質に迫る根気と,サブセットの善し悪しを判断するクライテリアを K は持っていた.

http://www.dodgson.org/omo/t/?date=20071103

誤解を恐れずに言えば、業務システムの開発において一番面白いのは実はここだ。

プログラミングとは、忠実に正確にまじめにシステムを動かすためのコードを書く作業ではない。

本当のプログラミングとは、コードの力を駆使して問題自体を解消してしまうような仕組みを創造するプロセスだ。その対象が身内なこともあれば、顧客なこともあるだろう。その意味で、「業務システム開発はクリエイティビティを発揮できない」なんていうのは、「私は無能です」と宣言しているようなものだ。

SIer を雇い入れてシステムを開発するときの根本的な誤りは、大人数のまじめで正確な作業をするコード書きを導入すれば問題の解決に結び付くと考えていることである。その場合の最もよい結果は、問題を自動的に処理し続ける大きなシステムができあがるというものだ。問題は残り、問題の処理を手伝うようなシステムが残る。問題のパターンに変化が生じるとシステムも変化を強いられ、根本的な解決は図られないままメンテナンスを続けるはめになる。しかも、大抵の場合、その構造に問題があることは誰一人として気付かない。

コードが世界を変えるのは何もあちらの業界だけではない。業務システムだって、アプローチが正しければコードの力で世界を(ビジネスを)変えることは可能だ。ただ、そのためには従来とは正反対のアプローチが必要になる。少人数の怠惰で優秀なプログラマを投入して問題自体を解決するような仕組みを作り上げる。問題は解消し、次に作るシステムは別の課題へ注力できる。

ここでも DRY の原則は有効だ。繰り返し同じ問題を扱うのは止めよう。あなたが(あるいはあなたの顧客が)年間で同じ作業を繰り返しているとしたら、それはきっと何かが間違っている。作業が発生する要因自体を叩いて、新しい問題に取り組もう。そのためにコードの力を使おう。

そして、そのために必要になるスキルセットは問題解決のための基礎的な分析力と解決策を考えるときの引き出しの数であり、人を巻き込んで味方を作っていく力であり、その仕組みを現実化するためのコードを書く力であると思う。

最後に、同じ文脈で過去におもしろいと思った文章を引用しておく。

で、自動化ができるかどうかにかかわらず、手順の確立 っていうのは大切だよっていう話。確立された手順って いうのは、みんなで共有できる知識なわけ。

もちろん、その知識をコード化するのが、自分らプログラマ にとって一番いいんだけど。でも、そうできないことも ある。そんなときは文章にするしかないんだな。だから、 手順を確立するっていうのは、その確立された手順を 文章にすることが含まれてるわけ。くどいようだけど、 文章よりコードのほうがいいんだけどね。

http://www.jitu.org/~tko/cgi-bin/bakagaiku.rb?bakaid=20071029

やがてくる未来ではソフトウェアの生態系がかわると私は信じている。その生態系を、ここでは 馴染系ソフトウェア (Situated Software) と呼ぶことにしよう。特定の場面や文脈のために設計されたソフトウェアのことだ。馴染系ソフトウェアを作る方法は、いわゆるウェブ学派(かつて私がプログラミングを勉強した場所)のやりかたとは対照的だ。ウェブ学派はスケーラビリティや汎用性、完全性を美徳としてきた。

私の生徒達はウェブ学派の流儀をあっけらかんと無視し、それでいて面白いものをつくっている。ここ一年ずっと、私はそれが気になって仕方がなかった。

馴染系ソフトウェア

K と働いてはじめて, ああ, 物事とはこう改善していくものなのかと知った. 何か問題を感じると K は試行錯誤を始める. 問題は私が諦めていたものもあるし, そもそも気付かないものもある. 試行錯誤の中には, はじめうまくいかないように見えたものもある.でも調整を重ね次第に様になっていく. 気がつくといつも何かがよくなっている. 目の前の問題が次々と片付いていく感覚. K の前で開発は加速し, コードの質は上がり, 技術的困難は片付き, チームは進化していった.

http://www.dodgson.org/omo/t/?date=20071103

最後、もう一つだけ追加。

SCMにしろBIにしろ、本質的には「経営」に直結するんですよ、ITってのは。

ITこそが、経営を変え、ビジネスを変えて、世の中を変えるんです。

それこそが「IT業界の面白さ」に他ならないと僕は思うんですけどねぇ。

http://d.hatena.ne.jp/codemaniax/20071031/1193837027
  

オープンソースの一つの価値

by tanabe on November 07, 2007

分野は違うけど、まぁ、こういうことだよな。

この夏キネ旬から刊行されたムック内の監督インタビューに以下のコメントがあってひどく共感しました。

「・・・(業界の)若い子はまず映画を観ない。映画も観なきゃ本も読まない人が大半です。それで、演出家だのシナリオライターになりたい、って、もう笑止千万ですよ。自分の引き出しの中身を増やしもしないで、『いつか羽ばたく日』を夢想しているんだから世話ないです(笑)。引き出しの中身は、それまで見てきた作品の数に素直に比例するから、数を観てないとまずアイディアを出せない。(中略)・・・情報がたくさんあったところで、必要な情報を選ぶ能力は養ってないし、どれが面白いかを選別する目が養われていない。目の前にある仕事が忙しいんだろうけど、せめて己の無能くらいは自覚してほしい人たちがたくさんいます(笑)」

http://d.hatena.ne.jp/kaoru1107/20071007

良いものはどんどん見た方がいい。悪いものも頭を使いながら見てみたら捨てたもんじゃない。本当にそう思います。

  

流れるような Java が Ruby ぽい件

by tanabe on October 26, 2007

それ、どこの Ruby? と思った。

思考を中断せずに流れるようにコーディングができるかどうかが重要なんだ。そして、よくできた流れるようなインターフェースは、可読性が高い。
流れるようなインターフェースとメソッドチェーンは違うもの

本文の主旨は言語がどうこうっていう話じゃなくてスタイルの問題だって話ね。念のため。

「流れるようなインターフェース」は、RSpec とかを見ても最近のコーディングスタイルのトレンドとして感じるし、よい名前も付いたし、来年あたり力強いコンセプトとして広まりそう。数年前の CoC のように。

上記のひがさんのエントリは誤解を解くための良い指針として押さえておくべき。そして、猫も杓子も流れるインターフェースと言い出して、珍妙なインターフェースが続出する未来はぜひ避けたい。

あと、コードの見た目は Ruby ぽい以上に Rails ぽい。手続き的でなく、よりメッセージ的なのかな。(OOP の文脈でメッセージという言葉を使うと誤解を招くが、ここでは読み手へのメッセージ性が強いということが言いたい。)

最後に、「Piers Cawleyから、いいフォローが入った。」の先から引用。

Think really hard about names.

名前重要。脳みそ振り絞って考えよう。

  

[Ruby] DecisionTable を簡単に作る

by tanabe on October 25, 2007

DecisionTable を書くのに全パターンを書くのはとても面倒。面倒なことはコンピュータにやらせよう。

ということで、Ruby で書いてみた。


class DecisionTable
  attr_accessor :patterns

  def initialize(patterns = [])
    @patterns = patterns
  end

  def horizontal
    rows
  end

  def vertical
    rows.transpose
  end

  def table
    format_table vertical
  end

  private
  def rows
    pattern_map(1, @patterns.dup)
  end

  def pattern_repeats(patterns)
    return 1 if patterns.empty?
    patterns.map {|r| r.size }.inject {|r, n| r * n }
  end

  def pattern_map(repeat, patterns)
    return [] if patterns.empty?
    pattern = patterns.shift
    return pattern.map {|p| [p] * repeat }.flatten * pattern_repeats(patterns), *pattern_map(repeat * pattern.size, patterns)
  end

  def format_table(table)
    table.map {|r| format_row r }.join("\n")
  end

  def format_row(row, separator="\t")
    row.map {|c| "\"#{c}\"" }.join(separator)
  end

end


if __FILE__ == $0
  patterns = [
    %w{m f},
    %w{5 10 15},
    %w{5 10 15},
    %w{0-10 11-45 45-60 60-65}
  ]

  dt = DecisionTable.new(patterns)
  puts dt.table
end


出力を Excel に貼って、各パターンの結果を書けばルールテーブルのできあがり。

  

Sun Tech Days 2007

by tanabe on October 22, 2007

すっかりスルーしてたのですが、Sun Tech Days 2007 に James Gosling が来るんですね。最近の Gosling の言葉として記憶にあるのが、http://www.rubyist.net/~matz/20060127.html#p01だったりするのがちょっとアレですが、それでも2時間のボリュームで、しかもヘタな真似はできない場での基調講演となれば見逃すわけにはいかないところ。

あとは時間作れるかだなぁ。

  

さくさく Smalltalk

by tanabe on October 10, 2007

いかんせん、Smalltalk さぱーりわからん。ということで、某 Smalltalker の教えのままに、「さくさくSmalltalk」購入。

今、読んでいるところなんだけど、これ良本ですね。教えてもらえてよかった。感謝。

サクサクSmalltalk―オブジェクト指向のアートとサイエンス
サイモン ルイス Simon Lewis 水口 朗 梅沢 真史 増田 英孝 今野 睦
東京電機大学出版局 (1996/08)
売り上げランキング: 206538
  

青木淳さんへ深く深く感謝。

by tanabe on September 22, 2007

Kent Beck の Smalltalk ベストプラクティスパターンを読みこなしたくて Smalltalk の文法・言語仕様を調べていたところ、まさかの出会いに驚かされた。

ぼくがオブジェクト指向プログラミングを勉強し始めてすぐの頃、真意を理解しようと何度も何度も繰り返し読んだページがあった。ここ数年はすっかり忘れており、目にすることもなかったので分からなかったのだけど、ひょんなことからそのページはあの青木淳さんの「オブジェクト指向システム分析設計入門」だったことが判明。なーんもわかっていなかったくせに、ここから学び始めた自分を誉めてやりたい!

特に「第1章 狭義のオブジェクト指向」はよく読んだ。何度繰り返したことかさっぱりわからないくらい読んだ。いやー、お世話になりました。今さらながら、どうもありがとうございました。