狂気的な定数管理を終わらせろ:Hack Enumによる「型駆動開発」の真髄
PHPの古いコードベースを開いたとき、最も吐き気がするのは `const` や魔法の文字列で埋め尽くされたロジックだ。`if ($status === ‘pending’)` といったコードが蔓延し、タイプミス一つでシステムが崩壊する。そんな脆弱な設計に頼るのは、今日で終わりにしよう。
Hackの `enum` は単なる定数の集まりではない。HHVMの静的型システムと密接に結びついた、「型の網羅性(Exhaustiveness)」を担保するための強力な武器だ。本稿では、PHPの泥沼から脱出し、Hackの堅牢な型システムを最大限に活かす設計手法を伝授する。
—
なぜ `const` は悪なのか?
PHPのクラス定数は、単なるラベルに過ぎない。型チェッカーはそれが「文字列」であることしか認識できず、その値が「有効な状態の集合」であるかどうかを証明できない。
一方で、Hackの `enum` は代数的データ型(ADT)の先駆けだ。`HH\MemberOf
—
移行ステップ:ただの定数から「型」へ
以下に、実務で即座に適用できるリファクタリングのパターンを示す。
1. PHP流の脆弱な定数管理(アンチパターン)
// 修正前:型安全が全く担保されていない
class OrderStatus {
const PENDING = ‘pending’;
const SHIPPED = ‘shipped’;
}
function process(string $status): void {
// 誰かが ‘pnding’ と打ち間違えても、静的解析は黙っている
if ($status === OrderStatus::PENDING) { / … / }
}
2. Hack Enumによる堅牢化
// 修正後:Enumで状態を定義する
enum OrderStatus: string {
PENDING = ‘pending’;
SHIPPED = ‘shipped’;
DELIVERED = ‘delivered’;
}
// 引数に型を指定することで、不正な値の侵入をコンパイル時に阻止する
function process(OrderStatus $status): void {
// switch文での網羅性チェック(後述)
}
—
実践:網羅的チェック(Exhaustive Checking)の恩恵
Hackの真骨頂は、`switch` 文における「網羅性チェック」だ。新しい状態(例: `CANCELLED`)をEnumに追加した瞬間、HHVMの型チェッカーは「未処理のケースがあるぞ」と警告を出す。
function getStatusLabel(OrderStatus $status): string {
// このswitch文で全パターンを網羅しないと、HHVMはエラーを吐く
return switch ($status) {
OrderStatus::PENDING => ‘処理待ち’,
OrderStatus::SHIPPED => ‘発送済み’,
OrderStatus::DELIVERED => ‘配送完了’,
// もしEnumに新しい値を追加してここを更新し忘れると、コンパイルエラーになる
};
}
この「メンテナンスの漏れをコンパイラが指摘してくれる」という体験は、大規模開発においてコストを劇的に下げる。
—
実務上のTips:HSLと組み合わせた高度な設計
API連携などの現場では、外部からの入力を安全にEnumへ変換する必要がある。ここで `HSL (Hack Standard Library)` を使うのがアーキテクトの嗜みだ。
use namespace HH\Lib\C;
// 不正な入力が来た場合、例外を投げるのではなく安全に扱う
function fromString(string $input): ?OrderStatus {
// Enum::getNames() 等を使い、安全にマッピングを行う
return OrderStatus::coerce($input);
}
パフォーマンスへの配慮
HackのEnumは、内部的には定数とほぼ同等のオーバーヘッドで動作する。HHVMのJITコンパイラは、Enumの値を最適化された整数や文字列比較としてインライン化するため、パフォーマンス上の懸念は無用だ。むしろ、型不整合によるランタイムエラーのデバッグコストを考えれば、Enumを使わないことは経済的損失と言える。
—
チーフアーキテクトからの助言
プロダクションコードにおいて、「型を信じるな、コンパイラに証明させろ」。
1. Enumを公開しすぎない: 内部状態は `enum` で閉じ、必要であれば `as string` で外部に出す。
2. 型エイリアスを活用する: 複雑なロジックには `type TStatus = OrderStatus;` のように型エイリアスを重ね、ドメインを明確にする。
3. PHPからの卒業: `string` や `int` を引数に取る関数を見かけたら、それはリファクタリングの絶好の機会だ。
Hackの型システムは、君たちが書くコードをより「予測可能」で「壊れない」ものにするために存在する。今日この瞬間から、魔法の文字列を排除し、型による厳格な規律をコードベースに持ち込んでほしい。
それが、世界最高峰のコードへの第一歩だ。健闘を祈る。