最終オブジェクト

「あなたは私ではない。どうして私が魚の気持ちを知らないと分かるのか?」

—「あなたは魚ではない。どうして魚の気持ちが分かるのか」と問われた時に荘子が返した言葉 (『荘子』紀元前4世紀)

終着点

ユーザーにとって見えるのは、入力と最終オブジェクトだけです。入力クラスで始まった旅が、最終オブジェクトとして届く—これが変容の到達点です。

基本構造

final readonly class SuccessfulOrder
{
    public string $orderId;
    public string $confirmationCode;
    public string $message;
    public Been $been;                            // 完了の証跡

    public function __construct(
        #[Input] Money $total,                    // 内在
        #[Input] CreditCard $card,                // 内在
        #[Inject] OrderIdGenerator $generator,    // 超越
        #[Inject] Receipt $receipt,               // 超越
        #[Inject] Been $been                      // 証跡の記録者
    ) {
        $this->orderId = $generator->generate();
        $this->confirmationCode = $receipt->generate($total);
        $this->message = "注文確認: {$this->orderId}";

        $this->been = $been->with(new OrderConfirmedContext(
            orderId: $this->orderId,
            total: $total->getAmount(),
            paymentMethod: $card->getType(),
            confirmation: $this->confirmationCode,
        ));
    }
}

Beenはフレームワークが提供し、他の超越と同じように注入されます。Beenはこの変容がどこから始まりどこに至ったかを既に知っています。知り得ないのは、コンストラクタの内側で何が起きたかです。その部分は最終オブジェクト自身がwith()で追記します。渡すのはOrderConfirmedContextのような、アプリケーションが定義するイベントコンテキストです。何を「完了の証跡」とするかはドメインによって異なります。SuccessfulOrderなら確認コードを、DeletedUserなら誰がいつ削除したかを記録するでしょう。コンテキストの構造と出力されるJSONは意味的ログで説明します。

入力クラスとは対照的に、最終オブジェクトはドメインの豊かさを完全に表現した存在です。内在が超越と出会い、変容を経て、これ以上変わる必要のない完全な状態に達しています。

時間的存在の完全性

Be Frameworkでは、オブジェクトの時間的存在を二つの軸で捉えます:

  • #[Be]: なりたい自分、向かう先(未来への方向性)
  • $been: 完了した自分(過去完了の証跡)

$orderIdや$confirmationCodeはビジネス上の本質的な値です。一方$beenは、コンストラクタの内側で何が起き、何を根拠に完了したかという証跡を記録します。

内側からの完全性

従来のプログラミングでは、オブジェクトが正しく処理されたかどうかを外部のテストが判定します。しかし最終オブジェクトは、自分が何であるかを自分自身の構造として持っています。何が入力され、何が起こり、何になったか—その全てが一つの存在の中に収まり、完了の証拠になっています。

入力クラスとの対比

入力クラス 最終オブジェクト
変容の出発点 変容の到達点
ユーザーが提供するもの ユーザーが受け取るもの
シンプルな構造 豊かで完全な状態

複数の最終的運命

オブジェクトはその性質によって複数の最終形態を持つことができます。ここで使っている$becomingは変容チェーンを起動する仕組みで、次章で説明します:

$order = $becoming(new OrderInput($items, $card));

if ($order instanceof SuccessfulOrder) {
    echo $order->confirmationCode;
} else {
    echo $order->message;  // エラーメッセージ
}

設計者の仕事

入力と最終オブジェクトの間にある変容の仕組みを設計すること—それが設計者の責務です。ユーザーが触れるのは両端だけですが、その間の存在クラスがシステムの骨格になります。

最終オブジェクトは、自分が完了したことを内側から知っています。


宣言された変容はどう動き出すのか。生成へ ➡️