Skip to content

Latest commit

 

History

History
89 lines (65 loc) · 4.95 KB

File metadata and controls

89 lines (65 loc) · 4.95 KB

ADR 0009: 公開APIの抽出はソースの静的解析で行い、API 対応表は生成する

  • 状態: 採用
  • 日付: 2026-08-29

背景

本ライブラリの差別化要因は「1人の開発者が全言語へ同一の API を提供すること」に尽きる (0001)。これを人手で維持するのは必ず破綻する。 C# に WriteBytes を足して Rust に write_bytes を足し忘れれば、 その時点でライブラリの価値そのものが失われる。

したがって機械で守る必要がある。守るべきものは2つ。

  1. 全言語の公開API集合が一致していること
  2. docs/api/ の対応表が実装と一致していること

選択肢

抽出の方法

方法 長所 短所
各言語の公式ツール(リフレクション / javap / cargo public-api / .d.ts 解析 / inspect) 正確。マクロ展開後も見える CI に5言語ぶんのツールチェーンとビルド成果物が要る。ツール自身のバージョン差で壊れる。5つの別々のツールが5通りの形式で出力するので、それを揃える層が結局要る
ソースの静的解析(正規表現) 依存は Python 3 だけ。ビルド不要で数秒。壊れても原因が1か所 マクロ生成やメタプログラミングは見えない。書き方の揺れに弱い

対応表の作り方

方法 長所 短所
人手で書く 説明を自由に書ける 必ず実装から遅れる。5言語 × 数百メンバを手で保守するのは非現実的
実装から生成する 原理的にずれない 説明文をどこから取るか決める必要がある

決定

  • 抽出はソースの静的解析で行う。 実装は spec/tools/extract_api.py
  • docs/api/*.md の対応表は生成する。 生成部分は <!-- generated:start --> / <!-- generated:end --> で囲み、 check_docs_sync.py が書き出す。 導入の説明文はその外側に手書きで置く
  • 説明文は基準実装である C# のドキュメントコメントから取る(0002)。 説明を直すときは C# のソースを直す
  • CI は生成結果と現在のファイルを突き合わせ、違えば落とす。 開発者は --write で書き直す

一致検査の粒度

型は完全一致を求め、メンバは求めない。

型が欠けているのは機能そのものの欠落を意味するので、 差異は extract_api.EXPECTED_TYPE_GAPS に理由つきで登録しなければ CI が落ちる。

一方メンバは、言語の作法による差異が正当に生じる。

  • Rust の section_mut() — 借用規則のため可変参照用の別メソッドが要る
  • Rust の as_longs() / into_longs() — 所有権を渡すかどうかで2つに分かれる
  • Java の setFoo() — 他言語はプロパティへ直接代入する
  • iter / items / entries / keys — コレクションの走査は言語ごとに作法が違う

これらを無理に揃えると、どの言語でも不自然な API になる。 メンバの差異は対応表に「—」としてそのまま表示し、 利用者が事実を見て判断できるようにする。

根拠

静的解析の弱点は、この設計では実際には効かない。 マクロ生成が見えない問題は Rust の scalar_accessors! だけで、 マクロ呼び出し行から名前を拾えば足りる。 書き方の揺れに弱い点は、全言語を同じ人間が同じ方針で書いているので起きにくい。 むしろ「揺れたら検出される」ほうが望ましい。

CI の軽さは、この検査が実際に回り続けるかを左右する。 5言語のビルドを揃えないと動かない検査は、 壊れたときに直されず放置されて形骸化する。 Python 3 だけで数秒で終わるなら、そうならない。

対応表を生成にしたことで、ドキュメントが実装より価値の高い成果物になった。 手書きの表は「書いた時点の実装のスナップショット」でしかないが、 生成した表は常に現在の実装そのものである。

影響

  • 新しい公開型を足したら、check_docs_sync.API_PAGES にも足さないと CI が落ちる。 これは意図した動作で、ドキュメントに載らない API を作らせないための仕掛けである
  • 静的解析が読めない書き方(複雑なメタプログラミング)を新たに導入する場合は、 抽出器も同時に直す必要がある。実装より抽出器のほうが先に壊れるので、気づける
  • 検証ツール(conformance)や内部ヘルパ(_ 始まりのファイル)は extract_api.EXCLUDED_FILES で対象外にしている