Community生产力与协作github.com

Nutz95/CursorCodingSkills

SOLID C++ / ESP32 固件护栏规则:控制文件和类大小、禁止嵌套类、在组合根处严格依赖注入、生产头文件中禁用 UNIT_TEST / 测试 ifdef(.cpp 中也尽量避免)、禁止硬编码密钥、每个公开头文件只包含一个类型、公开 API 需要 /// 注释、双核无线电固定(PRO_CPU 0 / APP_CPU 1)、FreeRTOS 安全模式。适用于编辑 ESP-IDF、Arduino-ESP32、PlatformIO 固件或 ESP-NOW / BLE / Wi-Fi 任务。

CursorCodingSkills 是什么?

该技能为 ESP32 固件开发提供了一套基于 SOLID 原则的严格编码护栏,专注于 C++ 代码质量与安全实践。它强制要求头文件与源文件的行数上限(400 行)、每个类的方法数上限(30 个)以及函数体长度上限(60 行),并禁止嵌套类,确保每个公开头文件只包含一个主要类型。在架构层面,技能要求通过接口(`I*`)实现依赖倒置,仅在组合根(如 `main.cpp`)处构造具体适配器,从而避免生产代码被测试构建标志(如 `UNIT_TEST`)污染。此外,它还涵盖了双核 FreeRTOS 的任务固定规则(无线电任务在核心 0,非无线电任务在核心 1)、硬编码密钥的禁止,以及公开 API 必须带有 `///` 注释的要求。该技能适用于 Cursor、Claude Code 等 AI 编码助手,帮助开发者遵循 ESP-IDF、Arduino-ESP32、PlatformIO 等平台的最佳实践,提升固件的可维护性与安全性。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/Nutz95/CursorCodingSkills/tree/HEAD/skills/solid-cpp-esp32

Installed? Explore more 生产力与协作 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

SOLID C++ ESP32

硬性限制

  • 优先将文件控制在 400 行以内;当翻译单元出现多个职责时请拆分
  • 每个类最多 约 30 个方法
  • 优先将函数体控制在 约 60 行 以内(提取辅助函数)
  • 禁止嵌套类 —— 将内部类型移至其自己的头文件/翻译单元
  • 当项目选择启用时(启动/严格交付面),每个公开头文件 恰好包含一个 主要类型(class / struct / enum / enum class)

语言与风格

  • 所有提交的代码/注释/文档必须使用 英语
  • 始终使用大括号包裹 if / for / while / switch
  • 非简单逻辑的函数体不得为单行
  • 使用描述性名称(telemetryManager,而不是 mgr / tmp,除非是简单的循环索引)
  • 优先在每个翻译单元使用一个 namespace 块
  • 头文件声明意图;.cpp 文件保持简洁直接
  • 公开方法(位于 I*.h 接口及其他选中的公开头文件中)需要一行 /// 意图注释

架构(SOLID + 依赖注入)

  • 优先在领域边界使用 接口(I*)
  • 在应用/领域代码中依赖抽象;仅在 main.cpp 或显式的组合根中构造 具体适配器
  • 硬件(BLE、Wi-Fi、显示、NVS、总线)应隐藏在接口之后,以便主机单元测试使用模拟对象 —— 而非使用 #ifdef 进行手术
  • 优先使用在 native / 主机构建上可进行单元测试的小型纯解析器
  • 优先使用组合而非不断膨胀的神对象
  • 立即将 FreeRTOS 的 void* 转换为具名类型指针
  • 优先使用项目辅助函数(例如安全的 C 字符串拷贝)而非 strncpy 变体

领域/层隔离

  • 将仅集线器使用的栈(web、认证、OTA、HTTP API)排除在桥接/叶子目标之外
  • 不要从错误的层 #include 具体适配器头文件;如果护栏规则列出了适配器名称,请遵守它

生产 API 中不得含有测试仪器

生产代码 不得 被测试构建标志所影响。

  • 头文件和 .cpp 中禁止出现:UNIT_TEST、#ifdef UNIT_TEST、#ifndef UNIT_TEST、#if defined(UNIT_TEST) 或任何等效的测试专用门控(esp_cpp_guardrails 默认强制禁止)
  • 优先使用依赖注入:提取一个接口,在主机测试中注入模拟对象,或 排除 设备适配器的翻译单元使其不参与 native / 主机 build_src_filter —— 绝不要用 ifdef 来桩化生产源代码
  • 平台检测(__has_include(<esp_random.h>)、ESP_PLATFORM)是可以的;但改变生产逻辑的测试构建标志则不行
  • 在头文件中保留可移植类型(std::mutex 等),或在仅设备使用的翻译单元中包含无条件的设备头文件

气味 → 修复:

气味修复
服务中围绕 Wi-Fi / BLE 调用使用 #ifndef UNIT_TEST注入 IWifiConnector / IBleClient;在主机测试中使用模拟对象
当 UNIT_TEST 时头文件桩化为不同类型总是使用可移植类型,或拆分设备适配器
神类需要 ifdef 才能在主机上编译拆分职责;组合根连接适配器

密钥

  • 永远不要 在源代码中硬编码 Wi-Fi 密码、OTA / Web 密码、设备密钥、PMK、令牌或 LAN 凭据
  • 通过环境变量/构建标志注入密钥(由 PlatformIO 或同等工具消费)—— 绝不要提交带有真实密钥的 .env

双核 FreeRTOS(ESP32)

经典 ESP32 有两个核心:

核心ID典型用途
PRO_CPU0Wi-Fi / BT / 无线电相关工作(ESP-NOW 收发循环、BLE/SPP 无线电任务)
APP_CPU1较重的应用工作:显示 UI、HTTP/Web、解析突发数据、SD 卡、非无线电循环

默认规则(仅在记录的特殊情况下覆盖):

  • 使用 xTaskCreatePinnedToCore(..., kRadioCoreId) 将无线电/栈敏感的任务固定到核心,其中 kRadioCoreId = 0
  • 将 UI/重载非无线电任务固定到 kAppCoreId = 1
  • 避免在核心 0 上执行长时间的阻塞工作;这会饿死无线电栈
  • 优先使用具名常量(kRadioCoreId / kAppCoreId)而非魔数 0 / 1

验证

  • 在结构性更改后运行项目的护栏脚本(或 tools/esp_cpp_guardrails)
  • 添加最小的主机/单元检查,当新逻辑被破坏时能够失败
  • 接口更改后要构建
  • 当行为、脚本、硬件假设或架构发生变化时更新 README
  • 当项目要求时,优先在合并前进行阻塞性代码质量审查

检查清单

  • 大括号无处不在;标识符/注释使用英语
  • 不超过约 400 行 / 约 30 个方法;无嵌套类
  • 具体适配器仅在组合根处;领域依赖于 I*
  • 头文件中无 UNIT_TEST / 测试 ifdef;在 .cpp 中也尽量避免
  • 无硬编码密钥
  • 新的公开接口方法带有 /// 注释
  • 无线电任务在核心 0 上;重载应用工作在核心 1 上(除非有记录的特例)
  • 护栏/测试通过

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相关技能