代碼格式化的規(guī)范并不重要,只要它們實用。它的定義形式?jīng)]有先天的好與壞,幾乎每個人都有自己的偏好。然而,對于一貫地采用同一格式化規(guī)則的總會增加可讀性。已經(jīng)熟悉某種特定風(fēng)格的讀者不必非要去掌握另一套當(dāng)?shù)亓?xí)慣,或譯解另一個角落里的語言語法。
這對Scala來說也特別重要,因為它的語法高度的重疊。一個例子是方法調(diào)用:方法調(diào)用可以用“.”后邊跟圓括號,或不使用“.”,后邊用空格加不帶圓括號(針對空元或一元方法)方式調(diào)用。此外,不同風(fēng)格的方法調(diào)用揭露了它們在語法上不同的分歧(ambiguities)。當(dāng)然一致的應(yīng)用慎重的選擇一組格式化規(guī)則,對人和機器來說都會消除大量的歧義。
我們依著Scala style guide?增加了以下規(guī)則:
用兩個空格縮進。避免每行長度超過100列。在兩個方法、類、對象定義之間使用一個空白行。
對作用域較短的變量使用短名字:
i
s,?j
s 和?k
s等可出現(xiàn)在循環(huán)中。
對作用域較長的變量使用長名字:
外部APIs應(yīng)該用長的,不需加以說明便可理解的名字。例如:Future.collect
?而非?Future.all
使用通用的縮寫,避開隱秘難懂的縮寫:
例如每個人都知道?ok
,err
,?defn
等縮寫的意思,而sfri
是不常用的。
不要在不同用途時重用同樣的名字:
使用val
(注:Scala中的不可變類型)
避免用?`````聲明保留字變量:
用typ
替代?type
用主動語態(tài)(active)來命名有副作用的操作:
user.activate()
而非?user.setActive()
對有返回值的方法使用具有描述性的名字:
src.isDefined
?而非src.defined
getters不采用前綴get
:
用get是多余的:?site.count
而非site.getCount
不必重復(fù)已經(jīng)被package或object封裝過的名字:
使用:
object User {
def get(id: Int): Option[User]
}
而非:
object User {
def getUser(id: Int): Option[User]
}
相比?get
?方法?getUser
?方法中的User是多余的,并不能提供額外的信息。
對引入行按字母順序排序:
這樣機方便了視覺上的檢查,也簡化了自動操作。
當(dāng)從一個包中引入多個時,用花括號:
import com.twitter.concurrent.{Broker, Offer}
當(dāng)引入超過6個時使用通配符:
e.g.:?import com.twitter.concurrent._
?
不要輕率的使用: 一些包導(dǎo)入了太多的名字
當(dāng)引入集合的時候,通過用import scala.collections.immutable(不可變集合)或scala.collections.mutable(可變集合)來限定名稱
可變和不可變集合有相同的名字。限定名稱讓讀者很明確知道使用的是哪個變量(e.g. "immutable.Map
")
(譯注,通常也會默認(rèn)immutable,而在使用mutable時顯示引入)
不要使用來自其它包的相對引用:
避免
import com.twitter
import concurrent
而應(yīng)該用清晰的:
import com.twitter.concurrent
(譯注,實際上上面的import不能編譯通過,第二個import應(yīng)該為:import twitter.concurrent 即import一個包實際是定義了這個包的別名。)
將import放在文件的頭部:
讀者可以在一個地方參考所有的引用。
花括號用于創(chuàng)建復(fù)合表達(dá)式,復(fù)合表達(dá)式的返回值是最后一個表達(dá)式。避免對簡單的表達(dá)式采用花括號;寫成:
def square(x: Int) = x*x
而不是:
def square(x: Int) = {
x * x
}
盡管第二種方式用在區(qū)分方法體的語句構(gòu)成很誘人。第一種選擇更加簡潔,易讀。避免語句上的繁文縟節(jié),除非需要闡明。
盡可能直接在函數(shù)定義的地方使用模式匹配。例如,下面的寫法 match應(yīng)該被折疊起來(collapse)
list map { item =>
item match {
case Some(x) => x
case None => default
}
}
用下面的寫法替代:
list map {
case Some(x) => x
case None => default
}
它很清晰的表達(dá)了 list中的元素都被映射,間接的方式讓人不容易明白。
使用ScalaDoc提供API文檔。用下面的風(fēng)格:
/**
* ServiceBuilder builds services
* ...
*/
而不是非標(biāo)準(zhǔn)的ScalaDoc風(fēng)格:
/** ServiceBuilder builds services
* ...
*/
不要訴諸于ASCII碼藝術(shù)或其他可視化修飾。用文檔記錄APIs但不要添加不必要的注釋。如果你發(fā)現(xiàn)你自己添加注釋解釋你的代碼行為,先問問自己是否可以調(diào)整代碼結(jié)構(gòu),從而可以明顯地可以看出它做了什么。相對于“it works, obviously” 更偏向于“obviously it works”
更多建議: