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

Eclipse 自動重構實戰探索:以《重構》經典案例驗證 IDE 能力邊界

     編輯:Java 相關知識

Eclipse JDT 提供業界領先的自動重構引擎。本文以 Martin Fowler《重構》第一章「視頻店租賃系統」為例,實地測試 Eclipse 重構功能在代碼結構層面的支援程度與局限,探索「工具輔助重構」的最佳實踐。

實驗環境與準備

  • Eclipse 3.x + 中文語言包
  • 導入《重構》書中初始代碼 (Customer, Rental, Movie)
  • 重構菜單:Alt+Shift+T 打開重構彈出菜單

Eclipse 版本信息

重構步驟一:提煉方法 — 將計價邏輯分離

目標

從 Customer.statement() 中提煉 amountFor(Rental) 方法。

操作與 IDE 行為

  1. 選中 switch 語句塊 → 重構 → 提煉方法
  2. 首次嘗試失敗:Eclipse 將局部變量 each 和 thisAmount 均作為參數 (未識別 thisAmount 為輸出參數)
  3. 修正策略:將 double thisAmount = 0; 移至 switch 之前,再次提煉
  4. Eclipse 正確識別:each 為輸入參數,thisAmount 為返回值

首次提煉參數分析 修正後提煉預覽

生成代碼

private double amountFor(Rental each) {
    double thisAmount = 0;
    switch (each.getMovie().getPriceCode()) {
        case Movie.REGULAR:
            thisAmount += 2;
            if (each.getDaysRented() > 2) thisAmount += (each.getDaysRented() - 2) * 1.5;
            break;
        case Movie.NEW_RELEASE:
            thisAmount += each.getDaysRented() * 3;
            break;
        case Movie.CHILDRENS:
            thisAmount += 1.5;
            if (each.getDaysRented() > 3) thisAmount += (each.getDaysRented() - 3) * 1.5;
            break;
    }
    return thisAmount;
}

後續優化

  • 重命名參數 each → aRental、局部變量 thisAmount → result (重構 → 重命名,全局更新引用)

重構步驟二:移動方法 — 計價職責下沉到 Rental

目標

將 amountFor 移至 Rental 類,重命名為 getCharge()。

操作序列

  1. 選中方法 → 重構 → 移動 → 目標類選 Rental、新方法名 getCharge
  2. Eclipse 在 Customer 保留委託樁方法:private double amountFor(Rental aRental) { return aRental.getCharge(); }
  3. 編譯錯誤:委託方法 private 導致 Rental.getCharge() 被迫為 private
  4. 修正:重構 → 更改方法簽名 將 getCharge() 改為 public
  5. 重構 → 內聯 移除 Customer.amountFor() 委託,直接調用 each.getCharge()
  6. 重構 → 內聯臨時變量 消除 thisAmount 變量

移動方法對話框 更改方法簽名 內聯方法 內聯臨時變量預覽

重構步驟三:提煉並移動常客積分計算

目標

將積分邏輯提煉為 getFrequentRenterPoints() 並移至 Rental。

IDE 局限

Eclipse 無法自動生成 frequentRenterPoints += getFrequentRenterPoints(rental) 形式,因局部變量在賦值左側。需手動調整:

  1. 提煉方法 (手動修改返回 int)
  2. 移動至 Rental
  3. 更改簽名為 public
  4. 內聯 Customer 中委託方法

重構步驟四:消除臨時變量 (totalAmount, frequentRenterPoints)

模式

Replace Temp with Query:將累加變量提煉為查詢方法。

IDE 現狀

Eclipse 不支援此重構 (截至測試版本)。需手動實現:

// 手動重構後
private double totalCharge() {
    return rentals.stream().mapToDouble(Rental::getCharge).sum();
}

private int totalFrequentRenterPoints() {
    return rentals.stream().mapToInt(Rental::getFrequentRenterPoints).sum();
}

重構步驟五:以多態取代條件邏輯 (State/Strategy 模式)

目標

消除 Movie.getCharge() 中的 switch-case,引入價格策略繼承體系。

操作嘗試

  1. 移動 getCharge() 至 Movie:Eclipse 提示「找不到接收者」
  2. 內聯 getMovie() 獲取 _movie 字段直接訪問
  3. 再次移動成功,但參數變為 Rental 需手動改為 int daysRented
  4. 同理處理 getFrequentRenterPoints()

生成代碼結構:

// Movie.java
public double getCharge(int daysRented) {
    switch (getPriceCode()) { ... }
}

// Rental.java
public double getCharge() {
    return _movie.getCharge(_daysRented);
}

重構步驟六:引入繼承體系 — IDE 能力邊界

終點:Eclipse 無法自動執行「引入狀態模式/策略模式」這類架構級重構。

  • 需手動創建 Price 抽象類及 RegularPrice, NewReleasePrice, ChildrensPrice 子類
  • Movie 持有 Price 引用,委託計價邏輯
  • 工廠方法根據 priceCode 返回具體策略

這印證了 Fowler 的觀點:自動重構工具止於「代碼結構級操作」,架構設計決策仍屬人類智慧領域。

Eclipse 重構功能支援度總結

類別功能成熟度建議
代碼結構級重命名 (類/方法/字段/變量)⭐⭐⭐⭐⭐放心使用,全局引用自動更新
提煉方法/變量/常量⭐⭐⭐⭐參數分析偶有偏差,需預覽確認
移動方法/字段⭐⭐⭐⭐委託樁自動生成,需配合內聯清理
內聯方法/臨時變量⭐⭐⭐⭐安全可靠
簽名變更更改方法簽名 (參數/返回類型/拋出異常)⭐⭐⭐⭐強大,支持重排參數
架構設計級提煉接口/超類⭐⭐⭐基礎骨架生成,細節需手工
推拉方法 (Pull Up/Push Down)⭐⭐⭐適用於明確繼承層次調整
引入設計模式 (State/Strategy/Decorator...)⭐不支援,屬於設計決策

實戰心法

  1. 小步快跑:每次重構單一目標,立即運行測試
  2. 善用預覽:Preview 按鈕是安全網,必看再應用
  3. 撤銷無憂:Ctrl+Z 可回滾重構,鼓勵嘗試
  4. 人機協作:IDE 負責機械性代碼變換,人負責設計意圖與邊界決策

掌握 Eclipse 重構快捷鍵 (Alt+Shift+R/T/M/L),讓重構成為日常編碼流暢一部分,而非階段性大手術。

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