tsl-playbook/docs/naming.md

7.1 KiB
Raw Blame History

命名规范Naming

本仓库命名规则与 Google C++ Style Guide 对齐:通过名字的“形状”快速判断实体类型(类型/函数/变量/常量等),减少阅读成本。

1. 选名原则

  • 可读一致:名字清晰可读,并随可见范围调整具体程度。
  • 少用生僻缩写:能写全称就写全称。
  • 驼峰/帕斯卡中的缩写规则:缩写(首字母缩写/词组缩写)在 PascalCase/camelCase按一个单词处理,写成“首字母大写其余小写”,不要写一串全大写。
    • 示例:UserId(不是 UserID)、UrlTable(不是 URLTable)、 StartRpcServer(不是 StartRPCServer)、HttpClient(不是 HTTPClient)。
  • 避免无意义词:如 datainfotmphandle 等。

2. 命名风格总览

对于以下规则,“单词”指英文中不带空格的词。

  • snake_case:全小写,下划线分隔单词,用于普通变量/参数等;私有类成员变量在此基础上末尾加下划线。
  • PascalCaseUpperCamelCase):每个单词首字母大写,无下划线,用于类型、顶层函数/方法、property以及少量公有成员字段。

大小写与关键字约定

  • TSL 语言大小写无关,但本指南仍要求按约定使用大小写以提升可读性;不要用仅大小写不同的名字区分不同实体。
  • 所有语法关键字统一使用全小写书写,例如 ifforclassfunctionunitreturn 等。
  • 调用内置/标准库方法时,推荐保持官方大小写形式(aaBBCC/lowerCamelCase例如 getSysParams("xxx")

3. 类型命名Type Names

TSL 的顶层声明只有三种:classunitfunction

  • **类class与单元unit**使用 PascalCase,不带下划线。
  • **顶层函数function**使用 PascalCase,详见函数命名章节。
  • 示例:UserAccountOrderUnitLoadMarketData()

4. 文件命名与顶层声明File Names

TSL 的语法要求:每个文件只能有一个顶层声明,且文件基名必须与该顶层声明名字一致

  • 顶层声明可能是 classunitfunction(见类型命名)。
  • .tsl 脚本文件:顶层声明只能是 function,因此文件基名 = 顶层函数名。
  • .tsf 代码文件:顶层声明可为 class/unit/function,文件基名需与之同名。

命名建议:

  • 基名统一使用 PascalCase,与顶层声明的推荐写法一致。
  • 示例:
    • LoadMarketData.tsl 中定义 function LoadMarketData(...).
    • UserAccount.tsf 中定义 type UserAccount = class ... end;.
    • DocxEnumerations.tsf 中定义 unit DocxEnumerations; ... end.

TSL 大小写无关,实际编译时按大小写比较不会出错,但仍应保持文件名与声明名的推荐写法一致以便检索与协作。

5. 变量命名Variable Names

5.1 普通变量与参数

  • 局部变量、函数参数、非成员变量使用 snake_case
  • 若参数名与 TSL 关键字冲突导致编译失败,使用前导下划线的 snake_case 作为例外,例如 _type_unit
  • 前导下划线 _ 仅用于上述关键字冲突的参数场景,不要用于其他局部变量、成员变量、函数/类型/单元名称或全局变量。
  • 示例:table_namemax_retry_countuser_id

5.2 类成员Class Data Members

  • 私有成员变量使用 snake_case_(尾随下划线)。
  • 尾随下划线 _ 仅用于私有成员变量不要用于局部变量、参数、公有成员字段、property 名称或顶层全局变量。
  • 公有成员变量若必须存在,使用 PascalCase;但不推荐外部直接访问公有字段
  • 对外暴露的成员优先使用 property
    • property 名称使用 PascalCase(视为对外 API
    • property 的 read/write 指向真实成员(通常为私有 snake_case_)。
  • 示例:
type User = class
public
    property UserId read user_id_ write user_id_;
private
    user_id_;
end;

5.3 全局/静态变量

  • 不推荐使用顶层全局/静态可变变量;优先封装到 unit/class 中,通过函数或 property 访问。
  • 若必须声明顶层全局/静态变量,使用 g_snake_case 前缀显式标识其全局性质,例如 g_user_cacheg_market_state
  • 全局/静态常量仍按常量规则使用 kPascalCase

5.4 布尔变量

  • 使用 is_ / has_ / can_ / should_ 等前缀表达语义。
  • 示例:is_readyhas_errorcan_retry

5.5 短名例外

  • 在极小作用域内可用习惯短名:ijnt 等。
  • 作用域一旦扩大,必须改为有含义的名字。

5.6 集合与复数命名Collections

  • 数组/列表/可迭代集合使用复数名词的 snake_caseusersorder_items
  • 若复数形式不直观或为不可数名词,使用后缀明确类型:news_listprice_items
  • **映射/字典key→value**使用 snake_case 并加后缀 _map,必要时可用 _by_<key> 表达键语义:user_mapprice_by_symbol
  • 集合/去重集合使用后缀 _setuser_id_setsymbol_set

6. 常量命名Constant Names

  • 编译期/全局期固定的常量使用 kPascalCase,以 k 开头。
  • 示例:kDaysInAWeekkAndroid8_0_0
  • 对于局部 const 但值来自参数/运行时的变量:
    • 可用普通变量名 snake_case
    • 不要用 k 前缀误导读者认为其全局固定。

6.1 单元枚举模拟Unit Enumerations

TSL 没有内置 enum,推荐使用 unit + constinterface 区域模拟枚举集合。

  • unit 名称使用 PascalCase,建议以 Enumerations/Enums 结尾表达用途。
  • 枚举值使用 const 定义并放在 interface 中;命名优先沿用外部/业务域既有前缀与风格(属于例外场景)。

示例:

unit DocxEnumerations;
interface

    // WdAlertLevel
    const wdAlertsAll = -1;
end.

7. 函数与方法命名Function Names

  • 所有普通函数/方法(包含 public/private)均使用 PascalCase
  • 特殊函数/运算符重载为语法固定名,必须使用全小写
    • 构造/初始化函数:create
    • 析构/释放函数:destroy
    • 运算符重载:operator+() 等,按语法使用小写 operator<op>() 形式。
  • 示例:AddTableEntry()DeleteUrl()OpenFileOrDie()
  • 推荐使用 property 语法对外暴露访问器property 名 PascalCaseread/write 绑定成员变量(见类成员章节)。
  • 不推荐新增显式 getter/setter仅当 property 无法表达语义时,才使用 getter/setter命名可与字段同形的 snake_case(如 count()set_count(x))。

8. 宏与编译期开关Macro Names

  • 能不用宏就不用。
  • 必须使用时,命名为全大写加下划线,并带项目/业务前缀:
    • TSL_ROUND(x)TSL_ENABLE_FOO

9. 例外Exceptions

  • 当命名需要与外部既有 API/协议保持一致时,可沿用对方风格。
  • 例如对接 C/C++ 库、历史接口、跨语言互操作代码等。