Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

lihong發表於2019-05-10

不完美的庫類

不完美的庫類(Incomplete Library Class)

當一個類庫已經不能滿足實際需要時,你就不得不改變這個庫(如果這個庫是隻讀的,那就沒轍了)。

問題原因

許多程式設計技術都建立在庫類的基礎上。庫類的作者沒用未卜先知的能力,不能因此責怪他們。麻煩的是庫往往構造的不夠好,而且往往不可能讓我們修改其中的類以滿足我們的需要。

解決方法

  • 如果你只想修改類庫的一兩個函式,可以運用  引入外加函式(Introduce Foreign Method)
  • 如果想要新增一大堆額外行為,就得運用  引入本地擴充套件(Introduce Local Extension)  。

收益

  • 減少程式碼重複(你不用一言不合就自己動手實現一個庫的全部功能,代價太高)

何時忽略

  • 如果擴充套件庫會帶來額外的工作量。

重構方法說明

引入外加函式(Introduce Foreign Method)

問題

你需要為提供服務的類增加一個函式,但你無法修改這個類。

class Report {
  //...
  void sendReport() {
    Date nextDay = new Date(previousEnd.getYear(),
      previousEnd.getMonth(), previousEnd.getDate() + 1);
    //...
  }
}

解決

在客戶類中建立一個函式,並一個第一個引數形式傳入一個服務類例項。

class Report {
  //...
  void sendReport() {
    Date newStart = nextDay(previousEnd);
    //...
  }
  private static Date nextDay(Date arg) {
    return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1);
  }
}

引入本地擴充套件(Introduce Local Extension)

問題

你需要為服務類提供一些額外函式,但你無法修改這個類。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

建立一個新類,使它包含這些額外函式,讓這個擴充套件品成為源類的子類或包裝類。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

中間人

中間人(Middle Man)

如果一個類的作用僅僅是指向另一個類的委託,為什麼要存在呢?

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

問題原因

物件的基本特徵之一就是封裝:對外部世界隱藏其內部細節。封裝往往伴隨委託。但是人們可能過度運用委託。比如,你也許會看到一個類的大部分有用工作都委託給了其他類,類本身成了一個空殼,除了委託之外不做任何事情。

解決方法

應該運用  移除中間人(Remove Middle Man) ,直接和真正負責的物件打交道。

收益

  • 減少笨重的程式碼。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

何時忽略

如果是以下情況,不要刪除已建立的中間人:

  • 新增中間人是為了避免類之間依賴關係。
  • 一些設計模式有目的地建立中間人(例如代理模式和裝飾器模式)。

重構方法說明

移除中間人(Remove Middle Man)

問題

某個類做了過多的簡單委託動作。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

讓客戶直接呼叫委託類。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

依戀情結

依戀情結(Feature Envy)

一個函式訪問其它物件的資料比訪問自己的資料更多。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

問題原因

這種氣味可能發生在欄位移動到資料類之後。如果是這種情況,你可能想將資料類的操作移動到這個類中。

解決方法

As a basic rule, if things change at the same time, you should keep them in the same place. Usually data and functions that use this data are changed together (although exceptions are possible).

有一個基本原則:同時會發生改變的事情應該被放在同一個地方。通常,資料和使用這些資料的函式是一起改變的。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

  • 如果一個函式明顯應該被移到另一個地方,可運用  搬移函式(Move Method)  。
  • 如果僅僅是函式的部分程式碼訪問另一個物件的資料,運用  提煉函式(Extract Method)  將這部分程式碼移到獨立的函式中。
  • 如果一個方法使用來自其他幾個類的函式,首先確定哪個類包含大多數使用的資料。然後,將該方法與其他資料一起放在此類中。或者,使用  提煉函式(Extract Method)  將方法拆分為幾個部分,可以放置在不同類中的不同位置。

收益

  • 減少重複程式碼(如果資料處理的程式碼放在中心位置)。
  • 更好的程式碼組織性(處理資料的函式靠近實際資料)。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

何時忽略

  • 有時,行為被有意地與儲存資料的類分開。這通常的優點是能夠動態地改變行為(見策略設計模式,訪問者設計模式和其他模式)。

重構方法說明

搬移函式(Move Method)

問題

你的程式中,有個函式與其所駐類之外的另一個類進行更多交流:呼叫後者,或被後者呼叫。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

在該函式最常引用的類中建立一個有著類似行為的新函式。將舊函式變成一個單純的委託函式,或是舊函式完全移除。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

提煉函式(Extract Method)

問題

你有一段程式碼可以組織在一起。

void printOwing() {
  printBanner();
  //print details
  System.out.println("name: " + name);
  System.out.println("amount: " + getOutstanding());
}

解決

移動這段程式碼到一個新的函式中,使用函式的呼叫來替代老程式碼。

void printOwing() {
  printBanner();
  printDetails(getOutstanding());
}
void printDetails(double outstanding) {
  System.out.println("name: " + name);
  System.out.println("amount: " + outstanding);
}

狎暱關係

狎暱關係(Inappropriate Intimacy)

一個類大量使用另一個類的內部欄位和方法。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

問題原因

類和類之間應該儘量少的感知彼此(減少耦合)。這樣的類更容易維護和複用。

解決方法

  • 最簡單的解決方法是運用  搬移函式(Move Method)  和  搬移欄位(Move Field)  來讓類之間斬斷羈絆。

 

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

  • 你也可以看看是否能運用  將雙向關聯改為單向關聯(Change Bidirectional Association to Unidirectional)  讓其中一個類對另一個說分手。

  • 如果這兩個類實在是情比金堅,難分難捨,可以運用  提煉類(Extract Class)  把二者共同點提煉到一個新類中,讓它們產生愛的結晶。或者,可以嘗試運用  隱藏委託關係(Hide Delegate)  讓另一個類來為它們牽線搭橋。

  • 繼承往往造成類之間過分緊密,因為子類對超類的瞭解總是超過後者的主觀願望,如果你覺得該讓這個子類自己闖蕩,請運用  以委託取代繼承(Replace Inheritance with Delegation)  來讓超類和子類分家。

收益

  • 提高程式碼組織性。
  • 提高程式碼複用性。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

重構方法說明

搬移函式(Move Method)

問題

你的程式中,有個函式與其所駐類之外的另一個類進行更多交流:呼叫後者,或被後者呼叫。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

在該函式最常引用的類中建立一個有著類似行為的新函式。將舊函式變成一個單純的委託函式,或是舊函式完全移除。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

搬移欄位(Move Field)

問題

在你的程式中,某個欄位被其所駐類之外的另一個類更多地用到。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

在目標類新建一個欄位,修改源欄位的所有使用者,令他們改用新欄位。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

將雙向關聯改為單向關聯(Change Bidirectional Association to Unidirectional)

問題

兩個類之間有雙向關聯,但其中一個類如今不再需要另一個類的特性。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

去除不必要的關聯。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

提煉類(Extract Class)

問題

某個類做了不止一件事。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

建立一個新類,將相關的欄位和函式從舊類搬移到新類。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

隱藏委託關係(Hide Delegate)

問題

客戶通過一個委託類來呼叫另一個物件。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

在服務類上建立客戶所需的所有函式,用以隱藏委託關係。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

以委託取代繼承(Replace Inheritance with Delegation)

問題

某個子類只使用超類介面中的一部分,或是根本不需要繼承而來的資料。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

在子類中新建一個欄位用以儲存超類;調整子類函式,令它改而委託超類;然後去掉兩者之間的繼承關係。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

過度耦合的訊息鏈

過度耦合的訊息鏈(Message Chains)

訊息鏈的形式類似於: obj.getA().getB().getC()

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

問題原因

如果你看到使用者向一個物件請求另一個物件,然後再向後者請求另一個物件,然後再請求另一個物件……這就是訊息鏈。實際程式碼中你看到的可能是一長串 getThis()或一長串臨時變數。採取這種方式,意味客戶程式碼將與查詢過程中的導航緊密耦合。一旦物件間關係發生任何變化,客戶端就不得不做出相應的修改。

解決方法

  • 可以運用  隱藏委託關係(Hide Delegate)  刪除一個訊息鏈。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

  • 有時更好的選擇是:先觀察訊息鏈最終得到的物件是用來幹什麼的。看看能否以  提煉函式(Extract Method) 把使用該物件的程式碼提煉到一個獨立函式中,再運用  搬移函式(Move Method)  把這個函式推入訊息鏈。

收益

  • 能減少鏈中類之間的依賴。
  • 能減少程式碼量。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

何時忽略

  • 過於侵略性的委託可能會使程式設計師難以理解功能是如何觸發的。

重構方法說明

隱藏委託關係(Hide Delegate)

問題

客戶通過一個委託類來呼叫另一個物件。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

 

解決

在服務類上建立客戶所需的所有函式,用以隱藏委託關係。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

提煉函式(Extract Method)

問題

你有一段程式碼可以組織在一起。

void printOwing() {
  printBanner();
  //print details
  System.out.println("name: " + name);
  System.out.println("amount: " + getOutstanding());
}

解決

移動這段程式碼到一個新的函式中,使用函式的呼叫來替代老程式碼。

void printOwing() {
  printBanner();
  printDetails(getOutstanding());
}
void printDetails(double outstanding) {
  System.out.println("name: " + name);
  System.out.println("amount: " + outstanding);
}

搬移函式(Move Method)

問題

你的程式中,有個函式與其所駐類之外的另一個類進行更多交流:呼叫後者,或被後者呼叫。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性

解決

在該函式最常引用的類中建立一個有著類似行為的新函式。將舊函式變成一個單純的委託函式,或是舊函式完全移除。

Java開發中存在這樣的程式碼,反而影響整體整潔和可讀性


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69917606/viewspace-2643915/,如需轉載,請註明出處,否則將追究法律責任。

相關文章