Architecture

設計を、実装のあとに隠さない。

BEAR.Sundayは、Webの制約をアプリケーション内部の設計原則として扱います。Resource、DI、AOP、Contextが役割を分けるため、コードの意味が読みやすく、長期運用に耐える構造になります。

Design philosophy

それぞれを、それぞれのままつなぐ。

BEAR.Sundayは、必要な技術を自分の中に取り込んで作り直しません。SQLはSQLのまま、検証はJSON Schemaのまま、リンクはHALのまま。重大な約束ごとほど、フレームワーク独自の発明ではなく、 公開された標準に従います。それぞれに仕事を任せるから、緊張ではなく調和が生まれます。

取り込まない

認証も検証もORMも抱え込みません。フレームワークは制約を与え、ライブラリは選べるまま。標準を選べる自由を残します。

独立して繋ぐ

JSON Schema、HAL、OpenAPI、SQL、PSRは、BEAR.Sundayの外でも通用する姿のまま使われます。投資がフレームワークに閉じ込められません。

重大なことは、標準に従う

検証はJSON Schema、リンクはHAL、API記述はOpenAPI。肝心な部分ほど独自構文を作らず、公開された標準で表します。だから文書化され、長く残り、他のツールやAIにもそのまま通じます。

緊張ではなく、調和

SQLにオブジェクトのふりをさせません。それぞれが得意なことだけをする。無理な抽象がないから、継ぎ目に摩擦が出ません。

つなぐ場所に一つの仕事を与え、型で渡し、反対側を隠す。だから差し替えられ、長く保てる。 これは機能ではなく、設計哲学でありひとつの美学です。

Resource Oriented Architecture

アプリケーションの入口をページやコントローラーではなく、URIで識別できるリソースとして設計します。状態、リンク、表現の境界が揃うため、Web API、HTML、CLIで同じ意味を共有できます。

Dependency Injection

Google GuiceのコンセプトをPHPへ発展させたRay.Diで、型とQualifierをKeyにして依存関係を解決します。Moduleが束縛を宣言し、Injectorがオブジェクトグラフを生成します。

Aspect Oriented Programming

キャッシュ、トランザクション、ログ、認可などの横断的関心をInterceptorとして分離します。リソースクラスはアプリケーションの意味に集中できます。

Context

prod-hal-api-app のようなcontext stringで環境・表現・アプリケーション種別を組み合わせます。環境分岐をアプリケーションコードに混ぜず、DI moduleで差分を表現します。

Context Agnostic Objects

contextはオブジェクトグラフ生成時だけ使われ、生成後のオブジェクトは自分がどのcontextで作られたかを知りません。APP_DEBUGのような実行モード参照を構造から排除します。

ADP Package Structure

フレームワークpackageもアプリケーションも、循環依存を避ける方向に構成されます。複数アプリケーションをHTTP境界ではなく、namespaceとDI bindingで統合し、他のPHPアプリケーションからもリソースとして呼び出せます。

Resource discipline

Resourceは、何でも書ける場所ではない。

BEAR.Sundayのリソース志向は、URLで呼べる部品を作ることではありません。 アプリケーションの意味を置く場所を定め、そこから外側へ表現と接続を展開するための制約です。

意味はResourceに置く

機能の意味をResourceに置きます。表現、依存、遷移、キャッシュ、ドキュメントは、そこから外側へ展開されます。

他者を操作せず、自分を律する

Resource methodは外側のresponse objectを操作する場所ではありません。自分の状態を決め、返すのも自分自身です。

表現に関心を持たない

Resourceが持つのは値、状態、リンクです。HTML、JSON、CLIへの表現はrendererの関心で、Resourceは表現を知りません。

In / Outを制約で宣言する

入力はmethod signature、型、属性、schemaで宣言されます。出力もbody、headers、links、schemaとして残り、暗黙の表示都合に埋もれません。

Ray.Di and Guice

依存解決は、実行時の探し物ではなく、宣言されたグラフの生成。

Ray.Diの中心には、Google Guice由来の考え方があります。アプリケーションコードは依存を取りに行かず、 constructorで必要なものを宣言します。Moduleは「このKeyにはこのProvider」という束縛を定義し、 Injectorは依存の依存までたどって、実行前にobject graphを組み立てます。

だからBEAR.SundayのDIは、便利な自動配線ではありません。context、binding、scope、interceptorを object graphの構成として扱い、生成後のオブジェクトから構成情報への参照可能性を消します。

Key

型とQualifier属性で依存を識別します。同じinterfaceでも、支払い用、ログ用、テスト用の実装を混同せずに扱えます。

Module

束縛を集める構成単位です。機能、環境、表現ごとのModuleを組み合わせ、contextに応じたobject graphを作ります。

Provider

生成が複雑な依存、遅延生成、scopeの混在を扱います。利用側は生成方法を知らず、必要な依存だけを宣言します。

Scope

prototype、singletonなどのライフサイクルを束縛側で制御します。オブジェクト自身が自分の寿命を知る必要はありません。

Interceptor

AOP Allianceに近いMethodInterceptorで、トランザクション、認可、キャッシュを本体コードから分離します。

Compiler

依存グラフからPHP factory codeを生成し、本番ではコンテナ初期化の負荷を抑えます。生成結果は追跡可能な構造になります。

Resource flow

リクエストから表現まで、同じ意味を運ぶ。

MVCのように役割名で分けるのではなく、リソースを中心に状態とリンクをまとめます。 レンダリングや転送は外側へ分離されるため、リソースは「何であるか」を保ちます。

01

Request: app://self/profile?id=1

02

Resource: Profile::onGet(int $id)

03

Body: 状態を配列または値オブジェクトとして保持

04

Links: HALや属性で遷移可能性を宣言

05

Renderer: HTML、JSON、HAL、CLIへ表現を変換

Long-term structure

変化はmoduleへ。リソースの意味は保つ。

環境差分はcontext moduleで表現する

生成後のオブジェクトはcontextを知らない

表現形式はrendererで切り替える

横断的処理はinterceptorで付与する

複数アプリをHTTPの壁なしに統合する

他のPHPアプリからBEARリソースを呼び出せる

Start with one resource

まずは小さく作り、構造を残す。