Effective Java 第三版——51. 仔細設計方法簽名
Tips
書中的原始碼地址: https://github.com/jbloch/effective-java-3e-source-code
注意,書中的有些程式碼裡方法是基於Java 9 API中的,所以JDK 最好下載 JDK 9以上的版本。
51. 仔細設計方法簽名
這一條目是API設計提示的大雜燴,但它們本身並足以設立一個單獨的條目。綜合起來,這些設計提示將幫助你更容易地學習和使用API,並且更不容易出錯。
仔細選擇方法名名稱。名稱應始終遵守標準命名約定(條目68)。你的主要目標應該是選擇與同一包中的其他名稱一致且易於理解的名稱。其次是應該是選擇與更廣泛的共識一致的名稱。避免使用較長的方法名。如果有疑問,可以從Java類庫API中尋求指導。儘管類庫中也存在許多不一致之處(考慮到這些類庫的規模和範圍,這是不可避免的),也提供了相當客觀的認可和共識。
不要過分地提供方便的方法。每種方法都應該“盡其所能”。太多的方法使得類難以學習、使用、文件化、測試和維護。對於介面更是如此,在介面中,太多的方法使實現者和使用者的工作變得複雜。對於類或介面支援的每個操作,提供一個功能完整的方法。只有在經常使用時,才考慮提供“快捷方式(shortcut)”。 如果有疑問,請將其刪除 。
避免過長的引數列表。目標是四個或更少的引數。大多數程式設計師不能記住更長的引數列表。如果你的許多方法超過了這個限制,如果未經常引用其文件的情況下,那麼你的API將無法使用。現代IDE編輯器會提供幫助,但是使用簡短的引數列表仍然會更好。 相同型別引數的長序列尤其有害 。使用者不僅不能記住引數的順序,而且當他們意外地弄錯引數順序時,他們的程式仍然會編譯和執行。只是不會按照作者的意圖去執行。
有三種技術可以縮短過長的引數列表。 一種方法是將方法分解為多個方法,每個方法只需要引數的一個子集。 如果不小心,這可能會導致太多方法,但它也可以通過增加正交性(orthogonality)來減少方法個數。 例如,考慮java.util.List介面。 它沒有提供查詢子列表中元素的第一個或最後一個索引的方法,這兩個索引都需要三個引數。 相反,它提供了 subList
方法,該方法接受兩個引數並返回子列表的檢視。 此方法可以 與indexOf
或 lastIndexOf
方法結合使用,這兩個方法都有一個引數,以生成所需的功能。 此外, subList
方法可以與在List例項上操作的任何方法組合,以對子列表執行任意計算。 得到的API具有非常高的功率重量( power-to-weight)比。
縮短過長引數列表的第二種技術是建立輔助類來儲存引數組。這些輔助類通常是靜態成員類(條目24)。如果看到一個頻繁出現的引數序列表示某個不同的實體,建議使用這種技術。例如,假設正在編寫一個表示紙牌遊戲的類,並且發現不斷地傳遞一個由兩個引數組成的序列,這些引數表示紙牌的點數和花色。如果新增一個輔助類來表示卡片,並用輔助類的單個引數替換引數序列的每次出現,那麼API和類的內部結構可能會受益。
結合前兩個方面的第三種技術是,從物件構造到方法呼叫採用Builder模式(條目2)。如果你有一個方法有許多引數,特別是其中一些是可選的,那麼可以定義一個物件來表示所有的引數,並允許客戶端在這個物件上進行多個“setter”呼叫,每次設定一個引數或較小相關的組。設定好所需的引數後,客戶端呼叫物件的“execute”方法,該方法對引數進行最後的有效性檢查,並執行實際的計算。
對於引數型別,優先選擇介面而不是類(條目64)。如果有一個合適的介面來定義一個引數,那麼使用它來支援一個實現該介面的類。例如,沒有理由在編寫方法時使用HashMap作為輸入引數,相反,而是使用Map作為引數,這允許傳入HashMap、TreeMap、ConcurrentHashMap、TreeMap的子Map(submap)或任何尚未編寫的Map實現。通過使用的類而不是介面,就把客戶端限制在特定的實現中,如果輸入資料碰巧以其他形式存在,則強制執行不必要的、代價高昂的複製操作。
與布林型引數相比,優先使用兩個元素列舉型別,除非布林型引數的含義在方法名中是明確的。列舉型別使程式碼更容易閱讀和編寫。此外,它們還可以方便地在以後新增更多選項。例如,你可能有一個 Thermometer
型別的靜態工廠方法,這個方法的簽名是以下這個列舉:
public enum TemperatureScale { FAHRENHEIT, CELSIUS }
Thermometer.newInstance(TemperatureScale.CELSIUS)
不僅比 Thermometer.newInstance(true)
更有意義,而且可以在將來的版本中將 KELVIN
新增到 TemperatureScale
中,而無需向 Thermometer
新增新的靜態工廠。 此外,還可以將溫度刻度(temperature-scale)依賴關係重構為列舉常量的方法(條目34)。 例如,每個刻度常量可以有一個採用double值並將其轉換為 Celsius
的方法。