首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

演化架構與緊急設計:重構識別隱性設計——解耦基礎設施與消除結構性複製

     編輯:Java 相關知識

重構是「在不改變外部行為前提下改善內部結構」的嚴格技術。擁有高覆蓋率單元測試是安全重構的前提;若無測試,先為核心/易錯區域補充功能測試作安全網。本文聚焦:如何透過重構發現代碼庫中隱藏的設計缺陷——基礎設施耦合與兩類複製。

基礎設施耦合:框架的甜蜜陷阱

框架提供 Helper 類誘導繼承(如 Struts ActionForm),換取自動表單填充、驗證等便利。代價:領域類強綁定框架,無法在非 Web 環境復用,繼承層次被佔用。

反模式:

public class ScheduleItem extends ActionForm { ... } // 領域類繼承框架類

改進:組合 + 介面隔離

public interface ScheduleItem { ... }           // 語義契約
public class ScheduleItemImpl implements ScheduleItem { ... } // 純領域邏輯
public class ScheduleItemForm implements ScheduleItem {       // 框架適配器
    private ScheduleItem delegate;                // 組合持有領域對象
    // 委派實作介面方法,框架只見此類
}

領域類零依賴框架,自由部署於 Swing、Service Layer 等任意環境。原則:**框架依賴你的代碼,你的代碼不依賴框架。**

違反 DRY 原則的兩種複製

1. 複製貼上:工具可檢測的顯性複製

CPD (Copy/Paste Detector) 掃描 Struts 2 代碼庫發現大量跨文件複製,多集中於 Portlet 支持模組(PortletApplicationMap vs ApplicationMap),暗示擴展設計缺失——本應用繼承/組合消除重複。

另一典型案例:ApplicationMap.java 與 Sorter.java 共享 27 行匿名 Map.Entry 實作,唯一差異在 context.getAttribute() vs context.getInitParameter()。前兆代碼結構完全相同,參數化即可消除。

複製掩蓋了「將條目加入屬性集」這一慣用模式,重構提煉共用方法可公開此設計意圖。

2. 結構性複製:工具難檢測的隱性殺手

定義:相同的空白,不同的值。代碼骨架完全一致(含縮排),僅字面量不同。典型例:Java Comparator 實作:

public class EmployeeNameComparator implements Comparator<Employee> {
    public int compare(Employee e1, Employee e2) { return e1.getName().compareTo(e2.getName()); }
}
public class EmployeeSalaryComparator implements Comparator<Employee> {
    public int compare(Employee e1, Employee e2) { return e1.getSalary() - e2.getSalary(); }
}

疊圖可見結構完全重合。屬性增多時,樣板代碼爆炸。

反射消除結構性複製:EmployeeSorter 範例

public class EmployeeSorter {
    public void sort(List<DryEmployee> list, String criteria) {
        Collections.sort(list, getComparatorFor(criteria));
    }
    private Method getSelectionCriteriaMethod(String field) { ... } // 反射取 getter
    public Comparator<DryEmployee> getComparatorFor(final String field) {
        return new Comparator<DryEmployee>() {
            public int compare(DryEmployee o1, DryEmployee o2) {
                Method m = getSelectionCriteriaMethod(field);
                Object v1 = m.invoke(o1), v2 = m.invoke(o2);
                return ((Comparable)v1).compareTo(v2);
            }
        };
    }
}

新增屬性零代碼修改,動態生成 Comparator。權衡:反射版圈複雜度 8,單一 Comparator 為 1。**當屬性數 ≥ 9 時,反射版總複雜度更低**,且消除結構性複製風險。

圈複雜度指標指導決策

JavaNCSS 測量提供客觀門檻:

  • 單一 Comparator 類:CC = 1
  • EmployeeSorter 總 CC = 8
  • 屬性數達 9 時,切換反射更划算

團隊可依專案屬性設定臨界值,建立「重構觸發機制」。

小結

重構不僅整理代碼,更是發現隱性設計的探針:

  1. 解耦基礎設施 → 釋放領域模型復用潛能
  2. 消除複製貼上 → 顯性化慣用模式
  3. 消除結構性複製 → 以元編程/反射提煉通用基礎設施

下篇將引入指標驅動重構,鎖定代碼庫中最需要重構、最可能藏匿設計寶藏的熱點區域。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved