空调吸气和排气_吸气剂和二传手被认为有害
空調吸氣和排氣
Java程序員習慣性地用“ getters”和“ setters”來修飾類,這種做法根深蒂固,以至于幾乎沒有人質疑為什么這樣做或是否應該這樣做。 最近,我認為最好不要這樣做,并且我開始在編寫的Java代碼中避免使用它。 在這篇博客文章中,我將解釋原因。 但是首先,要進行快速的歷史課程。
JavaBeans
Getters和setters起源于JavaBeans規范 ,該規范最初于1996年末發布,并于1997年8月更新為1.01版。最初的想法是使對象的創建成為可能,這些對象可以用作構建模塊來組成應用程序。 這個想法過去了,“用戶”可以使用某種構建器工具連接在一起,并自定義一組JavaBeans組件以一起充當應用程序。 例如,AWT應用程序中的按鈕將是Bean(AWT是Java UI庫Swing的前身)。 另外,一些JavaBeans更像是常規應用程序,然后可以將它們組合成復合文檔,因此電子表格bean可以嵌入到網頁內。
當遵循以下約定時,對象就是JavaBean:
該規范描述了許多不同的用例,但是從上面的描述可以清楚地看出,JavaBeans被視為具有行為的對象,而不僅僅是數據包。 這個想法已經淡出人們的視線,但是盡管JavaBean被很大程度上遺忘了,但是Java中的getter和setter方法的慣用法仍然存在。
隱喻是錯誤的
“獲取”和“設置”的概念似乎很自然,但這是否正確? JavaBeans約定使用“ get”來表示查詢,這是一個沒有副作用的操作,但在現實世界中,getting是一個會改變狀態的動作:如果我將一本書下架,則該書不再上架。 您可能會反對,這只是純粹的學問,但我認為這種誤解會鼓勵我們錯誤地思考我們編寫對象以進行交互的方式。 例如,如果我們有一個Thermometer類,那么大多數Java開發人員都會編寫代碼來讀取溫度,如下所示:
Temperature t = thermometer.getTemperature();確實,“獲取”溫度是溫度計的工作嗎? 沒有! 溫度計的作用是測量溫度。 我為什么要為此努力呢? 這是因為“獲取”是必要的陳述:它是溫度計的一項操作說明。 但是我們不想指示溫度計在這里做任何事情; 它已經在做它的工作(測量溫度),我們只想知道它的當前讀數是多少。 閱讀是由我們完成的。 因此,以這種方式編寫時,代碼更加自然:
Temperature t = thermometer.reading();我認為這更好地將責任歸于責任。 但是請務必考慮是否需要訪問器,因為…
對象不是數據結構
用getter和setter編寫類的習慣對我們的編碼方式有微妙的影響。 它自然化了我們應該進入對象以獲取所需數據,對其進行處理,然后使用結果更新對象的想法,而不是讓對象自己執行處理。 換句話說,它鼓勵我們將對象視為數據包。 我們通過getter提取數據,并通過setter更新它們。 同時,對數據進行操作的代碼位于其他位置。
如果我們的編碼習慣使我們傾向于將對象視為純數據結構,那么ORM框架會積極地實施它。 更糟糕的是,如果您使用的是Spring框架–如果您是Java開發人員,那么很有可能–默認情況下,它會將所有bean創建為單例。 (令人困惑的是,Spring bean與JavaBeans無關)。 因此,現在您有了一個由單例對象組成的系統,該系統在無行為的數據結構上運行。 如果您將代碼和數據分開聽起來像是您所熟悉的編程風格,那您就沒錯:我們稱其為過程編程。
考慮一下這是否是一件好事。 畢竟,Java應該是一種面向對象的編程語言。 OO的一大優點是我們可以編寫對象類,其名稱和交互作用反映問題域。 它使我們能夠編寫要解決的問題的代碼,而不會模糊基本編程結構和原始數據類型背后的全局。 它幫助我們透過樹林看木頭。 我們不應該放棄這一點。
該怎么做
盡可能停止編寫get and set! 有時這是適當的做法,但一定要停止使用IDE的功能來為您生成getter和setter。 這只是快速執行錯誤操作的便捷方法。 如果需要在對象上公開某個屬性,只需將其命名為該屬性,然后還要檢查是否確實需要公開該屬性。 詢問為什么要這樣做。 可以將任務委派給對象本身嗎? 例如,假設我有一個表示貨幣金額的類,并且希望對一堆交易進行匯總:
Amount total = new Amount(transactions.stream().map(Transaction::getAmount).mapToDouble(Amount::getValue).sum());代替getValue訪問器,為什么不給Amount類一個add()方法并讓它為我求和呢?
Amount total = transactions.stream().map(Transaction::getAmount).reduce(Amount.ZERO, Amount::add);這帶來了好處–也許您對使用雙精度表示貨幣金額的想法很感興趣。 沒錯,BigDecimal會更好。 第二個示例使此問題更易于修復,因為內部表示形式得到了更好的封裝。 我們只需要在一處更改它。
也許您想要獲取對象的數據以測試其是否等于某物。 在這種情況下,請考慮在對象上實現equals()方法,并為您測試是否相等。 如果使用Mockito創建間諜,則無需使用參數捕獲器:相反,您可以創建一個等值的對象作為示例,并將其直接傳遞給verify語句進行比較。
有時您必須創建訪問器。 例如,為了將數據持久存儲在數據庫中,您可能需要訪問數據的原始表示形式。 您是否真的必須遵循獲取/設置命名約定? 如果您的回答是“這就是用Java完成的方式”,那么我建議您回頭閱讀JavaBeans規范。 您是否真的在編寫JavaBean以按照規范描述的方式使用它? 您是否正在使用期望您的對象遵循約定的框架或庫?
必須創建變種器的次數將減少。 函數式編程現在正像一股狂潮一樣席卷整個行業,而不變數據的原理是一個很好的原則。 它也應該應用于OO程序。 如果沒有必要改變狀態,你應該考慮有必要不改變狀態,所以不用加一個賦值函數方法。 當您編寫導致出現新狀態的代碼時,將盡可能返回新實例來表示新狀態。 例如,BigDecimal實例上的算術方法不會更改其自己的值:它們返回表示其結果的新BigDecimal實例。 如今,我們擁有足夠的內存和處理能力,可以使這種編程方式變得可行。 而且Spring框架不需要注入依賴方法的setter方法,它也可以通過構造函數參數進行注入。 實際上,這種方法是Spring文檔推薦的方法。
某些技術確實要求類遵循JavaBeans約定。 如果您仍在為視圖層編寫JSP頁面,則EL和JSTL期望響應模型對象具有getter方法。 用于將對象與XML進行序列化/反序列化的庫可能需要它。 ORM框架可能需要它。 由于這些原因而被迫編寫數據結構時,建議您將其隱藏在體系結構邊界后面。 當對象泄漏到您的域中時,不要讓這些數據結構偽裝。
結論
在與使用其他語言工作的程序員交談時,我經常聽到他們批評Java。 他們說“太羅y”或“樣板太多”之類的話。 Java當然有其缺陷,但是當我更深入地詢問這些批評時,我通常會發現它們針對特定的實踐,而不是針對該語言的任何內在實踐。 做法不是一成不變的,它們會隨著時間的流逝而發展,不良做法可以得到解決。 我認為在Java中隨意使用get和set是一種不好的做法,如果放棄,我們會編寫更好的代碼。
翻譯自: https://www.javacodegeeks.com/2018/03/getters-and-setters-considered-harmful.html
空調吸氣和排氣
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的空调吸气和排气_吸气剂和二传手被认为有害的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: maven安装教程安装教程_Maven教
- 下一篇: 手机为什么卡顿反应慢