$30 off During Our Annual Pro Sale. View Details »

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

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

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

Hiraku NAKANO

July 26, 2017
Tweet

More Decks by Hiraku NAKANO

Other Decks in Technology

Transcript

  1. ۃΊΔʂ

    ϝιουνΣʔϯ
    @hiraku

    View Slide

  2. ࣗݾ঺հ
    • த໺ ୓ (@Hiraku)
    • https://github.com/hirak
    • ϝϧΧϦͷαʔόʔαΠυΤϯδχΞ
    • Composerؔ࿈ͷൃදΛΑ͍ͯ͘͠·͢
    • PHPΧϯϑΝϨϯεؔ੢2016 جௐߨԋ

    View Slide

  3. We are hiring!

    View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. ۃΊΔʂ

    ϝιουνΣʔϯ
    @hiraku

    View Slide

  8. ϝιουνΣʔϯͱ͸
    $talk
    ->setTitle('art of method chain')
    ->setContent('no plan')
    ->setLength('20min')
    ;
    ΦϒδΣΫτʹରͯ͠ɺ

    ϝιουΛଓ͚ͯॻ͚ΔΑ͏ʹ

    ͨ͠ύλʔϯ/APIσβΠϯͷ͜ͱ

    View Slide

  9. 5೥લʹൃදͨ͠΍ͭ
    https://www.slideshare.net/hinakano/xml-builder

    View Slide

  10. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. 1ষ

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

    View Slide

  19. σϝςϧͷ๏ଇ (࠷খ஌ࣝͷݪଇ)

    (Law of Demeter, LoD)
    • ιϑτ΢ΣΞͷઃܭɺಛʹΦϒδΣΫτࢦ޲
    ϓϩάϥϜͷઃܭʹ͓͚ΔΨΠυϥΠϯ
    • ʮ๏ଇʯͱ͍͏࿨༁͕ͩɺʮ͜ΕΛकͬͯΔ
    ίʔυͷํ͕͍͍Αʂʯͱ͍͏Α͏ͳओࢫ

    View Slide

  20. σϝςϧOK?
    0, /(
    B BCD
    UIJTB
    UIJTB
    C

    UIJTBC
    UIJTBC
    D

    View Slide

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

    ࣗ෼ͷϓϩύςΟͷϝιου΋
    ৮ͬͯ0,
    UIJTBC

    View Slide

  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 Կʁ
    ͜ΕͳΒ໭Γ஋Λؾʹ͢Δ·Ͱ΋ͳ͍

    View Slide

  23. ϝιουνΣʔϯͱ͸
    $talk
    ->setTitle('art of method chain')
    ->setContent('no plan')
    ->setLength('20min')
    ;
    ΦϒδΣΫτʹରͯ͠ɺ

    ϝιουΛଓ͚ͯॻ͚ΔΑ͏ʹ

    ͨ͠ύλʔϯ/APIσβΠϯͷ͜ͱ

    View Slide

  24. ͸͍

    View Slide

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

    ݪଇͷ̍ͭͰ͸͋Δ

    View Slide

  26. Ұ୴ɺLoD͸ஔ͍ͱ͍ͯɺ

    ࿩ΛਐΊ·͢ɻ

    View Slide

  27. 2ষ

    ϝιουνΣʔϯͷ

    ύλʔϯ
    ۃΊΔ!ϝιουνΣʔϯ

    View Slide

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

    View Slide

  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Ͱ͖ΔΑ͏ʹͳͬͨΑʂ

    View Slide

  30. return $this

    ʹର͢Δݸਓతཧղ
    • ౎౓$instance->ͬͯॻ͔ͳͯ͘Α͘ͳΔ
    • ͪΐͬͱ͚ͩShort hand
    • ͨͩͦΕ͚ͩͳͷͰɺLoDഁΔ΄ͲͷՁ஋͕
    ͋Δ͔…ͱ͍͏ͱඍົͳؾ΋͢Δ

    View Slide

  31. 2) PSR-7ͷAPIΈ͍ͨͳ΍ͭ
    (new GuzzleHttp\Psr7\Request('GET', 'http://example.com'))
    ->withHeader('foo', 'baa')
    ->withBody($body);
    return $thisͰ͸ͳ͘ɺ

    newͯ͠ࠓ·Ͱͷ৘ใΛίϐʔ

    (ผΠϯελϯεΛฦ͢)

    View Slide

  32. immutableͱ͸
    • setterͷͳ͍ΦϒδΣΫτ
    • ಺෦ΛมߋͰ͖ͳ͍ͷͰɺ

    clone͠ͳͯ͘΋҆શʹฦͤΔ
    • setterͰ͸ͳ͘ɺʮίϐʔͯ͠Ұ෦Λ্ॻ͖ʯ
    ͢ΔσβΠϯ

    View Slide

  33. immutable

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

    $obj->setBaa($baa);

    ͯ͠΋ҙຯ͕ͳ͍
    • $obj = $obj->setFoo($foo);

    $obj = $obj->setBaa($baa);
    • ه๏͕໘౗ͳͷͰɺϝιουνΣʔϯʹͨ͘͠ͳΔ(Θ͔Δ)

    View Slide

  34. ͪΐͬͱ࿩͕ҳΕ·͕ͨ͠
    • return $this͢Δ͚͕ͩϝιουνΣʔϯͰ͸
    ͳ͍
    • return new ͢Δύλʔϯ΋͋Δ

    View Slide

  35. return newͰ

    ༡ΜͰΈΔྫ

    View Slide

  36. ͓୊
    • ϝιουνΣʔϯͰ

    ೖΕࢠͰ͖ΔifจΛ

    ࡞Ε

    View Slide

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

    View Slide

  38. 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

    View Slide

  39. 3) +ϚδοΫϝιουͷཚ༻
    return $thisͰ͸ͳ͘ɺ

    newͯ͠ࠓ·Ͱͷ৘ใΛίϐʔ

    (ผΠϯελϯεΛฦ͢)

    View Slide

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

    View Slide

  41. IUNM NFUB@ UJUMF@ @
    ͳΜͯϝιου΍

    QVCMJDϓϩύςΟ͸ੜ͍͑ͯͳ͍ɻ
    ࣮ࡍʹॲཧ͍ͯ͠Δͷ͸
    @@DBMM
    ͱ@@HFU

    View Slide

  42. ϚδοΫϝιου

    ✅ίʔυྔ(ܶతʹݮΔ)
    • ❌ಡΈ΍͢͞
    • ❌֦ுੑ

    ❌PhpStormʹౖΒΕΔ
    • ׂͱݏ͍ͬͯΔPHPer͕ଟ͍ҹ৅(ओ؍)

    View Slide

  43. 4) fluent interface
    • ʮྲྀΕΔΑ͏ͳΠϯλʔϑΣʔεʯ
    • ϝιουνΣʔϯΛ΋͏গ͠ൃలͤͨ͞΋ͷ
    • આ໌͕೉͍͠ͷͰ࣍ͷষ΁

    View Slide

  44. 3ষ

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

    View Slide

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

    View Slide

  46. View Slide

  47. View Slide

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

    ͲΜͳϝιουΛ഑ஔ͢Δʁ

    View Slide

  49. …Ԟͷਂ͍࿩Ͱ͋Δ

    View Slide

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

    View Slide

  51. View Slide

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

    View Slide

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

    View Slide

  54. API = ϦϞίϯ

    View Slide

  55. APIσβΠϯʹ౰ͯ͸ΊͯΈΔ
    • ϩάΠϯ͕ඞཁͳΒɺϩάΠϯͷAPI͚͕ͩ

    ݟ͑ͯΔ΂͖
    • ͦͷঢ়ଶͰՄೳͳૢ࡞͚͕ͩ࢖͑Δ
    • linkͰػೳΛͭͳ͙RESTͷΑ͏ͳߟ͑ํ

    View Slide

  56. fluent interfaceͷߟ͑ํ
    • จ຺(ίϯςΩετ)ʹԠͯ͡ɺreturn͢Δ

    ΫϥεΛมߋ͢Δ
    • ඞཁे෼ͳϝιου͚ͩ৮ΕΔঢ়ଶΛอͭ

    View Slide

  57. 4ষ

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

    View Slide

  58. ΫΤϦϏϧμͬͯ͋Γ·͢ΑͶ
    • PHP্ͰSQLΛ૊ΈཱͯΔ΍ͭ
    • ΞϨΛfluent interfaceͰઃܭ(design)ͯ͠

    Έ·͠ΐ͏
    • ࣮૷·Ͱ͸ؒʹ߹Θͳ͔ͬͨ

    View Slide

  59. SELECTจͷ෮श
    ͍͍ͩͨҎԼͷॱͰॲཧ͞ΕΔ
    FROM → JOIN → WHERE → GROUP BY →
    HAVING → PROJECT → ORDER BY → LIMIT →
    UNION
    ࢦఆॱΛ͜ΕͰݻఆͰ͖ΔΑ͏ʹAPIઃܭ

    View Slide

  60. ࡉ͔͘ΫϥεΛ༻ҙ

    View Slide

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

    View Slide

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

    View Slide

  63. Demo

    View Slide

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

    View Slide

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

    View Slide

  66. ·ͱΊ

    View Slide

  67. Ԟਂ͖ϝιουνΣʔϯͷੈք
    • σϝςϧͷ๏ଇ͓͖֮͑ͯ·͠ΐ͏
    • ϝιουνΣʔϯͰDSLͬΆ͍΋ͷ࡞Δͱ

    ָ͍͠Α
    • return $thisҎ֎ʹ΋৭ʑ͋Δͷ͸͓֮͑ͯ͘
    ͱ͍͍Α

    View Slide

  68. ͦͷଞͷ࿩୊

    View Slide

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

    View Slide