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.6k
極める!メソッドチェーン #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
6.9k
github.com/mercari の今と昔 /github-mercari
hirak
8
2.9k
PHPStanで始める継続的静的解析 #phperkaigi /php-static-analysis
hirak
14
51k
evalこそパワー #phpkansai / phpkansai2017
hirak
2
1.4k
PHPのエラーと例外再入門 / php-error-and-exception
hirak
19
19k
メルカリ JP Tech Side / mercari-jp-tech-side
hirak
7
1.8k
グローバル展開を支える量子的なサービス設計 #mercariday / mercariday2017-api
hirak
22
13k
Composerプラグインを作ってみよう /phpcon2016
hirak
5
14k
packagist.jpの紹介と新機能 /#phpblt
hirak
4
2.6k
Other Decks in Technology
See All in Technology
可視化プラットフォームGrafanaの基本と活用方法の全て
hamadakoji
0
230
初中級者用如何使用backlog -VALE TUDOEDITION-
in0u
0
140
シフトレフトで挑む セキュリティの生産性向上
sekido
PRO
0
270
開発生産性をむしろ向上させる セキュリティパートナーの作り方 / Dev Productivity Con 2024
flatt_security
0
390
コミュニティサービスに「あなたへ」フィードを リリースするまでの試行錯誤
takapy
1
150
サーバーレスAPI(API Gateway+Lambda)とNext.jsで 個人ブログを作ろう!
shuntaka
PRO
0
560
GoとアクターモデルでES+CQRSを実践! / proto_actor_es_cqrs
ytake
1
160
地理情報とAPIのトレンド
nagix
0
160
テスト・設計研修【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
170
20240724_cm_odyssey_hibiyatech
hiashisan
0
110
累計ダウンロード数1億8000万を超えるアプリケーションプラットフォームのレガシーシステム脱却とモダン化への道
kmitsuhashi
0
120
簡単に始めるSnowflakeの機械学習
nayuts
1
190
Featured
See All Featured
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.4k
Testing 201, or: Great Expectations
jmmastey
33
6.9k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
189
16k
BBQ
matthewcrist
82
9k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
129
32k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
245
1.2M
StorybookのUI Testing Handbookを読んだ
zakiyama
15
4.9k
The MySQL Ecosystem @ GitHub 2015
samlambert
248
12k
Principles of Awesome APIs and How to Build Them.
keavy
124
16k
The Illustrated Children's Guide to Kubernetes
chrisshort
39
47k
Infographics Made Easy
chrislema
238
18k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
23
1.9k
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() •
Կ͔͍ํͳ͍͔ͳʔɻɻ