Skip to content

なぜ PSR 標準を使うのか?

NENE2 は独自の HTTP 抽象ではなく PSR-7・PSR-15・PSR-17 の上に構築されています。このページではその理由を説明します。

各標準がカバーする範囲

標準定義内容
PSR-7RequestInterfaceResponseInterfaceStreamInterface — HTTP メッセージの形状
PSR-15MiddlewareInterfaceRequestHandlerInterface — ミドルウェアとハンドラーの合成方法
PSR-17PSR-7 オブジェクトを生成するファクトリーインターフェース

独自抽象を使わない理由

独自の Request クラスはすぐ書けてコントロールしやすい。しかしコストは後から現れます。

  • 新しい HTTP ライブラリごとに独自アダプターが必要になる
  • あるプロジェクト向けに書いたミドルウェアが別プロジェクトに持ち込めない
  • テストに実行中の HTTP サーバーか独自クラス自体が必要になる

PSR-7 オブジェクトはイミュータブルな value object です。ServerRequestInterface を受け取り ResponseInterface を返すハンドラーは、それを呼び出すフレームワークに何の前提も置きません。

なぜイミュータブルなメッセージなのか

PSR-7 メッセージはイミュータブルです。withHeader()withBody() などのメソッドは既存インスタンスを変更せず新しいインスタンスを返します。これにより、後続ハンドラーが検査するリクエストをミドルウェアが暗黙に変更してしまうバグのクラスが排除されます。

php
// 各ミドルウェアがクリーンなコピーを受け取る — 元のリクエストは変更されない
$request = $request->withAttribute('request_id', $id);

なぜ PSR-15 ミドルウェアなのか

PSR-15 はミドルウェアのコントラクトをシングルメソッドで定義します。

php
public function process(
    ServerRequestInterface $request,
    RequestHandlerInterface $next
): ResponseInterface

これが意味すること:

  • PSR-15 ミドルウェアはどの PSR-15 パイプラインにも組み込める
  • パイプラインの順序は明示的なコードであり、隠れたフレームワークライフサイクルではない
  • ミドルウェアのユニットテストはモックの RequestHandlerInterface だけで済み、実行中サーバーは不要

具体的なパッケージ選択

NENE2 はメッセージオブジェクトに Nyholm PSR-7、ミドルウェアディスパッチャーに Relay を使用します(ADR 0001 参照)。これらは標準を実装しつつ、フレームワーク固有の API を上乗せしない軽量パッケージです。

トレードオフ

メリットコスト
相互運用可能なミドルウェア流暢な独自 API より冗長
イミュータブルなメッセージでバグ削減with* 呼び出しのたびにオブジェクト生成
サーバーなしでテスト可能PSR インターフェースの理解が必要

小規模な JSON API フレームワークにとって、相互運用性とテスタビリティのメリットは冗長さのコストを上回ります。

MIT ライセンスの下で公開されています。