【入門編】Hackの『Value Object』設計パターン:型システムでドメインを表現する – Hack言語 コア・静的型システムとHHVMのアーキテクチャ解析バイブル

やあ。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!

タイトルとURLをコピーしました