0depsムーブメント:ローカル依存関係と不変の契約
ソフトウェア開発者は、しばしば数百もの外部ライブラリをインストールします。現代のフレームワークは、数千もの間接的な依存関係(transitive dependencies)に依存しています。これは、あなたのアプリケーションが、見知らぬ誰かが書いたコードを実行していることを意味します。
これにより、ソフトウェア・サプライチェーンのリスクが生じます。
すべての依存関係は、攻撃対象領域(attack surface)を拡大させます。具体的には、以下のようなリスクがあります:
- セキュリティ上の欠陥の混入。
- サプライチェーン攻撃の標的になる。
- メンテナーによって放棄される。
- パブリックAPIが変更される。
- 後方互換性が失われる。
0depsムーブメントは、シンプルな問いを投げかけます。「もし、アプリケーションが自分自身で管理しているコードのみに依存していたらどうなるでしょうか?」
0depsモデルでは、必要な依存関係をプロジェクトのリポジトリに直接組み込みます。ビルド中にそれらを動的にダウンロードすることはしません。アプリケーションの実行に必要なものはすべて、最初からリポジトリ内に保持されます。
このアプローチには、以下のメリットがあります:
- 再現可能なビルド。
- 外部レジストリへの依存の低減。
- セキュリティ監査の一元化。
- 高い予測可能性。
核となる原則は、コードを静的なままにしておくことではありません。バグを修正し、セキュリティを向上させるためには、実装やアルゴリズムは進化しなければなりません。安定して維持されるのは、「パブリックな契約(public contract)」です。
各ライブラリは、慎重に設計されたインターフェースを公開します。例として、以下のようなものがあります:
- authenticate()
- createSession()
- verifyPasskey()
これらの関数は「契約」を定義します。この契約は決して変わりません。その背後にあるコードを書き換えたり、ライブラリ自体を完全に置き換えたりすることも可能です。アプリケーションの他の部分は、その変更に気づくことさえありません。
脆弱性が発見されたとき、通常は2つの問題に直面します:
- 欠陥の修正。
- アップデートによってアプリが壊れないかの確認。
0depsアーキテクチャでは、2番目の問題は解消されます。パブリックAPIはそのままに、内部の実装を更新するだけだからです。アプリケーションはコードを変更することなく、動作し続けます。
内部アダプターを使用して、外部との統合を分離します: Application -> Public Interface -> Adapter -> Implementation
もし明日、あるライブラリが消滅したとしても、変更が必要なのはアダプターだけです。アプリの他の部分が壊れることはありません。
0depsはソフトウェアを完璧にするものではありません。しかし、サプライチェーンのリスクを軽減します。悪意のあるパッケージ、レジストリの侵害、依存関係の混乱(dependency confusion)といった問題を防止します。
プロジェクトは数十年にわたって存続します。ライブラリやフレームワークは変化していきます。0depsを採用していれば、エコシステムがどのように進化しようとも、アプリケーションは同じ安定した契約を使い続けることができます。
