吸气剂/设定者。 邪恶。 期。
從2003年開始,艾倫·霍魯布(Allen Holub)討論了為什么吸氣劑和塞特方法是邪惡的著名文章,關于吸氣劑/塞特方法是否是反模式,應該避免使用,還是我們在面向對象中不可避免地需要它,這是一個古老的爭論。編程。 我將在討論中加我的兩分錢。
以下是本文的要旨:吸氣劑和吸氣劑是一種糟糕的做法,使用它的人不能被原諒。 同樣,為了避免任何誤解,我并不是說應盡可能避免進行get / set操作。 不,我是說您永遠不要讓它們靠近您的代碼。
傲慢到足以引起您的注意? 您使用該獲取/設置模式已有15年了,您是一位受人尊敬的Java架構師嗎? 而且您不想聽到陌生人的胡話嗎? 好吧,我了解您的感受。 當我偶然發現David West的《 對象思維》時,我的感覺幾乎是一樣的。 所以,請。 冷靜下來,嘗試理解,而我嘗試解釋。
現有參數
在面向對象的世界中,有一些反對“存取器”(getter和setter的別稱)的爭論。 我認為所有這些都不夠強大。 讓我們簡要地介紹一下它們。
詢問,不要告訴:艾倫·霍魯布(Allen Holub)說:“不要詢問您需要做的工作; 詢問具有信息的對象為您完成工作。”
違規封裝原理:一個對象可以被其他對象撕裂 ,因為它們能夠通過設置器將任何新數據注入該對象。 該對象根本無法足夠安全地封裝其自身的狀態,因為任何人都可以更改它。
公開的實現細節:如果我們可以從另一個對象中獲得一個對象,則說明我們過于依賴第一個對象的實現細節。 如果明天它會改變,例如,結果的類型,我們也必須改變代碼。
所有這些理由都??是合理的,但它們沒有要點。
基本誤解
大多數程序員認為對象是帶有方法的數據結構。 我引用的是Bozhidar Bozhanov的文章《 Getters and Setters Not Evil》 :
但是,人們為其生成getter和setter的大多數對象都是簡單的數據持有者。
這種誤解是巨大誤會的結果! 對象不是“簡單的數據持有人”。 對象不是具有附加方法的數據結構。 這種“數據持有人”的概念來自于過程語言(尤其是C和COBOL)的面向對象編程。 我再說一遍:對象不是一組數據元素和操作它們的函數。 對象不是數據實體。
之后怎么樣了?
球和狗
在真正的面向對象編程中,對象就是像您我一樣的活物。 它們是生命有機體,具有自己的行為,特性和生命周期。
生命有機體可以有二傳手嗎? 你能“把”球放到狗身上嗎? 并不是的。 但這正是以下軟件正在執行的操作:
Dog dog = new Dog(); dog.setBall(new Ball());聽上去怎么樣?
你能從狗身上得到一個球嗎? 好吧,如果她吃了并且正在做手術,您可能可以。 在那種情況下,是的,我們可以從狗那里“拿走”一個球。 這就是我在說的:
Dog dog = new Dog(); Ball ball = dog.getBall();還是一個更荒謬的例子:
Dog dog = new Dog(); dog.setWeight("23kg");您能想象現實中的交易嗎?
它看起來與您每天寫的內容相似嗎? 如果是,那么您就是程序程序員。 承認吧 這就是大衛·韋斯特(David West)在他的書的第30頁上說的:
將成功的程序開發人員轉換為成功的對象開發人員的第一步是放樣。
您需要放氣嗎? 好吧,在閱讀《西方的對象思維 》時,我肯定需要一個并收到了它。
對象思維
開始像對象一樣思考,您將立即重命名那些方法。 這可能是您將得到的:
Dog dog = new Dog(); dog.take(new Ball()); Ball ball = dog.give();現在,我們將狗當做一種真正的動物,當我們要求時,他可以從我們這里拿走球并將其還給他。 值得一提的是,狗不能退還NULL 。 狗根本不知道NULL是什么! 對象思維立即消除了代碼中的NULL引用 。
查爾斯·克里頓(1988)
除此之外,對象思考將導致對象的不變性,例如“狗的重量”示例。 您可以這樣改寫:
Dog dog = new Dog("23kg"); int weight = dog.weight();狗是一成不變的生物,不允許外界任何人改變自己的體重,大小或名字等。她可以根據要求告知自己的體重或名字。 公共方法沒有任何問題,可以證明對某個對象的某些“內部”請求。 但是這些方法不是“獲取器”,它們永遠不應帶有“獲取”前綴。 我們沒有從狗身上“得到”任何東西。 我們沒有得到她的名字。 我們要她告訴我們她的名字。 看到不同?
我們也不在這里談論語義。 我們正在將過程編程的思維方式與面向對象的思維方式區分開。 在過程編程中,我們正在處理數據,在需要時對其進行處理,獲取,設置和刪除。 我們負責,數據只是一個被動組件。 狗對我們來說什么都不是-它只是一個“數據持有者”。 它沒有自己的生活。 我們可以自由地從中獲取任何必要的東西,并將任何數據放入其中。 這就是C,COBOL,Pascal和許多其他程序語言的工作方式。
相反,在一個真實的面向對象的世界中,如果您愿意的話,我們將具有生命日期和死亡時刻的生物視為具有生命本身的物體,就像它們一樣。 我們可以請狗給我們一些數據(例如,她的體重),然后她可能會向我們返回該信息。 但是我們始終記得,狗是一種活躍的成分。 她決定在我們要求之后會發生什么。
這就是為什么在概念上讓任何方法都以set或get in object開頭是不正確的 。 但這并不像許多人認為的那樣破壞封裝。 無論您是想像一個對象還是仍在用Java語法編寫COBOL。
PS。 是的,您可能會問-JavaBeans,JPA,JAXB和許多其他依賴于get / set表示法的Java API呢? Ruby的簡化了訪問器創建的內置功能呢? 好吧,所有這些都是我們的不幸。 留在過程式COBOL的原始世界中,要比真正理解和欣賞真實對象的美麗世界要容易得多。
PPS。 忘了說,是的,通過setter進行依賴注入也是一種可怕的反模式。 關于它,在下一篇文章中!
相關文章
您可能還會發現以下有趣的帖子:
- OOP中的反模式
- 避免字符串串聯
- 對象應該是不可變的
- 為什么NULL是錯誤的?
- 實用程序類的OOP替代
翻譯自: https://www.javacodegeeks.com/2014/09/getterssetters-evil-period.html
總結
以上是生活随笔為你收集整理的吸气剂/设定者。 邪恶。 期。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是月相 月相是指什么
- 下一篇: 杠杆原理的完整公式是什么 杠杆原理的完整