程式筆記
Swift

別太獨立:Swift 語言的依賴關係與架構解謎

LANG:
K

kidneyweakx

December 20, 2025 (Updated: December 21, 2025)

在 Swift 的世界中,我們習慣了強大的 Xcode 和簡潔的語法,但隨著專案規模的成長,一個隱形的怪獸會開始在程式碼中徘徊:那就是失控的依賴關係

最近在開發多個 IOS App,專案小型的時候還不會有感覺,但目前專案規模已經成長到上百個檔案了,是時候該下手了,要不然開發效率往往毀於一旦。

開發效率的問題,主要出至於不知道是會想要修改這個檔案時,會影響到什麼 Swift 檔案,但是正在修改的時候又編譯不過,所以這時候我會希望有個靜態分析得好幫手。

# 那為何 Swift 的依賴關係如此「混亂」?

與 Java、Python 或 Rust 不同,Swift 的設計哲學讓同一個 Module 內的所有檔案預設共享命名空間。

  1. 消失的 import

在大多數語言中,如果你想使用另一個檔案的類別,你必須明確 import。但在 Swift 同一 Target 下,你不需要 import 任何東西就能存取同屬該 Target 的 internal 符號。這種便利是一把雙刃劍:

  • 優點:開發快速,減少冗餘程式碼。
  • 缺點:檔案間的依賴關係變成了一團亂麻(Spaghetti code)。你很難在不編譯的情況下,一眼看出改動 User.swift 會影響到哪些其他的 Swift 檔案。
  1. 腳本化與 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 (語義解析)

為了擺脫 Regex 的局限性(例如誤判註解、字串),我計畫引入 SwiftSyntax。這依然是 Pre-compilation,但它能精確理解 Swift 的抽象語法樹 (AST),區分出哪些是真正類別實例化,哪些只是 Protocol 的宣告。

3.Indexing 整合 (極致嚴謹)

最後,我計畫加入對 IndexStoreDB 的選配支援。當專案編譯完成後,工具可以讀取 Xcode 產生的索引資料庫。

  • 100% 準確率:結合編譯器的真實數據。
  • 跨 Module 分析:不只看 Target 內部,還能看見與第三方 Library 的深層關係。

# 讓架構看得見才能讓代碼變漂亮

很多時候,程式碼的亂不是技術不好(說不定是 ai 技術不好)而是看不見的代碼依賴關係

我希望能讓 Swift 開發者以簡單的 Python 腳本運行,並且有個 cytoscape 之類的管理員可以提醒你這個檔案是不是住海邊(管太多)

Shell
uvx --from . swift-deps-map --root . --graph-format cytoscape --graph-output deps.cyto.json

目前已經 Publish 到 PyPI 上 https://pypi.org/project/swift-deps-map/ ↗

程式碼也開源:https://github.com/kidneyweakx/swift-deps-map ↗

歡迎玩玩看,嘗試,提 Issue,或和我討論如何讓 Swift 依賴關係變更優雅