なぜこの形なのか

Strata の機能は「便利そうだから」ではなく、マイクロサービスで実際に困った場面から逆算して作っています。 ここでは主要な設計判断と、その理由を書きます。

なぜ関数レベルまで解析するのか

サービス単位の依存図(箱と矢印)は 5 分で描けますが、5 分で嘘になります。 図は手で描いた瞬間から実装とずれ、「本当にこの依存があるのか」を誰も確認できません。

Strata はコードから関数レベルの呼び出しグラフを作り、サービス間の矢印を 「どの関数がどの行で呼んでいるか」まで展開できる状態にしています。 図が信用できるのは、根拠まで降りられるからです。

なぜ proto を「正」にするのか

gRPC のマイクロサービスでは、クライアント側のコードとサーバ側のコードが別リポジトリ・別言語にあります。 両者を直接つなぐ手がかりはコードにはなく、間にある proto の RPC 名だけが共通言語です。

そこで Strata は .proto を索引にして「クライアント関数 → ⚡RPC → サーバ実装」を接続します。 .proto が無い場合(生成コードしか無いリポジトリ)は *_grpc.pb.go から service / RPC を復元します。 これは実際のリポジトリで「proto が消えていて追跡できない」場面に当たったための実装です。

なぜ HTTP / GraphQL / webhook まで対応したのか

現実のシステムは gRPC だけでできていません。BFF は REST、フロントは GraphQL、 決済や配送は webhook、というプロトコルが混ざった経路が普通です。 gRPC だけ追えても、経路はプロトコルの境目で途切れます。

Strata は同じ「定義・呼び出し・実装」の枠組みを HTTP と GraphQL にも適用し、 REST → gRPC → REST → 外部 SaaS のような経路を 1 本のフローとして表示します。 詳細は プロトコル横断の追跡 を参照してください。

なぜ「一意に決まるときだけ」線を引くのか

静的解析は、頑張るほど誤検出が増えます。そして一度でも嘘の依存を見せたツールは二度と信用されません

Strata は「取りこぼしても良いが、嘘は出さない」を優先します。 たとえば HTTP のパス一致で候補が 2 件以上あるときは、どちらにも線を引きません。 DI 越しのメソッド呼び出しも、import 先パッケージ内で名前が一意なときだけ接続します。

そのかわり、取りこぼす条件は仕様書に明記しています。

なぜ「地層(strata)」表示なのか

依存グラフをそのまま描くと、線が絡まって何も読めません。 Strata は依存の向きからノードを層に分け(レベル化)、層ごとに帯を敷いて表示します。

こうすると「下の層が上の層を呼んでいる線(=レイヤー違反)」が視覚的に浮き上がります。 色も分けてあり、正常な依存はグレー、上向きの違反はローズです。名前の由来もここにあります。

なぜ CI 検査(check)があるのか

アーキテクチャは、レビューで守ろうとすると必ず崩れます。人は毎回全体を見られないからです。

strata check は循環依存・禁止依存ルール・結合度のしきい値を検査して 違反があれば exit 1 します。ルールは strata.config.json に宣言として書くので、 「domain 層は infra を参照しない」といった決めごとが、レビュアーの記憶ではなく CI に残ります。

なぜ外部依存ゼロなのか

依存が増えるほど、導入のハードルと運用コストが上がります。 Strata は実行時依存ゼロで、Node.js の型ストリッピングにより TypeScript をそのまま実行します (ビルド不要)。ビューアもフレームワークを使わない素の HTML / CSS / JS です。

これは思想的な潔癖さではなく、職場で気軽に入れられることを優先した結果です。 git clone して node src/cli.ts serve . で動きます。