譯者:
本文來自 Android 大神 Jake Wharton,他是 ButerKnife 和 RxBinding 的開發者,
OkHttp,RxJava,Retrofit 等流行的 Android 開發庫的重要貢獻者,對安卓編程風格的演進具有不可磨滅的影響
每一天都會有為安卓應用和庫編寫的java代碼攜帶著一種傳染病誕生,這種傳染病的名字就叫做匈牙利命名法。
匈牙利命名法在安卓領域的推廣純粹是個意外,然而它依然受到錯誤的辯護。讓我們先來推垮幾個常見的主張:
- “《安卓 java 代碼風格指南》推薦使用匈牙利命名法”
根本就不存在所謂指導程序員如何編寫java代碼的《安卓java代碼風格指南》,絕大部分人口中子虛烏有的編碼風格指南來自于 《面向貢獻者的 AOSP 代碼樣式指南》
你可不是在為AOSP項目編寫代碼,因此你并不需要遵循他們的指南。
即便你正在編寫未來可能納入AOSP的代碼,你也不需要遵循這份指南,
幾乎所有AOSP所導入的java庫都沒有遵循它,甚至AOSP項目中的一部分開發人員都沒有這么做
- “Android 樣例使用匈牙利命名法”
一些樣例誕生于AOSP項目的開發平臺所以它們奉行AOSP的風格。而那些不來自AOSP的樣例,它們的作者要么錯誤地相信了別的主張,要么只是單純地忘了糾正編寫這些樣例時所使用的風格
- “那些額外的信息為 code review 提供了幫助”
使用變量名前綴m和s分別可以聲明變量是private/package的非靜態成員或靜態成員①,不然進行code review時將無法得知這些信息。這種方式能夠推斷那些代碼改動②中不可見的變量。從而,不管怎樣,一個變量的可見性都可以被顯而易見地得知。
在我反駁這種觀點之前,我們先來定義一下匈牙利命名法。根據維基百科,匈牙利命名法有兩種:
- 系統命名法將變量的數據類型加入到變量名當中。
一個long類型的用戶id在java中將被一個名為lUser的變量代表,以此來表示它的用途和數據類型
- 系統命名法將變量的數據類型加入到變量名當中。
- 應用命名法將變量在語義上的用途而不是邏輯上的用途或目的加入到變量名中。
保存私有信息的變量帶有某種前綴(如mUserId)而保存公有信息的變量則有另一種前綴,或者壓根沒有前綴
- 應用命名法將變量在語義上的用途而不是邏輯上的用途或目的加入到變量名中。
那么當你看見一個成員變量被使用時,究竟哪一種信息對code review來說更重要,是它的可見性還是數據類型?
可見性在code review當中是一種無需關注的屬性。成員變量已經出現并且能夠被使用,而且它的可見性大概也已經在上一個改動中被審閱過了
然而,成員變量的類型對于其在代碼改動中如何被使用有更加直接的影響。被正確調用的方法名,參數的位置,可以被調用的方法,這些全都與變量的類型直接相關。
因此提出應用匈牙利命名法是錯誤的不單只是因為它沒有用處,還因為系統匈牙利命名法能提供更多有關的信息。這可不是在說你應該使用系統匈牙利命名法,數據類型和可見性時常改動,而你將會忘記修改它們的名字。畢竟并不難發現靜態的mContext成員變量
- “額外的信息有助于開發”
Android Studio和IntelliJ IDEA會根據成員身份(靜態或非靜態)在視覺上區分非成員變量
IDE默認強制使用正確的可見性和數據類型,所以一個命名規定不會帶來任何東西。簡單敲擊鍵盤,就會有彈窗顯示變量的那三種(以及更多)屬性。

- “我想像谷歌官方一樣編寫java代碼”
盡管安卓和AOSP都是該公司的一部分,谷歌在他們的編碼風格指南中積極明確地禁止了匈牙利命名法的使用。公開的java風格指南是AOSP經年累月的內部習慣固化的產物。
安卓起源于谷歌之外,AOSP團隊早已染上了匈牙利命名的頑疾。現在對其進行修改將是一種無用的擾亂并且會給分支和第三方合作者帶來沖突。
但你對下面這個觀點的持續支持與實踐能夠讓我們在人生中根除這種疾病
朋友就不該再讓朋友使用匈牙利命名法③
— Jake Wharton
譯者注:
① field(成員): 根據oracle提供的文檔,field這個詞在未特指的情況下指的是非靜態的成員變量,
而在本文單純指成員變量,沒有額外的限定
② change(代碼改動):在該文中應指git等svn中的提交差異
③ 該文中標題中的不以及結尾處的兩個朋友原文中分別使用的是 mNo,mFriends,sFriends,
這里直接舍棄了匈牙利命名法的前綴來翻譯,至于作者使用這些前綴的意圖,感興趣的讀者可以自行借助原文進行思考