今日は、dRuby幸福の王子本のp.16 「2.2 Reminder」からです。ここでは、Reminderのアプリケーションを作って動かしてみます。いよいよdRubyを使ってアプリケーションを作成するときが来ました。要件は本に記載されている通りです。
だれでも書き込め、削除できるメモ帳。
ユーザインターフェイスはirb。2.2 Reminder
本の図を見ると大体の構造がわかりますね。公開されるReminderのオブジェクト(フロントオブジェクト)は以下です(転載)
# reminder0.rb
class Reminder
def initialize
@item = {}
@serial = 0
enddef [](key)
@item[key]
enddef add(str)
@serial += 1
@item[@serial] = str
@serial
enddef delete(key)
@item.delete(key)
enddef to_a
@item.keys.sort.collect do |k|
[k, @item[k]]
end
end
end
メモの文字列はハッシュに入れられると、で、ハッシュには1からのシリアル番号が振られ、それがキーになり添字でアクセスできるようになっていると。はい、理解しました。で、本に従い、irbからサーバーとクライアントを立ち上げて、リマインダーに登録してみます。
r.add('13:00 ミーティング')
r.to_a
=> [[1, "13:00 ミーティング"]]
無事登録できましたね。それから本の通り、ターミナルの数を増やしたり、クライアントを落としてから再度立ち上げたりしてみましたが、今まで登録した内容はちゃんと残っています。めでたし。
ところで、ここで
- サーバーを落とす
- もう一度サーバーを立ち上げる
- クライアントから操作する
とすると、今までリマインダーに登録した情報は消えています。つまりリマインダーの情報はサーバー側が持っているのですね。ここをもうちょっと調べるために、通信の内容を間単に見てみます。
- サーバー
- 192.168.0.4
- ポート
- 9898
- クライアント
- 192.168.0.2
としています。つまり、サーバーのURIは
druby://192.168.0.4:9898/
です。
クライアントから、
r = DRbObject.new_with_uri('druby://192.168.0.4:9898')
r.add 'foo'
r.add 'fooo'
r.add 'foooo'
としてみました。サーバーもクライアントもirbで起動しています。以下はそのパケットのダンプです。
送信のたびにデータ部(データ部とはTCPパケット内の、アプリケーションが自由に使えるデータが含まれる箇所の名前です。)のサイズが44,45,46と1byteずつ大きくなっているのは、addの引数の文字数の差だと思われます。サーバーから送られてくる15byteはメソッドの戻りだと思われます。
データの中身を見なくとも、送信されるデータが44byteと小さいですし、戻されるデータはリマインダーのデータ量に依存せず常に小さいので、本当にメソッド呼び出しだけしかしていない(クライアント側にリマインダーのフロントオブジェクトそのものが渡ってきているわけではない)ことがわかります。
では次に、フロントオブジェクトそのものではなく、フロントオブジェクトが参照している他のインスタンス(@itemとか)について見てみます。サーバー側のirbでリマインダーに情報を追加してみます。
irb(main):008:0> r.add 'hogehoge' => 1
それからサーバー側でオブジェクトIDを見てみます。ちなみに、__id__で返される数値のことをここではオブジェクトIDと呼んでいます。これは、各オブジェクトの間で重複しないように付けられた識別番号(住民票コードのようなもの)です。もちろんプロセスが違っていれば同じ値が振られることもありますが、同一プロセスの中ではユニークになります。
irb(main):011:0> str = r[1]
=> "hogehoge"
irb(main):012:0> str.__id__
=> 21567584
irb(main):013:0> r[1].__id__
=> 21567584
ふむふむ、続いてクライアント側のirbで同様のことをしてみます。
irb(main):009:0> str = r[1]
=> "hogehoge"
irb(main):010:0> str.__id__
=> 21563792
irb(main):011:0> r[1].__id__
=> 21778008
おや?クライアント側は、代入した時点で別のオブジェクトIDになっています。つまりstrとr[1]は別物です。これは多分、クライアント側の
irb(main):009:0> str = r[1]
この行で、r[1]をサーバー側に問い合わせた時点で、オブジェクトの参照ではなく複製されたものが取得されるからでしょう。つまりr[1]は値渡しです。通常のRubyプログラミングと違いますね。このあたりは多分色々と難しいことが多そうなので、本を読み進めながら徐々に理解していきたいと思います。
で、それから後ですが、ReminderCUIを作って遊び、「2.3 まとめ」をふむふむと読みました。はい、これで「2章:Hello, dRuby」は終わりにしたいと思います。結構長かったけど、dRubyの雰囲気は一応理解できた!つもりです。
本だと、この次は「3章:eRuby」に続きますが、このサイトでは「3章:eRuby」を飛ばして「4章:参照渡しと値渡し」に入ります。「3章:eRuby」を飛ばす理由は、Webアプリケーションの話が入ってくると、多分dRubyそのもの以外に色々と面倒なことが出てきて混乱しそうだからです。このサイトでは、まずdRubyのことを学びたいので、Webアプリケーションで活用することは後回しにしたいと思います。
「4章:参照渡しと値渡し」では、今日のこのエントリで見た付近の仕組みなども解説されているようなので、今から楽しみにしておきます。
dRubyは結構脳ミソが刺激されていいです。
