亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

  • 原文地址:why null is bad跳轉(zhuǎn)中...
  • 原文作者:Yegor Bugayenko
  • 譯者:高老莊里的猿

先來(lái)看個(gè) JAVA 中使用 null 作為返回值的簡(jiǎn)單例子:

「譯」為什么 null 不好?

 

該方法最大的問(wèn)題是返回 null 代替了對(duì)象。在面向?qū)ο笠?guī)范中使用 null 是個(gè)非常糟糕的做法,應(yīng)該極力避免。有很多論據(jù)可以支持這一觀點(diǎn),包括 Tony Hoare 的演講《Null References, The Billion Dollar Mistake》和 David West 的《Object Thinking》 整本書(shū)。接下來(lái)我將所有的論據(jù)做一些整理并使用合適的面向?qū)ο蠼Y(jié)構(gòu)代替 null 作為返回值。目前看來(lái),至少有兩種方法可以代替使用 null 。

1、使用空對(duì)象設(shè)計(jì)模式(最好定義一個(gè)常量)

「譯」為什么 null 不好?

 

2、當(dāng)不能返回一個(gè)對(duì)象時(shí),可以拋出異常來(lái)讓調(diào)用方 fail-fast(快速失敗)

「譯」為什么 null 不好?

 

現(xiàn)在來(lái)看看反對(duì)使用 null 的依據(jù),除了上面提到的 Tony Hoares 的演講和 David West 的書(shū)籍,還有 Robert Martin 的 《Clean Code》、 Steve McConnell 的《Code Complete》、John Sonmez 的 《Say “No” to “Null”》以及 StackOverflow 上的討論《Is returning null bad design? 》,這些我在寫(xiě)這篇文章之前都看過(guò)。

特殊錯(cuò)誤處理

每次將對(duì)象引用作為輸入時(shí)都必須檢查它是 null 的還是有效的,如果忘了檢查,將會(huì)導(dǎo)致運(yùn)行時(shí) NPE(Null Pointer Exception)。因此,你的代碼邏輯會(huì)被多種檢查和 if/then/else 分支所污染。看看下面例子:

「譯」為什么 null 不好?

 

這是 c 語(yǔ)言和其他很多面向過(guò)程編程語(yǔ)言處理異常所使用的方法,面向?qū)ο缶幊桃氘惓L幚碇饕褪菫榱讼@些特殊的錯(cuò)誤處理邏輯。在面向?qū)ο缶幊讨校覀儗惓R悦芭莸姆绞讲粩嗟南蛏蠏伋鲋钡綉?yīng)用層,這樣我們的代碼將變得更加小而美。

dept.getByName("Jeffrey").transferTo(dept2);

null 是面向過(guò)程編程的"封建余孽",請(qǐng)使用 null 對(duì)象或者異常代替之。

語(yǔ)義的二義性

為了顯示的將"函數(shù)會(huì)返回真實(shí)的對(duì)象或者 null "這層含義表達(dá)出來(lái),getByName() 必須命名為getByNameOrNullIfNotFound()。每個(gè)類(lèi)似的函數(shù)都應(yīng)該這樣做,否則會(huì)給代碼閱讀者來(lái)帶來(lái)歧義。

為了語(yǔ)義的準(zhǔn)確性,你應(yīng)該為函數(shù)定義更長(zhǎng)的名稱(chēng)。

為了消除歧義,函數(shù)盡量返回一個(gè)真實(shí)的對(duì)象、一個(gè) null 對(duì)象或者拋出一個(gè)異常。

有些人會(huì)爭(zhēng)辯說(shuō)有時(shí)為了性能,不得不返回 null。比如 java Map 接口中的 get() 方法,當(dāng)在 map 中找不到相應(yīng)的條目時(shí)會(huì)返回 null,例如:

「譯」為什么 null 不好?

 

由于 Map 的 get() 方法返回 null ,上面代碼只會(huì)在 map 中搜索一次。如果我們想重寫(xiě) Map 的 get() 方法以讓其在查找不到條目時(shí)拋出異常,代碼應(yīng)該這樣寫(xiě):

「譯」為什么 null 不好?

 

很明顯,這個(gè)方法比第一個(gè)方法慢兩倍,怎么辦呢? 我覺(jué)得 Map 的接口設(shè)計(jì)存在缺陷(無(wú)意冒犯作者),它應(yīng)該返回一個(gè)迭代器 Iterator 以便讓我們代碼可以像如下這樣:

「譯」為什么 null 不好?

 

BTW,這正是 C++ 標(biāo)準(zhǔn)庫(kù)(STL)中 map::find() 方法的設(shè)計(jì)思路。

計(jì)算機(jī)思維 vs 對(duì)象思維

假如某人知道 Java 對(duì)象是一個(gè)指向某個(gè)數(shù)據(jù)結(jié)構(gòu)的指針,并且 知道 null 是一個(gè)空指針(在英特爾 x86 處理器中等于 0x00000000),那他應(yīng)該能接收 if(employee == null) 這個(gè)語(yǔ)句。但是,如果以對(duì)象思維來(lái)進(jìn)行思考,這個(gè)語(yǔ)句就沒(méi)意義了。 從一個(gè)對(duì)象的角度來(lái)看,我們的代碼是這樣的:

  • Hello, 請(qǐng)問(wèn)是軟件部嗎?
  • 是的。
  • 麻煩讓我和你們的 employee(員工) Jeffrey 聊聊。
  • 請(qǐng)稍等...
  • Hello
  • 你是 NULL ?

上面對(duì)話的最后一句看起來(lái)很奇怪,不是嗎? 相反,如果他們?cè)诮拥轿蚁肱c Jeffrey 進(jìn)行通話的需求后直接掛斷電話會(huì)快速給我們制造個(gè)故障(異常)。這時(shí)我們可以嘗試著再次撥過(guò)去或者直接告訴我們的主管無(wú)法聯(lián)系到 Jeffrey 來(lái)完成更大的交易。

或者,他們可以讓我們與另一個(gè)人交談,他不是 Jeffrey,但如果我們需要“特定的” Jeffrey(null 對(duì)象)的話,他可以幫助我們解決大多數(shù)問(wèn)題,也可以拒絕幫忙。

Slow Failing(慢失敗)

與 failing fast(快速失敗)相反,上述代碼嘗試緩慢死亡并殺死其他人。它向調(diào)用者隱藏了失敗而不是讓其知道出了問(wèn)題需要馬上進(jìn)行異常處理。這個(gè)結(jié)論與上面"特殊錯(cuò)誤處理"章節(jié)的討論很接近。最好讓代碼盡可能脆弱,必要時(shí)讓它崩潰。

要確保你的方法對(duì)調(diào)用方提供的操作數(shù)有著極高的要求,如果調(diào)用方提供的數(shù)據(jù)不夠或者根本不符合方法主要的使用場(chǎng)景,拋出異常吧。或者返回一個(gè) null 對(duì)象,該對(duì)象暴露一些常見(jiàn)行為,并對(duì)所有其他調(diào)用拋出異常,參考如下:

「譯」為什么 null 不好?

 

可變的和不完整的對(duì)象

一般來(lái)說(shuō),強(qiáng)烈建議在設(shè)計(jì)對(duì)象時(shí)考慮到不變性。這意味著對(duì)象在實(shí)例化過(guò)程中獲得所有必要的內(nèi)容,并且在整個(gè)生命周期中永遠(yuǎn)不會(huì)更改其狀態(tài)。 null 通常被用在延遲加載中以使對(duì)象不完整且可變。例如:

「譯」為什么 null 不好?

 

這種技術(shù)雖然應(yīng)用廣泛,但在面向?qū)ο缶幊讨惺且环N反設(shè)計(jì)模式的。主要是因?yàn)樗挂粋€(gè)對(duì)象負(fù)責(zé)計(jì)算平臺(tái)的性能問(wèn)題,而這對(duì) Employee 對(duì)象應(yīng)該是透明的。

與其管理狀態(tài)并公開(kāi)業(yè)務(wù)相關(guān)的行為,不如讓對(duì)象處理好其自身結(jié)果的緩存---這就是延遲加載的目的。緩存不是 employee 該在辦公室里做的事,不是嗎?

解決辦法是不要像上面的例子那樣,以這種原始的方式使用延遲加載。相反,將這個(gè)緩存問(wèn)題移到應(yīng)用程序的另一層。例如在 Java中可以使用面向切面編程技術(shù)。 例如,jcabi-aspects 使用 @Cacheable 注解來(lái)緩存方法返回的值:

「譯」為什么 null 不好?

 

希望通過(guò)這篇文章的分析,能讓你停止在代碼中繼續(xù)使用 null 作為返回值。

來(lái)源:掘金 鏈接:https://juejin.im/post/5d740e7f5188251325775966

分享到:
標(biāo)簽:null
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定