第 14 课:验证循环 — 从代码到可提交

9 阅读8分钟

所属阶段:第三阶段「工作流实战」(第 12-20 课) 前置条件:第 13 课(TDD 全流程) 本课收获:一次完整通过验证循环的代码提交


一、本课概述

代码写完了、测试通过了,能提交吗?在 ECC 的世界里,答案是不能

测试通过只证明功能正确,但没有回答:代码风格规范吗?类型安全吗?有没有泄露密钥?有没有 SQL 注入?这些问题需要验证循环来回答。

本课回答三个问题:

  1. 验证循环有几步? — 四步检查 + 一步提交
  2. 每步防范什么风险? — 从逻辑错误到密钥泄露
  3. 失败了怎么办? — 修复后从头重跑,没有捷径

学完本课,你将能独立完成一次从代码到提交的完整验证流程。


二、验证循环四步

2.1 全景图

┌────────────────────────────────────────────────────────┐
                    验证循环                              
                                                         
  ┌──────┐   ┌──────┐   ┌──────────┐   ┌──────────┐    
   TEST    LINT    TYPECHECK│   SECURITY     
  │测试     │风格     │类型检查      │安全检查       
  └──┬───┘   └──┬───┘   └────┬─────┘   └────┬─────┘    
                                                    
                                                    
   PASS?      PASS?       PASS?          PASS?         
                                               
  Yes No     Yes No      Yes No         Yes No         
                                               
     └─→ 修复  从头重跑    └─→ 修复       └─→ 修复  
                                                   
                                                   
             全部 PASS  可提交                          
└────────────────────────────────────────────────────────┘

2.2 每步防范什么

步骤检查内容防范的风险典型工具
TEST单元/集成/E2E 测试逻辑错误、边界错误、回归Jest、Vitest、Mocha、pytest
LINT代码风格、格式、反模式风格不一致、潜在 Bug(未使用变量等)ESLint、Prettier、Ruff、golint
TYPECHECK类型安全类型不匹配、空值异常、接口不兼容tsc、mypy、go vet
SECURITY密钥泄露、注入、依赖漏洞密钥泄露、SQL 注入、XSS、已知 CVEsecurity-reviewer Agent、npm audit

2.3 为什么是这个顺序

顺序不是随意的,而是按发现成本从低到高排列:

  1. TEST 最先 — 如果逻辑都不对,检查风格毫无意义
  2. LINT 第二 — 风格问题最容易发现和修复
  3. TYPECHECK 第三 — 类型错误可能需要修改接口,影响范围较大
  4. SECURITY 最后 — 安全检查最严格,也最耗时

三、每步详解

3.1 TEST — 测试通过

这一步在第 13 课已经详细讲过。要点回顾:

# 运行所有测试
npm test

# 带覆盖率
npm test -- --coverage

# 要求:80%+ 覆盖率,所有测试 PASS

失败时:

  • 修复实现代码,不是修复测试(除非测试本身写错了)
  • 使用 tdd-guide Agent 辅助排查
  • 检查测试隔离性 — 是否有共享状态导致的耦合

3.2 LINT — 风格检查

Lint 检查代码是否符合项目约定的风格规范:

# JavaScript/TypeScript
npx eslint .

# Python
ruff check .

# Go
golangci-lint run

# Markdown(ECC 项目自身)
npx markdownlint-cli '**/*.md' --ignore node_modules

ECC 项目中的具体 Lint 配置

  • 使用 @eslint/js flat config
  • Markdown 使用 markdownlint-cli
  • 所有 Lint 检查必须在提交前通过

失败时:

  • 大部分 Lint 错误可以自动修复:npx eslint . --fix
  • 手动修复后重新运行 Lint
  • 不要用 // eslint-disable 绕过检查(除非有充分理由且加注释说明)

3.3 TYPECHECK — 类型检查

类型检查确保代码的类型安全:

# TypeScript
npx tsc --noEmit

# Python
mypy .

# Go(内置)
go vet ./...

失败时:

  • 类型错误通常意味着接口设计有问题
  • 不要用 any(TypeScript)或 # type: ignore(Python)绕过
  • 如果确实需要绕过,加注释说明原因

3.4 SECURITY — 安全检查

这是验证循环中最严格的一步。ECC 的 security.md 定义了 8 项强制安全检查:

提交前安全检查清单:
  □ 无硬编码密钥(API Key、密码、Token)
  □ 所有用户输入已验证
  □ SQL 注入防护(参数化查询)
  □ XSS 防护(HTML 已消毒)
  □ CSRF 保护已启用
  □ 认证/授权已验证
  □ 所有端点有速率限制
  □ 错误消息不泄露敏感数据

工具辅助:

# 依赖漏洞扫描
npm audit

# 密钥扫描
git diff --cached | grep -i "api_key\|secret\|password\|token"

# 使用 security-reviewer Agent
# 会自动扫描 CRITICAL 安全问题

失败时 — 安全响应协议

  1. 立即停止 — 不要继续提交
  2. 调用 security-reviewer Agent
  3. 修复所有 CRITICAL 问题
  4. 轮换任何可能已暴露的密钥
  5. 审查整个代码库是否有类似问题

四、任何一步失败 → 从头重跑

这是验证循环最重要的规则:

TEST 失败 → 修复 → 重跑 TEST → LINT → TYPECHECK → SECURITY
LINT 失败 → 修复 → 重跑 TEST → LINT → TYPECHECK → SECURITY
TYPECHECK 失败 → 修复 → 重跑 TEST → LINT → TYPECHECK → SECURITY
SECURITY 失败 → 修复 → 重跑 TEST → LINT → TYPECHECK → SECURITY

为什么修复后要从头重跑?

因为修复一个问题可能引入新的问题:

  • 修复类型错误可能破坏现有测试
  • 修复安全问题可能改变代码逻辑
  • 修复 Lint 错误可能改变代码格式影响行为

只有从头到尾全部 PASS,代码才是可提交的。


五、Conventional Commits 格式

验证循环通过后,就可以提交了。ECC 要求使用 Conventional Commits 格式:

5.1 格式

<type>: <description>

<optional body>

5.2 类型速查表

类型用途示例
feat新功能feat: add slugify utility function
fixBug 修复fix: handle empty string in slugify
refactor重构(不改行为)refactor: extract regex patterns to constants
docs文档docs: add JSDoc for slugify function
test测试test: add edge case tests for slugify
chore杂项(构建、依赖)chore: update eslint config
perf性能优化perf: cache compiled regex in slugify
ciCI/CDci: add coverage check to GitHub Actions

5.3 好的提交信息 vs 差的提交信息

# BAD — 描述做了什么(what)
git commit -m "update slugify.js"

# BAD — 太笼统
git commit -m "fix bug"

# GOOD — 描述为什么这样做(why)
git commit -m "fix: handle consecutive spaces in slugify to prevent double hyphens"

# GOOD — 带正文补充上下文
git commit -m "feat: add input validation to slugify

TypeError is thrown for non-string arguments to fail fast
at the call site rather than producing unexpected results
from implicit type coercion."

六、代码质量清单

在验证循环之外,coding-style.md 还定义了一份代码质量清单。这不是自动化检查,而是人工确认

提交前代码质量清单:
  □ 代码可读、命名清晰
  □ 函数短小(<50 行)
  □ 文件聚焦(<800 行)
  □ 无深层嵌套(>4 层)
  □ 错误处理完备
  □ 无硬编码值(使用常量或配置)
  □ 无 mutation(使用不可变模式)

6.1 每项的判断标准

检查项通过标准常见违规
可读性变量名表达含义,逻辑清晰单字母变量、嵌套三元表达式
函数 <50 行用行数计算,不含空行和注释一个函数做太多事
文件 <800 行200-400 行是理想范围所有逻辑放一个文件
嵌套 <4 层if/for/while 的嵌套深度用 early return 拍平
错误处理每个可能失败的操作都有处理空 catch 块、忽略 Promise rejection
无硬编码数字和字符串提取为常量if (retries > 3) 而非 MAX_RETRIES
无 mutation使用 spread、map、filter 而非修改array.push() 而非 [...array, item]

七、完整验证循环示例

用第 13 课写的 slugify 代码走一遍完整流程:

# Step 1: TEST
node --test slugify.test.js
# ✓ 7 tests passed → PASS

# Step 2: LINT
npx eslint slugify.js slugify.test.js
# No errors → PASS

# Step 3: TYPECHECK(如果是 TypeScript 项目)
# npx tsc --noEmit
# 纯 JavaScript 项目可跳过此步

# Step 4: SECURITY
# 检查无硬编码密钥
grep -r "api_key\|secret\|password" slugify.js
# No matches → PASS

# 检查依赖漏洞
npm audit
# 0 vulnerabilities → PASS

# 全部 PASS → 可提交
git add slugify.js slugify.test.js
git commit -m "feat: add slugify utility with full test coverage

Implements URL-friendly text conversion with:
- Space to hyphen conversion
- Special character removal
- Consecutive hyphen collapsing
- Input type validation

Coverage: 100% (8/8 tests passing)"

八、本课练习

练习 1:完整验证循环(25 分钟)

用第 13 课写的 slugify 代码(或第 13 课练习中的 truncate 代码),完整执行一遍验证循环:

  1. 运行测试,确认全部 PASS
  2. 运行 Lint,修复所有问题
  3. 运行类型检查(如适用)
  4. 执行安全检查清单(逐项确认)
  5. 用 Conventional Commits 格式提交

记录每一步的输出和修复过程。

练习 2:故意失败(15 分钟)

slugify.js 中故意引入以下问题,然后尝试通过验证循环:

  1. 改变一个正则让测试失败
  2. 添加一个未使用的变量让 Lint 报错
  3. 硬编码一个假的 API Key 让安全检查报警

观察验证循环如何捕获每种问题。

练习 3:代码质量清单审查(10 分钟)

对照代码质量清单的 7 项,审查你在第 13 课写的代码:

  • 函数是否 <50 行?
  • 有没有硬编码值?
  • 有没有 mutation?
  • 命名是否清晰?

列出所有不符合项并修复。

练习 4(选做):审查一个开源项目

找一个你熟悉的开源项目的某个 PR,用 ECC 的代码质量清单和安全检查清单审查它。记录你发现了什么问题。


九、本课小结

你应该记住的内容
验证循环四步TEST → LINT → TYPECHECK → SECURITY → 可提交
失败处理任何一步失败 → 修复 → 从头重跑
安全检查清单8 项强制检查(密钥、输入验证、注入、XSS、CSRF、认证、限流、错误消息)
Conventional Commits<type>: <description> — feat/fix/refactor/docs/test/chore/perf/ci
代码质量清单7 项人工确认(可读性、函数大小、文件大小、嵌套、错误处理、硬编码、mutation)
安全响应协议停止 → security-reviewer → 修复 → 轮换密钥 → 全局排查

十、下节预告

第 15 课:会话管理 — 上下文、模型与持久化

代码写好了、提交了,但还有一个隐藏的问题:你的 AI 助手的上下文窗口是有限的。下节课我们将学习如何管理上下文窗口、选择合适的模型、在会话之间持久化状态。这些技能决定了你能否在大型项目中高效使用 ECC。

预习建议:阅读 rules/common/performance.md,特别是 Model Selection Strategy 和 Context Window Management 两节。