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
HHVM/Hackで得る問題解決力 / hhvm-hack-problem-solving
Search
yuuki takezawa
September 04, 2018
Technology
3
2.3k
HHVM/Hackで得る問題解決力 / hhvm-hack-problem-solving
builderscon 2018 tokyo の資料です
yuuki takezawa
September 04, 2018
Tweet
Share
More Decks by yuuki takezawa
See All by yuuki takezawa
PHPでアクターモデルを活用したSagaパターンの実践法 / php-saga-pattern-with-actor-model
ytake
0
1.5k
PHP ステートレス VS ステートフル 状態管理と並行性 / php-stateless-stateful
ytake
0
150
PHPでアクターモデルを理解・体験しよう / Understand and experience the actor model in PHP
ytake
2
520
再考 アクターモデル/ reconsider actor model
ytake
0
1.2k
GoとアクターモデルでES+CQRSを実践! / proto_actor_es_cqrs
ytake
1
460
Phluxorでアクターモデルを 理解・体験しよう / toolkit-for-flexible-actor-models-in-php-phluxor
ytake
1
290
オブジェクトのおしゃべり大失敗 メッセージングアンチパターン集 / messaging anti-pattern collection
ytake
2
1.1k
DRE/SREのプラクティス融合によるクラウドネイティブなデータ基盤作り / dre_sre
ytake
0
830
技術的負債と向き合う取り組みでよかったもの / positive_efforts_to_tackle_technical_debt
ytake
10
3.9k
Other Decks in Technology
See All in Technology
LLM アプリケーションのためのクラウドセキュリティ - CSPM の実装ポイント-
osakatechlab
0
430
Global Azure2025(GitHub Copilot ハンズオン)
tomokusaba
2
800
Next.jsと状態管理のプラクティス
uhyo
6
2.2k
dbtとリバースETLでデータ連携の複雑さに立ち向かう
morookacube
0
890
雑に疎通確認だけしたい...せや!CloudShell使ったろ!
alchemy1115
0
230
自動化の第一歩 -インフラ環境構築の自動化について-
smt7174
1
130
テストコードにはテストの意図を込めよう(2025年版) #retechtalk / Put the intent of the test 2025
nihonbuson
PRO
9
1.7k
Cursorを全エンジニアに配布 その先に見据えるAI駆動開発の未来 / 2025-05-13-forkwell-ai-study-1-cursor-at-loglass
itohiro73
2
610
Part1 GitHubってなんだろう?その1
tomokusaba
3
810
分解し、導き、託す ログラスにおける“技術でリードする” 実践の記録
hryushm
0
340
時間がないなら、つくればいい 〜数十人規模のチームが自律性を発揮するために試しているいくつかのこと〜
kakehashi
PRO
23
5.7k
AWSを利用する上で知っておきたい名前解決の話
nagisa53
6
830
Featured
See All Featured
How GitHub (no longer) Works
holman
314
140k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.3k
For a Future-Friendly Web
brad_frost
177
9.7k
Rebuilding a faster, lazier Slack
samanthasiow
81
9k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
Mobile First: as difficult as doing things right
swwweet
223
9.6k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.2k
Why You Should Never Use an ORM
jnunemaker
PRO
56
9.4k
Fontdeck: Realign not Redesign
paulrobertlloyd
84
5.5k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
12k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Transcript
HHVM/HackͰಘΔղܾྗ yuuki takezawa builderscon 2018
Profile • ᖒ ༗و / ytake • גࣜձࣾΞΠελΠϧ CTO •
PHP, Hack, Go, Scala • Apache Hadoop, Apache Spark, Apache Kafka
ͱΓ͋͛Δ͜ͱ • ༷ʑͳղܾ • HackʹΑΔղܾ • ΞϓϦέʔγϣϯʹ͓͚Δղܾ
ղܾͱ • Λղܾ͢Δɺ ͢ͳΘͪղΛൃݟ͢Δ͜ͱͰ͋Γɺ ࢥߟͷҰ෦Ͱ͋Δ • νʔϜʹ͓͚ΔࢥߟͰ͋ͬͨΓ ΦϒδΣΫτࢦͰ͋ͬͨΓ
ͳͥHackΛ͏ͷ͔
എܠ • શମతʹPHPϝΠϯͷٕज़ελοΫ • WebΞϓϦέʔγϣϯ͕ϝΠϯ • GoͷΞϓϦέʔγϣϯ͍͔ͭ͘ • ੳॲཧScala͕͍͔ͭ͘
ݒ೦ • ͦΕ XX ͰͰ͖ΔΑ • ಛఆͷݴޠ͔͠Βͳ͍ • ։ൃͱ͍͏ߦҝʹΫϦΤΠςΟϒ͕͞ײ͡ΒΕͳ͍
બͷύϥυοΫε https://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice?language=ja
None
None
ΞϓϦέʔγϣϯ ϦϦʔε͢Δ·ͰͰͳ͘ɺ ϦϦʔε͔ͯ͠Β͕ຊ൪
։ൃऀ ΞϓϦέʔγϣϯͱͱʹ ͢Δ
None
։ൃͷଊ͑ํ • ͍ͭͷࢹͱগ͠ҧ͏ࢹΛՃͯ͠ΈΔ • ҧ͏ࢹͷ͋ͱɺ͍ͭͷݴޠ͔Β • ํʹಇ͘ݟ͑ํΛཆ͏͜ͱѱ͍͜ͱʁ • ͍ͭͷࢹ͚ͩɺѱ͍͜ͱʁ
None
None
ࢹΛม͑Δํ๏ͷҰͭͱͯ͠ HackΛར༻
PHP͕ ͪΐͬͱૣ͘ͳͬͨͭͰ͠ΐʁ
HHVM/Hack • ݴޠͷϕʔεʹ͋ΔͷPHPͷվળ • I/O͕ൃੜ͢Δͷʹରͯ͠ͷAsync/Await શͯʹରͯ͠࡞༻͢ΔΘ͚Ͱͳ͍ͷͰɺෑډ͕͍ • ݫ֨ͳܕνΣοΫͱίϨΫγϣϯɾ੬ऑੑରࡦ
for Developer • Atom + Nuclide • Visual Studio Code
+ Hack plugin • Docker (hhvm/hhvm)
.hhconfig
.hhconfig ͷجຊ • HackͰ࣮ߦڥʹઃஔ͢ΔϑΝΠϧ • ༷ʑͳઃఆΛهड़Ͱ͖Δ • PHPར༻Λఆ͠ͳ͍(PHPࠞࡏෆՄ) assume_php
= false(default: true) • Type Checker Ұ෦ແࢹ ignored_paths = [ "vendor/hhvm/hhast/.+" ]
.hhconfig ͋Ε͜Ε • λΠϓνΣοΧʔͷϝϞϦૢ࡞ • ࢀর͠͏ͳϞʔυՃ(3.28) disallow_return_by_ref disallow_array_cell_pass_by_ref
None
ۤ࿑ • IDEʹ͓͚Δิػೳͷಈ͖ • Τϥʔ༰͕Θ͔Βͳ͍ • PHPʹݟ͍͑ͯͯผͱ͍͏ೝࣝΛͭ·Ͱ • ใऩूྗ
Type Checker
None
Type Checker • ίϯύΠϥϥΠΫʹಈ͘ܕνΣοΫπʔϧ • Ϟʔυ3ͭ Partial / Strict /
Decl • σϑΥϧτͰPartial
Type Checker: Partial • PHPͷܕએݴ strictͱಉఔ • ඞཁҎ্ʹܕνΣοΫ͠ͳ͍ • ओʹPHPͷίʔυΛ
Hackͱ࣮ͯ͠ߦ͢Δ ίʔυҠ২தͷϑΝΠϧͰར༻ • ࢀর͠ ར༻Մೳ
Type Checker: Decl • <?hh // decl • ܕνΣοΫ͠ͳ͍ •
ଞͷίʔυνΣοΫ࣌ʹࢀর͞ΕΔ • New Hack code should never be written in decl mode
Type Checker: Strict • <?hh // strict • PHPґଘ͕ͳ͘ɺ100% HackͰ࣮͢Δ߹ʹબ
• ݫ֨ͳܕνΣοΫΛߦ͏ϞʔυͷͨΊɺ ίʔυϨϏϡʔ࣌ͷܕએݴʹ͍ͭͯͷٞඞཁ࠷খݶ • ఆ֎ͷܕมͳͲߦΘΕͳ͍ͨΊɺ ϨϏϡʔΫϥεઃܭɾΞʔΩςΫνϟͳͲʹ ϑΥʔΧεͰ͖Δ
for Example • ίϯετϥΫλͰॳظԽ͍ͯ͠ͳ͍ίʔυܯࠂ • isset͡Όͳͯ͘ɺarray_key_existsΛ͍ͳ͍͞ • ͨͩͷarray͡ΌΘ͔Βͳ͍ Vector͔Map͍ͳ͍͞
ߟ͑ํΛม͑Δ • ͱΓ͋͑ͣarray ͦͷarrayͲΜͳׂ͕͋ΓɺͲ͏͍͏ͷͳͷ͔ • arrayͰ͋Δඞཁ͕͋Δͷ͔Ͳ͏͔
Hackͷarrayࡾछྨ • array ௨ৗͷྻ • varray ͷΈͰߏ͞ΕΔྻ • darray σΟΫγϣφϦͷྻ
<?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; } } ܕҧ͍ Γܕҧ͍ Γܕҧ͍
ΞϓϦέʔγϣϯʹ͓͚Δ ղܾ
None
ܧঝΛ੍ޚ͢Δ • Sealed Class • Sealed Interface • Hack 3.27
Ҏ߱
<<__Sealed(Hoge::class)>> class SealedClass { } <<__Sealed(Sample::class)>> interface SealedInterface { }
ࢦఆͨ͠ΫϥεҎ֎ ܧঝෆՄ ࢦఆͨ͠ΫϥεҎ֎ ܧঝෆՄɾ࣮ෆՄ
ܧঝʹ͍ͭͯͷߟ͑ํ • final classͷΈͰ੍(ڐՄ)Λ͔͚Δ͔ • GenericsͰදݱͷΈڐՄ͢Δͷ͔ • ͦͷޙͷΞϓϦέʔγϣϯͷͱɺ ֦ுੑͰେ͖͘Ξϓϩʔν͕ҟͳΔ
ܕม
public function sum(): int { return 10 + "5e2"; }
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.
ܕม: mixed
public function get($id): mixed { return //Կ͔Λฦ٫͢Δ; } $container =
new Container(); $container->get('something');
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͚ʹهड़
final class Util { public function something(mixed $any): mixed {
if($any is int) { // } if($any is string) { // } } }
Type Constants
interface TypeInterface { abstract const type T; public function getNative():
this::T; }
class UserType implements TypeInterface { const type T = Vector<int>;
public function getNative(): this::T { return new Vector([1,2]); } }
Factory
class Sample { }
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ͳͲ
<<__ConsistentConstruct>> class Sample { } constructor੍ޚ
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จࣈྻࢦఆ ࣮֬ͳΠϯελϯεੜ
ࣝผͷҧ͍
final class BookId { private $id; public function __construct(string $id)
{ $this->id = $id; } public function getValue(): string { return $this->id; } }
final class BookId { public function __construct( private string $id
) {} public function getValue(): string { return $this->id; } }
ҧ͏දݱํ๏
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
ॻ੶දݱํ๏
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; } // লུ }
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; } // লུ } ݎ੍͍ ݎ੍͍
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) }
ॻ੶ίϨΫγϣϯදݱํ๏
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; } } ϑΟʔϧυ੍ͳ͠
type BookShape = shape( 'book_id' => string, 'title' => string,
'price' => int ); ϑΟʔϧυ੍
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
$v = new Vector([ new Book('1234', 'testing', 2999), new Book('1235',
'testing', 2999), ]); $v = $v->filter( ($t) ==> $t->getId() === '1234' )->immutable(); collection filter Πϛϡʔλϒϧʹ
ෳҙຯΛ࣋ͨͤͳ͍ͨΊͷ੍ޚ • ߹ͷ͍͍ΫϥεΛ࡞Βͳ͍ • ूΛΑΓߟ͑Δ • ͳΜͰͰ͖ΔΫϥεͰͳ͍ ͜Ε͔͠Ͱ͖ͳ͍Ϋϥε
ݫ֨ͳܕΛPHPΞϓϦέʔγϣϯʹద༻͢Δҙຯ • ͱΓ͋͑ͣಈ͘ঢ়ଶʹͰ͖Ε͍͍ • ༷มߋ͕͋Εܕ͕ͳ͍ํ͕ଟ༷ੑ͋ΔΜ͡Όͳ͍ʁ • ͦͦଞͷݴޠͰΑ͘ͳ͍ʁ
ͱΓ͋͑ͣಈ͘ঢ়ଶ͔Β ៉ྷʹ͢Δ࣌ؒͳ͔ͳ͔དྷͳ͍
None
બࢶͱࢹΛ͛Δ
Λղܾ͢Δɺ ͢ͳΘͪղΛൃݟ͢Δ͜ͱͰ͋Γɺ ࢥߟͷҰ෦
ղܾ͢ΔͨΊͷྗͱ ࢹ