せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【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

だと思いました。

面白かった。