型の迷宮を脱出せよ:`dynamic`と`mixed`の境界線で戦うアーキテクチャ戦略
Hackの静的型システムを前にして、多くのエンジニアが「レガシーPHPからの移行」という名の泥沼で足を取られる。既存のPHPコードベースをHackへ昇華させる際、最も罪深いのは「とりあえず動けばいい」という妥協でコード中に`mixed`を撒き散らすことだ。
今日は、HHVMの深淵を知る者として、`dynamic`と`mixed`を単なる「型がない」というラベルで片付ける愚を正し、型境界を戦略的に封じ込めるための「エンジニアリングの作法」を伝授する。
—
1. `dynamic` vs `mixed`:その「無知」の質を見極めよ
型チェッカー(HHVM Typechecker)が最も嫌うのは、型の正体が不明なままロジックが進行することだ。
- `mixed` (The Unknown): 「何が入ってくるかわからない」という受動的な無知。型チェッカーは「どんなメソッドも呼ぶな、どんな操作もするな」と警告する。これはシステムの末端で発生する、極めて厳格な制約だ。
- `dynamic` (The Bypass): 「私が責任を持つから黙っていろ」という能動的な放棄。型チェックをバイパスし、動的ディスパッチを許可する。これはレガシーコードとの境界線における「安全装置」である。
鉄則: `mixed`は「検査(Refinement)して消し去るもの」、`dynamic`は「隔離して排除するもの」だ。
—
2. 境界線の封じ込めパターン:`dynamic`は「防波堤」である
レガシーなPHP配列や外部APIの結果をHackの世界に引き込む際、いきなり厳格な`shape`や`class`にキャストしようとしてはいけない。まずは`dynamic`という境界線を設け、その内部で型を精査する。
実践:アダプターパターンによる型境界の構築
以下は、不確実な外部入力を安全にHackの型システムへ引き込むための設計例だ。
namespace App\Infrastructure;
use type HH\Lib\Dict;
/
- レガシーな外部APIレスポンスを扱うための境界クラス
/
final class UserDataGateway {
/
- 外部からの入力をdynamicとして受け取り、即座に型を確定(Refine)させる
/
public function fetchUser(mixed $raw_data): shape(‘id’ => int, ‘name’ => string) {
// 1. dynamicで一旦受ける(型チェックを一時停止)
$data = (dynamic)$raw_data;
// 2. 境界線で型を精査(Refinement)
if (!Dict\contains_key($data, ‘id’) || !is_int($data[‘id’])) {
throw new \InvalidArgumentException(“Invalid user data structure”);
}
// 3. 型が確定した状態で返却
return shape(
‘id’ => (int)$data[‘id’],
‘name’ => (string)($data[‘name’] ?? ‘Guest’),
);
}
}
ポイント:
- `mixed`を関数引数で受け取るのは「入り口」のみ。
- 内部で`dynamic`へキャストし、プロパティアクセスを許容しつつ、その直後に`is_int`等のガード節で型を絞り込む。これにより、型チェックの及ばない領域を数行以内に限定している。
—
3. パフォーマンスと型システム:`dynamic`のコスト
HHVMのJITコンパイラは、型が静的に確定している場合に最高のパフォーマンスを発揮する。`dynamic`がコード内に蔓延すると、JITは「どのメソッドが呼ばれるか」を予測できず、ガード命令(型チェックの命令)を大量に挿入せざるを得なくなる。
- `dynamic`の使用量 = JIT効率の低下
- `mixed`の放置 = 開発体験(DX)の低下とランタイムエラーの温床
段階的移行(Incremental Migration)においては、`dynamic`を広範囲に使うのではなく、「型変換用の小さな関数」の中に閉じ込めることが、パフォーマンスを維持しつつ型カバレッジを上げる唯一の解である。
—
4. チームへの提言:型境界を可視化せよ
もし君のコードレビューで、`dynamic`がクラスの広範囲で使われていたら、それは設計の敗北だ。以下のルールをチームに強制せよ。
1. `dynamic`はファイル単位で隔離せよ: レガシーとのブリッジコード以外のファイルに`dynamic`を持ち込ませない。
2. `mixed`はメソッドの入り口のみ: メソッドのシグネチャを`mixed`で定義し、メソッドの先頭で必ず型精査(`is`演算子や`instanceof`)を行い、型を確定させる。
3. `HH\Lib`を使い倒せ: `HH\Lib\C\contains` や `HH\Lib\Dict\get` 等のHSL(Hack Standard Library)を活用し、安全に型を確定させるコードを書くこと。
結びに代えて
Hackの静的型システムは、君たちを束縛するための鎖ではない。それは、複雑怪奇なWebシステムの荒波を航海するための「コンパス」だ。
`mixed`と`dynamic`を操ることは、カオスなPHPの遺産を秩序あるHackの世界へ招き入れるための外交術だ。境界線を厳格に引き、一歩ずつ型カバレッジを広げていく。その執念こそが、真に堅牢なプロダクションコードを生み出す。
さあ、型チェッカーを友とし、妥協のないコードを書き進めよう。次のコミットが、君のシステムの寿命を確実に延ばすはずだ。