?
如同寫(xiě)作,寫(xiě)代碼也是有代碼風(fēng)格(code style)。不過(guò)代碼風(fēng)格和文風(fēng)不一樣,一個(gè)人的文風(fēng)可以隨心所欲,代碼風(fēng)格最好是“千篇一律”。它的核心就是:便于閱讀。
如果你的代碼風(fēng)格也要隨心所欲,那么多年后,你再回顧你以前寫(xiě)的代碼,你心中可能只有一個(gè)疑問(wèn):
這TMD是誰(shuí)寫(xiě)!!!
當(dāng)然別人也是這樣想的,所以為了世界和平,請(qǐng)保持你的代碼風(fēng)格符合一定規(guī)則。這里,我們學(xué)習(xí)的是多個(gè)知名R包(dplyr, ggplot2)開(kāi)發(fā)者Hadley大神推薦的代碼風(fēng)格。
對(duì)象名(Object names)
每次寫(xiě)代碼的時(shí)候,我總要糾結(jié),這個(gè)變量叫啥名字,那個(gè)函數(shù)又要叫啥名字,于是半天過(guò)去了,代碼居然一行都沒(méi)寫(xiě)好。命名比較推薦的是用_分割不同單詞,比如說(shuō)code_style。當(dāng)然駝峰式命名 codeStyle 也行, 只要保證前后一致。如果你英文水平不錯(cuò),還可以讓變量名都是名詞,函數(shù)名都是動(dòng)詞。
記住: 千萬(wàn)不要把內(nèi)置的函數(shù)名或變量名用于命名,比如說(shuō)TRUE <- FALSE
。如果你老板對(duì)你太狠,你不想干了,倒是可以考慮一下。
合理使用空格
什么叫做合理使用空格呢? 其實(shí)就是在所用能用空格的地方都用上空格,比如說(shuō)
# 反面教材
average<-mean(feet/12+inches,na.rm=TRUE)
完全就可以改成
# 學(xué)習(xí)模范
average <- mean(feet / 12 + inches, na.rm = TRUE)
前后比較一下,你就會(huì)發(fā)現(xiàn)后者的閱讀更加舒服,沒(méi)有那么擁擠。但是不要過(guò)度, 但是你應(yīng)該不會(huì)這樣做。
# 過(guò)猶不及
average <- mean ( feet / 12 + inches, na.rm = TRUE )
不過(guò)如果是判斷語(yǔ)句,比如說(shuō)if, 那么在 () 前后增加空格就是合理的。
# 反面教材
if(debug)do(x)
plot (x, y)
# 學(xué)習(xí)模范
if (debug) do(x)
plot(x, y)
關(guān)于花括號(hào)
我們先看一個(gè)反面教材和學(xué)習(xí)模范的對(duì)比:
# 反面教材
if (y < 0 && debug)
message("Y is negative")
if (y == 0)
{ log(x) }
else
{y ^ x}
# 學(xué)習(xí)模范
if (y < 0 && debug) {
message("Y is negative")
}
if (y == 0) {
log(x)
} else {
y ^ x
}
有沒(méi)有發(fā)現(xiàn),合理的花括號(hào)的使用可以 非常清楚 得找到條件語(yǔ)句中的執(zhí)行部分,并且代碼更容易閱讀。簡(jiǎn)單來(lái)說(shuō)就是如下兩點(diǎn):
- { 不要獨(dú)立成行
- } 盡量獨(dú)立成行,除非后面緊跟else
每一行的長(zhǎng)度
每一行的長(zhǎng)度不要超過(guò)80個(gè)字符,這樣子在印刷的時(shí)候,可以調(diào)整合適的字體大小。什么,你不知道80個(gè)字符是多少? 沒(méi)事,Rstudio可以用 Ctrl + Shift + \ 進(jìn)行重排。或者每次你覺(jué)得自己的代碼寫(xiě)的太擠了,就另起一行吧。
每行縮進(jìn)
千萬(wàn)不要混用Tab和space,甚至就不要用Tab進(jìn)行縮進(jìn), 千萬(wàn)不要,記住千萬(wàn)不要。因?yàn)椴煌到y(tǒng)對(duì)Tab所占空白區(qū)域是不同的,對(duì)于Python而言,混用直接出錯(cuò)。
至于每一行縮進(jìn)多少就按照你自己喜歡的來(lái),Rstuido默認(rèn)是2個(gè)空格,我覺(jué)得挺好看的。
賦值
請(qǐng)用 <- 對(duì)變量賦值,不要用=, =僅僅用在函數(shù)里面的參數(shù)賦值。有一次我看到別人代碼里面通篇用=進(jìn)行賦值,我知道他之前學(xué)編程用的是Perl, 所以會(huì)把這些習(xí)慣帶過(guò)來(lái)。但是既然用了R, 那么愛(ài)屋及烏用<-吧!
# 反面教材
x = 123
# 學(xué)習(xí)模范
x <- 123
PS: 這條不是必須的,但是強(qiáng)烈推薦,這樣子別人立馬能看出來(lái)你寫(xiě)的是R代碼。當(dāng)然我已經(jīng)能夠熟練在Python和R里面切換使用賦值符號(hào)了。
請(qǐng)用注釋
如果這個(gè)代碼這輩子都不用第二次了,也不打算給任何人看,那么你不需要寫(xiě)注釋。否則,請(qǐng)寫(xiě)上你的注釋?zhuān)⑶冶WC你的注釋有意義,也就是解釋你為什么要寫(xiě)這行代碼,而不只是說(shuō)這行代碼干了什么
## 反面教材
# 往屏幕輸出"hello world"
print("hello world")
## 學(xué)習(xí)模范
# 為了讓初學(xué)者體驗(yàn)編碼非常簡(jiǎn)單,用"hello world"的方式和計(jì)算機(jī)交互
print("hello world")
最后,如果你已經(jīng)寫(xiě)了大量風(fēng)格迥異的代碼,不想一個(gè)個(gè)修改怎么辦?好在謝益輝大神寫(xiě)了fromatR幫助我們調(diào)整編碼風(fēng)格:
# install.packages("formatR")
# 用法
formatR::tidy_dir("R")
這個(gè)包主要完成了如下內(nèi)容,基本上完全按照代碼風(fēng)格修改:
- 單行代碼和注釋過(guò)長(zhǎng)會(huì)被重新組織成多行,更加容易閱讀
- 盡可能地增加空格和縮進(jìn)
- 大多數(shù)情況下會(huì)保留注釋
- 縮進(jìn)默認(rèn)空格為4個(gè), 但是可以修改
- 單行無(wú)}的else會(huì)被放回前一行
- 賦值操作的=會(huì)被替換成<-, 函數(shù)參數(shù)中=不在考慮范圍內(nèi)
- { 可以移到新的一行中。
當(dāng)然謝益輝大神在博客(地址為https://yihui.name/formatr/)里也詳細(xì)接好了formatR
注: 還可以用linter可以在寫(xiě)代碼時(shí)檢查潛在問(wèn)題。