Be Framework FAQ

0) 要旨(TL;DR)

Q. これは新しい”プログラミングパラダイム”ですか?

A. パターンは既存の問いに対するより良い答えです。パラダイムは問いそのものを変えます。

$emailは外部から検証されるのではなく、存在していること自体が正しさの証明です。意味変数も、自己決定も、自己証明も、コレオグラフィーも——個別の機能ではなく、「ドメインの自我を中心に世界を見る」という一つの視点からすべてが導出されます。

手続き型は HOW(どうやるか)を問い、オブジェクト指向は WHAT(それは何か)を問いました。存在指向は WHETHER(そもそも存在できるか)を問います。


1) パラダイム & 概念

Q1. MVCやDDDとどう違いますか?

A. レイヤーが異なり、共存できます。

Web MVCは実質的に入出力の責務分割であり、DDDはドメインのモデリング手法です。Be Frameworkは「存在の条件と時間的変容」でオブジェクトの生成を組み立てる設計パラダイムで、MVCのControllerから呼び出すことも、DDDの集約の内部で使うこともできます。

Q1-a. CQRSとはどう関係しますか?

A. CQRSは「データを変更する操作(Command)」と「データを読み取る操作(Query)」を分離するアーキテクチャです。Beでは、この分離が一つの存在型の中に自然に内在しています。

コンストラクタが意思決定(Command)、publicプロパティがデータ参照(Query)です。updateUser()のような汎用メソッドに埋もれがちなビジネス判断が、DeactivatedUserのような型名として表出するため、意図がコードから失われません。

Q2. OOP/FPのどちらですか?

A. OOPの要素が中心ですが、FPの要素も取り入れています。

Beでは#[Be]によりオブジェクトが自らの運命を宣言し、外部のオーケストレーターなしに自己組織化します。

Q2-a. FPの要素はどう活かされていますか?

A. 変容が完了した存在型はimmutableです。

副作用はコンストラクタに局在化され、完了後のオブジェクトは純粋なデータとして参照できます。事前条件(#[Input])と事後条件(publicプロパティ)が明確なため、各存在型を独立してテストでき、結果は常に予測可能です。

publicプロパティは伝統的OOPではタブー視されますが、本番ではオブジェクトが型として流通し、テストでは事後条件が直接検証できるという実利があります。(具体的なテスト手法はQ13を参照)

Q3. 「BEING(何であるか)」を先に定義する利点は?

A. 不正状態がそもそも表現できなくなります。

従来のコードに散在する防御的if文が必要なのは、不正な状態が型として表現可能だからです。Beでは型が存在条件そのものなので、不正状態を表す型が存在せず、ガード文ごと消えます。型=到達可能状態がそのままAPI仕様になります。

Q4. 「時間的存在の型」とは何ですか?

A. ValidatedUserSavedUserDeletedUserなど、進行中の特定の時を型名で表現しています。

Be Frameworkは時間とドメインは不可分と考えます。詳細は変容をご覧ください。


2) 主要機能

Q5. #[Be]属性は何をしますか?

A. オブジェクトの運命(次に何になるか)を宣言します。

単一または複数の変容候補を指定し、実行時に$beingプロパティの型で継続先が自動選択されます。

詳しくは変容をご参照ください。

Q6. $beingプロパティの役割は何ですか?

A. 現在の存在が導く次の存在を保持します。

ユニオン型を使用することで、結果の全可能性を明示しています。

Q6.5. $being$beenは特別なプロパティですか?

A. いいえ、特別なプロパティではありません。

これらはフレームワークが魔法的に解釈するものではなく、単なる規約です。

becoming()関数はプロパティ名を読むのではなく、プロパティに宣言された型を見て次のクラスを選択します。

そのため、$being$beenという名前である必要はありません。public Success|Failure $result;のように別の名前でも同じように動作します。

ただし、ドキュメント・サンプル・設計思想に合わせてこの名前を使用することで、「変容先(being)」「完了の証跡(been)」が一目で分かるというメリットがあります。

Q7. 変容の連鎖はどのように制御されますか?

A. #[Be]属性の連鎖により、自動的に次の変容が決定されます。

複数の変容先が可能な場合は、$beingプロパティのユニオン型で表現し、実際に代入された型によって次の変容先が決まります。この仕組みにより、複雑なビジネスロジックも宣言的に表現できます。

Q8. 「意味変数」とは何ですか?

A. 変数名=意味+制約です。$emailは「有効なEmail」でなければ存在できません。

分散しがちな検証(controller/validator/docs)を型に統合します。

(詳細:意味変数

Q8.5. 意味は違うが制約が同じ変数($userId$authorIdなど)はどう扱いますか?

A. 共通の基底クラスやトレイトで制約を共有し、継承で意味を分離します。

// src/Semantic/Abstract/Id.php - 共通制約を持つ基底クラス
namespace App\Semantic\Abstract;

abstract readonly class Id {
    public function __construct(public string $value) {
        if (!preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}/', $value)) {
            throw new InvalidIdException();
        }
    }
}

// src/Semantic/UserId.php - 意味変数として継承
readonly class UserId extends \App\Semantic\Abstract\Id {}
readonly class AuthorId extends \App\Semantic\Abstract\Id {}

// 使用例:変数名に意味が込められる
function updateArticle(UserId $userId, AuthorId $authorId) {
    // $userIdと$authorIdは混同不可能
}

Q9. 「存在理由層(Reason)」とは何ですか?

A. ある存在が成立するための根拠——道具一式をひとつのオブジェクトにまとめます。

従来のDIでは依存が個別にバラバラに注入されるため、「この存在が成り立つ前提条件は何か」が見えにくくなります。Reasonは存在の根拠を意味で束ねるので、テスト時にはその前提条件を丸ごと差し替えられます。

(詳細:存在理由層

Q10. $been(自己証明)は何のためですか?

A. その存在が完了した証跡(誰が・いつ・何を)を内在させます。

外部テストや監査ログと整合しやすくなります。

(詳細:最終オブジェクト


3) 設計・実装

Q11. どこで副作用を起こしますか?

A. コンストラクタの中で、Reasonに委譲して完結させます。

従来のサービス層はオブジェクトの外側から「保存しろ」「通知しろ」と操作していました。Beではオブジェクト自身がコンストラクタで副作用を完結させます。外部オーケストレーターは不要です。

Q12. 例外はどう扱いますか?

A. 意味的例外を用いて、失敗を集合で保持します(多言語メッセージ対応)。

「部分成功・部分失敗」もInvalid〜の”有効な存在”として表現できます。

(詳細:意味例外

Q13. テスト戦略は?

A. 各存在(型)を独立して検証します。

Q2-aで述べた通り、事前条件(#[Input])と事後条件(publicプロパティ)が明確なため、テスト対象のインターフェースが自明です。getterやリフレクションは不要で、publicプロパティを直接アサートします。

ユースケース全体のテストは#[Be]連鎖のスモークで十分に薄く保てます。DIコストはありますが、副作用の局在化とバグ削減で総合的にプラスになります。

Q14. いつ「線形」「分岐」「ネスト」を選びますか?

A. 手順依存=線形/条件で結果が排他的=分岐/独立処理の合流=ネストです。

迷ったら最小限の線形から始めることをお勧めします。

(詳細:実装指針


4) 既存資産との統合

Q15. 既存のMVCアプリに導入できますか?

A. はい。UseCase層をBeで置き換え、Controllerからbecoming(new …Input)を呼びます。段階的な移行が可能です。

Q16. DBや外部APIはどこで使いますか?

A. Reasonに閉じ込めます。存在型はDBスキーマやAPIの都合から自由になり、存在の定義と技術的手段が分離されます。

Q17. フレームワークの依存関係は?

A. コアはPHP標準+DI(例:Ray.Di)を使用します。Laravel/Symfony等との統合はアダプタ経由で可能です。

Q18. 静的解析やIDE補完は効きますか?

A. 型が”状態”なので効果的に効きます。

ユニオン型で分岐が明示化され、補完も安全です。


5) 運用・監査

Q19. ログはどう残りますか?

A. 変容の記録(from/to/理由/証跡)を構造化JSONで残すことが推奨されます。

意味的ログの仕組みは構想段階です。

Q20. 監査対応はどうなりますか?

A. $been(自己証明)により監査証跡の基盤を提供します。

個人情報はReasonレイヤで最小権限を徹底します。


6) マイグレーション

Q21. 既存コードの移行手順は何ですか?(最小ステップ)

A. 以下の手順をお勧めします:

  1. 代表ユースケースを1つ選びます
  2. 入力を…Inputとして抽出します(内在のみ)
  3. 変換先を(存在)として設計し、#[Be]を付与します
  4. 外部依存をReasonに集約します
  5. Controllerからbecoming(new …Input)を呼びます
  6. 意味変数へ検証を移管/例外を意味的に置換します

7) 将来機能

Q22. #[Accept](拡張意思決定)はどのような機能ですか?

A. 構想段階の機能です。

確定できない判断を専門家やAIへ委譲し、確定性と不確実性を一つのフレームで扱う予定です。 決定を第一級市民として外部から制御可能にします。


8) 例とスニペット

Q23. 典型フローの最小例はどのようなものですか?

A.

// 1) 入力(内在のみ)
#[Be(ValidatedUser::class)]
final readonly class UserInput {
    public function __construct(public string $name, public string $email) {}
}

// 2) 存在(変容の瞬間)
final readonly class ValidatedUser {
    public string $display;
    public bool $isValid;

    public function __construct(
        #[Input] string $name,
        #[Input] string $email,
        #[Inject] NameFormatter $fmt,
        #[Inject] EmailValidator $v
    ) {
        $this->display = $fmt->format($name);
        $this->isValid = $v->validate($email);
    }
}

// 3) 実行(自己組織化)
$user = $becoming(new UserInput($name, $email));

// 結果: ValidatedUser オブジェクト
// $user->display: "フォーマット済みの名前"
// $user->isValid: true (有効なメールの場合)

9) 重要用語の詳細解説

存在指向 / Ontological(オントロジカル)

「何をするか」ではなく「何が存在できるか」を中心に据える設計思想です。存在可能性と時間を第一級の抽象として扱い、プログラムの状態を時間的な存在として捉えます。その結果、存在できない状態は型として表現されないため、不正状態が自然に排除されます。

イマナンス / トランセンデンス(内在 / 超越)

内在(#[Input])はオブジェクトが本来持つ性質、超越(#[Inject])は外部から与えられる力です。変容は常に「内在 + 超越 → 新しい内在」の公式に従います。超越は内在を変え、自らは消えていきます。

存在理由層(Reason Layer)

ある存在が成立するために必要な根拠と道具一式をまとめたオブジェクトです。詳細はQ9を参照してください。

意味変数(Semantic Variables)

変数名そのものが意味と制約を表現する概念です。例えば$emailは名前で意味を表し、型として「有効なEmail」でなければ存在できないという制約を持ちます。分散しがちな検証ロジックを型レベルで統合します。

意味的例外(Semantic Exceptions)

失敗を単純な文字列ではなく、意味を持った構造化されたデータとして保持する仕組みです。多言語対応や監査要件に対応し、システムの動作を意味レベルで追跡可能にします。