Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

つながりをゆるふわにしよう Active supprt notifications

2,970 views

Published on

広島Ruby勉強会 #035 にて http://hiroshimarb.github.io/blog/2013/11/02/hiroshimarb-35/

ActiveSupport::Notifications について。
スライドをつくるための原稿はこっちにある。

https://gist.github.com/eiel/7177959

Published in: Technology
  • Be the first to comment

つながりをゆるふわにしよう Active supprt notifications

  1. 1. つながりをゆるふわにしよう ActiveSupport::Notifications 2013-11-02 広島Ruby勉強会 #035
  2. 2. Rails のコードリーディング • コード読んでるので毎月ピックアップ • http://railsdoc.eiel.info/ • 今回は ActiveSupport::Notifications
  3. 3. ActiveSupport::Notifications • 通知を実現するためのクラス • オブジェクト間を緩い繋りに
  4. 4. オブジェクトの繋り • オブジェクトはメッセージで繋る • メッセージを送る方法 • メソッドの呼び出し
  5. 5. オブジェクトの繋り • 直接メソッド呼び出し • 繋りが強い • ちょっと回り道をする • 繋りを緩くできる
  6. 6. どうして緩くしたいか • 変更箇所を減らしたい • 本質と関係ないものを分離
  7. 7. どうして通知が欲しいかみていく • 普通の呼び出し • 処理を後から登録 • 通知を使う
  8. 8. 普通の呼び出し • 強い繋り • 1対1の繋り
  9. 9. 普通の呼び出し 作る a b メソッドを呼ぶ
  10. 10. 問題点 • 後から処理を追加するのに • コードの変更が必要
  11. 11. 例 class A def hoge # hogeする end end ! a = A.new a.hoge
  12. 12. a を hoge するときに b.hoge して 欲しい
  13. 13. 例 class B def hoge # B hoge する end end ! class A def hoge # hoge する B.new.hoge end end
  14. 14. さらに追加したくなった
  15. 15. 例 class B def hoge # B hoge する end end ! class A def hoge # hoge する B.new.hoge B.new.hoge end end
  16. 16. Aを変更しなきゃいけない
  17. 17. Aが変えたくない場合がある • Aがライブラリやフレームワーク • 完成しているので変えられない • Aが自分が作ったBを知ってるわけがない
  18. 18. 処理を後から登録する • 少し弱くなった繋り • 1対多の繋り
  19. 19. 処理を後から登録する • ルールを決める • オブジェクトを登録できるように • 決めたメソッドを呼ぶ
  20. 20. 処理を後から登録する オブジェクトを登録 b b a メソッドを呼ぶ b b 0個からn個
  21. 21. 例 class A def hoge # hoge する objects.each do |object| object.hoge end end ! def objects @objects ||= [] end end ! a = A.new a.hoge
  22. 22. b.hoge を追加したい
  23. 23. 例 a = A.new a.objects << B.new a.hoge
  24. 24. Aの外側で Aに処理を追加できる
  25. 25. 問題点 • b を追加するのに a を知ってる必要がある • オブジェクトへの参照が必要
  26. 26. 通知を使う • 文字列で繋りを作る • だいぶ ゆるふわ • 多対多の繋り
  27. 27. 通知を使う • 通知を呼び出す側 • 相手のことを意識する必要がない • 呼ばれる側 • 相手のことを意識する必要がない
  28. 28. 処理を後から登録する 登録しておく b a 処理をお願いする 通知システム b a b メソッドを呼ぶ b
  29. 29. 通知システムを経由することで a と b の直接的な繋りを無くせる
  30. 30. 代わりに 通知システムに 強い繋りが
  31. 31. 具体例 class Notifications @@regists = Hash.new([]) ! def self.regist(key,object) @@regists[key] << object end ! def self.notify(key) @@regists[key].each do |object| object.hoge end end end
  32. 32. 具体例 # 通知 hoge があったときにすることを登録 Notifications.regist(‘hoge’, B.new) ! # 通知 hoge を発生させる Notifications.notify(‘hoge’)
  33. 33. ActiveSupport::Notifications • Rails で通知を使うためのクラス • Rails 3 で追加 • Developmentモードで • HTMLの生成時間と • SQLの実行時間
  34. 34. ActiveSupport::Notifications • やりすぎ注意 • 処理の流れを明確にしたいところでは 使わないように • Rails の中にも通知ポイントがある
  35. 35. 使い方 • 通知の仕方 • ActiveSupport::Notifications.instrument • 処理の登録 • ActiveSupport::Notifications.subscribe
  36. 36. 通知の仕方 • 後で処理を追加したくなりそうだなー。 • ActiveSupport::
 Notifications.instrument(name, payload) • name • 処理を登録する時に使う名前 • payload • 登録した処理に渡す追加情報
  37. 37. 処理の登録 • ActiveSupport::
 Notifications.subscribe(pattern,&block) • pattern • 通知のした際の name • 正規表現が使える • block • したい処理
  38. 38. pattern • pattern には正規表現が • /hoge/ であれば • instrument の name が • hoge.mogu • mogu.hoge • でも実行される
  39. 39. block • block の中で使える情報 • name • start • finish • id • payload
  40. 40. name • Notifications.instrument した時の引数 • pattern で指定しているので
 正確な名前が欲しい時に
  41. 41. 例 require ‘active_support/notifications’ ! include ActiveSupport ! Notifications.subscribe(/hoge/) do |name| puts name end ! Notifications.instrument(“hoge.goro”) Notifications.instrument(“goro.hoge”) # >> hoge.goro # >> goro.hoge
  42. 42. start finish • instrument側の
 処理の時間を測定できる • 始めの時間と終わりの時間 • instrumentする際にブロックを使う
  43. 43. 例 require ‘active_support/notifications’ ! include ActiveSupport Notifications.subscribe(/hoge/) do |name, start, finish| p [start, finish] end ! Notifications.instrument(“hoge”) do sleep(1) end # >> [2013-11-01 15:54:13 +0900, 2013-11-01 15:54:14 +0900]
  44. 44. id • 通知システム内の通知者のID • スレッドごとに変化する • (別に知らなくて良い気がする)
  45. 45. 例 require ‘active_support/notifications’ require ‘thread’ ! include ActiveSupport Notifications.subscribe(‘hoge’) do |name, s, f, id| p [name, id] end ! Notifications.instrument(‘hoge’) Notifications.instrument(‘hoge’) Thread.new { Notifications.instrument(‘hoge’) }.run
  46. 46. 例 結果 ["hoge", "8c71812749ca24e5a40e"] ["hoge", "8c71812749ca24e5a40e"] ["hoge", "c1050d011fe625537e41"]
  47. 47. payload • メソッドのように引数を使いたい
  48. 48. 例 require ‘active_support/notifications’ ! include ActiveSupport Notifications.subscribe(‘hoge’) do |n, s, f, i, payload| p payload end ! Notifications.instrument(‘hoge’, :hoge) Notifications.instrument(‘hoge’,{hoge: 1}) # >> :hoge # >> {:hoge => 1}
  49. 49. より深いどうでもいいところ • ActiveSupport::Notifications::Instrumenter • 通知処理を実質的にしているクラス • スレッド毎に存在
  50. 50. より深いどうでもいいところ • ActiveSupport::Notifications::Fanout • 登録した処理を管理しているところ • ActiveSupport::Notifications::Fanout::Subscribers • 処理はこのモジュールの中にあるクラスのいずれかに ラップされる • finish がいるかどうかとかで区分される • 呼ばれる予定処理を確認したりもできる
  51. 51. ご清聴ありがとうございました

×