HHVM/Hackで得る問題解決力 / hhvm-hack-problem-solving

17d4ef53b432ebf7c566fd6a11345570?s=47 yuuki takezawa
September 04, 2018

HHVM/Hackで得る問題解決力 / hhvm-hack-problem-solving

builderscon 2018 tokyo の資料です

17d4ef53b432ebf7c566fd6a11345570?s=128

yuuki takezawa

September 04, 2018
Tweet

Transcript

  1. HHVM/HackͰಘΔ໰୊ղܾྗ yuuki takezawa builderscon 2018

  2. Profile • ஛ᖒ ༗و / ytake • גࣜձࣾΞΠελΠϧ CTO •

    PHP, Hack, Go, Scala • Apache Hadoop, Apache Spark, Apache Kafka

  3. ͱΓ͋͛Δ͜ͱ • ༷ʑͳ໰୊ղܾ • HackʹΑΔ໰୊ղܾ • ΞϓϦέʔγϣϯʹ͓͚Δ໰୊ղܾ

  4. ໰୊ղܾͱ͸ • ໰୊Λղܾ͢Δɺ
 ͢ͳΘͪղΛൃݟ͢Δ͜ͱͰ͋Γɺ
 ࢥߟͷҰ෦෼Ͱ͋Δ • νʔϜʹ͓͚ΔࢥߟͰ͋ͬͨΓ
 ΦϒδΣΫτࢦ޲Ͱ͋ͬͨΓ

  5. ͳͥHackΛ࢖͏ͷ͔

  6. എܠ • શମతʹ͸PHPϝΠϯͷٕज़ελοΫ • WebΞϓϦέʔγϣϯ͕ϝΠϯ • Go੡ͷΞϓϦέʔγϣϯ΋͍͔ͭ͘ • ෼ੳॲཧ͸Scala੡͕͍͔ͭ͘

  7. ݒ೦ • ͦΕ XX Ͱ΋Ͱ͖ΔΑ
 • ಛఆͷݴޠ͔͠஌Βͳ͍ • ։ൃͱ͍͏ߦҝʹΫϦΤΠςΟϒ͕͞ײ͡ΒΕͳ͍

  8. બ୒ͷύϥυοΫε https://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice?language=ja

  9. None
  10. None
  11. ΞϓϦέʔγϣϯ͸ ϦϦʔε͢Δ·ͰͰ͸ͳ͘ɺ ϦϦʔε͔ͯ͠Β͕ຊ൪

  12. ։ൃऀ͸ ΞϓϦέʔγϣϯͱͱ΋ʹ ੒௕͢Δ

  13. None
  14. ։ൃͷଊ͑ํ • ͍ͭ΋ͷࢹ఺ͱগ͠ҧ͏ࢹ఺Λ௥Ճͯ͠ΈΔ • ҧ͏ࢹ఺ͷ͋ͱɺ͍ͭ΋ͷݴޠ͔Β • ૒ํ޲ʹಇ͘ݟ͑ํΛཆ͏͜ͱ͸ѱ͍͜ͱʁ • ͍ͭ΋ͷࢹ఺͚ͩɺ͸ѱ͍͜ͱʁ

  15. None
  16. None
  17. ࢹ఺Λม͑Δํ๏ͷҰͭͱͯ͠ HackΛར༻

  18. PHP͕ ͪΐͬͱૣ͘ͳͬͨ΍ͭͰ͠ΐʁ

  19. HHVM/Hack • ݴޠͷϕʔεʹ͋Δͷ͸PHPͷվળ • I/O͕ൃੜ͢Δ΋ͷʹରͯ͠ͷAsync/Await
 શͯʹରͯ͠࡞༻͢ΔΘ͚Ͱ͸ͳ͍ͷͰɺෑډ͕௿͍
 • ݫ֨ͳܕνΣοΫͱίϨΫγϣϯɾ੬ऑੑରࡦ

  20. for Developer • Atom + Nuclide • Visual Studio Code

    + Hack plugin • Docker (hhvm/hhvm)
  21. .hhconfig

  22. .hhconfig ͷجຊ • HackͰ࣮ߦ؀ڥʹઃஔ͢ΔϑΝΠϧ • ༷ʑͳઃఆΛهड़Ͱ͖Δ • PHPར༻Λ૝ఆ͠ͳ͍(PHPࠞࡏෆՄ) 
 assume_php

    = false(default: true)
 • Type Checker Ұ෦ແࢹ
 ignored_paths = [ "vendor/hhvm/hhast/.+" ]
  23. .hhconfig ͋Ε͜Ε • λΠϓνΣοΧʔͷϝϞϦૢ࡞
 • ࢀর౉͠࢖͏ͳϞʔυ΋௥Ճ(3.28)
 disallow_return_by_ref
 disallow_array_cell_pass_by_ref

  24. None
  25. ۤ࿑ • IDEʹ͓͚Δิ׬ػೳͷಈ͖
 • Τϥʔ಺༰͕Θ͔Βͳ͍ • PHPʹݟ͍͑ͯͯผ෺ͱ͍͏ೝࣝΛ΋ͭ·Ͱ • ৘ใऩूྗ

  26. Type Checker

  27. None
  28. Type Checker • ίϯύΠϥϥΠΫʹಈ͘ܕνΣοΫπʔϧ • Ϟʔυ͸3ͭ Partial / Strict /

    Decl 
 • σϑΥϧτͰ͸Partial
  29. Type Checker: Partial • PHPͷܕએݴ strictͱಉఔ౓ • ඞཁҎ্ʹܕνΣοΫ͸͠ͳ͍ • ओʹPHPͷίʔυΛ

    Hackͱ࣮ͯ͠ߦ͢Δ
 ίʔυҠ২தͷϑΝΠϧ౳Ͱར༻ • ࢀর౉͠ ར༻Մೳ
  30. Type Checker: Decl • <?hh // decl • ܕνΣοΫ͸͠ͳ͍ •

    ଞͷίʔυνΣοΫ࣌ʹ͸ࢀর͞ΕΔ • New Hack code should never be written 
 in decl mode
  31. Type Checker: Strict • <?hh // strict • PHPґଘ͕ͳ͘ɺ100% HackͰ࣮૷͢Δ৔߹ʹબ୒

    • ݫ֨ͳܕνΣοΫΛߦ͏ϞʔυͷͨΊɺ
 ίʔυϨϏϡʔ࣌ͷܕએݴʹ͍ͭͯͷٞ࿦͸ඞཁ࠷খݶ • ૝ఆ֎ͷܕม׵ͳͲ͸ߦΘΕͳ͍ͨΊɺ
 ϨϏϡʔ͸ΫϥεઃܭɾΞʔΩςΫνϟͳͲʹ
 ϑΥʔΧεͰ͖Δ
  32. for Example • ίϯετϥΫλͰॳظԽ͍ͯ͠ͳ͍ίʔυ͸ܯࠂ • isset͡Όͳͯ͘ɺarray_key_existsΛ࢖͍ͳ͍͞ • ͨͩͷarray͡ΌΘ͔Βͳ͍ Vector͔Map࢖͍ͳ͍͞

  33. ߟ͑ํΛม͑Δ • ͱΓ͋͑ͣarray
 ͦͷarray͸ͲΜͳ໾ׂ͕͋ΓɺͲ͏͍͏΋ͷͳͷ͔ • arrayͰ͋Δඞཁ͕͋Δͷ͔Ͳ͏͔

  34. Hackͷarray͸ࡾछྨ • array
 ௨ৗͷ഑ྻ • varray
 ஋ͷΈͰߏ੒͞ΕΔ഑ྻ • darray
 σΟΫγϣφϦͷ഑ྻ

  35. <?hh // strict class Sample { protected varray<string> $varray =

    varray[ 'php', 'hack' ]; protected darray<int, string> $darray = darray[ 'testing' => 'testing', 1 => 'testing' ]; public function failedVArray(): varray<int> { return $this->varray; } public function getDArray(): darray<string, string> { return $this->darray; } } ܕҧ͍ ໭Γܕҧ͍ ໭Γܕҧ͍
  36. ΞϓϦέʔγϣϯʹ͓͚Δ ໰୊ղܾ

  37. None
  38. ܧঝΛ੍ޚ͢Δ • Sealed Class • Sealed Interface • Hack 3.27

    Ҏ߱
  39. <<__Sealed(Hoge::class)>> class SealedClass { } <<__Sealed(Sample::class)>> interface SealedInterface { }

    ࢦఆͨ͠ΫϥεҎ֎ ܧঝෆՄ ࢦఆͨ͠ΫϥεҎ֎ ܧঝෆՄɾ࣮૷ෆՄ
  40. ܧঝʹ͍ͭͯͷߟ͑ํ • final classͷΈͰ੍໿(ڐՄ)Λ͔͚Δ͔
 • GenericsͰ஋දݱͷΈڐՄ͢Δͷ͔
 • ͦͷޙͷΞϓϦέʔγϣϯͷ੒௕ͱɺ
 ֦ுੑͰେ͖͘Ξϓϩʔν͕ҟͳΔ

  41. ܕม׵

  42. public function sum(): int { return 10 + "5e2"; }

  43. public function sum(): int { return 10 + "5e2"; }

    Typing error This is a num (int/float) because this is used in an arithmetic operation. It is incompatible with a string.
  44. ܕม׵: mixed

  45. public function get($id): mixed { return //Կ͔Λฦ٫͢Δ; } $container =

    new Container(); $container->get('something');
  46. private function invariantLoggerInterface( Container $container, ): LoggerInterface { $logger =

    $container ->get(LoggerInterface::class); invariant( $logger instanceof LoggerInterface, "Interface '\Psr\Log\LoggerInterface' is not implemented by this class", ); return $logger; } mixedͷ৔߹͸Կ͕ฦ٫͞ΕΔ͔Θ͔Βͳ͍ ظ଴஋ͷ΋ͷ͕ฦ٫͞ΕΔ͔Ͳ͏͔ ඞͣهड़ͯ͠ɺTypeChecker޲͚ʹهड़
  47. final class Util { public function something(mixed $any): mixed {

    if($any is int) { // } if($any is string) { // } } }
  48. Type Constants

  49. interface TypeInterface { abstract const type T; public function getNative():

    this::T; }
  50. class UserType implements TypeInterface { const type T = Vector<int>;

    public function getNative(): this::T { return new Vector([1,2]); } }
  51. Factory

  52. class Sample { }

  53. final class Factory { protected array $array = [ 'Sample'

    => Sample::class ]; public function get(string $id) { $key = \ucfirst(\strtolower($id)); if(\array_key_exists($key, $this->array)) { $class = $this->array[$key]; return new $class(); } } } class_existsͳͲ΋
  54. <<__ConsistentConstruct>> class Sample { } constructor੍ޚ

  55. final class Factory { protected Map<string, classname<Sample>> $map = Map{

    'Sample' => Sample::class }; public function get(string $id): Sample { $class = $this->map->get(\ucfirst(\strtolower($id))); if (!\is_null($class)) { return new $class(); } throw new \RuntimeException(); } } classจࣈྻࢦఆ ࣮֬ͳΠϯελϯεੜ੒
  56. ࣝผͷҧ͍

  57. final class BookId { private $id; public function __construct(string $id)

    { $this->id = $id; } public function getValue(): string { return $this->id; } }
  58. final class BookId { public function __construct( private string $id

    ) {} public function getValue(): string { return $this->id; } }
  59. ҧ͏දݱํ๏

  60. abstract class Identifier<T> { public function __construct( protected T $id

    ) {} public function getValue(): T { return $this->id; } } final class BookId<T> extends Identifier<T> { } Generics
  61. ॻ੶දݱํ๏

  62. class Book { private $id; private $title; private $price; public

    function __construct( BookId $id, BookTitle $title, Price $price ) { $this->id = $id; $this->title = $title; $this->price = $price; } public function getId(): BookId { return $this->id; } // লུ }
  63. class Book { public function __construct( private BookId<string> $id, private

    BookTitle<string> $title, private Price<int> $price ) {} public function getId(): BookId<string> { return $this->id; } // লུ } ݎ੍͍໿ ݎ੍͍໿
  64. object(Book)#2 (3) { ["id":"Book":private]=> object(BookId)#3 (1) { ["id":protected]=> string(36) "6ad4bb95-262c-4a5b-a6c7-ac9b5cadf707"

    } ["title":"Book":private]=> string(18) "HHVM/Hack Practice" ["price":"Book":private]=> int(2999) }
  65. ॻ੶ίϨΫγϣϯදݱํ๏

  66. class BookCollection { protected $books = []; public function __construct(array

    $books = []) { $this->books = $books; } public function toArray(): array { $books = []; foreach($this->books as $book) { $books[] = new Book( new BookId($book['id']), new BookTitle($book['title']), new Price($book['price']) ); } return $books; } } ϑΟʔϧυ੍໿ͳ͠
  67. type BookShape = shape( 'book_id' => string, 'title' => string,

    'price' => int ); ϑΟʔϧυ੍໿
  68. class BookCollection { protected Vector<Book> $v = Vector{ }; public

    function __construct( protected varray<BookShape> $array ) { $this->v = $this->vec(); } protected function vec(): Vector<Book> { $v = Vector{ }; foreach($this->array as $row) { $v->add(new Book( new BookId($row['book_id']), new BookTitle($row['title']), new Price($row['price']) )); } return $v; } public function toArray(): varray<Book> { return $this->v->toVArray(); } } shapeΛvarrayͰ to Vector
  69. $v = new Vector([ new Book('1234', 'testing', 2999), new Book('1235',

    'testing', 2999), ]); $v = $v->filter( ($t) ==> $t->getId() === '1234' )->immutable(); collection filter Πϛϡʔλϒϧʹ
  70. ෳ਺ҙຯΛ࣋ͨͤͳ͍ͨΊͷ੍ޚ • ౎߹ͷ͍͍ΫϥεΛ࡞Βͳ͍
 • ू໿ΛΑΓߟ͑Δ
 • ͳΜͰ΋Ͱ͖ΔΫϥεͰ͸ͳ͍
 ͜Ε͔͠Ͱ͖ͳ͍Ϋϥε

  71. ݫ֨ͳܕΛPHPΞϓϦέʔγϣϯʹద༻͢Δҙຯ • ͱΓ͋͑ͣಈ͘ঢ়ଶʹͰ͖Ε͹͍͍ • ࢓༷มߋ͕͋Ε͹ܕ͕ͳ͍ํ͕ଟ༷ੑ͋ΔΜ͡Όͳ͍ʁ • ͦ΋ͦ΋ଞͷݴޠͰΑ͘ͳ͍ʁ

  72. ͱΓ͋͑ͣಈ͘ঢ়ଶ͔Β
 ៉ྷʹ͢Δ࣌ؒ͸ͳ͔ͳ͔དྷͳ͍

  73. None
  74. બ୒ࢶͱࢹ໺Λ޿͛Δ

  75. ໰୊Λղܾ͢Δɺ
 ͢ͳΘͪղΛൃݟ͢Δ͜ͱͰ͋Γɺ
 ࢥߟͷҰ෦෼

  76. ղܾ͢ΔͨΊͷྗͱ ࢹ໺