過去一年專欄介紹了代碼度量、測試框架(TestNG、FIT、Selenium)及擴展工具(XMLUnit、StrutsTestCase、Cargo、DbUnit)。這些手段側重「事後檢測」——代碼寫完才能測試和度量,受限於初始設計。優秀設計的關鍵在於可維護性:粗劣設計的系統易寫難維,修改常牽一髮動全身,重構極其痛苦。測試雖提供安全網,但進展緩慢。與其事後重構,不如一開始就寫好代碼。本文介紹主動技巧——依賴倒置原則(DIP),它是編寫可維護、可測試高質量代碼的必要條件:對象應依賴抽象,而非實現。
DIP 與依賴注入(DI/IOC)無直接關係。DI 指運行時由 Spring 等框架鏈接依賴。兩者互補,同樣追求「面向抽象而非實現」。
耦合指組件間相互關係。鬆散耦合系統組件依賴接口/抽象類;緊密耦合系統依賴具體類。圖 1 展示 GUI 直接耦合數據庫:

GUI 依賴具體實現導致:數據庫未啟動 GUI 無法運行;測試極難隔離——需活數據庫測 GUI,需運行 GUI 測數據邏輯。清單 1-2 代碼中,按鈕直接調用硬編碼 SQL/JDBC 訪問數據庫,任何數據庫變更波及 GUI,測試與維護噩夢。
DAO(Data Access Object)模式用接口隔離底層數據訪問。圖 2 引入接口與工廠解耦:

WidgetDAO 定義 getOrderStatus()(清單 3)getOrderStatus() 僅調用 dao.getOrderStatus()(清單 4)WidgetDAOFactory.manufacture() 返回實現(清單 5-6)WidgetDAOImpl 操作數據庫(清單 7)MockWidgetDAOImpl 用於測試隔離(清單 8)GUI 完全不知曉具體實現,僅引用接口類型。可隨時替換實現(數據庫/文件系統/內存),互不影響。測試時注入 Mock 即可隔離 GUI 與數據庫,雙向受益。
您寫的代碼可能存活數十年(如 COBOL)。可維護代碼易於演進,DIP 是可靠路徑。面向抽象而非實現,為代碼庫注入靈活性,不僅便於當下修改,更造福未來的維護者。