鍍金池/ 教程/ Linux/ 編程規(guī)范
簡介
編程規(guī)范
雜項
源文件的布局
單位和全局可用變量
合約的結(jié)構(gòu)
通用模式
常見問題
深入理解 Solidity
安裝Solidity
智能合約介紹
合約
Solidity 編程實例
http://solidity.readthedocs.io/en/latest/security-considerations
類型
表達式和控制結(jié)構(gòu)

編程規(guī)范

概述

本指南用于提供編寫Solidity的編碼規(guī)范,本指南會隨著后續(xù)需求不斷修改演進,可能會增加新的更合適的規(guī)范,舊的不適合的規(guī)范會被廢棄。

當然,很多項目可能有自己的編碼規(guī)范,如果存在沖突,請參考項目的編碼規(guī)范。

本指南的結(jié)構(gòu)及規(guī)范建議大都來自于python的pep8編碼規(guī)范

本指南不是說必須完全按照指南的要求進行solidity編碼,而是提供一個總體的一致性要求,這個和pep8的理念相似(譯注:pep8的理念大概是:強制的一致性是非常愚蠢的行為,參見:pep8)。

本指南是為了提供編碼風(fēng)格的一致性,因此一致性這一理念是很重要的,在項目中編碼風(fēng)格的一致性更加重要,而在同一個函數(shù)或模塊中風(fēng)格的一致性是最重要的。而最最最重要的是:你要知道什么時候需要保持一致性,什么時候不需要保持一致性,因為有時候本指南不一定適用,你需要根據(jù)自己的需要進行權(quán)衡??梢詤⒖枷逻叺睦記Q定哪一種對你來說是最合適的。

代碼布局

縮進

每行使用4個空格縮進

tab或空格

空格是首選縮進方式

禁止tab和空格混合使用

回車(空行)

兩個合約之間增加兩行空行

規(guī)范的方式:

contract?A {

??? ...}

contract?B {

??? ...}

contract?C {

??? ...}

不規(guī)范的方式:

contract?A {

??? ...}contract?B {

??? ...}

contract?C {

??? ...}

合約內(nèi)部函數(shù)之間需要回車,如果是函數(shù)聲明和函數(shù)實現(xiàn)一起則需要兩個回車

規(guī)范的方式:

contract?A {

????function?spam();

????function?ham();

}

contract?B is A {

????function?spam() {

??????? ...

??? }

????function?ham() {

??????? ...

??? }

}

不規(guī)范的方式:

contract?A {

????function?spam() {

??????? ...

??? }

????function?ham() {

??????? ...

??? }}

源文件編碼方式

首選UTF-8或者ASCII編碼

引入

一般在代碼開始進行引入聲明

規(guī)范的方式:

import?"owned";

contract?A {

??? ...}

contract?B is owned {

??? ...}

不規(guī)范的方式:

contract?A {

??? ...}

import?"owned";

contract?B is owned {

??? ...}

表達式中的空格使用方法

以下場景避免使用空格

  • 括號、中括號,花括號之后避免使用空格

Yes規(guī)范的方式: spam(ham[1], Coin({name: “ham”}));

No不規(guī)范的方式: spam( ham[ 1 ], Coin( { name: “ham” } ) );

  • 逗號和分號之前避免使用空格

Yes規(guī)范的方式: function spam(uint i, Coin coin);

No不規(guī)范的方式: function spam(uint i , Coin coin) ;

  • 賦值符前后避免多個空格

規(guī)范的方式:

x?=?1;

y?=?2;

long_variable?=?3;

不規(guī)范的方式:

x?????????????=?1;

y?????????????=?2;

long_variable?=?3;

控制結(jié)構(gòu)

合約、庫。函數(shù)、結(jié)構(gòu)體的花括號使用方法:

  • 左花括號和聲明同一行

  • 右括號和左括號聲明保持相同縮進位置。

  • 左括號后應(yīng)回車

規(guī)范的方式:

contract?Coin {

????struct?Bank {

????????address?owner;

????????uint?balance;

??? }

}

不規(guī)范的方式:

contract?Coin

{

????struct?Bank {

????????address?owner;

????????uint?balance;

??? }

}

以上建議也同樣適用于if、else、while、for。

此外,if、while、for條件語句之間必須空行

規(guī)范的方式:

if?(...) {

??? ...

}

for?(...) {

??? ...

}

不規(guī)范的方式:

if?(...)

{

??? ...

}

while(...)

{

}

for?(...)

?{

??? ...;

}

對于控制結(jié)構(gòu)內(nèi)部如果只有單條語句可以不需要使用括號。

規(guī)范的方式:

if?(x?<?10)

??? x?+=?1;

不規(guī)范的方式:

if?(x?<?10)

??? someArray.push(Coin({

??????? name:?'spam',

??????? value:?42

??? }));

對于if語句如果包含else或者else if語句,則else語句要新起一行。else和else if的內(nèi)部規(guī)范和if相同。

規(guī)范的方式:

if?(x?<?3) {

??? x?+=?1;

}

else?{

??? x?-=?1;

}

if?(x?<?3)

??? x?+=?1;

else

??? x?-=?1;

不規(guī)范的方式:

if?(x?<?3) {

??? x?+=?1;}?

else?{

??? x?-=?1;}

函數(shù)聲明

對于簡短函數(shù)聲明,建議將函數(shù)體的左括號和函數(shù)名放在同一行。

右括號和函數(shù)聲明保持相同的縮進。

左括號和函數(shù)名之間要增加一個空格。

規(guī)范的方式:

function?increment(uint?x)?returns?(uint) {

????return?x?+?1;

}

function?increment(uint?x)?public?onlyowner?returns?(uint) {

????return?x?+?1;

}

不規(guī)范的方式:

function?increment(uint?x)?returns?(uint)

{

????return?x?+?1;

}

function?increment(uint?x)?returns?(uint)

{

????return?x?+?1;

}

function?increment(uint?x)?returns?(uint)

?{

????return?x?+?1;

}

function?increment(uint?x)?returns?(uint)?

{

????return?x?+?1;

}

默認修飾符應(yīng)該放在其他自定義修飾符之前。

規(guī)范的方式:

function?kill()?public?onlyowner {

??? selfdestruct(owner);

}

不規(guī)范的方式:

function?kill() onlyowner?public?{

??? selfdestruct(owner);

}

對于參數(shù)較多的函數(shù)聲明可將所有參數(shù)逐行顯示,并保持相同的縮進。函數(shù)聲明的右括號和函數(shù)體左括號放在同一行,并和函數(shù)聲明保持相同的縮進。

規(guī)范的方式:

function?thisFunctionHasLotsOfArguments(

????address?a,

????address?b,

????address?c,

????address?d,

????address?e,

????address?f,

) {

??? do_something;

}

不規(guī)范的方式:

function?thisFunctionHasLotsOfArguments(address?a,?address?b,?address?c,

????address?d,?address?e,?address?f) {

??? do_something;

}

function?thisFunctionHasLotsOfArguments(address?a,

????????????????????????????????????????address?b,

????????????????????????????????????????address?c,

????????????????????????????????????????address?d,

????????????????????????????????????????address?e,

????????????????????????????????????????address?f) {

??? do_something;

}

function?thisFunctionHasLotsOfArguments(

????address?a,

????address?b,

????address?c,

????address?d,

????address?e,

????address?f) {

??? do_something;

}

如果函數(shù)包括多個修飾符,則需要將修飾符分行并逐行縮進顯示。函數(shù)體左括號也要分行。

規(guī)范的方式:

function?thisFunctionNameIsReallyLong(address?x,?address?y,?address?z)

????public

??? onlyowner

??? priced

????returns?(address)

{

??? do_something;

}

function?thisFunctionNameIsReallyLong(

????address?x,

????address?y,

????address?z,)

????public

??? onlyowner

??? priced

????returns?(address)

{

??? do_something;

}

不規(guī)范的方式:

function?thisFunctionNameIsReallyLong(address?x,?address?y,?address?z)

??????????????????????????????????????public

????????????????????????????????????? onlyowner

????????????????????????????????????? priced

??????????????????????????????????????returns?(address) {

??? do_something;

}

function?thisFunctionNameIsReallyLong(address?x,?address?y,?address?z)

????public?onlyowner priced?returns?(address){

??? do_something;

}

function?thisFunctionNameIsReallyLong(address?x,?address?y,?address?z)

????public

??? onlyowner

??? priced

????returns?(address) {

??? do_something;

}

對于需要參數(shù)作為構(gòu)造函數(shù)的派生合約,如果函數(shù)聲明太長或者難于閱讀,建議將其構(gòu)造函數(shù)中涉及基類的構(gòu)造函數(shù)分行獨立顯示。

規(guī)范的方式:

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)

??? {

????????// do something with param5

??? }

}

不規(guī)范的方式:

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)

??? {

????????// 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) {

????????// do something with param5

??? }

}

對于函數(shù)聲明的編程規(guī)范主要用于提升可讀性,本指南不可能囊括所有編程規(guī)范,對于不涉及的地方,程序猿可發(fā)揮自己的主觀能動性。

映射 待完成

變量聲明

對于數(shù)組變量聲明,類型和數(shù)組中括號直接不能有空格。

規(guī)范的方式: uint[] x; 不規(guī)范的方式: uint [] x;

其他建議

  • 賦值運算符兩邊要有一個空格

規(guī)范的方式:

x?=?3;x?=?100?/?10;x?+=?3?+?4;x?|=?y?&&?z;

不規(guī)范的方式:

x=3;x?=?100/10;x?+=?3+4;x?|=?y&&z;
  • 為了顯示優(yōu)先級,優(yōu)先級運算符和低優(yōu)先級運算符之間要有空格,這也是為了提升復(fù)雜聲明的可讀性。對于運算符兩側(cè)的空格數(shù)目必須保持一致。

規(guī)范的方式:

x = 2**3 + 5;x = 2***y + 3*z;x = (a+b) * (a-**b);

不規(guī)范的方式:

x = 2** 3 + 5;x = y+z;x +=1;

命名規(guī)范

命名規(guī)范是強大且廣泛使用的,使用不同的命名規(guī)范可以傳遞不同的信息。

以下建議是用來提升代碼的可讀性,因此被規(guī)范不是規(guī)則而是用于幫助更好的解釋相關(guān)代碼。

最后,編碼風(fēng)格的一致性是最重要的。

命名方式

為了防止混淆,以下命名用于說明(描述)不同的命名方式。

  • b(單個小寫字母)

  • B(單個大寫字母)

  • 小寫

  • 有下劃線的小寫

  • 大寫

  • 有下劃線的大寫

  • CapWords規(guī)范(首字母大寫)

  • 混合方式(與CapitalizedWords的不同在于首字母小寫!)

  • 有下劃線的首字母大寫(譯注:對于python來說不建議這種方式)

注意

當使用CapWords規(guī)范(首字母大寫)的縮略語時,縮略語全部大寫,比如HTTPServerError 比HttpServerError就好理解一點。

避免的命名方式

  • l?- Lowercase letter el? 小寫的l

  • O?- Uppercase letter oh?大寫的o

  • I?- Uppercase letter eye?大寫的i

永遠不要用字符‘l'(小寫字母el(就是讀音,下同)),‘O'(大寫字母oh),或‘I'(大寫字母eye)作為單字符的變量名。在某些字體中這些字符不能與數(shù)字1和0分辨。試著在使用‘l'時用‘L'代替。?

合約及庫的命名

合約應(yīng)該使用CapWords規(guī)范命名(首字母大寫)。

事件

事件應(yīng)該使用CapWords規(guī)范命名(首字母大寫)。

函數(shù)命名

函數(shù)名使用大小寫混合

函數(shù)參數(shù)命名

當定義一個在自定義結(jié)構(gòu)體上的庫函數(shù)時,結(jié)構(gòu)體的名稱必須具有自解釋能力。

局部變量命名

大小寫混合

常量命名

常量全部使用大寫字母并用下劃線分隔。

修飾符命名

功能修飾符使用小寫字符并用下劃線分隔。

避免沖突

  • 單個下劃線結(jié)尾

當和內(nèi)置或者保留名稱沖突時建議使用本規(guī)范。

通用建議

待完成

上一篇:單位和全局可用變量下一篇:類型