您正在阅读的是开发版本的文档。有关最新发布的版本,请访问 Jazzy.

代码风格和语言版本

为了使产品的外观保持一致,我们将遵循外部(如果可能)为每种语言定义的风格指南。至于其他方面,如软件包布局或文档布局,我们需要借鉴当前流行的风格,制定自己的指导原则。

此外,开发人员应尽可能使用集成工具,以便在编辑器中检查是否遵循了这些指南。例如,每个人都应该在编辑器中内置 PEP8 检查器,以减少与风格相关的审查迭代。

此外,在可能的情况下,软件包应将样式检查作为其单元测试的一部分,以帮助自动检测样式问题(参见 自动).

C

标准

我们的目标是 C99。

风格

我们将使用 Python 的 PEP7 为我们的 C 风格指南,并作了一些修改和补充:

  • 我们将以 C99 为目标,因为我们不需要支持 C89(PEP7 建议)。

    • 理由:除其他外,它还允许我们同时使用 ///* */ 风格评论

    • 理由C99 现在几乎无处不在

  • C++ 风格 // 允许发表评论

  • (可选)总是将字面量放在比较运算符的左侧,例如 0 == 重新 而不是 重新 == 0

    • 理由 重新 == 0 太容易变成 重新 = 0 失手

    • 可选项,因为当使用 -墙 (或同等功能)时,现代编译器会发出警告

只有在不编写 Python 模块的情况下,以下所有修改才适用:

  • 请勿使用 Py_ 作为一切的前缀

    • 而不是使用软件包名称的 CamelCase 版本或其他适当的前缀

  • 有关文档字符串的内容不适用

我们可以使用 pep7 用于样式检查的 python 模块。编辑器集成似乎很薄弱,我们可能需要更详细地研究 C 语言的自动检查。

C++

标准

滚动目标是 C++17。

风格

我们将使用 谷歌 C++ 风格指南但有一些修改:

线路长度

  • 行的最大长度为 100 个字符。

文件扩展名

  • 头文件应使用 .hpp 扩展名。

    • 理由允许工具确定 C++ 或 C++ 文件的内容。

  • 实现文件应使用 .cpp 扩展名。

    • 理由允许工具确定 C++ 或 C++ 文件的内容。

变量命名

  • 全局变量使用小写,下划线以 g_

    • 理由:在整个项目中保持变量命名大小写一致

    • 理由:一目了然,易于分辨变量的作用域

    • 跨语言的一致性

函数和方法命名

  • 谷歌风格指南说 骆驼箱但 C++ std 库的 蛇箱 也允许

    • 理由ROS 2 核心软件包目前使用 蛇箱

      • 原因:可能是历史上的疏忽,也可能是个人偏好,但没有得到衬垫的检查

      • 不修改的理由:追溯性修改太具破坏性

    • 其他考虑因素:

      • cpplint.py 不检查这种情况(除审查外很难执行)

      • 蛇箱 可以使不同语言之间更加一致

    • 具体指导:

      • 对于现有项目,首选现有样式

      • 对于新项目,两者均可,但建议优先考虑与相关的现有项目相匹配

      • 最终决定权归开发商所有

        • 函数指针、可调用类型等特殊情况可能需要修改规则

      • 请注意,类仍应使用 骆驼箱 默认情况下

门禁控制

  • 删除对所有类别成员的私有要求,因此需要访问者

    • 理由:这对用户应用程序接口的设计限制过多

    • 我们应该优先考虑非公开成员,只有在需要时才将其公开

    • 在允许成员直接访问之前,我们应该考虑使用访问器

    • 我们应该有充分的理由允许成员直接访问,而不是因为这对我们来说很方便

例外情况

  • 允许例外

    • 理由:这是一个新的代码库,所以遗留问题对我们不适用

    • 理由:对于面向用户的应用程序接口来说,使用异常更符合 C++ 的习惯做法

    • 应明确避免在析构函数中出现异常

  • 如果我们打算用 C 语言包装由此产生的应用程序接口,就应该考虑避免使用 "异常"。

    • 理由:这样更容易用 C 语言包装

    • 理由:在我们打算用 C 语言封装的代码中,大部分依赖关系都不会使用异常情况

类功能对象

  • 对 Lambda 或 std::functionstd::bind

提升

  • 除非绝对需要,否则应避免升压。

评论和文件评论

  • 使用 ////** */ 评论 文献资料 目的和 // 注释和一般性评论的文体评论

    • 类和函数注释应使用 ////** */ 风格评论

    • 基本原理:这些建议用于 C/C++ 中的 Doxygen 和 Sphinx

    • 原理:混合 /* */// 便于对包含注释的代码进行块注释

    • 关于代码如何工作的说明或类和函数中的注释应使用 // 风格评论

指针语法对齐

  • 使用 烧焦 * c; 而不是 char* c;烧焦 *c; 正因为如此 char* c, *d, *e;

类隐私关键字

  • 请勿在 公众:, 私人受保护:如果所有缩进都是 2 的倍数,则更为一致。

    • 理由:大多数编辑器不喜欢不是(软)制表符大小倍数的缩进

    • 公众:, 私人受保护:或 2 个空格

    • 如果前面使用了 2 个空格,那么其他类语句也要多缩进 2 个空格

    • 首选零空格,即 公众:, 私人受保护: 与类

嵌套模板

  • 切勿在嵌套模板中添加空格

    • 首选 set<list<string>>; (C++11特性)改为 set<list<string>; >;set<; 列表<字符串>; >;

始终使用牙套

  • 请务必使用以下括号 如果, 不然, , 虽然对于即使正文只有一行。

    • 理由:由于在正文中使用宏,减少了视觉模糊和并发症的机会

开放式与拥抱式牙套

  • 使用开括号 功能, , 枚举结构 定义,但抱支架上 如果, 不然, 虽然, 对于等等

    • 例外情况:当 如果 (或 虽然等)的条件足够长,需要包线,那么就使用开放式支架(即不要搂抱)。

  • 当函数调用无法在一行中完成时,应在打开的括号处(而不是参数之间)换行,并在下一行中以 2 格缩进开始。对于更多的参数,在随后的行中继续使用 2 格缩进。注意 谷歌风格指南 在这一点上是自相矛盾的)。

    • 同样 如果 (和 虽然等)的条件,这些条件太长,无法写在一行中。

实例

没关系:

int 主要(int 参数, 烧焦 **参数)
{
  如果 (条件) {
    返回 0;
  } 不然 {
    返回 1;
  }
}

如果 ( &&;  || 两个) {
  ...
}

// 长条件;开放式支撑
如果 (
   &&;  || 两个 &&;  &&;  || 两个 &&;  &&;  || 两个 &&;  &&; )
{
  ...
}

// 短函数调用
call_func(动物, 酒吧);

// 长函数调用;在开括号处换行
call_func(
  动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧,
  动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧, 动物, 酒吧);

// 超长函数参数;为便于阅读,请将其分开
call_func(
  ,
  Fooooooooooooooooooooooooooooooooooooooo,
  酒吧, 蝙蝠);

这是 好的:

int 主要(int 参数, 烧焦 **参数) {
  返回 0;
}

如果 ( &&;
     ||
    两个) {
  ...
}

使用大括号而不是过多的缩进,例如用于区分构造函数代码和构造函数初始化列表

没关系:

返回类型 LongClassName::ReallyReallyReallyLongFunctionName(
  类型 参数名1,  // 缩进 2 个空格
  类型 参数名2,
  类型 参数名3)
{
  做点什么();  // 缩进 2 个空格
  ...
}

我的类::我的类(int 变异)
: some_var_(变异),
  其他变量(变异 + 1)
{
  ...
  做点什么();
  ...
}

这是 好吧,甚至有点奇怪(谷歌的方式?)

返回类型 LongClassName::ReallyReallyReallyLongFunctionName(
    类型 参数名1,  // 缩进 4 个空格
    类型 参数名2,
    类型 参数名3) {
  做点什么();  // 缩进 2 个空格
  ...
}

我的类::我的类(int 变异)
    : some_var_(变异),             // 缩进 4 个空格
      其他变量(变异 + 1) {  // 排成一队
  ...
  做点什么();
  ...
}

林特斯

我们结合谷歌的 cpplint.py去壳.

我们提供可自定义配置的命令行工具:

某些格式化器(如 ament_uncrustify 和 ament_clang_format)支持 --重新格式化 选项来就地应用更改。

我们还使用其他工具来检测并消除尽可能多的警告。以下是我们在所有软件包上尝试做的其他工作的不完全列表:

  • 使用编译器标志,如 -墙 -Wextra -Wpedantic

  • 运行静态代码分析,如 cppcheck我们已将其纳入 ament_cppcheck.

Python

版本

我们将以 Python 3 为开发目标。

风格

我们将使用 PEP8 指导方针 代码格式。

我们选择了以下更精确的规则,而 PEP 8 则保留了一些自由度:

工具,如 (ament_)pycodestyle Python 软件包应在单元测试和/或编辑器集成中使用,以检查 Python 代码风格。

衬垫中使用的 pycodestyle 配置为 这里.

与编辑器集成:

CMake

版本

我们将以 CMake 3.8 为目标。

风格

由于没有现成的 CMake 风格指南,我们将定义自己的风格指南:

  • 使用小写的命令名称 (查找软件包不是 FIND_PACKAGE).

  • 使用 蛇箱 标识符(变量、函数、宏)。

  • 使用空 否则()结束......() 命令。

  • 前无空白 ('s.

  • 缩进两格,不要使用制表符。

  • 多行宏调用的参数不要使用对齐缩进。只能使用两个空格。

  • 首选具有 设置(PARENT_SCOPE) 到宏。

  • 在使用宏时,用 _ 或一个合理的前缀。

Markdown / reStructured Text / docblocks

风格

以下文本格式规则旨在提高可读性和版本控制。

  • [仅 .md、.rst] 每节标题前空一行,后空一行。

    • 理由:这有助于在筛选文件时对文件结构有一个大致的了解。

  • [.rst only] 在重新编排的文本中,标题应遵循《指南》中描述的层次结构。 斯芬克斯风格指南:

    • # 带上划线(仅一次,用于文件标题)

    • * 带底线

    • =

    • -

    • ^

    • ";

    • 理由统一的层次结构有助于在筛选文档时了解嵌套级别。

  • [.md only] 在 Markdown 中,标题应使用 ATX 样式。 Markdown 语法文档

    • ATX 风格标头使用 1-6 个散列字符 (#) 表示页眉级别 1-6。

    • 在哈希值和标题之间应使用空格(如 # 标题 1),以便更直观地将它们分开。

    • 选择 ATX 风格的理由来自于 谷歌 Markdown 风格指南

    • 理由ATX 样式的标头更易于搜索和维护,并使头两级标头与其他各级标头保持一致。

  • [任何] 每个句子必须以新的一行开始。

    • 理由:对于较长的段落来说,开头的一处改动会使整个段落变得难以阅读,因为它贯穿了整个段落。

  • [任何] 每个句子都可以选择打包,以保持每行的简短。

  • [任何] 行尾不得留白。

  • [仅 .md、.rst] 代码块之前和之后必须有一个空行。

    • 理由空白仅在栅栏代码块的正前方和正后方有意义。按照这些说明操作可确保高亮功能正常一致地运行。

  • [仅 .md、.rst] 代码块应指定一种语法(例如 敲击).