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