格式化

2018-02-24 15:48 更新

代碼格式化的規(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列。在兩個方法、類、對象定義之間使用一個空白行。

命名

對作用域較短的變量使用短名字:

is,?js 和?ks等可出現(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是多余的,并不能提供額外的信息。

Imports

對引入行按字母順序排序:

這樣機方便了視覺上的檢查,也簡化了自動操作。

當(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")

(譯注,通常也會默認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ù)合表達式,復(fù)合表達式的返回值是最后一個表達式。避免對簡單的表達式采用花括號;寫成:

 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
 }

它很清晰的表達了 list中的元素都被映射,間接的方式讓人不容易明白。

注釋

使用ScalaDoc提供API文檔。用下面的風(fēng)格:

 /**
  * ServiceBuilder builds services
  * ...
  */

而不是非標準的ScalaDoc風(fēng)格:

 /** ServiceBuilder builds services
  * ...
  */

不要訴諸于ASCII碼藝術(shù)或其他可視化修飾。用文檔記錄APIs但不要添加不必要的注釋。如果你發(fā)現(xiàn)你自己添加注釋解釋你的代碼行為,先問問自己是否可以調(diào)整代碼結(jié)構(gòu),從而可以明顯地可以看出它做了什么。相對于“it works, obviously” 更偏向于“obviously it works”

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號