1. 程式人生 > >Android Code Style Guidelines for Contributors

Android Code Style Guidelines for Contributors

英文原文地址:

https://source.android.com/source/code-style.html#java-language-rules

剛入門在進行軟體開發的時候,可能在寫code的時候有的親是隨心所欲想怎麼寫就怎麼寫,只要功能OK就行,而有的親呢可能會想我的變數名要怎麼見名知意, 我的

code要怎麼寫才健壯等等,當然我更看好後一種想法的小夥伴了,因為有一個好的程式碼風格,你寫出來的code不光便於你自己理解,同時在團隊合作的時候更便於別人

的理解與維護,並且能夠體現自身的素養與功底,那麼我們就根據android對想要向他們提交patch的程式碼風格要求來學習一下,同時規範自己的每一行程式碼吧。

好了,劃線進入正題~~

===============================================================================================================================

如下這些規則不是指南也不是建議,而是嚴格的規定(口氣還是滿嚴肅的^V^).。如果想要向android貢獻程式碼,不遵循如下的規則提交將不會被接受。

雖然Android中並非所有存在的程式碼都遵循瞭如下這些規則,但是我們要求未來新增的任何新程式碼必須要遵循這些規則。

先簡單列一下本文的目錄

Java語言規則

  -不要忽略異常

  -不要捕獲通用異常

  -不要使用Finalizer

  -高校imports

Java庫規則

Java風格規則

  -使用javadoc標準註釋

  -寫短方法

  -在標準的位置定義屬性(欄位)

  -控制變數的有效域

  -將import語句排序

  -用空格進行縮排(即不要用tab)

  -遵循欄位命名約定

  -使用標準的Brace風格(條件語句除非在一行否則都需要加上花括號{})

  -控制單行的長度

  -使用標準的java註解

  -把縮寫當作一個單詞

  -使用TODO註解

  -少加log

  -保持一致性

Java測試程式碼風格規則

  -遵循測試方法命名約定

 正文內容如下,如果看到上面的目錄就能明白,可以不用看詳細解說,如果看過詳細解釋那麼目錄就可以作為條目溫習了

Java語言規則

android遵循標準的java編碼規則,另外添加了如下幾條規則:

不要忽略異常

有時人們很容易寫出像如下這種完全忽略異常的程式碼

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) { }
}

你必須不要再這麼寫程式碼了。也許你會覺得你的程式碼永遠不會遇到這個錯誤條件或者認為處理這個錯誤並不重要,像上面該這種

忽略異常的方式會在你的程式碼裡建立一座礦山留給其他人去征服在未來的某一天(相當於給別人埋坑)。你必須按照某種原則處理

你程式碼裡面的所有異常。特定的處理方式根據場景的不同做不同的處理。

每當有人在寫一個空的catch語句是都應該有一種毛骨悚然的感覺。雖然肯定有時候這樣寫確實是對的,但是你至少應該對這樣寫

有所思考。在java裡你無法逃避這種毛骨悚然的感覺。----James Gosling

可以接受的備選方案如下(按照優先順序排序):

-將異常拋給你的呼叫者

void setServerPort(String value) throws NumberFormatException {
    serverPort = Integer.parseInt(value);
}

-丟擲適合你的抽象層次的新異常,也即給丟擲的異常新增一些你的層次能夠知道的資訊
void setServerPort(String value) throws ConfigurationException {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new ConfigurationException("Port " + value + " is not valid.");
    }
}

-優雅的處理這個錯誤並在catch塊中給替換一個適當的值
/** Set port. If value is not a valid number, 80 is substituted. */

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        serverPort = 80;  // default port for server 
    }
}

-捕獲這個異常並丟擲一個執行時異常。注意這是危險的:僅僅在你確定發生這個錯誤後crash是適當的。
/** Set port. If value is not a valid number, die. */

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new RuntimeException("port " + value " is invalid, ", e);
    }
}

需要注意的是原異常會作為引數傳遞給RuntimeException的建構函式,如果你的程式碼必須在Java 1.3版本以下進行編譯,

那麼你將需要省略掉這個源頭異常,也就是這個執行時異常的真正原因。

-最後一招:如果你確定以及肯定你忽略掉這個異常是正確的選擇,那麼至少你應該在catch語句塊上寫下為什麼要這麼做,

或者列印log提醒曾經出現過異常

/** If value is not a valid number, original port number is used. */
void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        // Method is documented to just ignore invalid user input.
        // serverPort will just be unchanged.
    }
}

不要捕獲通用異常

有時候為了偷懶人們更願意用如下方式捕獲異常

try {
    someComplicatedIOFunction();        // may throw IOException 
    someComplicatedParsingFunction();   // may throw ParsingException 
    someComplicatedSecurityFunction();  // may throw SecurityException 
    // phew, made it all the way 
} catch (Exception e) {                 // I'll just catch all exceptions 
    handleError();                      // with one generic handler!
}

首先你不應該這麼做,幾乎在所有場景下這樣捕獲通用異常或者Throwable都是不恰當的,最好不要是Throwable,因為它包含

錯誤的異常,也就是Error.java,因為Error也繼承自Throwable,這樣如果直接捕獲Throwable,那麼真正的Error也被捕獲了。這樣

做是相當危險的,這就意味著你永遠不期望錯誤的出現,及時是RuntimeException例如ClassCastException,甚至或不捕獲了應用

層級的錯誤處理。它隱藏了你程式碼的錯誤處理效能。這就意味著如果在你呼叫的程式碼裡面某人添加了新的異常型別,編譯器並不

會提醒你有新的異常型別需要做特殊處理。畢竟在大多數情況下並非所有的異常都可以用同樣一種方式進行處理。

當然萬事無絕對,對於此規則也有一些例外的情況:某些測試程式碼和你想要捕獲所有錯誤的頂層程式碼(阻止這些錯誤顯示到UI介面上,

或者為了保證接下來批量的任務可以繼續執行下去)。在這種場景下你可以捕獲通用異常(Exception)或者Throwable並且恰當的處理。

在做這樣的決定前你需要做相當仔細的考慮,雖然你會在catch語句塊中添加註解說明在這裡做這樣的處理是安全的。

捕獲通用異常的替換處理方式如下:

-捕獲可能會在對應的try語句塊中所有異常,每個異常對應一個catch語句塊,雖然這樣寫會略顯尷尬,但是還是建議捕獲所有的異常,

  注意在catch語句中不要出現太多重複的程式碼

-重構你的程式碼使用多個try語句塊去實現細粒度更高的錯誤處理,例如從解析中將IO處理分離出來,在每個場景中將錯誤分開處理。

-重新丟擲這個異常,許多時候有些異常不需要在你這一層來進行處理,那就索性將它繼續丟擲去

記住:異常是你的朋友!當編譯器想你抱怨你沒有捕獲某一個異常的時候,不要皺眉,要微笑,編譯器只是想在編譯的時候就告訴你,

你有需要處理的潛在錯誤,不用到執行時候發現再處理

不要使用Finalizer

Finalizer是一種能夠在物件在被垃圾回收機制回收時執行一段程式碼的方法。

優點:可以方便做清理工作,尤其是外部資源

缺點:Finalizer什麼時候會被呼叫是沒有保證的,甚至它是否會被呼叫也是不確定的。

抉擇:我們不使用Finalizer。在大多數場景下,你可以將需要在Finalizer中所做的處理用一個好的異常處理來取代。如果你確實需要使用Finalizer,

你可以定義一個closer方法(或者類似的其它方法)並且在註解中寫清楚該方法什麼時候需要被呼叫。具體例子可以參考InputStream類。在這種情

況下在Finalizer中列印提示的log資訊是比較恰當的方式但並不是必須的,只要這裡列印log不會太頻繁以至於淹沒整理日誌。

高效Imports

當你想用用foo包中的Bar類時,你有如下兩種方式可以將它import進來

1.import foo.*;

優點:潛在的減少了import語句的數量

2.import foo.Bar;

優點:比較清晰的能夠知道具體哪個類是需要用到的,對於維護者來說增加了程式碼的可讀性。

抉擇:android程式碼中所有的import都使用後一種方式,但是java標準庫(java.util.*, java.io.*, etc)和單元測試程式碼(junit.framework.*)例外。

java類庫規則

在使用android中的java庫和工具是有約定的。在某些情況下,在一些重要的途徑中約定會有所改變,還有一些舊程式碼中會使用一些被廢棄的模式以及

類庫。當在處理這類程式碼時,允許跟隨已存在的程式碼風格。但當在建立新的元件的時候不要再使用被廢棄的庫。

Java風格規則

使用javadoc標準註解

 每一個檔案的頂部都應該有版權資訊語句,然後跟上包命語句,以及一系列的import語句,每一類語句塊之間用一個空白行隔開。在這之後就是類或者

介面的宣告。在javadoc註解中描述清楚這個類或者介面具體是用來做什麼的。參考如下:

/*
 * Copyright (C) 2013 The Android Open Source Project 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package com.android.internal.foo;

import android.os.Blah;
import android.view.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */

public class Foo {
    ...
}

你所寫的每一個類或者重要的公開方法都必須用javadoc註解進行註釋,至少包含一句用來描述你這個類和方法是用來做什麼的。這個語句應該

以第三人稱的口吻來描述。

/** Returns the correctly rounded positive square root of a double value. */
static double sqrt(double a) {
    ...
}

或者
/**
 * Constructs a new String by converting the specified array of 
 * bytes using the platform's default character encoding.
 */
public String(byte[] bytes) {
    ...
}

當然,你不必為每一個類似get和set這種並非很重要的方法新增javadoc註釋,例如setFoos這樣的方法javadoc中都會描述為"set Foos",這就沒有必要了。

如果你的方法做了一些很複雜的事情(例如強制約束或者有比較重要的副作用),這樣的方法你就必須要加上註解了。也就是如果不是類似屬性“Foo”這種

很明顯一眼就能看出其表達的意思,那麼你就應該要寫出具體的註解。

這樣每一個你所寫的方法,公開或者其它的,都會從javadoc中收益,如果javadoc註解寫得很清楚的話,更利於後期自己或其他人的維護。公開方法屬於

API的的一部分因此需要javadoc註解的支援。

寫短小的方法

在某種程度上這是可行的,方法應該儘量短小並且集中。然而在有些場景下長方法更合適,因此在方法長度上沒有硬性的規定。那麼如果方法的長度超過了

40行,就因該考慮一下是否能夠在不影響方法的架構的基礎上將方法分成幾個小的方法

將屬性欄位定義放在標準的位置

屬性欄位應該定義在檔案的頂部,即類的頂部,或者在即將使用這個欄位的方法的上面。

限制變數的作用域

本地變數的作用域應該儘量控制在最小的範圍內。這樣做能夠儘量增加你程式碼的可讀性以及可維護性,減少出現錯誤的可能性。變數的宣告儘量在某一範圍的

語句塊內,這個語句塊範圍能夠儘量小,最好是剛好覆蓋所有使用這個變數的語句。

本地變數應該在第一次使用前進行宣告,在每個本地變數被宣告的附近應該有對其進行初始化的語句。如果在宣告時沒有足夠的資訊來對其進行合理的初始化,

那麼你應該儘量推遲該變數的初始化指導你能夠進行初始化為止。

這個規則的例外是關於try-catch語句塊的。如過變數的初始化是依靠需要進行try-catch進行異常檢查的方法呼叫返回的值,那麼該變數必須在try語句塊中

進行初始化。如果該變數必須會在try語句塊外被用到,那麼你必須將該變數的宣告提出到try語句塊外,並給初始化一個不算是很合理的值。

// Instantiate class cl, which represents some sort of Set 
Set s = null;
try {
    s = (Set) cl.newInstance();
} catch(IllegalAccessException e) {
    throw new IllegalArgumentException(cl + " not accessible");
} catch(InstantiationException e) {
    throw new IllegalArgumentException(cl + " not instantiable");
}

// Exercise the set 
s.addAll(Arrays.asList(args));
但是即使在這種情況下,也可以將try-catch封裝在方法中來避免,如下所示
Set createSet(Class cl) {
    // Instantiate class cl, which represents some sort of Set 
    try {
        return (Set) cl.newInstance();
    } catch(IllegalAccessException e) {
        throw new IllegalArgumentException(cl + " not accessible");
    } catch(InstantiationException e) {
        throw new IllegalArgumentException(cl + " not instantiable");
    }
}

...

// Exercise the set 
Set s = createSet(cl);
s.addAll(Arrays.asList(args));

迴圈變數應該被宣告在for語句內,除非因此會有編譯錯誤除外:

for語句

for (int i = 0; i < n; i++) {
    doSomething(i);
}

foreach語句
for (Iterator i = c.iterator(); i.hasNext(); ) {
    doSomethingElse(i.next());
}

import語句排序

import語句的順序應該按照如下分組進行排列:
1.Android類的import語句
2.第三方類庫import語句(com,junit,net,org)
3.java和javax
要完全匹配IDE的設定,import順序應該是:
-每組import按照英文字母排序,並且大寫字母排在小寫字母的前面(例如 Z應該排在a的前面)
-在每組import語句之間應該有一個空白行來隔開(android, com, junit, net, org, java, javax)
import的排序原本上是沒有風格要求的。這就意味著要麼IDE自動匯入的時候總是在更改import的順序,或者
用IDE研發的coder關閉了IDE的自動import管理功能而自己手動進行import的書寫。這樣做被認為是很糟糕
的。當IDE中java風格被設定的時候,首選風格會影響所有方面。它幾乎滿足我們“選擇一個排序,並保持一致”
的需求。因此我們可以選擇一種風格,更新風格指南,使得所選風格遵循import排序的這種規則。我們期望所有
用IDE進行編碼的工程師能夠在沒有其它工程師的努力下遵循這種import排序的模式。

這種風格的選擇需要滿足如下條件:
-做imports的人想要檢視第一個import應該在android的頂部
-做imports的人想要檢視最後一個import應該在java的底部
-人類能夠很輕鬆的遵循這種風格
-整合開發環境能夠遵循這種風格

static import的使用以及放置的位置稍有爭議。有的人認為靜態匯入應該穿插在其它各組imports中,而有的人認為
應該單獨給靜態匯入分一個組。此外,我們還沒確定一種方法使得所有IDE都遵循一種排序方式。

當大多數人都認為import排序是一種很小的事情時,請作出你自己的裁決並保持一致。

用空格進行縮排
我們使用4個空格作為一個縮排塊,從來不使用tab進行縮排。當有疑問時,請保持和周圍code一致。
我們使用8個空格作為換行的縮排,包括方法呼叫和變數的賦值,例如:
正確的方式

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);


錯誤的方式
Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);



遵循欄位命名約定
-非公開(non-public)非靜態(non-static)的欄位名以“m”開頭
-靜態欄位名以“s”開頭
-其它欄位名以小寫字母開頭即可
-常量(public static final)欄位全部字母大寫
例如:
public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}


使用標準花括號風格

用來括住一段程式碼的花括號不需要另起一行,只需要跟在其前面的一行程式碼的最後就可以了,例如
class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

我們要求條件語句的內容需要用花括號包起來,除非整個條件語句能夠在一行中寫下,當然包括條件判斷
以及滿足該條件需要執行的語句。參考如下幾個例子:
合法
if (condition) {
    body(); 
}

合法
if (condition) body();

不合法
if (condition)
    body();  // bad!


限制單行的長度

在你的程式碼中每一行應該最多有100字元的長度。
這個規則有很多的爭議,不過最後的裁決是100字元的長度已經是長度的最大值了,不能超過這個長度了。
例外1:如果在註釋中有命令的例子或者url連結長度超過100個字元,為了命令以及url連結的方便複製貼上
長度可以超過100個字元
例外2:import語句可以不受這個規則的限制,因為畢竟人很少關注這個,而且這樣也簡化了工具(IDEs)的開發。
使用標準的Java註解
註解應該優先於其它修改針對統一語言元素來講。簡單的修飾註解(例如@Override)應該同其所修飾的語言元素
處於同一行[關於這一條我搜了下android的程式碼,有的確實遵循了,但是有沒有,個人認為還是單起一行比較美
觀]。如果需要好幾個註解,或者引數註解,那麼每個註解應該單獨佔一行。
有三個在java中預定義的註解在Android中的標準做法如下:
[email protected]:此註解必須用在被註解的元素是即將被棄用的,不鼓勵再繼續使用。當你使用這個註解時同時需
要在該元素上載入@Deprecated的javadoc標籤並寫明轉換的實現方法。另外,需要注意的是即使別標註為
@Deprecated的方法還是應該能夠工作的。
如果你在舊的程式碼中看到有方法被加上了@Deprecated的標籤請給它新增上@Deprecated的註解
[email protected]:此註解必須被用在子類重寫在父類中宣告或實現的方法上。
例如,如果你使用了@inheritdocs javadoc標籤,並且來自於某一個類(注意是類不是介面),那麼與此同時你
就必須給重寫的父類方法新增上@Overrride註解
[email protected]:此註解應該僅被用在無法消除警告的情況下。如果一個警告通過了“不可能消除”的測試,那麼
此註解就必須被使用了,為了確保所有的警告都準確反應出了程式碼中的問題。
當SuppressWarnings註解是必須的時候,它的前面必須加上一個TODO註釋,解釋“不能被消除”的情況。這通常是被
鑑定出一個違規類有不太合適的介面。例如:

// TODO: The third-party class com.third.useful.Utility.rotate() needs generics 
@SuppressWarnings("generic-cast")
List<String> blix = Utility.rotate(blax);



當@SuppressWarnings註解是必需的時候,程式碼應該被重構將被註解的軟體元素隔離開來。
將縮寫當作單詞
在給變數,方法和類命名時將縮略詞當作一個單詞。這樣這些名字可讀性就更強了:
Good & Bad Sample
JDK和Android程式碼庫針對縮寫處理都非常不一致。因此,實質上也是不可能讓你附近的程式碼都保持一致的,那麼硬著頭皮將縮寫當作
一個單詞吧。
使用TODO註釋
程式碼使用TODO註釋是一個臨時的,短期的解決方法,或者說是足夠好但是不完美的方法。
TODO註釋應該以TODO全大寫字元開頭,後面跟上冒號:
這樣
// TODO: Remove this code after the UrlTable2 has been checked in.


或者這樣
// TODO: Change this to use a flag instead of a constant.


如果你以"在未來某個時間做某事"的形式新增TODO註釋,那麼你要麼需要加上非常具體的日期("Fix by November 2005"),要麼寫上
非常具體的事件("Remove this code after all production mixers understand protocol V7.")。
保守的新增log
如果當log是必須的時候,如果該log沒有保持足夠合理以及間接那麼它必要會給效能帶來顯著的負面影響,從而立馬丟失了它的有效作用。
Log裝置給提供了五種不同級別的log,如下所述:
-ERROR:這個級別的log應該在發生了某些致命的事情時。即某些使用者可見的後果,並且不能夠恢復如果不通過明確的刪除某些資料,解除安裝
      應用程式,擦出資料分割槽或者重新刷機(或者更糟糕)這些方式。這個級別的日誌是會總被記錄的。這些被標記為ERROR的log資訊
      將被作為上報到資料統計收集伺服器上的候選者。
-WARNING:這個級別的log應該用在發生了嚴重並且在意料之外的事情時。即某些將會是使用者可見的後果但是很可能會被恢復而不會有數
      據丟失由於執行了某些明確的操作,範圍從等待或者重啟應用程式一直到重新下載應用程式的新版本或者重啟裝置。這個級別的log也
      是總會被記錄的。WARNING級別的log資訊也將被考慮是否上報給資料統計收集伺服器
-INFORMATIVE:這個級別的log資訊應該在需要提示發生某些大多數人比較關心的事情是列印。即當一個解決方案被採用但其極有可能會
      影響比較廣,雖然不一定是一個錯誤。這種狀態的log應該被在這個領域具有權威性的模組列印(避免非權威模組的log重複列印),這個級
             別的log也是總會被記錄的。
-DEBUG:這個級別的log列印是為了進一步提示在裝置上發生了什麼事情以便與調查和除錯非期望事情發生的原因。你應該只打印需要用來蒐集
      足夠的資訊以確定你的模組都發生了些什麼的log內容。如果你的除錯log資訊佔據了整個log日誌那麼你應該使用詳細日誌級別VERBOSE。
      這個級別也會被記錄,甚至是在釋出版本上,並且這個log需要被if (LOCAL_LOG)或者if (LOCAL_LOGD)語句塊包圍,而LOCAL_LOG[D]
      會被定義在你的類或者子模組中,這樣就存在了關閉所有這類log的可能性。因此在If (LOCAL_LOG[D])語句塊中不能有程式碼邏輯相關內容。
      並且所有的字串拼裝也只能在這個語句塊中進行。如果將if (LOCAL_LOG[D])語句塊提取成一個方法會導致字串的拼裝被提取到這個語
      句塊之外的話,是不建議這麼做的。
      也許現有程式碼中還有通過if (localLOGV)這種形式,雖然它的名字不規範,但是也被考慮為可以接受的。
-VERBOSE:這個級別的log應該用於可以列印一切資訊。這類log應該僅在除錯版本上被記錄,並且應該被if(LOCAL_LOGV)語句快包圍(或者其它
      等效的方式),因為這樣我們才可能在預設的版本上不記錄這個型別的log。任何關於這個log的字串拼裝都應該剝離在if (LOCAL_LOGV)
      中,以保證其不會出現在發行(release)版本中。
注意:
-在一個給定的模組中,除了VERBOSE級別的log資訊外,一個錯誤的日誌應該儘量只被列印一次:在一個模組的一連串函式呼叫中,應該僅最內層的
 方法呼叫應該返回錯誤,而該函式的呼叫者應該僅僅列印一些對與分離問題原因有重要作用的log資訊。
-在模組鏈中,除了VERBOSE級別的log資訊外,在低層模組中發現了來自於高層模組的無效資料,低層模組應該僅將這種情況列印在DEBUG級別的
  log資訊中,並且僅當日志提供了不會另外對呼叫者有效的資訊。具體來講,沒有沒有必要給拋Exception的場景(這個exception應該會攜帶
  所有的有效資訊),或者僅有包含一個錯誤程式碼的資訊的場景列印log。這一點在framework和apllication之間尤其重要,並且這種狀況由第三方應用程式
  導致時framework正確的處理方式就是不應該列印高於DEBUG級別的log資訊。能夠觸發INFORMATIVE或者更高級別的log資訊列印的場景是僅當一個
  模組或者應用程式發現了自身的錯誤或者其對應的低層級的錯誤。
-當在某種情況發生時,有部分log會被列印很多次,那麼比較好的做法應該是通過實現某中速率限制的機制來控制相同或者相似的log資訊被列印多次,
 以至於淹沒整個日誌。
-網路連線的斷開被認為是普遍並且完全可以預料到的場景,因此不應該隨便的列印這種場景發生的log資訊。網路連線的斷開如果給app帶來一定的後果
 那麼應該被記錄為DEBUG或者VERBOSE級別(完全取決於後果是否足夠嚴重並且足夠出乎意料到需要記錄在發行版本中)。
-A full filesystem on a filesystem that is accessible to or on behalf of third-party applications should not be logged at a level higher than INFORMATIVE
  真心無力翻譯,可能這方面接觸得少,搞不明白想表達什麼,之後明白了再翻譯吧 = =||
-無效資料來自於任何不可信的源頭(包括共享儲存上的檔案,或者來自任何網路的資料)被認為是預料之中的,當資料被發現為無效時(即便如此log也是
 被儘可能限制的)不應該列印高於DEBUG級別的log資訊
-請記住當你在給字串使用+操作符時,會隱式建立一個預設擁有16個字元大小緩衝區的StringBuilder物件以及幾個其它的臨時字串物件。即顯示建立
 StringBuilder並不會比用+操作符更加高的資源消耗(沒準可能會更高效)。與此同時也請記住呼叫Log.v的程式碼在發行版本上會被編譯並且執行,包括編譯
 字串,即使logs別沒有被讀取。
-所有是為了給人們閱讀以及出現在發行版本上的log日誌都應該精煉但不神祕,也就是不要太晦澀難懂,應該能夠被人合理的理解。這包括所有高於等於
 DEBUG級別的log
-當可能的時候,log應該保持在一行內如果合理的話。單行的長度應該在80或者100個字元長度以內。當長度超過了130或者160個字元長度(包括tag的長度)
  在可能的情況下應該儘量避免
-用於提示成功的log資訊的級別應該不得高於VERBOSE
-臨時log為了確認很難復現的問題應該使用DEBUG或者VERBOSE級別,and should be enclosed by if blocks that allow to disable it entirely at compile-time.
  後面這句翻譯不動了
-小心通過log發生的安全洩漏。私有資訊應該被避免列印。被保護內容的資訊毫無疑問必須應該避免列印。尤其是在寫framework程式碼時由於並不容易能夠
  知道哪些內容會是私有或者被保護的,所以在寫程式碼的時候更應該注意對安全的考慮
-System.out.println() (或者native程式碼中的printf() )應該永遠不被使用。System.out和System.err會被重定向到/dev/null,所以你的log將不會被列印到能看到的
  地方。然而,所有關於這寫呼叫的字串建立仍然會被執行。
-日誌的黃金規則是你的log可能沒有必要將被人的log推出快取區,就像別人的log可能不會推出你的一樣。
保持一致
我們的臨別思想:保持一致。當你在編輯程式碼的時候,花幾分鐘的時間看看附近的程式碼,然後決定你的程式碼風格。如果它們的if語句周圍有
間距,那麼你也應該這樣做。如果它們的註釋周圍有星號包圍,那沒你的註釋也應該有星號圍繞。
這篇程式碼風格的關鍵在與能夠有通用的編碼詞彙,這樣人們可以專注於你在說什麼,而不是你怎麼在說。我們在這裡介紹了整體風格規則以便
人們能夠知道這些詞彙。但是本地風格(程式碼原來的風格)也同樣很重要,也許你遵循了此文章所說的規則,但是你修改了一個檔案,在裡面添
加了打篇幅的不一樣風格的程式碼,這樣子完全改變了閱讀程式碼者的節奏,不可取,儘量阻止這樣的事情發生。
Java測試風格規則
遵循測試程式碼命名約定
當給測試方法命名的時候,你可以用下劃線來將當前正在測試的內容從具體測試case中分離出來。這個風格能夠更便於知道什麼內容被測試了。
例如:
For example:


testMethod_specificCase1 testMethod_specificCase2


void testIsDistinguishable_protanopia() {
    ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
    assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
    assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}

相關推薦

Android Code Style Guidelines for Contributors

英文原文地址: https://source.android.com/source/code-style.html#java-language-rules 剛入門在進行軟體開發的時候,可能在寫code的時候有的親是隨心所欲想怎麼寫就怎麼寫,只要功能OK就行,而有的親呢可能

【轉】Android:No implementation found for native

stat void for boa bte pre shared int jnienv 解決方法: 1.檢查native c code的定義: JNIEXPORT void Java_com_example_something_MyClass_getMyString(JNI

Appium Android測試環境搭建 for Mac

detail 資源 and 搭建 car log nbsp www 查找 Appium Android測試環境搭建 涉及的資源,工具都很多 ,從網上各種資料查找,整合一下資源,針對小白級別。 1、Appium安裝: 轉載自:http://www.cnblogs.com/os

Code as IaaS for Azure : Terraform 初步

生產環境 bili client 獨立 結果 network forms ply wid   節前有用戶提了兩個需求,PostgreSQL和Terraform,趁著過節有大塊的時間,把這兩個都粗略的過了下。之前已經把PostgreSQL相關測試結果寫了篇文檔,正好把Terr

Code as IaaS for Azure : Terraform 做多一點事情

命令 define compute 區域 ken 我們 指定 dns nag 上一篇大概介紹了怎麽用Terraform在Azure上創建一個虛擬機,接下來,我們會用Terraform來做一些更復雜的工作。 在開始工作前,我們還是要先解釋下會用到的幾個命令。 因為我用的是Wi

IDEA學習系列之剖析IDEA裏的Code Style(適合各種語言)(不斷更新)(圖文詳解)

ESS javascrip 挖掘 python pre scrip 學習 裏的 yaml   不多說,直接上幹貨!   File -> Settings -> Editor -> Code Style

android dialog style屬性設置

代碼 name owb ble frame parent 自帶 str res <!--最近做項目,用到alertDialog,用系統自帶的style很難看,所以查了資料自己定義了個style. res/value/style.xml內增加以下代碼:-->

android studio Authentication failed for

unset conf 用戶名 list androi password 輸入 平臺 mina 今天更新項目代碼提示 Authentication failed for 後來一起是把git平臺密碼修改了 忘了修改android studio 密碼所以更新失敗 我在and

拯救 Java Code Style 強迫癥

let expect intel daemon method 程序猿 常用 sta ofo 2018年10月31日 21:20:46 Java架構大數據 閱讀數:1更多個人分類: java 架構 linux 程序猿編輯這篇文章緣起於上一個持續交付的咨詢項目,當時正在指導客戶

Researchers Examine Emerging Marke Android industrial computer t for Used Electric Vehicle Batterie

www.inhandnetworks.com Second-life batteries from electric vehicles could provide businesses and homes with backup power while lowering electric

intelij IDEA設定goole code style風格

1.安裝google-java-format 外掛      file ->Setings... ->pligins     輸入上訴外掛安裝 2.下載IntelliJ Java Google Style file檔案   &n

Android Error:Execution failed for task ':app:compileDebugJavaWithJavac'

這個錯誤是很模糊,根本無法定位錯誤低點,這時就需要獲得詳細的錯誤日誌來推斷錯誤 首先,可以開啟黑視窗(CMD)定位到專案目錄,或者是直接用as,開啟下面的Terminal,效果跟黑視窗一樣,而且不用手動定位到目錄 然後輸入命令 gradlew compileDebu

Android Ignoring InnerClasses attribute for an anonymous inner class

例如:Ignoring InnerClasses attribute for an anonymous inner class (org.ksoap2.transport.KeepAliveHttpsTransportSE$1),但發現不一定跟org.ksoap2.transport.KeepA

Android解決style檔案不能使用自定義屬性

在自定義view的時候,通常會自定義一些屬性,為了便於統一使用,在style檔案中把自定義屬性賦值。但是我卻在自定義view中,取不到style中設定的值,如果在xml中設定屬性值卻能正常獲取,這是為什麼呢? 在res/attrs中自定義屬性attrs.xml: <

Android Error:Execution failed for task ':app:preDebugAndroidTestBuild'. > Conflict with dependency

錯誤內容: Error:Execution failed for task ':app:preDebugAndroidTestBuild'. > Conflict with dependency 'com.android.support:support-annotations' in

解讀google C++ code style談對C++的理解

C++是一門足夠複雜的語言.說它"足夠複雜",是因為C++提供了足夠多程式設計正規化--泛型, 模板, 面向物件, 異常,等等.順便說說,我已經很久沒有跟進C++的最新發展了(比如C++0x), 所以前面列舉出來的特性應該只是C++所有特性的一個部分罷了.C++特性過多很難駕馭好C++的原因之一.

Looking for Contributors and Sponsors for CVPM (Computer Vision Package Manager)

Documents: https://cvpm.autoai.org/GitHub: https://github.com/unarxiv/cvpm中文介紹(Chinese Intro): https://zhuanlan.zhihu.com/p/45672318CVPM (Computer Vision P

We helped a cook (refugee) become an Android Developer now working for a Startup

Hi HN, I just wanted to share an amazing story with you. A year ago we had an applicant applying for a scholarship (we enable people to learn how to code

Guidelines for a standardized data format for use in cross

There is an increasing number of linguistic databases worldwide, raising the possibility of a vast network for potential comparative studies. However, the

Omega 3 fatty acids found in seafood linked to healthy aging: Findings support guidelines for increased consumption of seafood f

With populations across the world living longer, there is a growing focus on healthy ageing -- a meaningful lifespan without major chronic diseases and wi