QUEST LOG · December 20, 2025· UPDATED October 29, 2026
独立しすぎ注意:Swift の依存関係とアーキテクチャの謎を解く
Swift の世界では、強力な Xcode と簡潔な文法にすっかり慣れています。でもプロジェクトが大きくなるにつれ、見えない怪物がコードの中をうろつき始めます。それが制御不能になった依存関係です
最近、iOS アプリを何本か開発しています。プロジェクトが小さいうちは気にならなかったのですが、今では規模が数百ファイルにまで膨らんできました。そろそろ手を打たないと、開発効率が台無しになってしまいます。
開発効率の問題は主に、あるファイルを修正したいときに、どの Swift ファイルに影響が出るのかがわからないこと、しかも修正している最中はビルドが通らないことから来ています。そんなときこそ、頼れる静的解析の相棒がほしくなるわけです。
# なぜ Swift の依存関係はこんなに「ぐちゃぐちゃ」なのか?
Java や Python、Rust と違って、Swift の設計思想では、同じ Module 内のすべてのファイルがデフォルトで名前空間を共有します。
- 消えた
import
多くの言語では、別のファイルのクラスを使いたければ明示的に import する必要があります。ところが Swift では、同じ Target 内なら何も import しなくても、その Target に属する internal シンボルにアクセスできます。この便利さは諸刃の剣です:
- メリット:開発が速く、冗長なコードが減る。
- デメリット:ファイル間の依存関係がぐちゃぐちゃに絡まる(スパゲッティコード)。コンパイルせずに、
User.swiftを変更したらほかのどの Swift ファイルに影響するのかを、ひと目で見抜くのは難しい。
- スクリプト化と
xcrunのブラックボックス
Xcode のビルドプロセスは、高度にカプセル化されたブラックボックスです。xcrun 経由で swiftc を呼ぶと、コンパイラはディレクトリ全体をスキャンしてシンボルテーブルを構築します。最終的なプロダクトにとってはありがたいのですが、開発者が「アーキテクチャのレビュー」をしたいときには極めて不親切です:
- ビルド時間の激増:依存関係が曖昧なので、インクリメンタルビルド(Incremental Build)がしょっちゅう効かなくなる。
- スクリプト化が難しい:循環依存をチェックするスクリプトを書こうとしても、Swift には「コンパイルせずに関係だけを見る」ための軽量なツールがそもそも用意されていない。
# 構造を浮かび上がらせる
最近 `swift-deps-map` というツールを開発しました。この記事では、なぜこれが大事だと思っているのか、そして「軽量な可視化」から始めて、「厳密な静的解析」へ向かう将来像をどう描いているのかをお話しします。
なぜこのツールを作ったのか? 設計の出発点
他人のものが使えるなら使えばいいのに、なぜ車輪の再発明をするのか。今いちばん正確な依存関係解析ツール(IndexStoreDB https://github.com/swiftlang/indexstore-db をベースにしたものなど)には、共通の前提があります。プロジェクトがビルドに成功していること。でも実際の開発では、依存関係グラフをいちばん見たいのは、コードが「まだ動かない」ときや「構造を組み替えている最中」だったりします。私が埋めたいのは、そのビルド前の空白期間です。
依存関係グラフをいちばん見たいのは、コードが「まだ動かない」ときや「構造を組み替えている最中」だったりします。私が埋めたいのは、そのビルド前の空白期間です。
# 現在の強み:ビルド前の可視化(Pre-compilation)
swift-deps-map の今のウリは、「速い」と「直感的」です:
- ゼロセットアップでスキャン:Xcode 環境やビルド成果物に依存せず、ソースコードさえあればスキャンできる。
- 視覚的なフィードバック:Mermaid と Cytoscape(JSON)へのエクスポートに対応。あってはならない矢印がひと目で見えると、リファクタリングのモチベーションが一気に上がる。
- 軽量な門番:Pre-commit Hook や CI の初期段階に置くのに向いていて、高コストな Build が始まる前に、まず一次「健康診断」を行える。
# 厳密さへ:ツールの今後
今の swift-deps-map は高速な静的スキャンに頼っていますが、いくつか機能を入れて、ツールの汎用性を高めたいと考えています
1.Lint ルールの導入(Strict Mode)
今のツールは事実を「見せる」だけですが、今後は Lint ルール を追加する予定です。
- 循環依存の警告(Cycle Detection):A が B に依存し、B がまた A に依存していたら、ターミナルに赤い警告をそのままぶちまける。
- 深さの制限:あるファイルの依存の深さが設定値を超えたら通知する。
2.SwiftSyntax の導入(意味解析)
正規表現の限界(コメントや文字列の誤検出など)から抜け出すため、SwiftSyntax を導入する予定です。これも依然として Pre-compilation ですが、Swift の抽象構文木(AST)を正確に理解でき、本当のクラスのインスタンス化なのか、単なる Protocol の宣言なのかを区別できます。
3.Indexing との統合(究極の厳密さ)
最後に、IndexStoreDB へのオプション対応を加える予定です。プロジェクトのビルドが終わったあと、Xcode が生成したインデックスデータベースをツールから読み込めるようにします。
- 100% の精度:コンパイラの実データと組み合わせる。
- Module をまたいだ解析:Target の内部だけでなく、サードパーティ Library との深い関係まで見える。
# アーキテクチャが見えてこそ、コードはきれいになる
コードが散らかるのは、たいてい技術力が低いからではなく(もしかすると AI の技術力が低いのかもしれませんが)、目に見えないコードの依存関係のせいです
Swift 開発者がシンプルな Python スクリプトとして実行できて、cytoscape みたいな管理人が「このファイル、あちこち口出ししすぎじゃない?」と教えてくれる、そんなツールにしたいと思っています
uvx --from . swift-deps-map --root . --graph-format cytoscape --graph-output deps.cyto.json
すでに PyPI に Publish 済みです https://pypi.org/project/swift-deps-map/
コードもオープンソースです:https://github.com/kidneyweakx/swift-deps-map
ぜひ触ってみて、試して、Issue を立てたり、Swift の依存関係をもっとエレガントにする方法を一緒に議論したりしましょう
公開中のアプリ
iOS・Android で無料。


