オブジェクト思考でたくさんのボール
オブジェクト思考というとよく継承の話が取り上げられます。 継承によるプログラムの再利用も確かに便利なのですが、継承以前のもっと基本的なところにもオブジェクト思考の便利さがあるように思います。 というわけで今日はオブジェクト思考のメリットについて考えてみます。
次のプログラムはスクリーン(画面)上にたくさんのボールを表示して動かすプログラムです。ボールの位置(x, y)と初速(ax, ay)を乱数で初期化しています。
オブジェクト思考でない実装(あとで書く)
Ballをクラスにしてオブジェクト思考な実装をするとこうなります。
SX = 640 #スクリーンの横幅 SY = 480 #スクリーンの縦幅 class Ball def initialize @x = rand(SX) @y = rand(SY) @ax = rand(5) - 2 @ay = rand(5) - 2 end def move @x += @ax @y += @ay @ax *= -1 if @x < 0 || @x >= SX @ay *= -1 if @y < 0 || @y >= SY end def draw #スクリーンへの描画処理 end end num_balls = 100 balls = Array.new(num_balls) { Ball.new } while 1 balls.each do |ball| ball.move ball.draw end end
ボールの座標計算や描画処理がballクラスの中に入り、外側にはそのボールを扱うための最低限のインターフェースだけが残りました。このように分離すると、ボールの表示や座標管理のために必要な変数がballクラスの外側から見えなくなります。見えなくなるというのがとても重要で、例えばこれがサッカーゲームならボール以外にも
- 選手
- サッカーゴール
- グラウンド
- 観客
- 点数表示
などいろんなものを同時に制御することになります。 これらのパーツをそれぞれオブジェクトとして実装し、必要なデータが必要なところだけでしか見えなくすれば、パーツごとの不必要な関連がなくなりすっきりします。同時にオブジェクト同士の必要な関連も明確になります。
[tDiary]特定のカテゴリの記事だけを
並べて表示することってできないのかな? ちょっと調べてみよう。
__
CVSから最新版をとってきたい。これで取得できた。
cvs -d:pserver:anonymous@cvs.sourceforge.net/cvsroot/tdiary login cvs -d:pserver:anonymous@cvs.sourceforge.net/cvsroot/tdiary co core
__
うお、タブだ!
あれ、カテゴリって純粋なプラグインじゃないんだ。 index.rb でこんな場合分けがされている。
elsif @cgi.valid?( 'category' ) tdiary = TDiary::TDiaryCategoryView::new( @cgi, "category.rhtml", conf )
__
なるほど、こういうことか。tdiary.rb の中で cgi#valid? が定義されている。
def valid?( param, idx = 0 ) begin self.params[param] and self.params[param][idx] and self.params[param][idx].length > 0 rescue NameError # for Tempfile class of ruby 1.6 self.params[param][idx].stat.size > 0 end end
この valid? 使って最初の挙動を場合分けする。
if @cgi.valid?( 'comment' ) then tdiary = TDiary::TDiaryComment::new( @cgi, "day.rhtml", conf ) elsif @cgi.valid?( 'date' ) (省略) elsif @cgi.valid?( 'category' ) tdiary = TDiary::TDiaryCategoryView::new( @cgi, "category.rhtml", conf ) else tdiary = TDiary::TDiaryLatest::new( @cgi, "latest.rhtml", conf ) end
ぱっと見それぞれはこんな挙動だと予想できる。
- comment …… コメントの書き込み
- date …… 記事表示
- category …… カテゴリ表示
- それ以外 …… 最近の記事表示
date モードは渡された値によってさらに場合分けされている。
date = @cgi.params['date'][0] if /^\d{8}-\d+$/ =~ date then tdiary = TDiary::TDiaryLatest::new( @cgi, "latest.rhtml", conf ) elsif /^\d{8}$/ =~ date tdiary = TDiary::TDiaryDay::new( @cgi, "day.rhtml", conf ) elsif /^\d{6}$/ =~ date then tdiary = TDiary::TDiaryMonth::new( @cgi, "month.rhtml", conf ) elsif /^\d{4}$/ =~ date then tdiary = TDiary::TDiaryNYear::new( @cgi, "month.rhtml", conf ) end
date モードのときに記事の形式パタンを定義したクラスを呼び出すようだ。
TDiaryLatest, TDiaryDay , TDiaryMonth, TDiaryNYearというクラスがあるから、これらのクラスの中で記事を抽出しているものと思われる。こういったクラスを作らずに、記事の検索条件をパラメータとして与えて表示する記事をセレクトしたり、並べ替えたりできるインターフェースがあるとといい気がするけどどうだろう、という思いを抱きつつこれらの中身を見てみよう。
__
ますは TDiaryLatest を読んでみる。
かなり長い……。挫折した。
[開発ログ]ノートPCにcoLinux(Debian)をインストール
なかなかうまくゆかず、調べていたら 自分のログ がヒット。なんか同じ感じではまってるじゃん。 が、なかなかうまくゆかず、調べていたら 同じっぽい現象 を発見。regeditで「TAP、ローカル エリア接続4、ネットワーク ブリッジ 」を検索して関係ありそうなものを片っ端から削除。するとようやくうまくいった。0.6.1と0.6.3が動いたので0.6.3を使うことにする。今回はDebianを使っている。
スワップファイルの作り方の解説と DHCPの設定方法と 起動方法の解説 あたりを参考した。
某出版社からメールを頂く
とある件で突然のメールが。ここで公開していいものかどうかわからないので内容は書けないけど、ちょっとビックリ。
--
こんなメールがあったものだからいろいろ考えてしまった。
この話がどうなるかはまだぜんぜんわからないし、まあこの件は別としてもここ最近妙な流れを感じる。今年はなにかと転機のなる年かもしれない。
このサイトを立ち上げて2年がたち、その間にほんとに多くのことを勉強して、最近はようやく世間とのずれがだいぶ埋まってきた感じがする。当初は「ブログって何?」「Lispって何?」だったから。
知識だけではなくて、 Ruby 方面を中心にコミュニティやそのイベントに積極的に参加してきた成果として、著名な知り合いがいっぱいできた。あらためて振り返ってみるとほんとうにたくさん。そういう人たちから学べることもすごく多い。
ともあれ自分を見失わないように注意しつつ、まずは開発をがんばらねば。今年はサービスを開始しますよ。
あの結城さんが……
あの結城浩さんが身近なところに出没。たぶん偶然なのだけど今月になって二つの小さな期間限定プロジェクトのMLやIRCでお見かけして、直接的なやり取りはないもののなんか不思議な縁を感じる。もちろん一方的に感じているだけだろけど。
Haskell はじめました。
青木さんの本のレビュー参加を機に Haskell の勉強をはじめました。関数型言語は初めての経験なのですごく楽しいです。
Ruby でメタプログラミングをやるようになってから急速に Ruby がわかってきた感のある今日この頃ですが、 Haskell を学ぶことによってより Ruby の理解度も深まるんじゃないかと期待しています。