Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
極める!メソッドチェーン #phpstudy / fluent-interface
Search
Hiraku NAKANO
July 26, 2017
Technology
8
2.7k
極める!メソッドチェーン #phpstudy / fluent-interface
2017/07/26 第116回 PHP勉強会の発表資料です。
Hiraku NAKANO
July 26, 2017
Tweet
Share
More Decks by Hiraku NAKANO
See All by Hiraku NAKANO
iD決済を支える技術 / #merpay_techtalk
hirak
33
7.1k
github.com/mercari の今と昔 /github-mercari
hirak
8
3k
PHPStanで始める継続的静的解析 #phperkaigi /php-static-analysis
hirak
14
52k
evalこそパワー #phpkansai / phpkansai2017
hirak
2
1.5k
PHPのエラーと例外再入門 / php-error-and-exception
hirak
19
19k
メルカリ JP Tech Side / mercari-jp-tech-side
hirak
7
1.9k
グローバル展開を支える量子的なサービス設計 #mercariday / mercariday2017-api
hirak
22
13k
Composerプラグインを作ってみよう /phpcon2016
hirak
5
14k
packagist.jpの紹介と新機能 /#phpblt
hirak
4
2.7k
Other Decks in Technology
See All in Technology
Culture Deck
optfit
0
420
プロセス改善による品質向上事例
tomasagi
2
2.6k
OpenID Connect for Identity Assurance の概要と翻訳版のご紹介 / 20250219-BizDay17-OIDC4IDA-Intro
oidfj
0
280
クラウドサービス事業者におけるOSS
tagomoris
1
820
速くて安いWebサイトを作る
nishiharatsubasa
10
13k
転生CISOサバイバル・ガイド / CISO Career Transition Survival Guide
kanny
3
1k
データマネジメントのトレードオフに立ち向かう
ikkimiyazaki
6
980
あれは良かった、あれは苦労したB2B2C型SaaSの新規開発におけるCloud Spanner
hirohito1108
2
590
Developer Summit 2025 [14-D-1] Yuki Hattori
yuhattor
19
6.2k
エンジニアの育成を支える爆速フィードバック文化
sansantech
PRO
3
1.1k
AndroidXR 開発ツールごとの できることできないこと
donabe3
0
130
急成長する企業で作った、エンジニアが輝ける制度/ 20250214 Rinto Ikenoue
shift_evolve
3
1.3k
Featured
See All Featured
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
The Language of Interfaces
destraynor
156
24k
Build The Right Thing And Hit Your Dates
maggiecrowley
34
2.5k
Documentation Writing (for coders)
carmenintech
67
4.6k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.2k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
114
50k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
A designer walks into a library…
pauljervisheath
205
24k
How GitHub (no longer) Works
holman
314
140k
Transcript
ۃΊΔʂ ϝιουνΣʔϯ @hiraku
ࣗݾհ • த (@Hiraku) • https://github.com/hirak • ϝϧΧϦͷαʔόʔαΠυΤϯδχΞ •
Composerؔ࿈ͷൃදΛΑ͍ͯ͘͠·͢ • PHPΧϯϑΝϨϯεؔ2016 جௐߨԋ
We are hiring!
None
None
None
ۃΊΔʂ ϝιουνΣʔϯ @hiraku
ϝιουνΣʔϯͱ $talk ->setTitle('art of method chain') ->setContent('no plan') ->setLength('20min') ;
ΦϒδΣΫτʹରͯ͠ɺ ϝιουΛଓ͚ͯॻ͚ΔΑ͏ʹ ͨ͠ύλʔϯ/APIσβΠϯͷ͜ͱ
5લʹൃදͨͭ͠ https://www.slideshare.net/hinakano/xml-builder
None
ͪΖΜ߹๏ͳPHPߏจ
Χοίলུ&Մมϝιου໊ ด͡λά͕ͳ͍͜ͱͷ໌ࣔ ด͡λάิ
࠷ۙॻ͍ͨͭ PHPͷߴΦγϟϨةݥྻϥΠϒϥϦspindle/collectionΛ࡞͍ͬͯΔ - Qiita http://qiita.com/Hiraku/items/bb6318d1d2c26ae7f30a
·ΔͰͯ͠ͳ͍…
ϝιουνΣʔϯେ͖ • ੍ͰPHPΒ͘͠ͳ͍ߏจΛ࡞Δઓ • PHPߏจ͕ශऑͩͬͨ • ݺͼग़͠νΣʔϯͰ͖ͳ͍ͱ͔()()()() • །Ұੲ͔Β͑ͨͷ͕ϝιουνΣʔϯ
͓͜ͱΘΓ • ϥΠϒϥϦΛఏڙ͢ΔਓԿΛߟ͑Δ͖͔ʁ Έ͍ͨͳΛ͠·͢ • ҰੲલͷJavaͷম͖͔͠͠Εͳ͍
࣍ 1. σϝςϧͷ๏ଇ 2. ϝιουνΣʔϯͷύλʔϯ৭ʑ 3. APIσβΠϯͷ͓ 4. σϞతͳͭ
1ষ σϝςϧͷ๏ଇ ۃΊΔ!ϝιουνΣʔϯ
σϝςϧͷ๏ଇ (࠷খࣝͷݪଇ) (Law of Demeter, LoD) • ιϑτΣΞͷઃܭɺಛʹΦϒδΣΫτࢦ ϓϩάϥϜͷઃܭʹ͓͚ΔΨΠυϥΠϯ •
ʮ๏ଇʯͱ͍͏༁͕ͩɺʮ͜ΕΛकͬͯΔ ίʔυͷํ͕͍͍Αʂʯͱ͍͏Α͏ͳओࢫ
σϝςϧOK? 0, /( B BCD UIJTB UIJTB C UIJTBC UIJTBC
D
৮ͬͯྑ͍ͷ 0, ϩʔΧϧมɺҾ৮ͬͯ0, B ࣗͷϝιου৮ͬͯ0, UIJTB ࣗͷϓϩύςΟͷϝιου ৮ͬͯ0, UIJTBC
$talk ->setTitle('art of method chain') ->setContent('no plan') ->setLength('20min') ; $talk->setTitle('art
of method chain'); $talk->setContent('no plan'); $talk->setLength('20min'); LoDकͬͨํ͕͍͍ͷʁ ϝιουͷΓ is Կʁ ͜ΕͳΒΓΛؾʹ͢Δ·Ͱͳ͍
ϝιουνΣʔϯͱ $talk ->setTitle('art of method chain') ->setContent('no plan') ->setLength('20min') ;
ΦϒδΣΫτʹରͯ͠ɺ ϝιουΛଓ͚ͯॻ͚ΔΑ͏ʹ ͨ͠ύλʔϯ/APIσβΠϯͷ͜ͱ
͍
ϝιουνΣʔϯLoDҧ • LoDతʹɺ$this->set...; $this->set...; ͱͦΕ ͧΕॻ͖͘ • LoDɺϥΠϒϥϦઃܭऀ͕͓͖ͬͯ͘ ݪଇͷ̍ͭͰ͋Δ
Ұ୴ɺLoDஔ͍ͱ͍ͯɺ ΛਐΊ·͢ɻ
2ষ ϝιουνΣʔϯͷ ύλʔϯ ۃΊΔ!ϝιουνΣʔϯ
LoDΛഁͬͯ·Ͱ ϝιουνΣʔϯͰ ԿΛ͍ͨ͠ͷ͔ʁ
1) return $this class Chainable { function setA($val) { $this->a
= $val; return $this; } function setB($val) { $this->b = $val; return $this; } } (new Chainable) ->setA('a') ->setB('b'); ࿈ଓͰsetͰ͖ΔΑ͏ʹͳͬͨΑʂ
return $this ʹର͢Δݸਓతཧղ • $instance->ͬͯॻ͔ͳͯ͘Α͘ͳΔ • ͪΐͬͱ͚ͩShort hand • ͨͩͦΕ͚ͩͳͷͰɺLoDഁΔ΄ͲͷՁ͕
͋Δ͔…ͱ͍͏ͱඍົͳؾ͢Δ
2) PSR-7ͷAPIΈ͍ͨͳͭ (new GuzzleHttp\Psr7\Request('GET', 'http://example.com')) ->withHeader('foo', 'baa') ->withBody($body); return $thisͰͳ͘ɺ
newͯ͠ࠓ·ͰͷใΛίϐʔ (ผΠϯελϯεΛฦ͢)
immutableͱ • setterͷͳ͍ΦϒδΣΫτ • ෦ΛมߋͰ͖ͳ͍ͷͰɺ clone͠ͳͯ҆͘શʹฦͤΔ • setterͰͳ͘ɺʮίϐʔͯ͠Ұ෦Λ্ॻ͖ʯ ͢ΔσβΠϯ
immutable ʹର͢Δݸਓతཧղ • ΓΛड͚औΒͳ͍ͱ݁Ռ͕ফ͑ͯ͠·͏ • $obj->setFoo($foo); $obj->setBaa($baa); ͯ͠ҙຯ͕ͳ͍ • $obj
= $obj->setFoo($foo); $obj = $obj->setBaa($baa); • ه๏͕໘ͳͷͰɺϝιουνΣʔϯʹͨ͘͠ͳΔ(Θ͔Δ)
ͪΐͬͱ͕ҳΕ·͕ͨ͠ • return $this͢Δ͚͕ͩϝιουνΣʔϯͰ ͳ͍ • return new ͢Δύλʔϯ͋Δ
return newͰ ༡ΜͰΈΔྫ
͓ • ϝιουνΣʔϯͰ ೖΕࢠͰ͖ΔifจΛ ࡞Ε
ϒϩοΫʹΦϒδΣΫτΛͯ ΊΔ • ifnewΛฦ͢ • endifϒϩοΫΛ ऴΘΒͤͯͱʹ Δ
<?php abstract class Context { protected $parent = null; function
__construct(Context $parent=null) { $this->parent = $parent; } abstract function if(bool $bool): Context; abstract function say(string $str): Context; function endif(): Context { return $this->parent; } } class TrueContext extends Context { function if(bool $bool): Context { if ($bool) { return new self($this); } else { return new FalseContext($this); } } function say(string $str): Context { echo $str,PHP_EOL; return $this; } } class FalseContext extends Context { function if(bool $bool): Context { return new self($this); } function say(string $str): Context { return $this; } } function dsl(): TrueContext { return new TrueContext; } ͍͍ͩͨ ͜Ε͙Β͍ Ͱ࡞ΕΔ ϝιουνΣʔϯDSLͰϒϩοΫΛ࡞ΔςΫχοΫ: Architect Note http://blog.tojiru.net/article/272060766.html
3) +ϚδοΫϝιουͷཚ༻ return $thisͰͳ͘ɺ newͯ͠ࠓ·ͰͷใΛίϐʔ (ผΠϯελϯεΛฦ͢)
ϚδοΫϝιου • __get(){}ɺ__call(){}ΛΫϥεʹੜ͓ͯ͘͠ • ϓϩύςΟ/ϝιουʹΞΫηεग़དྷͳ͍ͱ͖ ʹࣗಈతʹݺΕΔ • Rubyͷmethod_missingΈ͍ͨͳͭ
IUNM NFUB@ UJUMF@ @ ͳΜͯϝιου QVCMJDϓϩύςΟੜ͍͑ͯͳ͍ɻ ࣮ࡍʹॲཧ͍ͯ͠Δͷ @@DBMM ͱ@@HFU
ϚδοΫϝιου • ✅ίʔυྔ(ܶతʹݮΔ) • ❌ಡΈ͢͞ • ❌֦ுੑ • ❌PhpStormʹౖΒΕΔ •
ׂͱݏ͍ͬͯΔPHPer͕ଟ͍ҹ(ओ؍)
4) fluent interface • ʮྲྀΕΔΑ͏ͳΠϯλʔϑΣʔεʯ • ϝιουνΣʔϯΛ͏গ͠ൃలͤͨ͞ͷ • આ໌͕͍͠ͷͰ࣍ͷষ
3ষ APIσβΠϯͷ ۃΊΔ!ϝιουνΣʔϯ
ঢ়گ • ͋ͳͨɺͱ͋ΔWebαʔϏεͷPHP൛SDK Λ࡞Δ͜ͱʹͳΓ·ͨ͠ • ͦͷWebαʔϏεେྔͷػೳ͕͋Γ·͢ɻ • SDKͳͷͰɺੜcurlͰୟ͘ΑΓศརʹ͍ͨ͠
None
None
SDKͷAPIσβΠϯ • SDKϢʔβʔ෦࣮ΛΑ͘Βͳ͍ • Ͱ͖ΕυΩϡϝϯτ͚ͩͰ͍͜ͳ͍ͨ͠ • ͲΜͳΫϥε͕͋ͬͯɺ ͲΜͳϝιουΛஔ͢Δʁ
…Ԟͷਂ͍Ͱ͋Δ
ςϨϏͷϦϞίϯ
None
Α͋͘ΔςϨϏͷϦϞίϯ • Ϙλϯ͕͍ͬͺ͍͋Δ • ͲΕΛԡ͍͍ͤͷʁ໎͏ • (ͨͿΜ)ςετେมͦ͏… • ͍ͭͰ͋ΒΏΔϘλϯ͕ԡͤΔ
ղܾҊ • ͍͞͠ΐϘλϯ1ݸ(ిݯ)ͷΈ • ిݯ͕ೖΔͱɺ͏ʹΐʔΜͱϘλϯ͕ੜ͑ͯ͘Δ • ૢ࡞͢ΔͨͼʹɺϘλϯ͕͏ʹΐʔΜͱੜ͑ͯ͘ Δ or ফ͑Δ
• ϘλϯݮΒͤͦ͏Ͱ͢Ͷʂ
API = ϦϞίϯ
APIσβΠϯʹͯΊͯΈΔ • ϩάΠϯ͕ඞཁͳΒɺϩάΠϯͷAPI͚͕ͩ ݟ͑ͯΔ͖ • ͦͷঢ়ଶͰՄೳͳૢ࡞͚͕ͩ͑Δ • linkͰػೳΛͭͳ͙RESTͷΑ͏ͳߟ͑ํ
fluent interfaceͷߟ͑ํ • จ຺(ίϯςΩετ)ʹԠͯ͡ɺreturn͢Δ ΫϥεΛมߋ͢Δ • ඞཁेͳϝιου͚ͩ৮ΕΔঢ়ଶΛอͭ
4ষ SELECTจϏϧμʔ ۃΊΔ!ϝιουνΣʔϯ
ΫΤϦϏϧμͬͯ͋Γ·͢ΑͶ • PHP্ͰSQLΛΈཱͯΔͭ • ΞϨΛfluent interfaceͰઃܭ(design)ͯ͠ Έ·͠ΐ͏ • ࣮·Ͱؒʹ߹Θͳ͔ͬͨ
SELECTจͷ෮श ͍͍ͩͨҎԼͷॱͰॲཧ͞ΕΔ FROM → JOIN → WHERE → GROUP BY
→ HAVING → PROJECT → ORDER BY → LIMIT → UNION ࢦఆॱΛ͜ΕͰݻఆͰ͖ΔΑ͏ʹAPIઃܭ
ࡉ͔͘ΫϥεΛ༻ҙ
ΓΛ࣍ͷίϯςΩετʹ
ͱ͍͏Θ͚Ͱదʹ࡞ͬͨͭ https://github.com/hirak/php-query-builder (APIσβΠϯͷͳͷͰதϞοΫঢ়ଶ)
Demo
fluent interfaceͷ͍͍ͱ͜Ζ • IDEͷิͱΈ߹ΘͤΔͱޮՌ͙ͭΜͩ
APIઃܭऀͷ಄ͷத • LoDʹै۪ͬͨͳઃܭʹ͢Δ͖͔ʁ • ίϯςΩετΛಋೖͯ͠fluent͗Έʹ͢Δ͔ʁ • ΞϓϦͷUIΛߟ͑Δ͜ͱͱࣅ͍ͯΔ • ਖ਼ղͳ͍͚Ͳɺ͍Ζ͍ΖͳྲྀΛ͓ͬͯ ͘ͱɺཱ͍͔͔ͭͭʁ
·ͱΊ
Ԟਂ͖ϝιουνΣʔϯͷੈք • σϝςϧͷ๏ଇ͓͖֮͑ͯ·͠ΐ͏ • ϝιουνΣʔϯͰDSLͬΆ͍ͷ࡞Δͱ ָ͍͠Α • return $thisҎ֎ʹ৭ʑ͋Δͷ͓֮͑ͯ͘ ͱ͍͍Α
ͦͷଞͷ
Unified Variable Syntax (PHP7) • PHP7͔ΒɺνΣʔϯͰ͖ΔߏจͷόϦΤʔ γϣϯ͕૿͑ͯΔ • abc()()ɺBaa::a()::foo() •
Կ͔͍ํͳ͍͔ͳʔɻɻ