【Ruby】【るびま】Rubyの排他制御。例外の考え方。=メソッドオーバーロードのトレードオフ
Rubyist Magazine - Ruby コードの感想戦 【第 2 回】 WikiR
引き続き、
須藤さんと咳さんのコードレビュー文通を読んでるよ。
他人のコードみるのもレビューも勉強になる。
楽しい。
ある意味このブログも、
せかい&師匠のコードレビュー合戦(文通)みたいな面もあるよね。
もうちょっと整理して書けば、良い内容になるかもしれない。
=メソッド命名の光と影
「self.src = 」。どうですかこの奇妙さは!
http://magazine.rubyist.net/?0041-CodePostMortem
詳しくは本文を見てもらうことにして、
自分でも手を動かして理解してみよう。
class Page def initialize self.src="hoge" end def src=(text) @src = text+text end attr_reader :src end p Page.new.src #<= "hogehoge"
class Page def initialize src="hoge" end def src=(text) @src = text+text end attr_reader :src end p Page.new.src #<= nil
そうだよね。
selfレシーバーをつけないと変数宣言と解釈されてしまう。
これを奇妙と取るかどうか。。むむむ。
src を source にするべきかは議論があると思います。
分かるー。
どこまで省略していいのか迷う。
個人的にはcandidate をcnd って書けたらなあ、、
って思うけど、これは自明でないからだめだとおもう。
長いんだよね。。
「関心事について分けて書く」
と
「役割を分離する」
のトレードオフがすごく面白い。
インスタンス変数でsynchronize制御!?
以下のコード、
「どうしてインスタンスごとに生成される @monitorで
排他制御できるの!?
と思ってインスタンス変数の情報を出力してみた。
require "monitor" class Counter attr_reader :count def initialize @count = 0 @monitor = Monitor.new @hoge = Hoge.new end def up p @monitor #<= 追加 @monitor.synchronize do count = @count sleep(0.00000001) @count = count + 1 end end end counter = Counter.new threads = [] 100.times do threads << Thread.new do 100.times do counter.up end end end threads.each(&:join) p counter.count
■実行結果
#<Monitor:0x2d274f8 @mon・・・ #<Monitor:0x2d274f8 @mon・・・ #<Monitor:0x2d274f8 @mon・・・
同じオブジェクトを参照してるんだ。
それなら排他できるのも理解できるけど、なぜ同じ。。?
と思ってよくよく見ると・・・
counter.up
なんだー。
スレッドごとにCounterインスタンスを作成していたわけではなかったのか。
早とちりしていました。
Counter.new.up
当然、こうやって書いたら排他は効かない。
Rubyのスレッドコード見たの初めてだったから、
何か特別なことがあるかと思ったけど、ここら辺はJavaと同じ。
例外の扱い
私は「例外を握りつぶす」という表現がよくわかりません。
えええっ。
例外の握りつぶしって絶対だめなことだと思ってたけど、、
そうではない考え方もあるのか。
この記事では、
例外は「アプリケーションに対するフックポイントを用意する」
という文脈で語られているように思うけれど、
デバッグとかするとき、エラーメッセージ出てないと大変じゃないの?
Rubyはコンパイルしないから、
そこまでエラーメッセージが命綱にはならないのか?
アプリケーションにとって役に立つ例外はなんでしょう。do_request に関して言えば、ここで例外をあげてもアプリケーションができることはないし、積極的に例外を捨てることが正しいと判断しました。
ううむ。。
こんな風に、処理はうまくいかなかった (うまくいかなかったら false を返すという仕様のメソッドだと考えると、メソッドはうまく動いているとも言えるんだよなー) けど例外があがらないケースって多々ありますよね。
ううむ。。
業務アプリを作るうえでは
業務例外で例外を投げるな、
という考え方があると思うんだけど。
それに習うと、「処理は上手くいかなかった」はエラーであって、
例外には当たらないのではないかな。
例外についてはもうちょっと勉強しよう。
最後のほうまで読んだら、須藤さんからの例外に対するコメントも書いてあった。
httpdのログにはPOSTの内容が残らないので再現できないんですよねぇ。・・・
私はデバッグのしやすさを大事にしたいんだなぁと思いました。
そうそう!
デバッグ視点だよね。同じ!
最後に一つ。
def synchronize(&blk) @montiro.synchronize(&blk) end
これは誤字では?
def synchronize(&blk) @monitor.synchronize(&blk) end
だと思いました。
面白かった。