Page 1
http://www.flickr.com/photos/mio-spr/2042538806
2008‐11‐19(Wed); AppleStore, SapporoRuby Sapporo Night vol.8
Fluent interfaceについて少しTalking about “Fluent interface”
島田 浩二SHIMADA Koji; Nihon Ruby-no-kai; RubySapporo
snoozer.05@ruby‐sapporo.org
日本Rubyの会/Ruby札幌
Page 2
それでは、よい設計を。
Ken Pugh 著, 角谷信太郎 監訳「インターフェイス指向設計」監訳者まえがきより
Page 3
アジェンダ✓動機✓ 2種類の利用者✓ 3つの車輪✓ 1つの視点✓まとめ
Page 5
http://rubyconf.org/
RubyConf 2008
Page 6
http://www.nealford.com/downloads/conferences/canonical/Neal_Ford-Advanced_DSLs_in_Ruby-slides.pdf
Neal Ford,Advanced DSL in Ruby
Page 7
http://www.nealford.com/downloads/conferences/canonical/Neal_Ford-Advanced_DSLs_in_Ruby-slides.pdf
Neal Ford,Advanced DSL in Ruby
Page 8
http://www.nealford.com/downloads/conferences/canonical/Neal_Ford-Advanced_DSLs_in_Ruby-slides.pdf
Neal Ford,Advanced DSL in Ruby
Page 9
?メソッドチェーンとの違いは?
DSLとはどう違うのか?
Page 12
✓ “気持ちよく書けるもの” 程度の漠然とした理解しかなかった
✓メソッドチェーンやDSLとの違い、関係をきちんと理解したい
動機
Page 13
http://www.flickr.com/photos/quanle/251201209/
Fluent interface :流れるようなインターフェイス
Page 14
http://www.flickr.com/photos/jw3000/12703492
Page 15
http://capsctrl.que.jp/kdmsnr/wiki/bliki/?FluentInterface
Martinfowler’s Biki
Page 16
JMock APIExpect.Once.On(mockLogger) .Method(“LogError”) .With(Has.Substring(USER_NAME) & Has.Substring(“access defined”));
mainframe.expects(once()) .method(“buy”).with(eq(QUANTITY)) .will(returnValue(TICKET));
Page 17
✓ 流れるようなアクションで特定の文脈を表現
✓ 読みやすさを第一にインターフェイスを設計
✓ 慣習 << 流れるようなスタイル
Fluent interface
Page 18
?メソッドチェーンとの違いは?
DSLとはどう違うのか?
Page 21
http://www.flickr.com/photos/srijith/1867095482
“Fluent”流れるような
Page 22
流れるようなインターフェイス
✓何に対して?✓何が流れる?
Page 26
インターフェイスの利用者
✓コードを書く人✓コードを読む人
Page 29
http://www.flickr.com/photos/mdd/175282811
コードを書く人
Page 30
コードを書く人は、
✓実現したいことに関するコンテキストを持っている
✓コンテキストの一部をインターフェイスを利用して表現しようとしている
Page 31
コードを書く人にとって、
✓流れ: コンテキストの一部⇒コードへの変換
✓流れるような: 表現したい順に手を動かしていける
Page 32
http://www.flickr.com/photos/ozyman/443545349
コードを読む人
Page 33
コードを読む人は、
✓コンテキストを通してコードを見ているとは限らない
✓処理を理解すると共に、コンテキストに関する情報を集めている
Page 34
コードを読む人にとって、
✓流れ: コード⇒していること+コンテキストの情報
✓流れるような: 目で追う順に情報を理解していける
Page 36
読んだことが流れるように頭に入ってくる
考えたことを流れるようにコードにすることが出来る
コード
Fluent interfaceが生み出したい“流れ”
インターフェイス利用者
Page 37
Fluent interface✓ 流れるようなアクションで特定の文脈を表現
✓ 読みやすさを第一にインターフェイスを設計
✓ 慣習 << 流れるようなスタイル
Page 40
http://www.flickr.com/photos/fuckr/91530309
“Interface”インターフェイス
Page 41
流れるようなインターフェイス
✓どうやって?
Page 43
http://capsctrl.que.jp/kdmsnr/wiki/bliki/?FluentInterface
Martinfowler’s Biki
Page 44
Evolving an EDSL in Java
http://www.mockobjects.com/files/evolving_an_edsl.ooplsa2006.pdf
Page 46
Fluent interfaceの車輪
✓ メソッドチェーン✓ カスケード✓ セマンティクス
http://www.flickr.com/photos/17258892@N05/2588347668
Page 48
http://www.flickr.com/photos/good_day/117131491/
メソッドチェーンmethod chain
Page 49
✓ メソッド呼び出しを連鎖的に繋げていき一連の処理を表現
✓ 「aの結果をbしてcしたい」✓ e.x Unixのパイプ
メソッドチェーン
Page 50
インターフェイス利用者
A B C
オブジェクト オブジェクト オブジェクト
ab
c
メソッドチェーン
aの結果をbしてcしたい
Page 51
メソッドチェーン
data.grep(/foo/).uniq.sort.join(“¥n”).display
tmp1 = data.grep(/foo/)tmp2 = tmp1.uniqtmp3 = tmp2.sorttmp4 = tmp3.join(“¥n”)tmp4.display
Page 53
http://www.flickr.com/photos/jacky83/2311687241
カスケードcascade
Page 54
✓ Smalltalkでサポートされているシンタックスシュガー
✓ 一つのオブジェクトに対する一連の処理を記述
✓ 一連のメッセージを流し込む✓ 「Aに対してaしてbしてcしたい」
カスケード
Page 55
カスケードTranscript clear.Transcript nextPutAll: ‘SHIMADA Koji’.Transcript cr.Transcript flush.
Transcript clear; nextPutAll: ‘SHIMADA Koji’; cr; flush
Page 56
インターフェイス利用者
A
オブジェクト
a
b
c
カスケード
Aにaしてbしてcしたい
Page 58
✓ Javaでは言語としてカスケードをサポートしていなかった
✓ 自分自身を返り値とすれば、メソッドチェーンで実現することができる
✓ 慣習には背くけど
カスケード
Page 59
カスケードexpectation.setCount(once());expectation.setMethod(“buy”);expectation.setArgument(eq(QUANTITY));expectation.setResult(TICKET);
expectation.setCount(once()) .setMethod(“buy”) .setArgument(eq(QUANTITY)); .setResult(TICKET);
Page 61
http://www.flickr.com/photos/mio-spr/428995450
セマンティクスsemantics
Page 63
✓ 実現手段ではなく、意図を伝えるメソッド名をつける
✓ それ単体では利用者に価値を生み出さない操作をどうするか? ⇒シンタックスとしてしまう
✓ 利用者に価値を生み出す単位で、操作の意図が伝わることが重要
セマンティクスを表現する
Page 64
JMock API
mainframe.expects(once()) .method(“buy”).with(eq(QUANTITY)) .will(returnValue(TICKET));
expectation.setCount(once()) .setMethod(“buy”) .setArgument(eq(QUANTITY)); .setResult(TICKET);
Page 66
data.grep(/foo/).uniq.sort.join(“¥n”).display
それ単体でも利用者にとって価値のある操作は、そのままでも十分意図が伝わる
セマンティクスを表現する
(1..10).map{|i| i*i}.select{|i| i % 2 == 0}
Page 67
data.grep(/foo/).uniq.sort.join(“¥n”).display
セマンティクスを表現する
(1..10).map{|i| i*i}.select{|i| i % 2 == 0}
mainframe.expects(once()) .method(“buy”).with(eq(QUANTITY)) .will(returnValue(TICKET));
Page 69
Fluent interfaceの車輪
✓ メソッドチェーン✓ カスケード✓ セマンティクス
http://www.flickr.com/photos/17258892@N05/2588347668
Page 70
Fluent interface✓ 流れるようなアクションで特定の文脈を表現
✓ 読みやすさを第一にインターフェイスを設計
✓ 慣習 << 流れるようなスタイル
Page 72
rate = Discount.newrate.cash = 0.05rate.membership = 0.02rate.price = 0.01product.apply_discount(rate)
Page 73
product.apply( Discount.for. cash(0.05). membership(0.02). price(0.01))
Page 74
class Discount ... def Discount.for Discount.new end def cash(discount) @for_cash = discount self endend
Page 75
class Discount ... def Discount.for Discount.new end def cash(discount) @for_cash = discount self endend
Page 76
class Discount ... def Discount.for Discount.new end def cash(discount) @for_cash = discount self endend
Page 77
class Product ... def apply(discount) @discount = discount end ...end
Page 78
product.apply( Discount.for. cash(0.05). membership(0.02). price(0.01))
Page 81
✓責務の振り分け✓返り値✓引数✓メソッド名
Page 85
http://www.flickr.com/photos/srijith/1867095482
流れ
Page 86
読んだことが流れるように頭に入ってくる
考えたことを流れるようにコードにすることが出来る
コード
Fluent interfaceが生み出したい“流れ”
インターフェイス利用者
Page 87
読んだことが流れるように頭に入ってくる
考えたことを流れるようにコードにすることが出来る
コード
Fluent interfaceが生み出したい“流れ”
インターフェイス利用者
Page 88
読んだことが流れるように頭に入ってくる
考えたことを流れるようにコードにすることが出来る
コード
Fluent interfaceが生み出したい“流れ”
インターフェイス利用者
Page 89
読んだことが流れるように頭に入ってくる
考えたことを流れるようにコードにすることが出来る
コード
Fluent interfaceが生み出したい“流れ”
インターフェイス利用者
Page 90
Fluent interfaceという観点でインターフェイスを見つめる行為は、インターフェイスの具体的な利用者のことを強く考えさせてくれる
Page 91
...a programmer’s job is too communicatewith other programmers, not just a machine.
Programming, then, is a human task done by humans for humans.
Oh, and writing good code at the same time.
プログラムは、マシンにだけではなく、自分以外のプログラマに向けて書かれるべきなんだ。
そうすることで、プログラミングは人による、人のための、人の仕事になる。
もちろん、それは良いコードにもなっているんだよ。
- Kent Beck「Implementation Patterns」
Page 92
Fluent interfaceはインターフェイスも人に向けて書かれるべきだと改めて教えてくれている
http://www.flickr.com/photos/suvcougar/
Page 94
インターフェイス設計に動線というメタファを持ってこれないだろうか
Page 96
動線✓ 建物の中を、人が自然に動く時に通ると思われる径路
✓ 建物の間取りをするときに気をつけるべきこと
✓ 設計の際に利用者の行動パターンを予測し、より明快に、また移動距離が長くならないよう考慮する
http://ja.wikipedia.org/wiki/%E5%8B%95%E7%B7%9A
Page 97
利用者の行動パターンを予測し、より明快に、移動距離を短く
Page 99
http://www.flickr.com/photos/storm-crypt/2280100565
どうやって見つけるか
Page 101
これまでの作業は机の上でできています。確かに現場の条件をよーく考慮して、このスケッチは出来ています。でも気をつけて下さい! これは、あくまで、机の上の「絵」にすぎません。現場で、直接、原寸で、絵を描いて、はじめてリアルな形となるのです。
Page 103
どうやって見つけるか
✓ TDD✓ テストコードが最初の利用者✓インクリメンタルな開発✓ こまめにリリースすることで実際の利用者からフィードバックを受ける
Page 104
http://www.flickr.com/photos/nibaq/1735007
学び方
Page 105
Fluent interface in wild✓ named_scope✓ User.not_admin.age(10..20)
✓ RSpec✓ user.active.should be_all {|u| not u.deleted }
✓ ActiveSupport✓ Date.parse('2008-11-19').yesterday.ago(1.second)
Page 107
✓ 2種類の利用者✓ コードを読む、コードを書く✓ 3つの車輪✓ メソッドチェーン、カスケード、セマンティクス
✓ 1つの視点✓ 利用者に価値があるかどうか
ここまでのまとめ
Page 108
“インターフェイスに対してプログラミングするのであって,実装に対してプログラミングするのではない” (GoF)
Page 109
より良いインターフェイスを探求する僕らの冒険はまだ始まったばかり
http://www.flickr.com/photos/pedrosz/2287112249
Page 111
http://www.flickr.com/photos/mio-spr/2042538806
2008‐11‐19(Wed); AppleStore, SapporoRuby Sapporo Night vol.8
Fluent interfaceについて少しTalking about “Fluent interface”
島田 浩二SHIMADA Koji; Nihon Ruby-no-kai; RubySapporo
snoozer.05@ruby‐sapporo.org
日本Rubyの会/Ruby札幌