前言
这是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。因为这样容易产生混淆,容易和数字0、1不可区分。
合约、库(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
网友评论