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

2,568 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
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,568
On SlideShare
0
From Embeds
0
Number of Embeds
590
Actions
Shares
0
Downloads
3
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

つながりをゆるふわにしよう 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. ご清聴ありがとうございました

×