面试的时候被问:"你们团队怎么保证代码质量?"

我当时说了句"靠code review"。面试官点点头,又问:"除了人工review,有没有用什么自动化工具?"我又卡了。

后来进了一个正规团队才知道,代码质量不是靠人眼看出来的,是靠工具跑出来的。人总会疲劳、会疏忽,但工具不会。

在机器人开发中,代码质量问题尤其重要。你写的代码要控制真实的硬件,一个内存泄漏可能导致机器人跑着跑着就停了,一个未初始化的变量可能让机械臂做出危险动作。今天介绍几个C++开发中最常用的代码质量工具。

clang-tidy:C++代码的瑞士军刀

clang-tidy是LLVM项目的一部分,基于Clang编译器做静态分析。它不仅能检查代码风格,还能发现潜在的bug、性能问题、现代C++用法建议等。

基本用法:

clang-tidy robot_node.cpp -- -I./include -std=c++17

但实际项目中,通常配合compile_commands.json使用。这个文件记录了每个源文件的编译参数,CMake可以自动生成:

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

然后直接对整个项目跑:

clang-tidy -p build/ src/robot_node.cpp

clang-tidy的检查项叫"check",分很多类别:

bugprone-*        容易出bug的写法
performance-*     性能问题
modernize-*       建议用现代C++写法
readability-*     可读性问题
clang-analyzer-*  静态分析发现的问题

你可以选择启用哪些检查。比如只关注bug和性能:

clang-tidy -checks='bugprone-*,performance-*' src/*.cpp

一个典型的clang-tidy发现:

// 它会告诉你这个写法有问题
void processData(std::vector<Point> points) {  // 应该用const引用
    // ...
}

// 建议改成
void processData(const std::vector<Point>& points) {
    // ...
}

这种传值不传引用的问题,编译器不会报错,但每次调用都会拷贝整个vector。在机器人项目里,点云数据动辄几万个点,这种拷贝的开销是很大的。

cppcheck:轻量但实用

cppcheck是另一个静态分析工具,和clang-tidy互补。它不依赖编译器,可以直接分析源码。

cppcheck --enable=all src/

cppcheck擅长的是一些clang-tidy不太关注的领域:数组越界、空指针解引用、内存泄漏、未初始化变量。它还会检查一些逻辑错误,比如条件永远为true的if语句。

cppcheck的速度很快,适合在CI里跑。而且它支持C和C++混合的项目,如果你的机器人项目里有嵌入式代码(通常是C写的),cppcheck也能分析。

两个工具一起用效果最好。clang-tidy偏向代码风格和现代C++实践,cppcheck偏向逻辑错误和安全问题。

clang-format:统一代码风格

代码风格不统一是团队协作的大问题。有人用4空格缩进,有人用tab;有人大括号换行,有人不换行。这些在code review时浪费大量时间。

clang-format自动统一代码风格。你定义一个.clang-format配置文件放在项目根目录:

BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 100
BreakBeforeBraces: Attach
AllowShortFunctionsOnASingleLine: Empty

然后一键格式化所有代码:

clang-format -i src/*.cpp include/**/*.h

-i表示直接修改文件。不加-i的话会输出到终端,你可以先看看格式化后的效果。

大部分团队会在CI里加一个检查步骤:跑clang-format,如果有文件被修改了就说明代码没格式化,直接拒绝合并。这样就不用人在review里纠结风格问题了。

机器人项目中的代码规范

机器人项目通常是C++和Python混合的。C++部分用clang-format加clang-tidy,Python部分用black加pylint(或者ruff)。

除了格式化和静态分析,还有一些机器人项目特有的规范建议。

命名规范。ROS2社区的惯例是:类名用CamelCase,函数和变量用snake_case,常量用UPPER_SNAKE_CASE。消息类型用PascalCase。遵循社区惯例能让你的代码更容易被其他人理解。

头文件保护。每个头文件都要有include guard:

#pragma once
// 或者传统的
#ifndef MY_PACKAGE_LIDAR_DRIVER_H
#define MY_PACKAGE_LIDAR_DRIVER_H
// ...
#endif

错误处理。机器人程序不能随便崩溃。所有可能失败的操作(文件读写、网络通信、硬件访问)都要有错误处理。用try-catch或者返回错误码,至少要有日志记录。

把这些工具串起来

工具装好了不代表就万事大吉了。关键是要把它们融入日常工作流。

最简单的方式是pre-commit hook。每次git commit之前自动跑格式化和静态分析:

pip install pre-commit

在项目根目录创建.pre-commit-config.yaml:

repos:
  - repo: https://github.com/pre-commit/mirrors-clang-format
    rev: v16.0.0
    hooks:
      - id: clang-format
  - repo: https://github.com/cpplint/cpplint
    rev: 1.6.0
    hooks:
      - id: cpplint

然后pre-commit install,以后每次commit都会自动检查。格式不对的代码根本提交不上去。

IDE集成也很重要。VS Code装clang-tidy和clang-format的扩展,写代码的时候就能实时看到warning,不用等到CI跑完才知道。CLion更直接,内置了这些工具的支持。

在机器人项目里,我建议在CI流水线中加四个阶段:编译、静态分析(clang-tidy + cppcheck)、格式化检查(clang-format)、单元测试。四个都通过了才能合并。一开始团队可能会抱怨太严格,但习惯之后你会发现代码质量确实上了一个台阶。

面试中怎么聊代码质量

面试官问代码质量,你可以说:"我们项目在CI里跑了clang-tidy和cppcheck,所有warning都当成error处理。代码风格用clang-format统一,PR必须通过格式化检查才能合并。另外我们用AddressSanitizer在测试时检测内存问题。"

这种回答说明你了解现代C++开发的工程实践,不是只会写代码不管质量。

代码质量工具的使用经验

在实际项目中,clang-tidy是最常用的静态分析工具,它能检查出潜在的空指针、未初始化变量、不必要的拷贝等问题。配置方法是写一个.clang-tidy文件放在项目根目录,选择需要的检查项。cppcheck则更轻量,适合快速扫描。CI中集成这些工具可以在代码合并前自动发现问题。面试时提到在CI中集成了clang-tidy,每次PR自动检查,会让人觉得你有很强的工程意识。

给你的建议

先在你自己的项目里跑一遍clang-tidy和cppcheck。第一次跑你可能会被几百个warning吓到,别慌。先把最严重的修了(内存相关的),然后逐步清理。

clang-format配置一次就行。把.clang-format文件放到项目根目录,配好VS Code或者CLion的自动格式化,以后保存文件就自动格式化了,完全不用操心。

最后,代码规范不是束缚,是效率。统一的代码风格让所有人都能快速读懂别人的代码,这在团队协作中太重要了。


上一篇:第103篇 性能分析工具——perf/flamegraph定位机器人性能瓶颈

下一篇预告:第105篇 CI/CD自动化——GitHub Actions/Jenkins在机器人项目中的应用

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐