やあ。Hackの世界へようこそ。HHVMの深淵を覗き込み、型という名の「静かなるガードレール」を愛する君なら、きっと素晴らしいコードを書けるはずだ。
今日は、Hackの厳格な静的型システムを使いこなし、ビジネスの複雑さを型に閉じ込める「Value Object(値オブジェクト)」という設計手法について話そう。
「プリミティブな型(intやstring)だけで十分じゃないか?」なんて思っていたら、それはまだHackの真の力に触れていない証拠だよ。さあ、一緒に深掘りしていこう。
—
なぜプリミティブ型だけでは不十分なのか?
例えば、決済システムを作るとしよう。`int`型で「金額」を扱うコードはよくあるよね。
// 危険な香りがする設計
function processPayment(int $amount, int $userId): void {
// ここで $amount と $userId を間違えて渡しても、HHVMは文句を言わない
}
もし引数の順番を間違えて `processPayment($userId, $amount)` と呼び出してしまったら?型チェッカーは何も警告してくれない。これが「プリミティブへの依存」が引き起こす悲劇だ。
Value Objectで「意味」を型に刻む
HackのStrict Mode(`<<__Strict>>`)は、単なる記法じゃない。「型はドメインの知識そのものであるべき」という哲学を強制するものだ。
Value Objectは、ただの値を「意味のある型」でラップする。こうすることで、コンパイル時(型チェック時)に誤った代入を弾くことができるんだ。
実践:MoneyとUserIdを型にする
<<__Strict>>
namespace Domain;
// 値を不変(immutable)にするのが鉄則
readonly final class Money {
public function __construct(
public int $amount,
public string $currency,
) {
// コンストラクタでドメインの正当性を担保する
invariant($amount >= 0, “金額は0以上である必要があります”);
}
}
readonly final class UserId {
public function __construct(public int $id) {}
}
// これなら間違えようがない!
function processPayment(Money $amount, UserId $userId): void {
// 処理内容…
}
この設計のメリット
- 型安全性: `processPayment(new UserId(1), new Money(100, ‘JPY’))` と書こうとすれば、型チェッカーが即座にエラーを吐いて止めてくれる。
- バリデーションの集中: `invariant` を使うことで、不正なデータがドメイン層に侵入するのを防げる。
- 可読性: 引数を見ただけで、それが何を意味するかが明確だ。
—
陥りやすい罠と解決策
初学者がよくやる失敗パターンをいくつか挙げておくね。
罠1:Value Objectを「可変」にしてしまう
Value Objectは「値」だ。一度生成されたら、その内容は変わっちゃいけない。
- 対策: `readonly` プロパティや、プロパティを外部から変更できない設計を徹底すること。Hackの `readonly` キーワードを活用しよう。
罠2:型チェッカーのパフォーマンスを気にして躊躇する
「クラスを大量に作るとHHVMが遅くなるのでは?」と心配する人がいるけれど、心配無用だ。HHVMのJITコンパイラは、このような小さなオブジェクトの生成・破棄を驚くほど効率的に最適化する。型安全性というメリットに比べれば、コストはほぼゼロだ。
罠3:プリミティブに戻りたくなる(Unwrapの誘惑)
「結局 `int` で計算したいから」と言って、すぐに `->amount` を取り出して直接計算してしまうケース。
- 対策: 演算ロジックもValue Objectの中に押し込もう。
// こうすれば、外側から int を直接いじらなくて済む
public function add(Money $other): Money {
invariant($this->currency === $other->currency, “通貨単位が異なります”);
return new Money($this->amount + $other->amount, $this->currency);
}
—
最後に:型は「守り」ではなく「表現」だ
Hackの静的型システムを使いこなすということは、「このコードで何が起こりうるか」を、実行する前に全て定義し尽くすということだ。
Value Objectを導入すると、最初はコード量が増えたように感じるかもしれない。でも、それは「将来のバグを今この瞬間に摘み取っている」という投資なんだ。
ここをクリアすれば、君はもうHackの初心者じゃない。型チェッカーと対話しながら、堅牢で美しいシステムを構築していこう。
もし分からないことがあれば、いつでもHHVMの型チェッカーを動かして「文句」を言わせてごらん。それが君を一番成長させてくれる最高の教師だからね。
それじゃ、また次の深淵で会おう。Happy Hacking!