簡體   English   中英

Java方法命名約定:太多的getter

[英]Java method naming conventions: Too many getters

為什么Java方法名稱如此廣泛地使用“get”前綴? 至少在我的Java程序中,有很多方法的名稱以“get”開頭。 get方法的百分比非常高。 由於通貨膨脹,我開始覺得“獲得”這個詞正在失去意義。 這是我的代碼中的噪音。

我注意到在函數/聲明性編程和PL / SQL中使用了不同的命名約定。 方法名稱只是說明方法返回的內容。 取而代之的account.getAmount()Time.getIsoFormattedDateString(Date date) ,他們將使用account.amount()Time.isoFormattedDateString(Date date) 這對我來說非常有意義,因為函數的名稱描述了評估方法的結果(假設沒有副作用,反正不應該這樣)。 “get”前綴似乎是多余的。

我剛剛開始閱讀“清潔代碼”一書。 它說方法應該只做一件事,那件事通常應該是以下之一:

  1. 通知某個事件的對象,通常將事件作為參數傳遞。
  2. 詢問有關某個對象的問題,通常使用方法名稱形成自然語言語句,將對象作為參數傳遞並返回布爾值。
  3. 獲取一些東西,可能傳遞一些查找鍵或一些要轉換為參數的對象,並始終返回所需的對象/值。

我的問題是關於第三類。 對於這種方法,是否存在除“get”之外的命名約定? 選擇方法名稱/前綴時使用什么標准?

這是一個例子:

我有一個類有兩個方法getDates()getSpecialDates() getDates()只返回私有變量的值(對日期集合的引用)。 據我所知,這是一個標准的吸氣劑。 getSpecialDates()是不同的; 它調用getDates() ,從另一個類中獲取過濾器,應用過濾器並返回實際上是getDates()的子集。

getSpecialDates()方法可以命名為computeSpecialDates()findSpecialDates()selectSpecialDates()elicitSpecialDates()等等。 或者我可以簡單地將其命名為specialDates() 然后,為了保持一致性,我可以將getDates()重命名為dates()

為什么要分開應該以“get”為前綴的方法和不應該使用的方法,以及為什么要為“get”找到替換詞呢?

我個人不會在任何可能的情況下使用 getter和setter(意思是:我不使用任何需要它的框架,例如Struts)。

我更喜歡在可能的情況下編寫不可變對象( 公共最終字段),否則我只使用公共字段:更少的鍋爐板代碼,更高的生產率,更少的副作用。 get / set的最初理由是封裝(盡可能讓你的對象變得害羞),但事實上,我並不經常需要它。

Effective Java中 ,Joshua Bloch提出了這個引人注目的建議:

類應該是不可變的,除非有一個很好的理由使它們變得可變......如果一個類不能變成不可變的,盡可能地限制它的可變性。

在同一本書中,他也說(但我不想在這里復制整本書):

JavaBeans模式有嚴重的缺點。

我完全贊同這一點,因為JavaBeans最初是針對一個非常狹窄的問題領域:在IDE中操縱圖形組件。 使用一種旨在解決另一個問題的解決方案是一種不好的做法。

它來自JavaBeans命名約定

有這么多get *方法的部分原因是Java不支持“屬性”la .net / COM,Java bean等使用函數getX和setX來復制名為X的屬性的功能。一些IDE用於Java利用這一點來允許設置和檢索屬性。

getter和setter方法通常用Java編寫的原因之一是因為使用了JavaBeans約定。

但是,標准Java API本身並不一致。 例如,類String有一個length()方法,接口Collection定義了一個size()方法,而不是getLength()getSize()

Java不支持統一訪問原則 ,因此您必須編寫getter和setter方法來訪問屬性。

一個原因是它是Java Bean Spec的重要組成部分。

方法名稱如getSpecialDates()computeSpecialDates()findSpecialDates()selectSpecialDates()elicitSpecialDates() ,對我來說是命令,因為在名稱中使用了動詞(動作)。 每次調用它們時,命令都會產生副作用。 而諸如date()dates()specialDates() [nouns]之類的方法名稱是返回有用值而沒有副作用的方法。 多次調用該方法每次都返回相同的值,除非調用其副作用是更改狀態的命令。

需要Java開發人員使用常見的get / set約定的原因之一是許多框架依賴於它來創建bean和設置字段。 例如,如果您為Spring bean配置了一些屬性,如<property name="foo" value="bar" />並且類中沒有名為setFoo()方法,則會在bean創建時出錯。

正如許多人已經說過的那樣,get ..()和set()...是Java Beans Convention的一部分。 這對於與Java Spec的其他部分進行互操作是必要的。 例如,在JSP中,您可以通過指定不帶get前綴的屬性名來從Java訪問成員。

鑒於豆: -

public class Foo {
  public int getX() { return 1; }
}

我們可以執行以下JSP來獲取X: -

<jsp:useBean id="aFoo" class="Foo" />
<c:out value="${aFoo.X}" />

對於這種方法,是否存在除“get”之外的命名約定?

是的,你可以使用is而不是get for boolean屬性。

什么“得到”當我們生活在一個日子和時代時,任何值得擁有的IDE都會為你的私有變量生成getter和setter,如果你不想閱讀它們,你可以將它們折疊起來?

你真正的問題應該是關於設計:為什么你的對象有這么多屬性? 如果你的物品只有吸氣劑和制定者,你是否患有“貧血領域模型”?

C# {get, set}表示法稍微好一些,因為它減少了代碼行,但你仍然需要為每個變量輸入那個討厭的“get”。

正如其他人所提到的,它適用於Java Bean。 但是,如果您使用的是Java,請僅命名方法getXXX(),如果它只返回一個值而不執行任何其他操作。 就像你暗示的那樣,如果它正在做其他事情,請將它命名為不同的東西,例如computeXXX()。

我有時會發現50行代碼的getXXX()方法 - 如果是這樣的話,你做錯了。

前提1:方法應該只做一件事。 前提2:一個getter方法 - 它是否使用get前綴 - 應該沒有副作用。 鑒於我提出的這兩個前提:一個方法,其作用是獲取某些東西,並且以相對簡單的廉價方式這樣做,不需要在其名稱中使用動詞。

吸氣劑的存在理由並不是要做點什么,而是要評價一些東西。 我們對該方法的作用不感興趣。 由於它沒有副作用,因此該方法中的任何計算都不會引起任何興趣。 我們只對該方法返回的內容感興趣。 方法名稱應以名詞的形式反映出來。 僅由名詞組成的方法名稱應始終為“getters”。

前綴“get”中的信息可以從缺少動詞推斷出來。 這比使用get前綴更簡單,更直觀。

可以假設其名稱僅由名詞組成並具有返回值的方法沒有副作用並且相對便宜。 名稱包含動詞且沒有返回值的方法存在副作用。 可以假設其名稱包含動詞並具有返回值的方法相對昂貴並且可能具有副作用。

似乎每個人都在寫“獲得”的原因僅僅是源於JavaBeans模式的教條傳統。 當您真正計划使用需要它的工具/框架時,請保留get前綴!

就個人而言,我沉迷於get 它只是人類的語言。 當你想要的東西,你想要get的東西。 get前綴沒有錯。 關於命名約定,我可以想到數據庫查詢的Select前綴 - 例如SelectUsers

由於通貨膨脹,我開始覺得“獲得”這個詞正在失去意義。 這是我的代碼中的噪音。

我略微不同意這個結論。 我不會說它失去了它的含義,我會說,因為廣泛使用帶有get前綴的方法將完成你期望它們做的事情。

對於以下示例:

Time.isoFormattedDateString(Date date)

這是否根據輸入參數設置格式類型,以便所有后續調用都使用此格式?

我知道有人會得出這樣的結論,因為它是一個靜態方法,但是如果在一個實例上調用這個方法,你會確定嗎? 可能,但get的使用消除了所有歧義:

getIsoFormattedDateString(Date date)

在我看來,屬性是一個更優雅的解決方案,而不是完全放棄。

歷史片段:如果你看一些最早的Java 1.0 API(JavaBeans之前的版本),你會發現它們沒有'get'前綴。 例如,java.awt.Container#minimumSize()被#getMinimumSize()替換為棄用。

我認為這是“給你的變量和函數有意義的名字”理想的一個子集。

許多人都注意到,“get”在Java Bean中具有特定的含義。 因此,我認為它應該僅限於用於檢索內部變量的值,可能帶有副作用。 我認為“獲取”涉及次要計算是可以接受的,例如進行數據類型轉換或從嵌入類中提取值或重新解釋其他值,例如“public int getRightMargin(){return width-margin.left;}”。 任何副作用都應限於獲得該值的真正“副作用”的東西,比如設置一個表示它已被檢索的標志。

但如果有嚴肅的計算,我認為它不應該被稱為“獲取”。 也許“計算”或其他什么。

如果我們在命名函數中使用一致的術語會很好,例如,如果我們都同意“讀取”意味着主要活動是從數據庫中檢索某些東西,而“計算”意味着要進行計算或某些操作。 但這可能是不現實的:也許有太多的細微差別。

一種選擇是為返回原始值或不可變值的方法保留get前綴,但刪除返回可用於修改原始收件人的引用的方法的前綴。

例如,在java.util.Mapsize()可以被稱為getSize()但是keySet() 不會被稱為getKeySet()

我只使用get和set來設置只獲取或設置屬性而不是mutch的方法。

好吧,雖然JavaBeans規范要求你聲明getter和setter,但我通常不會聲明它們,除非它是絕對必要的(如許多MVC框架的情況)。 我在Java職業生涯中做了很多工作,我傾向於將變量聲明為公共變量(是的,它聽起來有點不OOPy)。 但我喜歡它,因為它看起來簡潔,“我知道我在做什么。 它的唯一優勢是線路數量減少。

Java Bean對其命名約定非常敏感,比如假設您聲明了一個變量名Name,並將相應的setter設置為setName()。 但它會產生錯誤,因為setName必須對應於'name'而不是Name。 另一個例子是boolean isReadey; 使用getter isReady()。 再次出錯,因為它尋找布爾准備好了。 因此,在代碼之前,您必須熟悉此命名約定。 但我個人更喜歡這種慣例,因為它使程序員的工作變得簡單,並且在花費很少時間之后似乎有點合乎邏輯。

“get”前綴仍然很重要,因為:

  • 方法應該聲明一個動作,因此它必須在其名稱中包含一個動詞

  • get表明變量的狀態不會改變

  • 您可以輕松地將方法account()與此表達式中的變量account區分開來:

    newAccount = currentAccount + account() ---這個account()什么作用?


您在代碼中看到太多getter的原因應該讓您擔心!

  • 你可以將你的班級分成較小的班級或
  • 只是更好地隱藏你的代碼,因為你不必透露你的班級實習生,甚至應該盡可能地隱藏它們!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM