Solidity語言學習筆記————6、全域性變數風格指南

FLy_鵬程萬里發表於2018-06-22

風格指南

概述

本指南旨在約定 solidity 程式碼的編碼規範。本指南是不斷變化演進的,舊的、過時的編碼規範會被淘汰, 而新的、有用的規範會被新增進來。

許多專案會實施他們自己的編碼風格指南。如遇衝突,應優先使用具體專案的風格指南。

本風格指南中的結構和許多建議是取自 python 的 pep8 style guide 。

本指南並 不是 以指導正確或最佳的 solidity 編碼方式為目的。本指南的目的是保持程式碼的 一致性 。 來自 python 的參考文件 pep8 。 很好地闡述了這個概念。

風格指南是關於一致性的。重要的是與此風格指南保持一致。但專案中的一致性更重要。一個模組或功能內的一致性是最重要的。 但最重要的是:知道什麼時候不一致 —— 有時風格指南不適用。如有疑問,請自行判斷。看看其他例子,並決定什麼看起來最好。並應毫不猶豫地詢問他人!

程式碼結構

縮排

每個縮排級別使用4個空格。

製表符或空格

空格是首選的縮排方法。 
應該避免混合使用製表符和空格。

空行

在 solidity 原始碼中合約宣告之間留出兩個空行。

正確寫法:

contract A {
    ...
}


contract B {
    ...
}


contract C {
    ...
}
錯誤寫法:
contract A {
    ...
}
contract B {
    ...
}

contract C {
    ...
}

在一個合約中的函式宣告之間留有一個空行。

在相關聯的各組單行語句之間可以省略空行。(例如抽象合約的 stub 函式)。

正確寫法:

contract A {
    function spam() public;
    function ham() public;
}


contract B is A {
    function spam() public {
        ...
    }

    function ham() public {
        ...
    }
}
錯誤寫法:
contract A {
    function spam() public {
        ...
    }
    function ham() public {
        ...
    }
}

原始檔編碼格式

首選 UTF-8 或 ASCII 編碼。

Imports 規範

Import 語句應始終放在檔案的頂部。

正確寫法:

import "owned";


contract A {
    ...
}


contract B is owned {
    ...
}
錯誤寫法:
contract A {
    ...
}


import "owned";


contract B is owned {
    ...
}

函式順序

排序有助於讀者識別他們可以呼叫哪些函式,並更容易地找到建構函式和 fallback 函式的定義。

函式應根據其可見性和順序進行分組:

  • 建構函式
  • fallback 函式(如果存在)
  • 外部函式
  • 公共函式
  • 內部函式和變數
  • 私有函式和變數

在一個分組中,把 constant 函式放在最後。

正確寫法:

contract A {
    function A() public {
        ...
    }

    function() public {
        ...
    }

    // External functions
    // ...

    // External functions that are constant
    // ...

    // Public functions
    // ...

    // Internal functions
    // ...

    // Private functions
    // ...
}
錯誤寫法:
contract A {

    // External functions
    // ...

    // Private functions
    // ...

    // Public functions
    // ...

    function A() public {
        ...
    }

    function() public {
        ...
    }

    // Internal functions
    // ...
}

表示式中的空格

在以下情況下避免無關的空格:

除單行函式宣告外,緊接著小括號,中括號或者大括號的內容應該避免使用空格。

正確寫法:

spam(ham[1], Coin({name: "ham"}));
錯誤寫法:
spam( ham[ 1 ], Coin( { name: "ham" } ) );
除外:
function singleLine() public { spam(); }

緊接在逗號,分號之前:

正確寫法:

function spam(uint i, Coin coin) public;
錯誤寫法:
function spam(uint i , Coin coin) public ;

賦值或其他操作符兩邊多於一個的空格:

正確寫法:

x = 1;
y = 2;
long_variable = 3;
錯誤寫法:
x             = 1;
y             = 2;
long_variable = 3;

fallback 函式中不要包含空格:

正確寫法:

function() public {
    ...
}

控制結構

用大括號表示一個合約,庫、函式和結構。 應該:

  • 開括號與宣告應在同一行。
  • 閉括號在與之前函式宣告對應的開括號保持同一縮排級別上另起一行。
  • 開括號前應該有一個空格。

正確寫法:


contract Coin {
    struct Bank {
        address owner;
        uint balance;
    }
}
錯誤寫法:
contract Coin
{
    struct Bank {
        address owner;
        uint balance;
    }
}

對於控制結構 if, else, while, for 的實施建議與以上相同。

另外,諸如 if, else, while, for 這類的控制結構和條件表示式的塊之間應該有一個單獨的空格, 同樣的,條件表示式的塊和開括號之間也應該有一個空格。

正確寫法:

ifif  (...)(...) {
    ...
}

for (...) {
    ...
}
錯誤寫法:
if (...)
{
    ...
}

while(...){
}

for (...) {
    ...;}

對於控制結構, 如果 其主體內容只包含一行,則可以省略括號。

正確寫法:

if (x < 10)
    x += 1;
錯誤寫法:
if (x < 10)
    someArray.push(Coin({
        name: 'spam',
        value: 42
    }));

對於具有 else 或 else if 子句的 if 塊, else 應該是與 if 的閉大括號放在同一行上。 這一規則區別於 其他塊狀結構。

正確寫法:

if (x < 3) {
    x += 1;
} else if (x > 7) {
    x -= 1;
} else {
    x = 5;
}


if (x < 3)
    x += 1;
else
    x -= 1;
錯誤寫法:

if (x < 3) {
    x += 1;
}
else {
    x -= 1;
}

函式宣告

對於簡短的函式宣告,建議函式體的開括號與函式宣告保持在同一行。

閉大括號應該與函式宣告的縮排級別相同。

開大括號之前應該有一個空格。

正確寫法:

function increment(uint x) public pure returns (uint) {
    return x + 1;
}

function increment(uint x) public pure onlyowner returns (uint) {
    return x + 1;
}
錯誤寫法:
function increment(uint x) public pure returns (uint)
{
    return x + 1;
}

function increment(uint x) public pure returns (uint){
    return x + 1;
}

function increment(uint x) public pure returns (uint) {
    return x + 1;
    }

function increment(uint x) public pure returns (uint) {
    return x + 1;}

函式的可見性修飾符應該出現在任何自定義修飾符之前。

正確寫法:

function kill() public onlyowner {
    selfdestruct(owner);
}
錯誤寫法:
function kill() onlyowner public {
    selfdestruct(owner);
}

對於長函式宣告,建議將每個引數獨立一行並與函式體保持相同的縮排級別。閉括號和開括號也應該 獨立一行並保持與函式宣告相同的縮排級別。

正確寫法:

function thisFunctionHasLotsOfArguments(
    address a,
    address b,
    address c,
    address d,
    address e,
    address f
)
    public
{
    doSomething();
}
錯誤寫法:
function thisFunctionHasLotsOfArguments(address a, address b, address c,
    address d, address e, address f) public {
    doSomething();
}

function thisFunctionHasLotsOfArguments(address a,
                                        address b,
                                        address c,
                                        address d,
                                        address e,
                                        address f) public {
    doSomething();
}

function thisFunctionHasLotsOfArguments(
    address a,
    address b,
    address c,
    address d,
    address e,
    address f) public {
    doSomething();
}

如果一個長函式宣告有修飾符,那麼每個修飾符應該下沉到獨立的一行。

正確寫法:

function thisFunctionNameIsReallyLong(address x, address y, address z)
    public
    onlyowner
    priced
    returns (address)
{
    doSomething();
}

function thisFunctionNameIsReallyLong(
    address x,
    address y,
    address z,
)
    public
    onlyowner
    priced
    returns (address)
{
    doSomething();
}
錯誤寫法:
function thisFunctionNameIsReallyLong(address x, address y, address z)
                                      public
                                      onlyowner
                                      priced
                                      returns (address) {
    doSomething();
}

function thisFunctionNameIsReallyLong(address x, address y, address z)
    public onlyowner priced returns (address)
{
    doSomething();
}

function thisFunctionNameIsReallyLong(address x, address y, address z)
    public
    onlyowner
    priced
    returns (address) {
    doSomething();
}

對於繼承合約中需要引數的建構函式,如果函式宣告很長或難以閱讀,建議將基礎建構函式像多個修飾符的風格那樣 每個下沉到一個新行上書寫。

正確寫法:

contract A is B, C, D {
    function A(uint param1, uint param2, uint param3, uint param4, uint param5)
        B(param1)
        C(param2, param3)
        D(param4)
        public
    {
        // do something with param5
    }
}
錯誤寫法:
contract A is B, C, D {
    function A(uint param1, uint param2, uint param3, uint param4, uint param5)
    B(param1)
    C(param2, param3)
    D(param4)
    public
    {
        // do something with param5
    }
}

contract A is B, C, D {
    function A(uint param1, uint param2, uint param3, uint param4, uint param5)
        B(param1)
        C(param2, param3)
        D(param4)
        public {
        // do something with param5
    }
}

當用單個語句宣告簡短函式時,允許在一行中完成。

允許:

function shortFunction() public { doSomething(); }

這些函式宣告的準則旨在提高可讀性。 因為本指南不會涵蓋所有內容,作者應該自行作出最佳判斷。

對映

待定

變數宣告

陣列變數的宣告在變數型別和括號之間不應該有空格。

正確寫法:

uint[] x;
錯誤寫法:
uint [] x;

其他建議

  • 字串應該用雙引號而不是單引號。

    正確寫法:

str = "foo";
str = "Hamlet says, 'To be or not to be...'";
錯誤寫法:
str = 'bar';
str = '"Be yourself; everyone else is already taken." -Oscar Wilde';
  • 操作符兩邊應該各有一個空格。

正確寫法:

x = 3;
x = 100 / 10;
x += 3 + 4;
x |= y && z;
錯誤寫法:
x=3;
x = 100/10;
x += 3+4;
x |= y&&z;

  • 為了表示優先順序,高優先順序操作符兩邊可以省略空格。這樣可以提高複雜語句的可讀性。你應該在操作符兩邊總是使用相同的空格數:

正確寫法:

x = 2**3 + 5;
x = 2*y + 3*z;
x = (a+b) * (a-b);
錯誤寫法:
x = 2** 3 + 5;
x = y+z;
x +=1;

命名規範

當完全採納和使用命名規範時會產生強大的作用。 當使用不同的規範時,則不會立即獲取程式碼中傳達的重要 元 資訊。

這裡給出的命名建議旨在提高可讀性,因此它們不是規則,而是透過名稱來嘗試和幫助傳達最多的資訊。

最後,基於程式碼庫中的一致性,本文件中的任何規範總是可以被(程式碼庫中的規範)取代。

命名方式

為了避免混淆,下面的名字用來指明不同的命名方式。

  • b (單個小寫字母)
  • B (單個大寫字母)
  • lowercase (小寫)
  • lower_case_with_underscores (小寫和下劃線)
  • UPPERCASE (大寫)
  • UPPER_CASE_WITH_UNDERSCORES (大寫和下劃線)
  • CapitalizedWords (駝峰式,首字母大寫)
  • mixedCase (混合式,與駝峰式的區別在於首字母小寫!)
  • Capitalized_Words_With_Underscores (首字母大寫和下劃線)

..注意:: 當在駝峰式命名中使用縮寫時,應該將縮寫中的所有字母都大寫。 因此 HTTPServerError 比 HttpServerError 好。 
當在混合式命名中使用縮寫時,除了第一個縮寫中的字母小寫(如果它是整個名稱的開頭的話)以外,其他縮寫中的字母均大寫。 因此 xmlHTTPRequest 比 XMLHTTPRequest 更好。

應避免的名稱

  • l - el的小寫方式
  • O - oh的大寫方式
  • I - eye的大寫方式

切勿將任何這些用於單個字母的變數名稱。 他們經常難以與數字 1 和 0 區分開。

合約和庫名稱

合約和庫名稱應該使用駝峰式風格。比如:SimpleTokenSmartBankCertificateHashRepositoryPlayer

結構體名稱

結構體名稱應該使用駝峰式風格。比如:MyCoinPositionPositionXY

事件名稱

事件名稱應該使用駝峰式風格。比如:DepositTransferApprovalBeforeTransferAfterTransfer

函式名稱

函式名稱不同於結構,應該使用混合式命名風格。比如:getBalancetransferverifyOwneraddMemberchangeOwner

函式引數命名

函式引數命名應該使用混合式命名風格。比如:initialSupplyaccountrecipientAddresssenderAddressnewOwner。 在編寫操作自定義結構的庫函式時,這個結構體應該作為函式的第一個引數,並且應該始終命名為 self

區域性變數和狀態變數名稱

使用混合式命名風格。比如:totalSupplyremainingSupplybalancesOfcreatorAddressisPreSaletokenExchangeRate

常量命名

常量應該全都使用大寫字母書寫,並用下劃線分割單詞。比如:MAX_BLOCKSTOKEN_NAMETOKEN_TICKERCONTRACT_VERSION

修飾符命名

使用混合式命名風格。比如:onlyByonlyAfteronlyDuringThePreSale

列舉變數命名

在宣告簡單型別時,列舉應該使用駝峰式風格。比如:TokenGroupFrameHashStyleCharacterLocation

避免命名衝突

  • single_trailing_underscore_

當所起名稱與內建或保留關鍵字相沖突時,建議照此慣例在名稱後邊新增下劃線。

一般建議

待定


相關文章