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

ActiveSupport::Notifications
2013-11-02 広島Ruby勉強会 #035
Rails のコードリーディング

• コード読んでるので毎月ピックアップ
• http://railsdoc.eiel.info/
• 今回は ActiveSupport::Notifications
ActiveSupport::Notifications

• 通知を実現するためのクラス
• オブジェクト間を緩い繋りに
オブジェクトの繋り

• オブジェクトはメッセージで繋る
• メッセージを送る方法
• メソッドの呼び出し
オブジェクトの繋り
• 直接メソッド呼び出し
• 繋りが強い
• ちょっと回り道をする
• 繋りを緩くできる
どうして緩くしたいか

• 変更箇所を減らしたい
• 本質と関係ないものを分離
どうして通知が欲しいかみていく

• 普通の呼び出し
• 処理を後から登録
• 通知を使う
普通の呼び出し

• 強い繋り
• 1対1の繋り
普通の呼び出し

作る
a

b

メソッドを呼ぶ
問題点

• 後から処理を追加するのに
• コードの変更が必要
例
class A
def hoge
# hogeする
end
end
!
a = A.new
a.hoge
a を hoge するときに b.hoge して
欲しい
例
class B
def hoge
# B hoge する
end
end

!
class A
def hoge
# hoge する
B.new.hoge
end
end
さらに追加したくなった
例
class B
def hoge
# B hoge する
end
end

!
class A
def hoge
# hoge する
B.new.hoge
B.new.hoge
end
end
Aを変更しなきゃいけない
Aが変えたくない場合がある

• Aがライブラリやフレームワーク
• 完成しているので変えられない
• Aが自分が作ったBを知ってるわけがない
処理を後から登録する

• 少し弱くなった繋り
• 1対多の繋り
処理を後から登録する

• ルールを決める
• オブジェクトを登録できるように
• 決めたメソッドを呼ぶ
処理を後から登録する
オブジェクトを登録

b

b

a

メソッドを呼ぶ

b

b

0個からn個
例
class A
def hoge
# hoge する
objects.each do |object|
object.hoge
end
end

!
def objects
@objects ||= []
end
end

!
a = A....
b.hoge を追加したい
例

a = A.new
a.objects << B.new
a.hoge
Aの外側で
Aに処理を追加できる
問題点

• b を追加するのに a を知ってる必要がある
• オブジェクトへの参照が必要
通知を使う

• 文字列で繋りを作る
• だいぶ ゆるふわ
• 多対多の繋り
通知を使う
• 通知を呼び出す側
• 相手のことを意識する必要がない
• 呼ばれる側
• 相手のことを意識する必要がない
処理を後から登録する
登録しておく

b

a
処理をお願いする 通知システム
b

a

b
メソッドを呼ぶ
b
通知システムを経由することで
a と b の直接的な繋りを無くせる
代わりに
通知システムに
強い繋りが
具体例
class Notifications
@@regists = Hash.new([])

!
def self.regist(key,object)
@@regists[key] << object
end

!
def self.n...
具体例

# 通知 hoge があったときにすることを登録
Notifications.regist(‘hoge’, B.new)
!
# 通知 hoge を発生させる
Notifications.notify(‘hoge’)
ActiveSupport::Notifications

• Rails で通知を使うためのクラス
• Rails 3 で追加
• Developmentモードで
• HTMLの生成時間と
• SQLの実行時間
ActiveSupport::Notifications

• やりすぎ注意
• 処理の流れを明確にしたいところでは
使わないように

• Rails の中にも通知ポイントがある
使い方
• 通知の仕方
• ActiveSupport::Notifications.instrument
• 処理の登録
• ActiveSupport::Notifications.subscribe
通知の仕方
• 後で処理を追加したくなりそうだなー。
• ActiveSupport::

Notifications.instrument(name, payload)

• name
• 処理を登録する時に使う名前
• payload
• 登...
処理の登録
• ActiveSupport::

Notifications.subscribe(pattern,&block)

• pattern
• 通知のした際の name
• 正規表現が使える
• block
• したい処理
pattern
• pattern には正規表現が
• /hoge/ であれば
• instrument の name が
• hoge.mogu
• mogu.hoge
• でも実行される
block
• block の中で使える情報
• name
• start
• finish
• id
• payload
name

• Notifications.instrument した時の引数
• pattern で指定しているので

正確な名前が欲しい時に
例
require ‘active_support/notifications’

!
include ActiveSupport

!
Notifications.subscribe(/hoge/) do |name|
puts name
e...
start finish
• instrument側の

処理の時間を測定できる

• 始めの時間と終わりの時間
• instrumentする際にブロックを使う
例
require ‘active_support/notifications’

!
include ActiveSupport
Notifications.subscribe(/hoge/) do |name, start, finish|...
id

• 通知システム内の通知者のID
• スレッドごとに変化する
• (別に知らなくて良い気がする)
例
require ‘active_support/notifications’
require ‘thread’

!
include ActiveSupport
Notifications.subscribe(‘hoge’) do |nam...
例 結果

["hoge", "8c71812749ca24e5a40e"]
["hoge", "8c71812749ca24e5a40e"]
["hoge", "c1050d011fe625537e41"]
payload

• メソッドのように引数を使いたい
例
require ‘active_support/notifications’

!
include ActiveSupport
Notifications.subscribe(‘hoge’) do |n, s, f, i, payload|...
より深いどうでもいいところ

• ActiveSupport::Notifications::Instrumenter
• 通知処理を実質的にしているクラス
• スレッド毎に存在
より深いどうでもいいところ
• ActiveSupport::Notifications::Fanout
• 登録した処理を管理しているところ
• ActiveSupport::Notifications::Fanout::Subscribers
...
ご清聴ありがとうございました
つながりをゆるふわにしよう Active supprt notifications
つながりをゆるふわにしよう Active supprt notifications
Upcoming SlideShare
Loading in...5
×

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

1,681

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
1,681
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
2
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. ご清聴ありがとうございました
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×