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