区块链技术与金融白话区块链金马带你定投区块链

【Solidity智能合约系列】11--编码规范

2018-06-11  本文已影响13人  唠嗑008

前言

这是Solidity智能合约语言的最后一讲了,这一节主要说说Solidity编码规范的问题。

代码格式相关

缩进

使用使用空格(spaces)而不是Tab,用4个空格来表示缩进。避免混合使用Tab空格

空白行(Blank Lines)

合约之间应该有2行空格

规范的写法

contract A {
    ...
}


contract B {
    ...
}


contract C {
    ...
}

不规范的写法:

contract A {
    ...
}
contract B {
    ...
}

contract C {
    ...
}

在一个合约的2个函数之间应该有1个空行。例如:

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

没有实现的话,空行可以省去.

规范的写法:

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 {
        ...
    }
}

控制每一行的最大长度(Maximum Line Length)

控制每一行在79(或者99)个字符以内,方便读者解读代码

1、第一个参数不应该附加在开头的括号上
2、应该只使用一个缩进
3、每个参数应该在单独的一行
4、这个标识符 );应该放在最后一行

函数调用

推荐的方式

thisFunctionCallIsReallyLong(
    longArgument1,
    longArgument2,
    longArgument3
);

不推荐的方式:

thisFunctionCallIsReallyLong(longArgument1,
                              longArgument2,
                              longArgument3
);

thisFunctionCallIsReallyLong(longArgument1,
    longArgument2,
    longArgument3
);

thisFunctionCallIsReallyLong(
    longArgument1, longArgument2,
    longArgument3
);

thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3
);

thisFunctionCallIsReallyLong(
    longArgument1,
    longArgument2,
    longArgument3);

对应的赋值语句

thisIsALongNestedMapping[being][set][to_some_value] = someFunction(
    argument1,
    argument2,
    argument3,
    argument4
);

不规范的写法:

thisIsALongNestedMapping[being][set][to_some_value] = someFunction(argument1,
                                                                   argument2,
                                                                   argument3,
                                                                   argument4);

事件定义(Event Definitions and Event Emitters)

规范写法:

event LongAndLotsOfArgs(
    adress sender,
    adress recipient,
    uint256 publicKey,
    uint256 amount,
    bytes32[] options
);

LongAndLotsOfArgs(
    sender,
    recipient,
    publicKey,
    amount,
    options
);

不规范写法:

event LongAndLotsOfArgs(adress sender,
                        adress recipient,
                        uint256 publicKey,
                        uint256 amount,
                        bytes32[] options);

LongAndLotsOfArgs(sender,
                  recipient,
                  publicKey,
                  amount,
                  options);

源文件编码

推荐使用UTF-8 或者 ASCII编码

Imports

Import语句应该在文件最上方

推荐使用:

import "owned";


contract A {
    ...
}


contract B is owned {
    ...
}

不推荐使用:

contract A {
    ...
}


import "owned";


contract B is owned {
    ...
}

函数规范(Order of Functions)

函数顺序

函数排序能够帮助读者识别他们可以调用哪些函数,并且更容易找到构造函数,回退函数

函数应该根据其可见行和顺序来分组(官方推荐的的函数顺序是)
1、构造函数
2、回退函数 (如果有)
3、外部函数(external)
4、公有函数(public)
5、内部函数(internal)
6、私有函数(private)

同一类函数,constant函数放在后面。

推荐的方式:

contract A {
    // 构造函数
    function A() public {
        ...
    }

    // 回退函数
    function() public {
        ...
    }

    // 外部函数
    // ...

    // 带有constant 外部函数 
    // ...

    // 公有函数
    // ...

    // 内部函数
    // ...

    // 私有函数
    // ...
}

不推荐的格式:

contract A {


    // 外部函数
    // ...

    // 公有函数
    // ...

    // 内部函数
    // ...
    
    function A() public {
        ...
    }

    function() public {
        ...
    }

    // 私有函数
    // ...
}

表达式中的空格

在以下情形,避免使用没有必要的空格

一个单行的表达里,在小括号、中括号、大括号里应该避免不必要的空格

推荐:

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;

在回退函数不要包含空格

推荐:

function() public {
    ...
}

不推荐:

function () public {
    ...
}

控制结构(Control Structures)

表示合约定义、函数定义、库定义、结构体定义的大括号,推荐使用方式:

左括号应该跟定义在一行

contract Coin {
    struct Bank {
        address owner;
        uint balance;
    }
}

不推荐:

contract Coin
{
    struct Bank {
        address owner;
        uint balance;
    }
}

控制语句if, else, while, for左括号也应该跟条件控制在一行

推荐:

if (...) {
    ...
}

for (...) {
    ...
}

不推荐:

if (...)
{
    ...
}

while(...){
}

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

如果控制结构的方法体内的语句只有1行,那么大括号是可以省略的。

推荐:

if (x < 10)
    x += 1;

不推荐:

if (x < 10)
    someArray.push(Coin({
        name: 'spam',
        value: 42
    }));

明确函数的可见性

所有的函数(包括构造函数)应该在定义的时候明确函数的可见性,例如应该使用:

function explicitlyPublic(uint val) public {
    doSomething();
}

不推荐:

function implicitlyPublic(uint val) {
    doSomething();
}

对于包含有else 或者 else if子句的if语句, else 或者 else if应该放置在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 kill() public onlyowner {
    selfdestruct(owner);
}

不推荐方式:

function kill() onlyowner public {
    selfdestruct(owner);
}

命名规范

在命名中要避免单独的使用小写的l,大写的I,大写的O。因为这样容易产生混淆,容易和数字01不可区分。

合约、库(Library)、结构体、事件、枚举的命名

合约、库、结构体、事件的命名应该使用大驼峰(首字母大写的方式)命名法。例如:SimpleToken, SmartBank, CertificateHashRepository, Player

函数、函数参数、局部变量、状态变量、修饰器(Modifier)的命名

除了构造函数以外的函数、函数参数、局部变量、状态变量、修饰器(Modifier)都应该使用小驼峰(mixedCase)命名法。比如:getBalance, transfer, verifyOwner, addMember, changeOwner

常量

常量应该使用全大写及下划线分割大词的方式,如:MAX_BLOCKS,TOKEN_NAME, CONTRACT_VERSION。

区分函数和事件

为了防止函数和事件(Event)产生混淆,声明一个事件使用大写并加入前缀(可使用LOG)。对于函数, 始终以小写字母开头,构造函数除外。

// 不建议
event Transfer() {}
function transfer() {}

// 建议
event LogTransfer() {}
function transfer() external {}

参考:
https://solidity.readthedocs.io/en/v0.4.23/style-guide.html

上一篇下一篇

猜你喜欢

热点阅读