Skip to content

Instantly share code, notes, and snippets.

@koriym
Created April 9, 2026 03:16
Show Gist options
  • Select an option

  • Save koriym/4432b28bd474b33052efda40889e31fc to your computer and use it in GitHub Desktop.

Select an option

Save koriym/4432b28bd474b33052efda40889e31fc to your computer and use it in GitHub Desktop.
深層比較:BEAR.Sunday vs Laravel

(koriym) 以下はqwen3-coder-next:latest を用いて「https://bearsunday.github.io/llms-full.txt を理解して、BEAR.SundayとLaravelを深く比較してください」という問いに対する答えです。


(qwen) 以下は、表面のコマンドや構文ではなく、「設計思想・アーキテクチャ哲学・長期 的保全性」という深層を、BEAR.Sunday と Laravel で徹底的に比較したものです。


🧠 深層比較:BEAR.Sunday vs Laravel

(「フレームワークがプログラマに問いかける問い」の違い)

📌 本質的な違い
Laravel は「アプリケーションを書くための道具箱」
BEAR.Sunday は「アプリケーションを『設計するための制約』」

Laravel BEAR.Sunday
設計哲学の根幹 Elegant syntax & Developer experience first(開発者の満足感) REST / ROA as constraints(Webの原理を守るための制約)
→ 「どう書くか」を美しく・楽しくする → 「何を、どのように分離するか」で強制的整合性を担保
「自由は制約の下に最大限に」
メタファー 「カスタムビルダー(DIYツールセット)」 「建築基準法(すべての建物に共通する構造原理)」
→ 工法は自由だが、結果の整合性は開発者の責任 → 工法は限定されるが、結果の整合性はフレームワークが保証

🔍 1. 状態管理と境界:世界をどう「划分」するか

▶ Laravel:「Controller が境界」

  • リクエスト → Controller(状態変更+表示+ロジックの混合体)
  • Controller 内で DB → Service → View を直列に呼び出す
  • 状態の変化が「コントローラ内での処理フロー」に依存
  • → 状態整合性を守るには、各 Controller が気をつける必要がある

▶ BEAR.Sunday:「Resource が境界」

  • リクエスト → ResourceObject純粋な状態定義
  • HTTPメソッド(GET/POST…)=状態変化の「種類」(CRUD不是!)
  • onGet()状態を読み取る命令onPost() は**状態を変化させる命令 **
  • 状態はリソース内部にカプセル化、外部は URI と Link でしかアクセス 不可
  • → 整合性は REST制約(状態レス、リンク)で保証

✅ 深層の違い:

  • Laravel:「どう状態を変えるか」に焦点(手続き的)
  • BEAR.Sunday:「何が状態を持つか、どうリンクするか」に焦点(構造的)

🔍 2. 依存性注入(DI):「依存」の扱い方

項目 Laravel BEAR.Sunday
注入対象 主に「サービスクラス」(App\Services\* **すべての実行
単位**(リソース、インターセプタ、ロガー、SQL接続、DateTime)
注入の契機 コンストラクタ/プロパティ(app() ファサードで遅延解決可
コンパイル時var/tmp/app.php に生成されたルートオブジェクト木)

| | 特徴 | 実行時解決 → 実行時エラーの可能性あり | コンパイル時解決 → 実行時エラー極小化(vendor/bin/bear.compile で前検証) | | 依存の可視化 | php artisan tinker で手動確認 | var/tmp/module.dot → Graphvizで可視化(依存グラフが静的ドキュメント) | | AOPとの連携 | 限定的(Middleware は横断だが、メソッド単位は困難) | メソッド単位で宣言的#[Transactional], #[Cacheable] で AOP アスペク トを埋め込み) |

✅ 深層の違い:

  • Laravel:「依存を解決するための仕組み」(ツールとしてのDI)
  • BEAR.Sunday:「依存関係そのものを設計の一部として固定化する哲学」( 構造としてのDI)

🔑 Key Insight
BEAR.Sunday の DI は、「コンポーネントを結合する接着剤」ではなく、「結合 ルールを明示する規約」 です。
AppModule::configure()「このアプリケーションの構造定義書」 に なります。


🔍 3. データ永続化と「SQL」の扱い方

項目 Laravel BEAR.Sunday
ORMの役割 中核(Eloquent がロジックとDBを結合) 選択肢の一つ
直接SQL or Ray.MediaQuery for interface → SQL)
SQLの場所 PHP内(メソッドチェーン or ダイナミッククエリ) **外部フ
ァイル**(var/sql/ticket_item.sql
型安全性 PHPDoc / 一部靜的解析(Psalm プラグイン必要) **PHPインタ
ーフェース → SQL実行オブジェクトの自動生成**(型推論完全)
トランザクション DB::transaction() で明示的管理
#[Transactional] 属性でメタ情報として宣言(AOPで自動ラップ)

▶ 具体例:投稿作成(Laravel → BEAR.Sunday)

Laravel(Eloquent)

// app/Http/Controllers/PostController.php
public function store(Request $request)
{
    $request->validate(['title' => 'required|max:255']);
    $post = new Post();
    $post->title = $request->title;
    $post->user_id = auth()->id();
    $post->save(); // ← トランザクション?エラー?状態管理は開発者の責任
    return redirect()->route('posts.show', $post);
}

BEAR.Sunday(Ray.MediaQuery)

// src/Query/PostCommandInterface.php
#[DbQuery('post_add')]
public function add(string $title, DateTimeInterface $now, int $userId): void;

// src/Resource/App/Posts.php
#[Transactional] // ← トランザクションはアスペクトとして定義
#[ReturnCreatedResource] // ← Created resource を body に含める
public function onPost(string $title): static {
    $this->command->add($title, new DateTimeImmutable(), $this->userId); // ← 現在時刻はDIで自動挿入
    $this->code = 201;
    $this->headers['Location'] = "/posts?id=" . $lastId;
    return $this;
}

✅ 深層の違い:

  • Laravel:「ロジックを書く」(データをどう扱うか)
  • BEAR.Sunday:「境界を宣言する」(「誰が何をどう做的に扱うか」を外部化)

🔍 4. 時間軸:長期保守性の視点

項目 Laravel BEAR.Sunday
バージョンアップポリシー major version → 破壊的変更(v8→v9で構造再設計) semver は守るが、major升级はしない(Eternal 1.x)
→ 5年運用で数回の大規模マイグレーションが必要 → 10年後も、現在のコードは動作し続ける(非推奨のクラスは deprecated で残す)
ライブラリ依存 自身のパッケージ群(Monolog, Illuminate, etc.) 優良サードパーティ選択(Aura.Sql, Twig, Doctrineなど)
→ フレームワークとライブラリが一体化 → 変更コスト大 → フレームワーク=骨架、ライブラリ=臓器 → 独立交換可能
コンテキストの寿命 APP_ENV=production は実行時解決 → コード内で条件分岐(=if (env('APP_ENV')) prod-hal-api-appコンパイル時解決
実行時ロジックに env() が一切不要

💡 実体験から
Laravelで10年運用する場合、DBスキーマ、PHP構文、フレームワークAPI の3層の変更に耐える必要あり。
BEAR.Sunday は、リソース設計(URI, JSON Schema)が永続仕様 → バージョンアップに伴う「変更範囲」が明確で、影響解析容易。


🔍 5. 「テスト」への哲学的アプローチ

項目 Laravel BEAR.Sunday
テストの単位 FeatureTest(HTTPレイヤー)+ UnitTest(ロジック) すべて Resource レベル(URIベースの統合テスト)
HTTPテスト test()->get('/posts')(フレームワーク独自API) resource->get('app://self/posts')HTTPリクエストと同一のインタフェース
→ 実行環境(Web/CLI)によってコードが分離 同じコードで Web/CLI/HTTPテスト(統合テストが自然)
モックの範囲 Service レイヤー(Mockery::mock(PostService::class) リソースの依存すべて[SpyModule] で呼び出し回数・引数を記録)

▶ 特に注目:Hypermedia API テスト

// Laravel: リンクの遷移をコードで記述(実装依存)
$response = $this->get('/api/posts');
$link = $response->json('_links.next.href');
$this->get($link);

// BEAR.Sunday: RESTの原則(Hypermedia as the engine of application state)をテスト
$index = $this->resource->get('/'); // ← リソースの状態遷移を追跡
$nextLink = json_decode($index)->_links->next->href;
$next = $this->resource->get($nextLink);

→ BEAR.Sunday では、テストコードが「アプリケーション仕様」そのもの になる。


🔑 結論:二者択一ではなく、問いの転換

Laravel BEAR.Sunday
問い 「どう書くと楽か?」 「何を分離すべきか?」
設計目標 開発者の生産性(短期的生産性) アプリケーションの生残性(長期的保守性)
適したアプリ • MVP/スタートアップ(急速開発が優先)
• 内部管理ツール
• カスタマーポータル
• 核心业务システム(10年単位運用)
• マルチ
チャネル統合システム
• AI連携 API サービス
開発者の成熟度 中〜上級(構造を自分で守る) 上級〜 architect(構造を強制する)

📌 付録:BEAR.Sunday を選ぶなら「ここで立ち止まる」べき3つの問い

BEAR.Sunday を導入する際、チームが必ず直面する「設計的問い」を列挙します。
(Laravelでは「どう書くか」で済むところを、「なぜこうするか」に踏み込む)

  1. このリソース、本当に「独立した状態」を持つか?
    → 同じデータでも、app://self/userapp://self/profile を分けるか?
    分離基準 = アプリケーションの「境界設計」

  2. この変更は、リンクの変更で済むか?それともリソースの変更か?
    → 状態変更を「リンクの追加」(Hypermedia)で表現するか、「状態の置き換え」(REST)で表現するか
    → ここが、アプリの「意味的丰かさ」に直結

  3. このキャッシュ、依存関係ツリーは?
    #[Embed] で埋め込まれたリソースが更新されると、どのリソースのETagも更新されるか?
    → これを設計しないと、CDNキャッシュは効かない

これらの問いに「直感的に答えられる」なら、BEAR.Sunday は力を発揮します。
「答えの出ない問いに時間をかけたくない」なら、Laravel が適しているでしょう。


🌟 最後に:BEAR.Sunday の「深層の深層」

BEAR.Sunday が守る最大の制約は、「REST制約を破らないこと」ではなく、「アプリケーションを『 Web の原理に忠実なもの』として設計し続けること」です。
→ それは、「アプリケーションの意味的構造」を「ユーザーが理解しやすい形」で表現し続けるための、最短パスです。

Laravel は「どのように動かすか」を美化するフレームワーク。
BEAR.Sunday は「なぜ動かすか」を可視化する制約。


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment