天天看點

linux 歧義的檔案名,當心那些有歧義的命名

關鍵點

“别人還能把這個名字了解成什麼意思?”通過不斷的問自己這個問題來積極檢查每一個命名。

事實上,這種富有創造性的、不斷嘗試“錯誤了解”的方法,能夠有效的發現歧義的命名,并修正它們。正如本文中的示例,我們将随時通過“騎驢看唱本 ——邊走邊瞧”的方式來 探讨所見到名字的誤解之處,然後選取一個更好的名字。

示例:Filter()

假設寫了一段代碼來操作資料庫結果的集合:results = Database.all_objects.filter("year <= 2011")

那麼,results包含什麼資料呢?所有滿足year<=2011的對象

所有不滿足year<=2011的對象

問題的由來是從filter這個有歧義的詞開始的,它沒有清楚表達它的意思是“選取”還是“剔除”。是以,應該避免使用filter,它太容易造 成誤解!

如果這裡想要的效果是“選取”,一個更好的名字是select;如果想要的是“剔除”,更好的名字則是exclude。

為布爾值取名

當為布爾值變量命名或者函數傳回布爾值的時候,要特别注意真和假所表達出來的真實意思,這裡就有一個很危險的例子:bool read_password = true;

這句代碼意思取決于當時怎麼閱讀的(沒有其他的意思了),顯然這裡有兩種截然不同的了解:需要讀密碼

密碼已經被讀過了

在這個用例下,做好避免用單詞read,可以考慮使用need_password或者user_is_authenticated來代替。

通常情況下,添加單詞is、has、can或者should可以讓布爾值的意思更加清晰易懂。

比如說有個函數叫SpaceLeft(),乍一看,就會想到這個函數傳回的值是數字。如果需要明确傳回值是布爾值,一個更好的名字是 HasSpaceLeft()。

還有,盡量避免使用反義短句來命名。例如:bool disable_ssl = false;

改成如下代碼則更容易了解,同時更契合原意:bool use_ssl = true;

符合使用者期望

很多名字是帶有誤導性的,因為對于某個名字,使用者自已有一個預想的定義,但是代碼的意思可能恰恰不是這個意思。如此情況下,最好作出“讓步”并改 變名字,消除 誤導性。

示例:get*()

許多程式員都在使用這樣的編碼規範:某個方法以get開頭來表達一個“輕量級的通路器”以傳回内部成員。違反這個規範将很容易誤導使用者。 避免下面的例子中java代碼段的做法:public class StatisticsCollector {public void addSample(double x) { ... }public double getMean() {// Iterate through all samples and return total / num_samples}...}

這裡,getMean的實作是枚舉過去所有的資料,并計算其平均值。如果資料量很大的時候,這一步的開銷将會是非常大的。但是,一個不了解情況的 程 序員則會很粗心的調用它并且假設這是一個很廉價的調用。

是以,這個方法應該改名成類似computeMean()這樣的,看起來這樣就是一個代價高昂的操作了(或者,另一個選擇就是改寫其實作,變成一 個名副其實的輕量級操作)。

示例:list::size()

這裡講一個C++标準庫裡的命名問題。這段代碼導緻的結果是,很難定位和修複類似導緻伺服器龜速運作之類的問題:void ShrinkList(list& list, int max_size) {while (list.size() > max_size) {FreeNode(list.back());list.pop_back();}}

這樣的bug的導緻是作者沒有意識到list.size()是一個O(n)複雜度的操作——它挨個計數連結清單的節點得出總數而不是傳回已計算 好的總個數,這将導緻ShrintList是一個O(n2) 的操作。

從技術角度講,這段代碼沒有問題,也能通過所有的單元測試。但是當調用ShrintList()并傳入一個包含上億數量級的list時,它可能将 耗費數小時的時間。

或許你會認為,這個是調用者的錯誤使用,他/她沒有認真仔細的閱讀相關的文檔!确實是這樣的,但是,事實上,這裡的list.size()不是一 個恒準時(constant-time)操作,這太意外了!其他所有的C++容器類都是恒準時的size()方法呀。

假如把size()更名成countSize()或者countElements(),類似的錯誤就會大大減少了。C++标準庫的實作者可能想的 是使用一個size()方法去和其他的容器比對,像vector和map,這樣API的一緻性看起來更好。正是由于這樣的做了,導緻程式員容易誤 用并認為這是一個很快的操作,和其他的容器一樣!幸運的是,最新的C++标準要求size()是O(1)複雜度。