Skip to content

Latest commit

 

History

History
79 lines (55 loc) · 4.96 KB

0009-static-api-extraction.md

File metadata and controls

79 lines (55 loc) · 4.96 KB

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で対象外にしている