極める!メソッドチェーン #phpstudy / fluent-interface

極める!メソッドチェーン #phpstudy / fluent-interface

2017/07/26 第116回 PHP勉強会の発表資料です。

2295fec4d38f59366f983d38628e6ca0?s=128

Hiraku NAKANO

July 26, 2017
Tweet

Transcript

  1. ۃΊΔʂ
 ϝιουνΣʔϯ @hiraku

  2. ࣗݾ঺հ • த໺ ୓ (@Hiraku) • https://github.com/hirak • ϝϧΧϦͷαʔόʔαΠυΤϯδχΞ •

    Composerؔ࿈ͷൃදΛΑ͍ͯ͘͠·͢ • PHPΧϯϑΝϨϯεؔ੢2016 جௐߨԋ
  3. We are hiring!

  4. None
  5. None
  6. None
  7. ۃΊΔʂ
 ϝιουνΣʔϯ @hiraku

  8. ϝιουνΣʔϯͱ͸ $talk ->setTitle('art of method chain') ->setContent('no plan') ->setLength('20min') ;

    ΦϒδΣΫτʹରͯ͠ɺ
 ϝιουΛଓ͚ͯॻ͚ΔΑ͏ʹ
 ͨ͠ύλʔϯ/APIσβΠϯͷ͜ͱ
  9. 5೥લʹൃදͨ͠΍ͭ https://www.slideshare.net/hinakano/xml-builder

  10. None
  11. ΋ͪΖΜ߹๏ͳPHPߏจ

  12. Χοίলུ&Մมϝιου໊ ด͡λά͕ͳ͍͜ͱͷ໌ࣔ ด͡λάิ׬

  13. ࠷ۙॻ͍ͨ΍ͭ PHPͷߴ଎ΦγϟϨةݥ഑ྻϥΠϒϥϦspindle/collectionΛ࡞͍ͬͯΔ࿩ - Qiita http://qiita.com/Hiraku/items/bb6318d1d2c26ae7f30a

  14. ·ΔͰ੒௕ͯ͠ͳ͍…

  15. ϝιουνΣʔϯେ޷͖ • ੍໿಺ͰPHPΒ͘͠ͳ͍ߏจΛ࡞Δ௅ઓ • PHP͸ߏจ͕ශऑͩͬͨ • ݺͼग़͠νΣʔϯͰ͖ͳ͍ͱ͔()()()() • །Ұੲ͔Β࢖͑ͨͷ͕ϝιουνΣʔϯ

  16. ͓͜ͱΘΓ • ϥΠϒϥϦΛఏڙ͢Δਓ͸ԿΛߟ͑Δ΂͖͔ʁ Έ͍ͨͳ࿩Λ͠·͢ • ҰੲલͷJavaͷম͖௚͔͠΋͠Εͳ͍

  17. ໨࣍ 1. σϝςϧͷ๏ଇ 2. ϝιουνΣʔϯͷύλʔϯ৭ʑ 3. APIσβΠϯͷ͓࿩ 4. σϞతͳ΍ͭ

  18. 1ষ
 σϝςϧͷ๏ଇ ۃΊΔ!ϝιουνΣʔϯ

  19. σϝςϧͷ๏ଇ (࠷খ஌ࣝͷݪଇ)
 (Law of Demeter, LoD) • ιϑτ΢ΣΞͷઃܭɺಛʹΦϒδΣΫτࢦ޲ ϓϩάϥϜͷઃܭʹ͓͚ΔΨΠυϥΠϯ •

    ʮ๏ଇʯͱ͍͏࿨༁͕ͩɺʮ͜ΕΛकͬͯΔ ίʔυͷํ͕͍͍Αʂʯͱ͍͏Α͏ͳओࢫ
  20. σϝςϧOK? 0, /( B BCD UIJTB UIJTB C UIJTBC UIJTBC

    D
  21. ৮ͬͯྑ͍΋ͷ 0, ϩʔΧϧม਺ɺҾ਺͸৮ͬͯ0, B ࣗ෼ͷϝιου͸৮ͬͯ0, UIJTB ࣗ෼ͷϓϩύςΟͷϝιου΋ ৮ͬͯ0, UIJTBC

  22. $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 Կʁ ͜ΕͳΒ໭Γ஋Λؾʹ͢Δ·Ͱ΋ͳ͍
  23. ϝιουνΣʔϯͱ͸ $talk ->setTitle('art of method chain') ->setContent('no plan') ->setLength('20min') ;

    ΦϒδΣΫτʹରͯ͠ɺ
 ϝιουΛଓ͚ͯॻ͚ΔΑ͏ʹ
 ͨ͠ύλʔϯ/APIσβΠϯͷ͜ͱ
  24. ͸͍

  25. ϝιουνΣʔϯ͸LoDҧ൓ • LoDతʹ͸ɺ$this->set...; $this->set...; ͱͦΕ ͧΕॻ͘΂͖ • LoD΋ɺϥΠϒϥϦઃܭऀ͕஌͓ͬͯ͘΂͖
 ݪଇͷ̍ͭͰ͸͋Δ

  26. Ұ୴ɺLoD͸ஔ͍ͱ͍ͯɺ
 ࿩ΛਐΊ·͢ɻ

  27. 2ষ
 ϝιουνΣʔϯͷ
 ύλʔϯ ۃΊΔ!ϝιουνΣʔϯ

  28. LoDΛഁͬͯ·Ͱ ϝιουνΣʔϯͰ ԿΛ͍ͨ͠ͷ͔ʁ

  29. 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Ͱ͖ΔΑ͏ʹͳͬͨΑʂ
  30. return $this
 ʹର͢Δݸਓతཧղ • ౎౓$instance->ͬͯॻ͔ͳͯ͘Α͘ͳΔ • ͪΐͬͱ͚ͩShort hand • ͨͩͦΕ͚ͩͳͷͰɺLoDഁΔ΄ͲͷՁ஋͕

    ͋Δ͔…ͱ͍͏ͱඍົͳؾ΋͢Δ
  31. 2) PSR-7ͷAPIΈ͍ͨͳ΍ͭ (new GuzzleHttp\Psr7\Request('GET', 'http://example.com')) ->withHeader('foo', 'baa') ->withBody($body); return $thisͰ͸ͳ͘ɺ


    newͯ͠ࠓ·Ͱͷ৘ใΛίϐʔ
 (ผΠϯελϯεΛฦ͢)
  32. immutableͱ͸ • setterͷͳ͍ΦϒδΣΫτ • ಺෦ΛมߋͰ͖ͳ͍ͷͰɺ
 clone͠ͳͯ͘΋҆શʹฦͤΔ • setterͰ͸ͳ͘ɺʮίϐʔͯ͠Ұ෦Λ্ॻ͖ʯ ͢ΔσβΠϯ

  33. immutable
 ʹର͢Δݸਓతཧղ • ໭Γ஋Λड͚औΒͳ͍ͱ݁Ռ͕ফ͑ͯ͠·͏ • $obj->setFoo($foo);
 $obj->setBaa($baa);
 ͯ͠΋ҙຯ͕ͳ͍ • $obj

    = $obj->setFoo($foo);
 $obj = $obj->setBaa($baa); • ه๏͕໘౗ͳͷͰɺϝιουνΣʔϯʹͨ͘͠ͳΔ(Θ͔Δ)
  34. ͪΐͬͱ࿩͕ҳΕ·͕ͨ͠ • return $this͢Δ͚͕ͩϝιουνΣʔϯͰ͸ ͳ͍ • return new ͢Δύλʔϯ΋͋Δ

  35. return newͰ
 ༡ΜͰΈΔྫ

  36. ͓୊ • ϝιουνΣʔϯͰ
 ೖΕࢠͰ͖ΔifจΛ
 ࡞Ε

  37. ϒϩοΫʹΦϒδΣΫτΛ౰ͯ ͸ΊΔ • if͸newΛฦ͢ • endif͸ϒϩοΫΛ ऴΘΒͤͯ΋ͱʹ ໭Δ

  38. <?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
  39. 3) +ϚδοΫϝιουͷཚ༻ return $thisͰ͸ͳ͘ɺ
 newͯ͠ࠓ·Ͱͷ৘ใΛίϐʔ
 (ผΠϯελϯεΛฦ͢)

  40. ϚδοΫϝιου • __get(){}ɺ__call(){}ΛΫϥεʹੜ΍͓ͯ͘͠ • ϓϩύςΟ/ϝιουʹΞΫηεग़དྷͳ͍ͱ͖ ʹࣗಈతʹݺ͹ΕΔ • Rubyͷmethod_missingΈ͍ͨͳ΍ͭ

  41. IUNM NFUB@ UJUMF@ @ ͳΜͯϝιου΍
 QVCMJDϓϩύςΟ͸ੜ͍͑ͯͳ͍ɻ ࣮ࡍʹॲཧ͍ͯ͠Δͷ͸ @@DBMM ͱ@@HFU

  42. ϚδοΫϝιου • ✅ίʔυྔ(ܶతʹݮΔ) • ❌ಡΈ΍͢͞ • ❌֦ுੑ • ❌PhpStormʹౖΒΕΔ •

    ׂͱݏ͍ͬͯΔPHPer͕ଟ͍ҹ৅(ओ؍)
  43. 4) fluent interface • ʮྲྀΕΔΑ͏ͳΠϯλʔϑΣʔεʯ • ϝιουνΣʔϯΛ΋͏গ͠ൃలͤͨ͞΋ͷ • આ໌͕೉͍͠ͷͰ࣍ͷষ΁

  44. 3ষ
 APIσβΠϯͷ࿩ ۃΊΔ!ϝιουνΣʔϯ

  45. ঢ়گ • ͋ͳͨ͸ɺͱ͋ΔWebαʔϏεͷPHP൛SDK Λ࡞Δ͜ͱʹͳΓ·ͨ͠ • ͦͷWebαʔϏε͸େྔͷػೳ͕͋Γ·͢ɻ • SDKͳͷͰɺੜcurlͰୟ͘ΑΓ͸ศརʹ͍ͨ͠

  46. None
  47. None
  48. SDKͷAPIσβΠϯ • SDKϢʔβʔ͸಺෦࣮૷ΛΑ͘஌Βͳ͍ • Ͱ͖Ε͹υΩϡϝϯτ͚ͩͰ࢖͍͜ͳ͍ͨ͠ • ͲΜͳΫϥε͕͋ͬͯɺ
 ͲΜͳϝιουΛ഑ஔ͢Δʁ

  49. …Ԟͷਂ͍࿩Ͱ͋Δ

  50. ςϨϏͷϦϞίϯ໰୊

  51. None
  52. Α͋͘ΔςϨϏͷϦϞίϯ • Ϙλϯ͕͍ͬͺ͍͋Δ • ͲΕΛԡͤ͹͍͍ͷʁ໎͏ • (ͨͿΜ)ςετେมͦ͏… • ͍ͭͰ΋͋ΒΏΔϘλϯ͕ԡͤΔ

  53. ղܾҊ • ͍͞͠ΐ͸Ϙλϯ1ݸ(ిݯ)ͷΈ • ిݯ͕ೖΔͱɺ͏ʹΐʔΜͱϘλϯ͕ੜ͑ͯ͘Δ • ૢ࡞͢ΔͨͼʹɺϘλϯ͕͏ʹΐʔΜͱੜ͑ͯ͘ Δ or ফ͑Δ

    • Ϙλϯ͸ݮΒͤͦ͏Ͱ͢Ͷʂ
  54. API = ϦϞίϯ

  55. APIσβΠϯʹ౰ͯ͸ΊͯΈΔ • ϩάΠϯ͕ඞཁͳΒɺϩάΠϯͷAPI͚͕ͩ
 ݟ͑ͯΔ΂͖ • ͦͷঢ়ଶͰՄೳͳૢ࡞͚͕ͩ࢖͑Δ • linkͰػೳΛͭͳ͙RESTͷΑ͏ͳߟ͑ํ

  56. fluent interfaceͷߟ͑ํ • จ຺(ίϯςΩετ)ʹԠͯ͡ɺreturn͢Δ
 ΫϥεΛมߋ͢Δ • ඞཁे෼ͳϝιου͚ͩ৮ΕΔঢ়ଶΛอͭ

  57. 4ষ
 SELECTจϏϧμʔ ۃΊΔ!ϝιουνΣʔϯ

  58. ΫΤϦϏϧμͬͯ͋Γ·͢ΑͶ • PHP্ͰSQLΛ૊ΈཱͯΔ΍ͭ • ΞϨΛfluent interfaceͰઃܭ(design)ͯ͠
 Έ·͠ΐ͏ • ࣮૷·Ͱ͸ؒʹ߹Θͳ͔ͬͨ

  59. SELECTจͷ෮श ͍͍ͩͨҎԼͷॱͰॲཧ͞ΕΔ FROM → JOIN → WHERE → GROUP BY

    → HAVING → PROJECT → ORDER BY → LIMIT → UNION ࢦఆॱΛ͜ΕͰݻఆͰ͖ΔΑ͏ʹAPIઃܭ
  60. ࡉ͔͘ΫϥεΛ༻ҙ

  61. ໭Γ஋Λ࣍ͷίϯςΩετʹ

  62. ͱ͍͏Θ͚Ͱద౰ʹ࡞ͬͨ΍ͭ https://github.com/hirak/php-query-builder (APIσβΠϯͷ࿩ͳͷͰத਎͸ϞοΫঢ়ଶ)

  63. Demo

  64. fluent interfaceͷ͍͍ͱ͜Ζ • IDEͷิ׬ͱ૊Έ߹ΘͤΔͱޮՌ͸͹͙ͭΜͩ

  65. APIઃܭऀͷ಄ͷத • LoDʹै۪ͬͨ௚ͳઃܭʹ͢Δ΂͖͔ʁ • ίϯςΩετΛಋೖͯ͠fluent͗Έʹ͢Δ͔ʁ • ΞϓϦͷUIΛߟ͑Δ͜ͱͱࣅ͍ͯΔ • ਖ਼ղ͸ͳ͍͚Ͳɺ͍Ζ͍Ζͳྲྀ೿Λ஌͓ͬͯ ͘ͱɺ͍͔ͭ໾ཱ͔ͭ΋ʁ

  66. ·ͱΊ

  67. Ԟਂ͖ϝιουνΣʔϯͷੈք • σϝςϧͷ๏ଇ͓͖֮͑ͯ·͠ΐ͏ • ϝιουνΣʔϯͰDSLͬΆ͍΋ͷ࡞Δͱ
 ָ͍͠Α • return $thisҎ֎ʹ΋৭ʑ͋Δͷ͸͓֮͑ͯ͘ ͱ͍͍Α

  68. ͦͷଞͷ࿩୊

  69. Unified Variable Syntax (PHP7) • PHP7͔ΒɺνΣʔϯͰ͖ΔߏจͷόϦΤʔ γϣϯ͕૿͑ͯΔ • abc()()ɺBaa::a()::foo() •

    Կ͔࢖͍ํͳ͍͔ͳʔɻɻ