MIT《The Missing Semester》2026 Coding Agents 相关新章节

谈笑风生 23 views 0 replies
#1 ·

MIT《The Missing Semester》

  1. Coding Agents(AI 编程智能体):如何利用 AI 编写、修改、测试和理解代码。
  2. Code Quality(代码质量):如何通过代码检查、自动化测试和 CI 保证软件质量。
  3. 软件工程沟通与协作(Communication & Collaboration):如何写好技术文档、提交记录、Issue 和 Pull Request,以及如何进行 Code Review。

这三节课其实有非常紧密的联系:

Coding Agents 帮助你更高效地编写代码,Code Quality 帮助你验证代码,Communication & Collaboration 帮助整个团队理解、审查和维护代码。

下面分别讲解技术原理、具体例子、实际使用方法以及课程练习。

第一节:Coding Agents(AI 编程智能体)

一、什么是 Coding Agent?

Coding Agent 是一种能够使用外部工具完成编程任务的 AI 系统。

普通聊天 AI 通常主要通过对话提供解释和代码建议。

Coding Agent 除了生成文本,还可以在得到相应权限的情况下:

  • 读取项目中的源代码。
  • 修改文件、创建新文件。
  • 在终端执行命令。
  • 运行自动化测试和类型检查。
  • 分析错误并尝试修复。
  • 搜索相关文档。
  • 检查 Git 修改记录。

因此,它不只是告诉你如何修改代码,而是可以实际执行相关开发步骤。

1. 普通 AI 与 Coding Agent 的区别

能力 普通 AI 对话 Coding Agent
解释代码 可以 可以
生成代码 可以 可以
自动读取项目文件 取决于工具 通常支持
直接修改项目 取决于工具 通常支持
执行测试 需要执行工具 通常支持
根据报错迭代修复 需要反馈 可以通过工具循环完成

课程建议采用一个理解模型:

把 Coding Agent 想象成一名能力较强、但仍然需要指导和监督的初级工程师。

你负责告诉它目标、限制和验收标准,它负责执行具体任务,你则要检查结果。

二、Coding Agent 如何工作?

这是课程最重要的技术原理。

传统 LLM(Large Language Model,大语言模型)主要根据输入上下文生成输出。

但 Coding Agent 在此基础上增加了一个负责执行工具调用的程序,教材称为 Agent Harness。

User Prompt

用户提出编程需求

LLM

分析上下文,生成下一步动作

Agent Harness(智能体运行框架)

文件读写

终端命令

运行测试

工具结果反馈给模型,继续分析和修正

例如,你告诉 Agent:

将这个 Python 脚本改造成命令行工具,使用 argparse 解析参数,添加类型注解,并确保类型检查通过。

Agent 可能执行这样的流程:

  1. 读取 Python 文件。
  2. 分析程序当前结构。
  3. 修改代码,增加 argparse。
  4. 添加 Type Hints(类型注解)。
  5. 执行 mypy 类型检查。
  6. 如果有错误,就继续修改。
  7. 检查通过后向你报告结果。

这个过程最关键的地方,是 Feedback Loop(反馈循环)。

它不是只生成一段代码,而是利用真实的工具运行结果验证自己的工作。

三、LLM 的 Context Window 是什么?

Context Window(上下文窗口)指模型在一次推理中能够处理的上下文长度限制。

例如,一个项目可能包含:

project/
├── app.py
├── database.py
├── utils.py
├── tests/
├── docs/
└── README.md

如果 AI 同时读取大量文件、文档、终端输出和历史对话,就会消耗上下文容量。

这会带来两个问题:

  • 上下文可能超过模型的容量限制。
  • 即使没有超过限制,大量无关信息也可能干扰模型完成当前任务。

因此,有效使用 Coding Agent,不只是写出好的 Prompt,还需要管理提供给它的上下文。

课程介绍了三种常见方法:

方法 含义 适用场景
Clear Context 开始新的对话 切换到完全不同的任务
Rewind 回退之前的对话步骤 Agent 沿错误方向工作
Compaction 压缩已有对话信息 对话过长,需要保留重要上下文

这部分还有一个重要结论:

提供更多上下文不一定更好,提供准确且相关的上下文才更重要。

四、Coding Agent 有哪些实际用途?

1. Implementing Features:实现新功能

假设你有一个 Python 项目,需要增加 CSV 导出功能。

你可以要求 Agent:

在现有项目中增加导出 CSV 的功能。保留现有 API,增加单元测试,运行全部测试,并列出修改的文件。

这比简单要求“帮我写一个 CSV 函数”更完整。

因为你不仅告诉它要做什么,还明确了不能破坏什么,以及如何验收。

2. Fixing Errors:修复错误

例如:

mypy .

报告:

error: Incompatible return value type

你可以要求 Agent 找出原因、修复问题,再重新运行 mypy。

这种能够自动运行检查工具的任务非常适合 Agent。

3. Refactoring:重构代码

Refactoring 指在尽量保持外部行为不变的前提下,改善代码结构。

例如,将一个 500 行的 Python 文件拆分成:

project/
├── api.py
├── models.py
├── services.py
└── utils.py

Agent 可以帮助调整导入路径、函数位置以及相关测试。

但是必须验证重构没有破坏原有功能。

4. Code Review:代码审查

可以让 Agent 检查:

  • 潜在 Bug。
  • 不合理的异常处理。
  • 缺失的测试。
  • 安全风险。
  • 重复代码。

例如:

Review the changes since the last commit. Focus on correctness, security and missing tests.

但这不意味着 AI 的审查结果一定正确。它可能遗漏真实问题,也可能把正常代码误判为 Bug。

5. Code Understanding:理解陌生代码库

这对新加入项目的开发者尤其有用。

例如:

Explain how authentication works in this repository. Identify the main entry points and relevant files.

Agent 可以阅读相关文件,帮助你理解认证流程。

这比漫无目的地逐个阅读文件通常更高效。

6. Vibe Coding

教材还介绍了 Vibe Coding。

其含义是:开发者主要通过自然语言描述目标,由 AI 完成绝大部分实际代码编写。

这种方式适合快速原型和探索性项目,但对于长期维护的软件,开发者仍然需要理解代码、安全边界和测试结果。

五、进阶 Agent:AGENTS.md、Skills、Subagents 和 MCP

这四个术语很容易混淆。

1. AGENTS.md:项目级指导文件

假设你的项目中有:

project/
├── AGENTS.md
├── src/
└── tests/

AGENTS.md 可以用于告诉兼容的 Coding Agent 如何在这个项目中工作。

例如:

# Project Instructions

- Use Python 3.12.
- Format code with Ruff.
- Run pytest after changing code.
- Do not modify generated files.
- Do not commit API keys.

它的作用类似于一份给 AI 开发者阅读的项目说明。

不同 Agent 对指令文件的名称、作用范围和加载规则可能不同。

2. Skills:按需加载的专门工作流程

AGENTS.md 一般用于项目级约定。

Skill 则可以把某项专门任务的操作方法单独封装。

例如:

skills/
└── code-review/
    └── SKILL.md

里面可以说明:

  • 如何分析代码变更。
  • 重点检查哪些风险。
  • 如何运行测试。
  • 如何组织审查结果。

Agent 在需要进行代码审查时,再按自身支持的机制加载对应的 Skill。

这样可以减少每次对话都加载大量无关指导信息的问题。

3. Subagent:子智能体

Subagent 是由主 Agent 调用、负责特定任务的智能体。

例如,主 Agent 正在实现新功能,同时可以将代码检查任务交给专门的子智能体。

Main Agent

负责整体开发任务

Code Agent

实现功能

Checking Agent

运行 mypy、ruff

教材提供的练习就是创建一个 Python Code Checking Subagent,使它能够:

  • 对上一次 Git Commit 后修改过的 Python 文件执行 mypy。
  • 运行 ruff。
  • 检查代码格式和静态分析问题。
  • 向主 Agent 返回检查结果。

4. MCP:Model Context Protocol

MCP 是一种用于连接 AI 应用与外部工具或数据源的开放协议。

例如,Agent 可以通过支持的 MCP 服务访问文档或其他工作系统。

因此,它和前面的概念并不相同:

概念 主要解决的问题
AGENTS.md Agent 应当遵守哪些项目规则?
Skill Agent 如何完成某类专门任务?
Subagent 哪个专门 Agent 来完成子任务?
MCP Agent 如何连接外部工具和数据源?

5. Parallel Agents:并行智能体

教材还介绍了让多个 Agent 同时开发。

例如:

  • Agent A 修改前端。
  • Agent B 修改后端。
  • Agent C 增加测试。

如果多个 Agent 直接修改同一工作目录,就可能发生冲突。

因此课程推荐结合 Git Worktree,为不同 Agent 提供相对独立的工作目录。

六、Coding Agents 的风险

教材特别强调了几个风险:

第一,AI 可能产生错误代码。即使代码可以运行,也不代表它满足业务要求。

第二,AI 可能陷入调试循环。它不断尝试修改,但没有真正定位问题,甚至造成更多修改。

第三,隐私与安全。部分 Coding Agent 会把代码、上下文或工具结果传输给云端模型。使用前需要理解相关权限和数据处理方式。

第四,过度依赖。如果完全不理解生成的代码,短期看似节省了时间,长期却可能降低你独立开发和排查问题的能力。

因此,教材特别提醒:不要把允许 Agent 不经确认执行危险操作的模式当作日常默认配置。即使使用隔离容器或虚拟机,也必须考虑网络、文件挂载和凭证的安全边界。

这一节的核心不是“让 AI 替代程序员”,而是:

学会如何提出明确任务、提供正确上下文,并通过真实工具验证 AI 的工作结果。

第二节:Code Quality(代码质量)

这一节讨论一个非常实际的问题:

程序可以运行,是否意味着代码质量很好?

答案是否定的。

例如,下面两段 Python 代码在正常输入下可以产生相同结果:

def add(a,b):return a+b
def add(a: int, b: int) -> int:    return a + b

第二段代码结构更清晰,而且具有类型注解。

但即使第二段代码写得很整洁,也不能证明它没有逻辑错误。

因此,课程介绍了一系列不同层次的质量保证工具:

Formatting、Linting、Testing、Pre-commit Hooks、Continuous Integration 和 Command Runners。

一、Formatting:代码格式化

Formatting 是自动统一代码风格的过程。

例如,你写了:

def calculate(a,b):  return a+b

格式化工具可以调整为:

def calculate(a, b):    return a + b

通常可以自动处理:

  • 空格与缩进。
  • 引号风格。
  • 过长代码行。
  • 换行方式。
  • 一些语法布局规则。

常见工具包括:

语言 工具
Python Ruff Formatter、Black
JavaScript / TypeScript Prettier
Go gofmt
多种文件格式 Prettier 等

例如,Python 项目使用 Ruff:

ruff format .

就可以按照配置格式化项目。

还可以配置 IDE 在保存文件时自动格式化。

为什么这很重要?

假设一个团队有十个人,每个人都习惯不同的缩进、换行和引号方式。

代码审查时,就会出现大量无意义的格式变化。

统一格式的好处,是让程序员把注意力集中在真正重要的逻辑修改上。

二、Linting:静态代码检查

Formatting 和 Linting 的区别非常重要。

Formatting 关注代码怎么写得整齐;Linting 关注代码中是否存在可疑或不合理的写法。

例如:

import osdef calculate():    x = 10    return 42

这里的 os 没有使用,x 也没有被使用。

代码能够运行,但存在没有必要的内容。

Linter 可能报告:

Unused import: os
Local variable x is assigned but never used

使用 Ruff:

ruff check .

可以运行规则检查。

某些可安全自动修复的问题可以使用:

ruff check --fix .

但是,不是所有 Lint 警告都意味着代码一定错误。

部分规则可能产生 False Positive(误报),而且自动修复仍需要检查结果。

Formatter、Linter 和 Type Checker 的区别

工具 主要检查内容 示例
Formatter 格式与排版 空格、缩进、换行
Linter 可疑写法和代码规范 未使用变量、复杂条件
Type Checker 类型是否一致 函数返回 str 却声明为 int

例如:

def get_age() -> int:    return "twenty"

mypy 这类类型检查工具可以指出返回值与声明的类型不一致。

但类型检查通过,也不意味着程序逻辑一定正确。

Semgrep 是什么?

教材还介绍了 Semgrep。

普通文本搜索主要匹配字符,而 Semgrep 可以根据程序语言结构搜索代码模式。

例如:

semgrep -l python \
  -e "subprocess.Popen(..., shell=True, ...)"

它可以帮助找出符合特定调用模式的 Python 代码。

这种能力对于自定义安全检查、查找危险 API 用法和执行团队代码规则非常实用。

三、Testing:自动化测试

这是代码质量部分最重要的概念之一。

假设你写了:

def divide(a, b):    return a / b

你手动运行:

print(divide(10, 2))

输出:

5.0

于是你认为程序正确。

但这只验证了一个输入组合。

例如:

divide(10, 0)

会发生什么?

它会抛出 ZeroDivisionError。

这不一定意味着实现错误,因为函数的设计可能本来就要求分母非零。但它说明,我们需要明确函数的预期行为并测试。

1. Unit Test:单元测试

单元测试通常针对单个函数或较小的功能单元。

例如:

# calculator.pydef add(a: int, b: int) -> int:    return a + b

使用 pytest:

# test_calculator.pyfrom calculator import adddef test_add():    assert add(2, 3) == 5def test_add_negative():    assert add(-2, 3) == 1

执行:

pytest

如果实现符合断言,测试就会通过。

assert 的意思是:断言后面的条件必须成立。

2. Integration Test:集成测试

单元测试主要检查单个组件。

集成测试则关注多个组件协同工作时是否正常。

例如:

API
 ↓
Business Logic
 ↓
Database

一个 API 的业务逻辑可能完全正确,但数据库连接配置错误,导致整个功能不可用。

集成测试可以覆盖这种跨组件的问题。

3. Functional / End-to-End Test

端到端测试会从用户使用场景出发,测试一条较完整的业务流程。

例如,一个购物网站:

用户登录
   ↓
选择商品
   ↓
加入购物车
   ↓
提交订单
   ↓
确认结果

这类测试通常更接近用户实际使用系统的方式。

4. 其他测试方法

教材还介绍了:

  • Test-Driven Development(TDD):先编写测试,再实现功能。
  • Regression Testing(回归测试):为已经修复的 Bug 增加测试,防止再次出现。
  • Property-Based Testing(基于性质的测试):描述程序应当始终满足的性质,并自动生成输入进行验证。
  • Mocking(模拟依赖):在测试中用可控对象代替数据库、网络 API 等外部依赖。

例如,除法函数的一项性质是:

对于任意满足条件的数 a 和非零数 b:

[ (a/b)\times b\approx a ]

这里通常要考虑浮点数误差。

Property-Based Testing 工具可以根据这种性质生成大量不同的输入,而不局限于几个手写测试案例。

四、Code Coverage:代码覆盖率

假设你有一个函数:

def classify(x):    if x > 0:        return "positive"    elif x < 0:        return "negative"    else:        return "zero"

你只测试:

classify(10)

虽然测试通过,但你并没有测试负数和零。

Code Coverage(代码覆盖率)用于衡量执行测试时,哪些代码被运行过。

假设某个项目的行覆盖率为 75%

75% 已执行

25% 未执行

使用 pytest-cov 可以生成覆盖率报告,例如:

pytest --cov=. --cov-report=html

然后查看 HTML 报告,找到哪些代码没有得到测试。

但是教材特别提醒:

高覆盖率不等于高质量测试。

假设一个测试只是调用函数,却完全不检查结果,那么它也可能提高覆盖率。

因此,比起盲目追求 100%,更重要的是测试关键行为、边界情况和错误处理是否正确。

五、Pre-commit Hooks:提交前自动检查

你已经学过 Git,因此这一部分比较容易理解。

正常提交流程:

修改代码
   ↓
git add
   ↓
git commit

如果我们希望每次提交前都自动检查代码格式和 Lint 问题,就可以使用 Git Hook。

例如:

修改代码
   ↓
git add
   ↓
Pre-commit Checks
   ├── Formatter
   ├── Linter
   └── Other Checks
   ↓
git commit

Pre-commit Hook 可以在提交前运行配置好的检查任务。

如果检查不通过,提交通常会被阻止,直到问题得到修复。

它主要解决:

防止不符合项目规范的代码轻易进入版本历史。

不过本地 Hook 可以被跳过,团队也不能假设每个人都正确安装了 Hook。

这就是为什么还需要 CI。

六、Continuous Integration(CI):持续集成

这是现代软件开发中非常重要的工程实践。

假设你的项目托管在 GitHub。

每次开发者提交代码或创建 Pull Request 时,CI 系统都可以自动运行检查。

Git Push / Pull Request

GitHub Actions (CI)

Format

Lint

Test

PASS

检查通过

FAIL

反馈错误

例如,一个 GitHub Actions 工作流可以写成:

name: Python CI

on: [push, pull_request]

jobs:
  quality:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install tools
        run: python -m pip install ruff pytest

      - name: Lint
        run: ruff check .

      - name: Format check
        run: ruff format --check .

      - name: Test
        run: pytest

这是一个用于理解 CI 的简化示例。

它会在 push 或 Pull Request 事件发生时检查项目。

真实项目还需要根据依赖安装方式、测试配置和安全策略调整工作流。

CI 和 CD 的区别

  • CI(Continuous Integration):持续集成,自动构建、检查和测试代码。
  • Continuous Deployment(持续部署):在满足条件后,将修改自动部署到目标环境。

例如,课程网站可以在提交代码后自动运行检查,再构建并部署到 GitHub Pages。

七、Command Runners:命令运行器

项目变大之后,开发者可能需要记住很多命令:

uv run ruff check .
uv run ruff format .
uv run pytest
uv run mypy .

教材介绍了 just 这样的 Command Runner。

你可以在项目中定义:

lint:
    uv run ruff check .

format:
    uv run ruff format .

test:
    uv run pytest

然后执行:

just lint
just test

它的本质是:

给复杂或常用的项目命令提供统一、易记的入口。

这也能够降低新成员加入项目时的学习成本。

八、Regular Expressions:正则表达式

这部分虽然看起来与代码质量不同,但在代码搜索、日志分析和批量替换中非常实用。

Regex(Regular Expression,正则表达式)是一种描述文本匹配模式的语言。

1. 最基础的正则表达式

例如:

abc

匹配字符串中的 abc。

\d+

匹配一个或多个数字。

\d{4}-\d{2}-\d{2}

匹配类似:

2026-01-14

的日期形式。

但注意,它同样可能匹配:

2026-01-99

因为这个正则表达式检查的是字符格式,而不是日期是否合法。

2. 常见正则语法

符号 意思 示例
. 匹配一个字符 a.c
* 前面的模式重复 0 次或多次 a*
+ 前面的模式重复 1 次或多次 a+
? 前面的模式出现 0 次或 1 次 a?
\d 数字字符 \d{4}
\w 单词字符 \w+
[abc] a、b、c 中的一个 [abc]
^ 字符串或行的开头,取决于模式 ^Hello
$ 字符串或行的结尾,取决于模式 end$
(...) 捕获分组 (\d+)
a\|b 两个模式二选一 cat\|dog

3. Capture Group:捕获组

假设你有一个日期:

2026-01-14

只想获取月份 01。

可以使用:

import retext = "2026-01-14"match = re.match(    r"\d{4}-(\d{2})-\d{2}",    text)print(match.group(1))

输出:

01

其中括号:

(\d{2})

表示捕获两位数字。

.group(1) 表示获取第一个捕获组的内容。

4. Greedy 和 Non-greedy:贪婪与非贪婪匹配

这是正则表达式中非常容易出错的地方。

假设字符串为:

"name": "Alice", "college": "MIT"

如果使用:

"name": "(.*)"

.* 默认是贪婪匹配,可能匹配尽可能长的内容,把后面的字段也包含进去。

而:

"name": "(.*?)"

使用非贪婪匹配,会尽量在第一个符合条件的位置停止。

但教材特别提醒:

对于 JSON、HTML 等具有复杂结构的数据,不应该依赖简单正则表达式进行完整解析。

例如,要提取 JSON 中的 name:

import jsondata = '{"name": "Alice", "college": "MIT"}'person = json.loads(data)print(person["name"])

这比尝试编写一个处理所有 JSON 转义情况的正则表达式更加可靠。

第三节:Communication & Collaboration(工程沟通与团队协作)

这一节与前面两节有所不同。

前两节主要讲技术工具,而这节课强调:

优秀的软件工程师不仅需要写出正确的代码,还要让其他人能够理解、审查、使用和维护这些代码。

课程开头提出了一个非常重要的原则:

记录和传达 Why(为什么),而不仅仅是 What(做了什么)。

因为代码通常已经能告诉别人“程序做了什么”,但往往无法告诉别人“当初为什么这样设计”。

一、Code Comments:怎样写有价值的注释?

先看一个没有太大价值的注释:

# Increase counter by onecounter += 1

这段注释几乎没有增加任何信息。

因为代码已经能够清楚表达它的行为。

再看另一种:

# Retry at most three times because the upstream# service rate-limits repeated failed requests.MAX_RETRIES = 3

第二段注释不仅解释了常量的含义,还解释了为什么选择这个值。

这就更有价值。

教材推荐的注释类型

类型 应该解释什么
TODO 哪些工作尚未完成,为什么暂时没有做
References 算法、规范或实现依据来自哪里
Correctness Arguments 为什么这段复杂代码能够产生正确结果
Hard-learned Lessons 过去遇到过哪些不明显的问题
Rationale for Constants 某个固定数值为什么这样设置
Load-bearing Choices 哪些看似普通的实现细节不能随意修改
Why not 为什么没有使用一个看起来更简单的方案

例如:

# Do not replace this ordered collection# with a set: later processing depends# on preserving the original input order.

它不是在描述代码执行了什么,而是在提醒未来的维护者:

这里有一个容易被忽略的设计约束。

如果没有这段注释,其他程序员可能出于性能考虑将其替换为普通集合,从而意外改变程序行为。

这里还涉及一个非常重要的写作原则:

注释应该补充代码无法充分传达的信息,而不是重复代码。

二、README:让其他人理解你的项目

README 通常是别人接触一个项目时看到的第一份文档。

教材建议 README 尽早回答四个问题:

  1. What does this do? —— 这个项目做什么?
  2. Why should I care? —— 为什么它对我有用?
  3. How do I use it? —— 如何使用它?
  4. How do I install it? —— 如何安装它?

注意它的顺序。

很多开发者习惯先写一大段安装教程。

但用户首先想知道的是:这个工具是否解决自己的问题。

例如,一个 Python CSV 清洗工具的 README 可以这样组织:

README.md 示例结构

CSV Cleaner

A command-line tool for cleaning duplicate rows in CSV files.

首先说明项目的用途

Why use it?

Remove duplicate rows automatically without manually editing spreadsheets.

解释项目的实际价值

Usage

csv-cleaner input.csv --output clean.csv

展示用户如何使用

Installation

pip install csv-cleaner

最后说明安装过程,命令仅作示例

一个好的 README 应该让用户能够快速判断项目是否适合自己,并在需要时找到详细信息。

三、Commit Messages:如何写高质量的 Git 提交信息?

你之前学过:

git commit -m "fix bug"

这虽然是有效命令,但提交信息的价值很低。

因为它没有解释:

  • 修复了什么 Bug?
  • 为什么 Bug 会发生?
  • 为什么采用当前修复方式?
  • 是否存在副作用?

教材推荐使用:

Problem → Solution → Implications

即:

问题 → 解决方案 → 影响

例如,假设系统中的付款请求偶尔被重复处理。

一个较好的提交信息可以写成:

Prevent duplicate payment processing

Problem:
Network retries may submit the same payment
request multiple times.

Solution:
Use an idempotency key to identify repeated
requests and reuse the existing result.

Implications:
Payment requests now require a stable
idempotency key from the caller.

这个提交信息不仅说明了修改内容,还解释了问题背景以及可能产生的影响。

这在几个月后调查历史问题时会非常有用。

Atomic Commits:原子提交

教材还推荐将代码按照独立的逻辑变化组织成 Commit。

例如:

较好的提交组织

Commit A: Add user authentication

Commit B: Add authentication tests

Commit C: Update authentication docs

不理想的提交组织

Commit A: Fix login, update payment, rename files, format code, change README

把无关修改塞进同一个 Commit,会让代码审查和后续排查问题变得更加困难。

你之前学过的:

git add -p

就可以帮助你将文件中的不同修改块分开暂存,创建逻辑上更清晰的提交。

四、Bug Reports:如何写好错误报告?

假设你发现某个软件有问题。

你提交了一个 Issue:

This doesn't work. Please fix it.

维护者很可能不知道问题发生在哪里。

课程建议,一个好的 Bug Report 至少应该说明:

  • Environment:操作系统、软件版本及相关配置。
  • Expected Behavior:预期行为。
  • Actual Behavior:实际发生的结果。
  • Reproduction Steps:如何复现问题。
  • Attempted Solutions:你已经尝试过哪些解决方式。

例如:

Bug Report 示例

Title: CSV export fails when the input is empty

Environment

Python 3.12, Ubuntu 24.04, application v1.2.0

Expected Behavior

The command should produce an empty CSV file containing the header row.

Actual Behavior

The program raises an IndexError.

Steps to Reproduce

  1. Create an empty input CSV file.
  2. Run csv-cleaner input.csv --output result.csv.
  3. Observe the exception.

What I Tried

Tested with a non-empty CSV file; the problem did not occur.

这种报告让维护者更容易理解和复现问题。

Minimal Reproducible Example:最小可复现示例

这是软件工程中非常重要的能力。

假设你的程序有 10,000 行代码,某个功能发生异常。

你可以尝试将导致错误的代码逐渐简化:

10,000 行项目
      ↓
500 行相关模块
      ↓
50 行相关逻辑
      ↓
10 行最小复现代码

最终得到一个只包含问题核心的示例。

这样的示例非常有价值,因为它可以排除不相关因素,帮助维护者快速定位错误。

有时你在缩小问题范围的过程中,就会自己发现根本原因。

五、Pull Request:如何向项目贡献代码?

Pull Request(PR)是 GitHub 等平台中常见的协作机制。

它让开发者提出代码修改,并邀请维护者审查、讨论和合并。

一个典型的工作流程是:

1

阅读 CONTRIBUTING.md

2

建立开发分支

3

实现一个明确的修改

4

运行格式检查与测试

5

创建 Pull Request

6

进行 Code Review

7

根据反馈修改并合并

教材建议你在提交 PR 前,先确认项目是否已有类似的 Issue 或正在进行的工作。

还要尽量控制 PR 的范围,不要为了实现一个小功能而同时修改大量无关文件。

一个好的 PR 描述不仅要说明修改了什么,还要解释:

为什么需要这个修改,以及为什么当前实现值得被项目接受。

维护者需要长期承担代码维护责任,因此合理的技术方案也可能因为维护成本过高或不符合项目方向而被拒绝。

六、Code Review:如何审查别人的代码?

Code Review 不只是寻找 Bug。

它还帮助团队共享知识、发现不合理的设计以及提高代码可维护性。

教材提出了几个很实用的原则。

1. Review the Code, Not the Person

评价代码,而不是评价程序员。

不理想:

You wrote confusing code.

更好的方式:

This function is difficult to follow. Could we split validation and processing into separate functions?

第二种表达更加聚焦于问题,也更容易推动改进。

2. Actionable Feedback

评论应该尽量可执行。

例如:

不理想:

Don't use globals.

更好的方式:

Could we replace these global variables with a configuration object to make testing easier?

3. 区分必须修改和个人建议

并不是所有 Review Comment 都应该阻止 PR 合并。

例如:

Blocking Issue:

一个身份验证函数允许未授权用户访问数据。

这是需要优先解决的正确性和安全问题。

Suggestion:

某个变量名可以更清楚。

这是可以讨论的改进建议,不一定需要阻止合并。

4. 不要无限追求细节

代码审查需要关注重要问题。

如果审查者不断纠结无关紧要的排版细节,会消耗开发者和维护者的时间。

这也是前面为什么需要 Formatter:机器可以自动处理的问题,就没有必要让人工 Review 占用大量时间。

七、Education:如何提出好的技术问题?

教材引用了 Julia Evans 关于如何提问的建议。

其中最重要的技巧是:

先说明你的理解,再指出你不理解的具体部分。

例如:

不理想:

I don't understand Docker.

更好的问题:

My understanding is that Docker containers share the host kernel, while virtual machines have their own guest OS. Does that mean Docker containers cannot run a different kernel from the host?

第二个问题更加具体。

回答者能够直接看出你已经理解了什么,以及需要澄清什么。

同样,提问时还应该尽量说明自己尝试了什么,以及遇到了怎样的结果。

这不仅适用于人与人之间的沟通,也适用于向 AI 提问。

八、AI Etiquette:AI 使用规范

教材最后讨论了 AI 在软件工程中的使用规范。

它强调:

当 AI 对你的工作有实质性贡献时,应该按照项目或组织的规则披露 AI 的使用情况。

例如:

  • AI 只帮助润色了 README。
  • AI 实现了某个函数,但你编写并验证了测试。
  • 整个应用主要由 AI 生成。

这几种情况并不相同。

教材还提醒,如果公司或团队对数据隐私、合规、代码生成以及 AI 使用有特殊要求,开发者应该遵守相关政策。

在考试、技术面试等考核情境中,也需要遵守明确的工具使用规则。

AI 可以帮助你提高效率,但不能代替你对代码正确性和工程责任的判断。

第四部分:如何将三节课结合起来?

我们用一个具体项目,把三份课程材料连接起来。

假设你准备开发一个 Python 命令行工具:

CSV Cleaner:自动删除 CSV 文件中的重复记录。

第一阶段:利用 Coding Agent 开发

你向 Coding Agent 提出任务:

Create a Python CLI that reads a CSV file, removes duplicate rows, and writes the cleaned data to a new file. Use argparse for command-line arguments, include type annotations, and add unit tests. Do not overwrite the input file.

Agent 可以阅读文件、创建程序、编写测试,并尝试执行检查。

第二阶段:通过 Code Quality 验证

代码生成后,你运行:

ruff format .
ruff check .
mypy .
pytest

分别检查代码格式、潜在问题、类型一致性和功能正确性。

接下来通过 Pre-commit Hook 和 GitHub Actions 自动运行这些检查。

这样,即使 AI 修改了代码,也必须经过相同的质量验证流程。

第三阶段:通过 Communication & Collaboration 交付

你创建清晰的提交记录:

git add .
git commit -m "Add CSV deduplication CLI"

编写 README,说明工具用途、使用方法和安装方法。

然后创建 Pull Request,向审查者说明:

项目解决了什么问题、采用了什么实现方式、如何测试,以及是否存在已知限制。

完整的软件工程工作流

需求与验收标准

明确什么才算完成

Coding Agent + Developer

生成、理解、修改代码

Formatter + Linter + Type Checker + Tests

自动验证代码质量

Git Commit + Pull Request

记录修改目的和技术决策

CI + Human Code Review

自动检查与人工判断,共同决定能否合并

这三个部分共同构成了现代软件工程实践的核心。

第五部分:课程练习与学习路线

三份教材包含了很多练习。如果你刚开始学习,我建议先完成下面这些具有代表性的任务。

综合学习任务

0/8 已完成

用 Coding Agent 完成一个小功能

让 AI 修改一个 Python 程序,并观察它如何读取文件、运行命令和修复错误。

创建 Agent 项目指导文件

编写 AGENTS.md,规定代码风格、测试命令和禁止修改的文件,测试 Agent 是否遵守。

配置 Ruff 和 pytest

让一个 Python 项目具备代码格式化、静态分析和单元测试。

练习覆盖率分析

执行带覆盖率的测试,找出未覆盖代码,并为关键情况补充测试。

配置 GitHub Actions

在 Push 和 Pull Request 时自动运行格式检查、Lint 和测试。

练习正则表达式

使用捕获组提取日期月份,比较贪婪与非贪婪匹配,再用 JSON 解析器处理结构化数据。

编写 README 和 Commit Message

说明项目用途、使用方法,并在提交说明中解释 Problem、Solution 和 Implications。

进行一次 Code Review

审查一份真实或练习用的 PR,区分 Blocking Issues 与 Suggestions,并提出可执行的反馈。

三节课最重要的知识总结

课程 最值得记住的原则
Coding Agents AI 可以执行编程任务,但必须有明确目标、合适上下文和结果验证
Code Quality Formatter、Linter、Type Checker、Tests 和 CI 解决不同层次的代码质量问题
Communication & Collaboration 优秀的技术沟通应该解释 Why,让其他人理解和长期维护你的工作

最终需要建立的思维方式是:

不要只是追求把代码写出来,而是要确保代码符合需求、经过验证、容易理解,并能够由其他工程师继续维护。

这三节课真正教给你的,就是如何从“会写程序的人”逐渐成长为“能够可靠交付软件的工程师”。

我虽然行过死荫的幽谷,也不怕遭害,因为你与我同在。
诗篇 23:4