##Introduction 此文件主要參考 Google Jave Style 。
本文件目的為統一編程風格,避免零亂的程式風格,同時將 Check Style 裡面的檢查項目條列以供參考,方便閱便以及調整。
Google 說他們的 Code Style document 是一個 hard and fast rule,我們要超越 Google 所以我們也必須將 Code Style 視為 hard and fast rule,這或許關乎代碼的美感,但更關乎程序員的尊嚴。
Google 文件說每個文件名稱都必須是 .java
結尾。
編碼設成 UTF-8 不過份吧?
最大檔案大小不可以超過 3MB
之所以空白字元重要,可以看一下空白之神的故事,關於空白字元有很多注意的事項,我們在這裡只提一下 Trailing space,每一行結尾都不要有空白字元 。附贈,哪一天被空白給婊了都不知道 。
//Good
LG.log("Hi");
//Bad, 根本就一樣啊,好啦,用 '.' 代表空格
LG.log("Hi");.
關於回車\r
,\t
這類的字元比較少用到,這裡就不多加約束,但請自愛。
一個程式的結構順序大約如下
- 版權宣告
- Package 宣告
- Import 宣告
- Class Java Doc
- Class 本體
每個部分請用 一行空白來區隔。
####版權宣告 目前有兩種選擇
option1:
//這種應該會有修正,因為公司搬家
/**
* Copyright (c) 2000-${year} xxxxxx.
* Tun-Hwa South Road, Taipei, Taiwan, R.O.C. All Rights Reserved.
*/
option2:
//這種好,公司搬家也不怕
/**
* Copyright (c) xxxxx, Inc All Rights Reserved.
*/
Package 宣告是不受單行字數限制,即便他一千個字元,也是合法,不要把他斷掉了
// Good
package com.ebizprise.cp.logger.util;
// Bad
package com.ebizprise.
cp.logger.util;
永遠都不要使用萬用字元 import,盡可能不使用 static import
// Good
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
// Bad
import org.apache.commons.logging.*;
import 也是有順序和群集性的,每個群集需要用一行空白來分開
// Good
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.ebizprise.cp.util.format.MsgFormater;
// Bad
import org.apache.commons.logging.Log;
import com.ebizprise.cp.util.format.MsgFormater;
import org.apache.commons.logging.LogFactory;
每個 Class 都必須寫說明,說明裡面包含三個項目
- Class 目的以及特殊注意事項
- Author 作者
Class 目的裡面可透過html syntax
來說明,特殊注意使用事項,可以在這邊多加描敘,在這裡永遠都是寫越多越好,越詳細越好。
作者的部分,主要標注出這個 Class 的作者,在這裡我有點意見,如果可以透過 SVN Blame
之類的機制知道Class 被誰改過這個標準似乎意義就降低了,同時如果此Class被多人改過,作者標很多個就會變成名人堂性質,實質意義下降。
Class 的成員變量也是有順序和群聚性的,這裡似乎沒有一個標準作法告訴我們應該怎麼做,但原則上就是邏輯類似的變量放在一起。
如果你的多個 function 是 overloaded 的,請你行行好把他們聚集在一起,避免別人(或是你) 下次在找 function 的時候把他們滑鼠的滾輪給滾壞了。
這個標題就說明了一切。
// Good
if (isTrue) {
System.out.println("Hi");
}
// Bad
if (isTrue)
System.out.println("Hi");
我們採用埃及式開關括號法,規則如下:
- 開括號前不會有空白行, 但會有一格空白
- 開了括號會有一行空白
- 關括號前會有一行空白
- 如果關括號的後面,有分號,
else
等,則和關括號同一行。
// Good
if (isTrue) {
System.out.println("Hi");
} else {
System.out.println("Hello");
}
// Bad
if (isTrue)
{
System.out.println("Hi");
}
else
{
System.out.println("Hello");
}
// Bad - 開括號前少了帥氣的空格
if (isTrue){
System.out.println("Hi");
}
else{
System.out.println("Hello");
}
有時候無可避免的我們會出現空 block 的狀況,在這裡我們就讓開關括號同一行
//Good
void hello(){}
//Bad
void hello() {
}
目前的規範是 140 個字元,但有一些例外的狀況
- 有些東西是無法切割的像是 URL,就不在140個字元的規範內
- Package name 以及 import lib
斷行就沒有全面性的標準原則,在很多情況下都是合法的斷行
Tips: 或許我們可以透過一些重構的方法,減少斷行的發生
Google 斷行的原則有點抽象,prefer to break at a higher syntactic level,應該是可以從語法的角度下去定義,這句話我還不能參透,但可以繼續看下去。
1.如果我們需要在 non-assignment operator,我們的斷行必須要在 non-assignment operator 之前(整句話不知道在講啥,看例子)
// 像 . 就是一個 non-assignment operator
// Better
if(StringUtils.isNotEmpty(eventItem.getUiEventInfo()
.getCampaignName())){
promoEventItem_list.add(eventItem);
}
//Bad
if(StringUtils.isNotEmpty(eventItem.getUiEventInfo().
getCampaignName())){
promoEventItem_list.add(eventItem);
}
結論是在這種情況下,怎麼斷都醜,就不是 Code Style 層面要解決,而應該往上到重構層面解決。
2.當我們需要在 assign operator 附近斷行的時候,我們通常會斷在 assign operatior 之後。
// Good
doTouchAEventCode =
getGenericEventService().doTouchAEventCode(eventType, eventCode);
// Bad
doTouchAEventCode
= getGenericEventService().doTouchAEventCode(eventType, eventCode);
3.如果是 method 或是 constructor 的小括號,需要跟在method name 之後,就就是斷行要在小括號之後。
// Good
doTouchAEventCode = getGenericEventService().doTouchAEventCode(
eventType, eventCode);
// Bad
doTouchAEventCode = getGenericEventService().doTouchAEventCode
(eventType, eventCode);
4.如果要在逗號(,)附近斷行,應該是在逗號的後面斷行。
//Good
LG.debug(this.getClass().getCanonicalName(),
"import event data begin....");
//Bad
LG.debug(this.getClass().getCanonicalName()
,"import event data begin....");
斷行後的縮排至少都需要在四格以上,但有一些狀況下的連續斷行,他們允許在同一層縮排裡。
空白行這帖藥很利害,服用了以後,可以讓你的 Code 變清楚,簡單的說邏輯區塊之前就是加入空白行的好時點,什麼是邏輯區塊?看例子:
// Method 就是一種比較明顯的邏輯區塊
// Good
public void hello() {
}
public void byeBye() {
}
// Bad
public void hello() {
}
public void byeBye() {
}
另外一種空行的時間點,就是像寫作文一樣的分段,這個分段很重要, 如果能夠搭配註解服用,你的 Code 可以說是好讀到一個不行。
// 讀取 Excel 檔案
InputStream inputStream = importData.getInputFile();
HSSFWorkbook inputExcelWorkbook = new HSSFWorkbook(inputStream);
// 取第一個 Sheet裡面的第一列,標題列
HSSFSheet worksheet = inputExcelWorkbook.getSheetAt(0);
Iterator<Row> rowIterator = worksheet.iterator();
同樣的 import 也是有群聚性的,所以也應該要空白分開,但我打娘胎來,我沒整理過 import,因為我用 Eclipse,相信你也是。
空白之神可謂亦正亦邪,空白之神可以分成 Vertical whitespace 垂直空白 以及 horizontal whitespace 水平空白兩種,我們先從垂直空白說明起:
垂直空白其實就是空行,那空白行出現的時機,應該是什麼時候呢?
- 連續的邏輯區塊中間需要