對(duì)象方法也有不工作的時(shí)候
本文作者介紹
Michael Feathers
Michael Feathers是Object Mentor International公司的技術(shù)顧問。他的工作不僅是技術(shù)開發(fā),他還參與對(duì)世界各地技術(shù)團(tuán)隊(duì)進(jìn)行培訓(xùn)、指導(dǎo)等工作。他曾開發(fā)了將JUnit遷移到 C++的CppUnit的初始部分,還有FitCpp——一個(gè)C++版的FIT基礎(chǔ)測(cè)試框架。他是《Working Effectively with Legacy Code》一書的作者。
重構(gòu)的方式千差萬別。當(dāng)在分析一個(gè)很大的方法時(shí),我會(huì)首先看一下它的整體結(jié)構(gòu),心里對(duì)如何分解它有了一個(gè)初步的感覺。里面的條件判斷代碼塊通常都會(huì)是我認(rèn)為有問題、可以入手的地方。
- if (...) {
- ...
- }
當(dāng)看到有一個(gè)像這樣的if語句后,我知道我面臨著選擇。我可以 提取這個(gè)if語句以及和它相關(guān)的代碼塊到一個(gè)新方法里,或者我只提取相關(guān)代碼塊。我并不知道這樣或那樣做哪一種更好——這要根據(jù)上下文來判斷。有時(shí)候這個(gè) 條件語句非常重要,有必要重點(diǎn)突出它,而另一些時(shí)候,這些if語句和它的代碼塊可以干凈的提取出去,使得調(diào)用它的程序的顯得更整潔干凈。但是,我們?nèi)绾握{(diào) 用這個(gè)提取出去的方法呢?
讓我來看看一個(gè)實(shí)際例子:
- if (alarmEnabled) {
- Alarm alarm = new Alarm();
- ...
- ...
- alarm.sound();
- }
我們可以把整個(gè)if語句和它的代碼塊提取到一個(gè)叫做soundAlarm
的方法里。
- soundAlarm();
這樣好嗎?
大多數(shù)人最初的反應(yīng)會(huì)說:現(xiàn)在的這塊代碼有時(shí)會(huì)說謊。它告訴我們它將要響起警報(bào),但有時(shí)候它并不響。通常,如果有這樣說謊的代碼不是一件好事,所以,選擇另外一種重構(gòu)策略可能更好:
- if (alarmEnabled) {
- soundAlarm();
- }
但是,這樣看起來并不像之前那樣干凈。
這 種兩難抉擇讓我想起了Null對(duì)象模式。Null對(duì)象模式就是一種經(jīng)常會(huì)讓人感覺代碼在說謊的另一個(gè)例子。在主調(diào)代碼里,我們看到有消息發(fā)送到一個(gè)對(duì)象, 但讓人震驚的是,我們發(fā)現(xiàn)相應(yīng)的動(dòng)作并沒有發(fā)生。但并不是所有的人都會(huì)有這種感覺。我所在的這個(gè)團(tuán)隊(duì)里大量的使用了Null對(duì)象模式,我們對(duì)代碼的理解有 這樣的共識(shí):當(dāng)你告訴一個(gè)對(duì)象做X時(shí),有時(shí)候它并不去做——發(fā)送執(zhí)行X的消息意味著有時(shí)X事件并不一定會(huì)發(fā)生。這要由這個(gè)對(duì)象決定。
我的直覺告訴我,這沒什么,但你需要理解為什么會(huì)這樣,這是十分重要的——這是一個(gè)內(nèi)部的理解問題。
如果說多態(tài)有任何意義,它至少在說對(duì)象是自己管理自己的。我們給它發(fā)送一個(gè)消息,這是由它來決定應(yīng)該去做什么。這是面向?qū)ο蟮暮诵模彩?Alan Kay 最初的對(duì)對(duì)象的認(rèn)識(shí)之一——消息只是它們的信息傳遞。這種觀點(diǎn)在如今并不占主導(dǎo)地位。
當(dāng)我非常想讓這種提取變的更易懂時(shí),我通常有兩種策略——使用一種意指一個(gè)事件的名字,或泛化這個(gè)操作。在這種情況下,我會(huì)選擇使用一個(gè)事件風(fēng)格的過去式的名字。
- intruderDetected();//入侵檢測(cè)
這種事件風(fēng)格的命名方式的好處是,它強(qiáng)調(diào)了事件條件,而不是動(dòng)作。現(xiàn)在,我們可以將任何想要的東西都放到intruderDetected
方法里。
我們還可以選擇去泛化這個(gè)操作。相對(duì)于說我們要想起警報(bào),我們可以換成說我們要向世界通知一個(gè)關(guān)于我們的狀態(tài)的信息。
- performNotifications();//執(zhí)行通知
如果使用一個(gè)像performNotifications
這樣的名字,我就能使事情變得抽象。這里的通知是一個(gè)還是多個(gè)并不重要。關(guān)鍵是,主調(diào)程序觸發(fā)這個(gè)動(dòng)作,但不意味著動(dòng)作沒有發(fā)生就可以解釋成在撒謊。
盡管這樣,我仍然疑惑,我們是否應(yīng)該永遠(yuǎn)不要相信一個(gè)顯示它肯定將會(huì)做某事的方法名?
如果它沒有做,我們可以認(rèn)為它在撒謊嗎?
原文鏈接:https://michaelfeathers.silvrback.com/when-it-s-okay-for-a-method-to-do-nothing