https://aptos.dev/en/build/smart-contracts/book/coding-conventions

Move 编码规范

本节列出了一些 Move 的基本编码规范,Move 团队发现这些规范非常有帮助。这些只是建议,如果你有其他格式化指南和规范的偏好,随时可以使用。

命名

  • 模块名称: 应使用小写蛇形命名法,例如 fixed_point32vector
  • 类型名称: 如果不是原生类型,应使用驼峰命名法,例如 CoinRoleId
  • 函数名称: 应使用小写蛇形命名法,例如 destroy_empty
  • 常量名称: 如果表示错误代码,应使用大写驼峰命名法并以 E 开头(例如 EIndexOutOfBounds);如果表示非错误值,则应使用大写蛇形命名法(例如 MIN_STAKE)。
  • 泛型类型名称: 应具有描述性,或在适当情况下使用反描述性,例如,TElement 用于向量泛型类型参数。通常情况下,模块中的“主要”类型应与模块同名,例如 option::Optionfixed_point32::FixedPoint32
  • 模块文件名: 应与模块名称相同,例如 option.move
  • 脚本文件名: 应使用小写蛇形命名法,并与脚本中的“主要”函数名称匹配。
  • 混合文件名: 如果文件包含多个模块和/或脚本,文件名应使用小写蛇形命名法,且名称不应与内部的特定模块/脚本匹配。

导入

  • 所有模块的 use 语句应位于模块的顶部。
  • 函数应从声明它们的模块中以完全限定的方式导入和使用,而不是在顶层导入。
  • 类型应在顶层导入。当发生名称冲突时,应使用 as 将类型在本地重命名。

例如,如果有一个模块:

module 0x1::foo { struct Foo { } const CONST_FOO: u64 = 0; public fun do_foo(): Foo { Foo{} } // ...}

它将被导入并使用如下:

module 0x1::bar { use 0x1::foo::{Self, Foo}; public fun do_bar(x: u64): Foo { if (x == 10) { foo::do_foo() } else { abort 0 } } // ...}

如果在导入两个模块时发生本地名称冲突:

module 0x1::other_foo { struct Foo {} // ...} module 0x1::importer { use 0x1::other_foo::Foo as OtherFoo; use 0x1::foo::Foo; // ...}

注释

  • 每个模块、结构体和公共函数声明应有注释。
  • Move 有文档注释 ///、常规单行注释 //、块注释 /* */ 和块文档注释 /** */

注释示例

文档注释必须直接位于它们所注释项的上方。例如,以下是有效的:

/// 我的精彩模块,文档注释可以在这里使用
module 0x42::example { // 双斜杠可以在任何地方   
   // 双斜杠可以在任何地方   
   /// 我精彩的常量  
   const MY_VALUE: u64 = 5;   
   /// 我精彩的错误信息  
   const E_MY_ERROR: u64 = 10;   
   #[view]  
   /// 我精彩的视图函数  
   fun show_me_the_money() {    
       // ...  
   }   
   /* 同样,块注释可以在任何地方 */ 
}

下面是一些文档注释 /// 将会失败的示例:

module 0x42::example {   
   /// 我精彩的视图函数 <- 必须在注解下方,正好位于被注释项上方  
   #[view]  
   fun show_me_the_money() {    
       // ...    
       /// 在函数内部  
   }   
   /// 没有附加到任何东西  
}

格式化

Move 团队计划编写一个自动格式化工具来强制执行格式化规范。然而,在此之前:

  • 除了 scriptaddress 块的内容不应缩进外,其他地方应使用四个空格的缩进。
  • 如果行超过 100 个字符,应进行换行。
  • 结构体和常量应在模块中的所有函数之前声明。