Sean Goedecke 最近在博客里抛出一个刺耳的问题:软件工程可能不再是终身职业。不是因为 AI 会取代程序员——至少不是直接取代——而是因为 AI 正在悄悄抽走职业成长的底层机制:从任务中学习。
这个论点比"AI 要抢饭碗"更值得认真对待。
学习发生在哪里
程序员的能力增长,绝大部分不是来自读书或上课,而是来自干活。你写了一个复杂的缓存策略,踩了并发竞态的坑,修了三天——这个过程本身就是你下次设计缓存时的判断力来源。Goedecke 的核心观察是:当你让 AI 完成这个任务,你就跳过了那个"踩坑→修复→内化"的循环。
这不是说 AI 让你变笨。你依然聪明,但你的经验库增长变慢了。就像用导航开车的人方向感会退化一样——不是因为脑子坏了,是因为练习少了。
具体来说,影响发生在三个层面:
- 调试能力:AI 给你一个能跑的方案,你没经历从报错到定位到修复的过程,下次遇到类似问题时你的直觉会变弱。
- 架构判断:AI 帮你搭好骨架,你没亲手做过取舍,下次面对新项目的约束条件时,你不知道哪些设计是脆弱的。
- 领域理解:AI 把业务逻辑翻译成代码,你没在翻译过程中反复咀嚼需求文档,对业务边界的认知停留在表面。
这些能力不是"知识",是"肌肉记忆"。跳过举铁直接拿奖牌,肌肉不会长。
反对用 AI 的逻辑为什么站不住脚
有人因此主张:工作中不该用 AI。逻辑链条是——用 AI → 学得少 → 技术退化 → 职业寿命缩短 → 所以别用。
Goedecke 指出这个推理有漏洞。问题不在"用不用 AI",而在"怎么用"。完全不用 AI 的人,在交付速度上会被同行碾压,同样面临职业风险。真正的两难是:
用 AI 交付快但学得少,不用 AI 学得多但交付慢。两条路都指向职业寿命缩短,只是方向不同。
这才是让人不舒服的地方。不是选"好路"还是"坏路",是两条路都有坑。
把 AI 用成学习加速器而非替代品
出路不是拒绝 AI,而是改变使用方式。核心原则:让 AI 做你本来不会做的事,而不是做你本来会做但懒得做的事。
下面是一个可以实际操作的策略,附带可运行的代码示例。
策略:AI 生成练习,你手动完成
与其让 AI 直接写生产代码,不如让它生成刻意练习的材料。你手动完成练习,AI 再做对比反馈。这样你既保留了学习循环,又利用了 AI 的生成能力。
"""
deliberate_practice.py
用 AI 生成练习题,手动完成后再让 AI 评审
使用方式:
1. 运行脚本,拿到一道练习题
2. 在 exercises/ 目录下手动写你的解答
3. 再次运行脚本,AI 会对比你的解答与参考实现,给出反馈
依赖:pip install openai
"""
import os
import json
import openai
client = openai.OpenAI() # 默认从环境变量读取 OPENAI_API_KEY
EXERCISES_DIR = "exercises"
def generate_exercise(topic: str, difficulty: str = "intermediate") -> dict:
"""让 AI 生成一道练习题,包含题目描述和参考实现"""
prompt = f"""
生成一道关于 {topic} 的编程练习题,难度为 {difficulty}。
要求:
- 题目描述要具体,有明确的输入输出要求
- 参考实现要简洁但完整,用 Python
- 题目应该涉及常见的边界情况或陷阱
- 不要太简单(纯语法),也不要太复杂(需要外部依赖)
以 JSON 格式返回,结构为:
{{
"title": "题目标题",
"description": "题目描述,包含输入输出示例",
"reference_solution": "参考实现的 Python 代码",
"key_learning_points": ["这道题要练习的核心知识点列表"]
}}
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
def review_my_solution(exercise: dict, my_solution: str) -> str:
"""让 AI 评审你的手动解答,对比参考实现给出反馈"""
prompt = f"""
你是一位严格的代码评审教练。
题目:{exercise['title']}
描述:{exercise['description']}
参考实现:
```python
{exercise['reference_solution']}
```
学员的解答:
```python
{my_solution}
```
请对比两个实现,从以下角度给出反馈:
1. 正确性:是否满足题目要求?有没有遗漏边界情况?
2. 效率:时间/空间复杂度与参考实现的差异?
3. 可读性:命名、结构是否清晰?
4. 关键学习点:学员是否抓住了这道题要练习的核心知识点?
不要直接给出改进后的完整代码。指出具体问题,让学员自己修改。
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
def main():
topic = input("输入你想练习的主题(如 concurrency, caching, tree traversal): ")
# Step 1: 生成练习
exercise = generate_exercise(topic)
print(f"\n{'='*60}")
print(f"题目:{exercise['title']}")
print(f"{'='*60}")
print(exercise['description'])
print(f"\n核心学习点:{', '.join(exercise['key_learning_points'])}")
# 保存题目信息供后续评审用
os.makedirs(EXERCISES_DIR, exist_ok=True)
exercise_file = os.path.join(EXERCISES_DIR, f"{exercise['title'].replace(' ', '_')}.json")
with open(exercise_file, 'w') as f:
json.dump(exercise, f, indent=2)
print(f"\n题目信息已保存到 {exercise_file}")
print(f"请在 {EXERCISES_DIR}/ 目录下创建你的解答文件,然后再次运行此脚本进行评审。")
# Step 2: 评审(如果已有解答文件)
solution_file = os.path.join(EXERCISES_DIR, f"{exercise['title'].replace(' ', '_')}_my.py")
if os.path.exists(solution_file):
with open(solution_file, 'r') as f:
my_solution = f.read()
print(f"\n{'='*60}")
print("AI 评审反馈:")
print(f"{'='*60}")
feedback = review_my_solution(exercise, my_solution)
print(feedback)
else:
print(f"\n请将你的解答写入 {solution_file},然后重新运行脚本获取评审。")
if __name__ == "__main__":
main()
运行方式:
# 安装依赖
pip install openai
# 确保设置了 API Key
export OPENAI_API_KEY="sk-..."
# 第一次运行:生成练习题
python deliberate_practice.py
# 输入主题,如 "concurrency"
# 手动写解答
# 在 exercises/ 目录下创建对应的 _my.py 文件
# 第二次运行:获取评审
python deliberate_practice.py
# 输入相同主题,脚本会检测到你的解答文件并给出反馈
这个流程的关键设计:AI 生成题目但不直接给你答案,你手动解题后再让 AI 评审。学习循环完整保留——你经历了思考、试错、实现的过程,AI 只是在两端辅助,没有跳过中间的挣扎。
生产代码中的折中方案
练习模式适合日常学习,但生产项目有交付压力,不可能每行代码都手写。这时候需要一个折中策略:
分层使用 AI:
| 层级 | AI 角色 | 你的角色 | 学习保留度 |
|---|---|---|---|
| 架构设计 | 生成候选方案,列出利弊 | 做最终取舍,写核心模块接口 | 高 |
| 核心逻辑 | 不使用,手动实现 | 全程手写,包括错误处理 | 最高 |
| 工具/胶水代码 | 直接生成 | 只做代码审查 | 低(但这部分本来学习价值也低) |
| 测试用例 | 生成基础用例 | 补充边界用例,写断言逻辑 | 中 |
| 调试 | 提供排查思路 | 手动验证,定位根因 | 中高 |
简单说:高学习价值的部分自己写,低学习价值的部分让 AI 写,中间地带让 AI 辅助但不替代。
一个具体的 Git 工作流实践:
# 核心模块:手动开发,完整提交历史
git log --oneline src/core/cache_strategy.py
# e3a1f 修复并发竞态条件
# 7b2c0 添加 TTL 逐出逻辑
# 4d9a1 初始实现
# 每个提交都是一个学习节点
# 工具脚本:AI 生成,只做审查
ai-generate "写一个脚本,把 CSV 日志转成 JSON 格式,保留时间戳和错误级别字段"
# 生成后只做功能验证和代码审查,不逐行手写
# 测试:AI 生成骨架,你补边界
ai-generate "为 cache_strategy.py 生成 pytest 测试骨架"
# 你手动补充:并发写入测试、内存溢出测试、TTL 边界测试
提交历史本身就是学习日志。如果核心模块的 git log 里全是"AI 生成"的单次大提交,你回头看时找不到决策轨迹,等于没留下经验。
职业寿命的真正变量
Goedecke 的文章最终指向一个更深层的问题:软件工程的职业寿命,取决于你能否持续积累不可替代的经验。AI 的威胁不是直接替代你,而是让你在不知不觉中停止积累。
几个自检问题值得定期问自己:
- 最近六个月,你手动解决过的最难的 bug 是什么? 如果答案是"没有",你的调试肌肉可能在萎缩。
- 你最近做的一个架构决策,AI 能不能在 10 秒内给出相同方案? 如果能,这个决策的学习价值接近零。
- 你的 git log 里,核心模块的提交是不是越来越稀疏? 稀疏意味着你越来越依赖一次性大生成,而不是迭代式学习。
如果三个答案都不乐观,你不需要停用 AI,但需要重新分配它在你工作流中的位置。
软件工程可能不再是终身职业,但这个"可能"的权重取决于你现在的选择。让 AI 做它擅长的事——生成、搜索、转化——把需要挣扎的部分留给自己。挣扎才是生长的地方。