別太獨立:Swift 語言的依賴關係與架構解謎
kidneyweakx
December 20, 2025 (Updated: December 21, 2025)
在 Swift 的世界中,我們習慣了強大的 Xcode 和簡潔的語法,但隨著專案規模的成長,一個隱形的怪獸會開始在程式碼中徘徊:那就是失控的依賴關係
最近在開發多個 IOS App,專案小型的時候還不會有感覺,但目前專案規模已經成長到上百個檔案了,是時候該下手了,要不然開發效率往往毀於一旦。
開發效率的問題,主要出至於不知道是會想要修改這個檔案時,會影響到什麼 Swift 檔案,但是正在修改的時候又編譯不過,所以這時候我會希望有個靜態分析得好幫手。
# 那為何 Swift 的依賴關係如此「混亂」?
與 Java、Python 或 Rust 不同,Swift 的設計哲學讓同一個 Module 內的所有檔案預設共享命名空間。
- 消失的
import
在大多數語言中,如果你想使用另一個檔案的類別,你必須明確 import。但在 Swift 同一 Target 下,你不需要 import 任何東西就能存取同屬該 Target 的 internal 符號。這種便利是一把雙刃劍:
- 優點:開發快速,減少冗餘程式碼。
- 缺點:檔案間的依賴關係變成了一團亂麻(Spaghetti code)。你很難在不編譯的情況下,一眼看出改動
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 (語義解析)
為了擺脫 Regex 的局限性(例如誤判註解、字串),我計畫引入 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
目前已經 Publish 到 PyPI 上 https://pypi.org/project/swift-deps-map/
程式碼也開源:https://github.com/kidneyweakx/swift-deps-map
歡迎玩玩看,嘗試,提 Issue,或和我討論如何讓 Swift 依賴關係變更優雅
Related Articles
Saved by the Logs: How to Recover a Forgotten Keystore Password via IDE Build Logs.
最遙遠的距離,是密碼就在 IDE 裡但我看不見
Hexo 升級 V5 排除疑難雜症
因為剛好把電腦重灌,然後這個 blog 就躺在D槽等著我幫他換新的環境,然後他就被我快樂的升級了。 hexo 更新 v5.0 hexo 更新到 V5 的步驟相當容易 就可以自動更新了,但是版本大更新,往往都會附帶一些小問題,像他就給我了幾個warning 更新後 Error 解決方法 修改\ config.yml的部分成新版的,原始external\ link只有true的選項,更新後可決定是否開...
C# 用 VID 和 PID 自動連線 serialport
原本 C 的 serial port function官方範例,是類似這樣的 這種方法每次開啟都還要再去跟改port相當的麻煩,所以就找了別人針對windows寫的function,再返回靜態的 port string 給 ,效果相當好。 完整內容可參照下方連結😁 code來源
