V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
sampeng
V2EX  ›  程序员

我宣布, CC 目前最佳使用方式是 Spec+Agents+TDD

  •  
  •   sampeng · 23 小时 55 分钟前 · 636 次点击

    这一周都在自己的 mcp 上尝试各种开发方法。

    最终结论是 Spec 先定义好需求,实现计划,然后进行 TDD 是最舒服,成功率最高的方式。

    之前我实现了一个 gitlab 的 Spec 的 mcp ,但是还是不得劲,单元测试瞎写,纯炼丹。就是属于那种他过不去就自己改单元测试,或者单元测试写一大堆但是重复的不少。最主要的问题是上下文问题。claude code 在使用 Spec 的开发模式进行开发的时候非常容易触发压缩。尤其是对于大一点的 Spec 。压缩带来的问题更严重,随机的丢失上下文。这是一件非常麻烦的事。

    这周发布的 agents ,让我眼前一亮,因为上下文隔离就可以很好的避免上下文污染。

    我测试了 3 天,完全是可行的。QA 的 agents 只负责单元测试的修改。Developer 的 agents 只负责代码的编写保证单元测试通过。最后的重构和优化阶段非常重要,我调试了很多次才搞定。也就是形成 Red-Green-Refactor 的完整流程。一开始我没觉得最后的阶段有用,真的实现和跑了一些复杂接口实现的时候这玩意就有用了。不会一直拉屎拉到无法看懂。我要求他重构的时候把不用的清理掉,大函数拆解,发现重构机会。但当然还是有点问题,10 次里有 1 次没聚焦到这次的修改范围,目前把上下文在 prompt 里补充了好像还行。

    prompt

    please think hard about, 请读取 issues $ARGUMENTS 的详情,你会得到一个任务树;
    
    你不得实现任何业务,应该调度角色来完成
    
    ## 名词理解
    **业务实现计划**
    指定的 $ARGUMENTS 是业务实现计划的 issue ID ,包含了业务实现的详细步骤和文件修改计划。
    
    **单元测试计划**
    查看 `$ARGUMENTS` 的详情,你会得到一个任务树,link 中的 labels 含有`type::Testing`的 issue 是单元测试计划的 issue ID ,包含了单元测试的详细步骤和文件修改计划。
    
    **使用子任务尽可能的并行的分析和拆解 TDD 循环列表**
    
    子任务中 link 的 label 为`type::TDD-interface`的 issue 是以接口为单位的 TDD 工作大纲。
    读取 tdd-interface 的子任务的 label 为`type::TDD`的 issue 是 TDD 工作流中的具体的 TDD 循环任务
    请创建和使用子代理来并行的调查 TDD 循环的列表。子任务中 link 的 label 为`type::TDD-interface`的 issue 是以接口为单位的 TDD 工作大纲,TDD 工作大纲的子任务的 label 为`type::TDD`,并且状态为 open 的 issue 是 TDD 工作流中的具体的 TDD 循环任务。
      - 每开始一个 TDD 循环,必须先设置 tdd 循环任务状态为`inprogress`,使用`gitlab-issues-workflow-status(issue_id="", status="inprogress")`。
      - 每完成一个 TDD 循环的步骤,必须设置 tdd 循环任务中的 AC 对应步骤为 checked 。
        - 完成 RED 阶段,设置 TDD 循环任务中的 AC 的 RED 步骤为 checked
        - 完成 GREEN 阶段,设置 TDD 循环任务中的 AC 的 GREEN 步骤为 checked
        - 完成 REFACTOR 阶段,设置 TDD 循环任务中的 AC 的 REFACTOR 步骤为 checked
      - 每完成一个 TDD 循环,必须检查 tdd 循环任务的 AC 是否完全满足,使用`gitlab-issues-workflow-status(issue_id="", status="done")`将任务状态改为`done`。
      - 分析和检查 AC 的步骤一步完成了哪一步没完成。
    
    对 TDD 循环列表创建 todowriter 列表,每一项就是 TDD 的一个循环,tdd 循环来源于子任务的调查结果。
    
    ### TDD 工作流的阶段
    
    **角色定义**:
    
    **QA**: `tdd-qa-partner`子代理角色负责实现单元测试,只允许实现测试代码,不允许修改业务代码。
    **Developer**: `tdd-code-implementer`子代理角色角色负责实现业务代码,只允许实现业务代码,不允许修改测试代码。
    
    
    ### TDD 循环
    **Workflow Guidance**:
    
    - **第一**让`tdd-code-implementer`基于设计文档的接口定义,实现最小的接口或者 struct 定义,要确保 make test 是能通过的。
    - tdd 以接口为单位进行迭代开发,每个接口都经过严格的测试驱动开发( TDD )流程,确保每个接口都经过 Red-Green-Refactor 的完整流程。
    - 要告知角色,只做一个阶段的事,不允许做任何其他阶段的工作。
    - 避免一次性创建所有接口,专注于一个功能一个功能地 TDD 循环,确保每个功能都经过测试和验证。
      - 严格检查每个 Phase 的 TDD 循环的 Red ,Green 和 Refactor 阶段是否都做了。不能跳过任何阶段。
      - 不是 QA 和 Developer 的任何独立完成的任务,是描述的 Phase 的 TDD 循环。
      - 确保都做过步骤 Red→Green→Refactor
      - QA 和 Developer 角色需要紧密协作,交替按照 TDD 循环进行红绿优化循环。
      - 每个循环步骤都务必聚焦于设计需求和测试需求所涉及的文件和代码,**不得擅自修改和优化其他的代码文件**
      - QA 和 Developer 都不是一次性完成他们的工作,而是一个接口一个接口的去进行实现和测试。
      - 每次 QA 和 Developer 开始的时候,你**必须把设计文档和测试文档的 issues id 以及 TDD 循环迭代給到子代理角色**,并让子代理角色先自己去分析和理解上下文。
    - 在一个循环完整结束后,在需求设计的 issues 上使用`gitlab-workitem-create-note(issue_id="", description="TDD 循环完成,进入下一个循环")` 添加进度笔记,记录当前循环的完成情况。
    - QA 和 Developer 除了在 TDD 循环中使用绝对不会自行去实现实现计划的接口和单元测试任务。
    
    #### Phase 0: Ready for TDD,
    1. 只定义即将测试的一个方法(如 AddLabel )
    2. 创建必要的数据结构
    
    #### Phase 1: **TDD 循环**
    每次 QA 和 Developer 开始的时候,你**必须把设计文档、测试文档和 TDD 循环迭代的 issuesID 給到子代理角色**,并让子代理角色先自己去分析和理解上下文。
    1. Red: QA(`tdd-qa-partner`) 为接口编写失败测试
    2. Green: Developer(`tdd-code-implementer`) 实现最小代码让测试通过
    3. Refactor: QA(`tdd-qa-partner`)和 Developer(`tdd-code-implementer`),都需要检查(codereview)和优化(refactor)在这个循环中自己修改过的代码,重构不需要考虑向下兼容,务必一次性改成最正确的实现,为了避免代码修改冲突,交替进行重构和协调。不能并行执行
    
    #### Phase 2: 逐步扩展
    1. 添加下一个方法到接口
    2. 重复 TDD 循环
     
    #### **phase 分解的例子**
    分解的任务必须严格按照 TDD 循环的步骤进行,确保每个方法都经过 Red-Green-Refactor 的完整流程。
    

    ⏺ Update Todos ☒ Phase 0: Ready for TDD - 创建最小接口定义,确保 make test 通过
    ☒ TDD 循环 1: ContentBlockHelper.GetAcceptanceCriteria() - Red→Green→Refactor ☒ TDD 循环 2: ContentBlockHelper.SetAcceptanceCriteria() - Red→Green→Refactor ☐ TDD 循环 3: ContentBlockHelper.GetImplementationPlan() - Red→Green→Refactor ☐ TDD 循环 4: ContentBlockHelper.SetImplementationPlan() - Red→Green→Refactor ☐ TDD 循环 5: IssuesManager.SetAcceptanceCriteria()编排逻辑 - Red→Green→Refactor ☐ TDD 循环 6: IssuesManager.AddLabel()去重逻辑 - Red→Green→Refactor

    
    
    ##### TDD 工作流的重构阶段
    QA 负责:
    - 重构测试代码(提取测试辅助函数、优化测试数据设置)
    - 确保测试仍然验证正确的业务逻辑
    - 检查测试覆盖率是否受影响
    - 验证重构后测试仍然能发现潜在 bug
    - 发现的改进机会都必须在重构阶段处理,不得延后到下一个 TDD 循环
    
    Developer 负责:
    - 重构实现代码(提取小函数、优化算法、改善命名)
    - 确保代码结构更清晰
    - 优化性能(在不改变行为的前提下)
    - 处理代码重复和设计改进
    - 发现的改进机会都必须在重构阶段处理,不得延后到下一个 TDD 循环
    
    
    共同协作:
    - 讨论接口设计是否需要调整
    - 确保测试和实现的重构方向一致
    - 运行完整测试套件验证重构成功
    - 代码审查确保质量
    
    实际操作流程:
    重构阶段开始:
    ├─ QA:重构测试代码,保持测试意图不变
    ├─ Developer:重构实现代码,保持行为不变
    ├─ 协作:运行测试确保全部通过
    ├─ 协作:代码审查和讨论
    └─ 提交重构后的代码,进入下一个 TDD 循环
    
    第 1 条附言  ·  21 小时 44 分钟前
    第 2 条附言  ·  1 小时 29 分钟前
    补充一下效果





    13 条回复    2025-08-01 12:22:28 +08:00
    oudioppa
        1
    oudioppa  
       22 小时 48 分钟前
    直接放到 gitgist 吧...
    sampeng
        2
    sampeng  
    OP
       22 小时 27 分钟前 via iPhone
    @oudioppa 有道理
    hihanley
        3
    hihanley  
       22 小时 9 分钟前
    @sampeng op 放了踢我一下
    sampeng
        4
    sampeng  
    OP
       21 小时 41 分钟前
    @oudioppa @hihanley

    https://gist.github.com/SamPeng87/bcd420be34f84957897637596937d71d

    理论上能用,但可能会有点问题,就是我在 prompts 里面强制使用一些我自己定义的 tools 。。。因为上下文都是通过 gitlab 的 issues 来供应的,因为太多了。md 文件其实不是太好管理。。多了就乱套了

    但用了几天,确实已经能够标准的 TDD 流程运转了。。只不过。。是个 token 怪物。因为从逻辑上来说是每个函数的接口的新增,修改,都自动是干净的上下文,要重新获取上下文。但是效果确实还可以。中间有问题你停下来,也能理解继续调度正确的子任务去干活
    hihanley
        5
    hihanley  
       20 小时 58 分钟前
    @sampeng 感谢,我试试再来回复
    mydev6666666
        6
    mydev6666666  
       20 小时 55 分钟前
    这个要怎么使用?是不是要建 3 个 agents? 我今天建了一个,我是想让 claude code 实现 spec 然后让 augmentcode, aug 这个比较贵。
    sampeng
        7
    sampeng  
    OP
       20 小时 35 分钟前
    @mydev6666666 两个 agents ,一个是 qa 的角色,一个是 developer 的角色。tdd.md 是一个斜杠命令。可能需要处理一下我这些任务的上下文要有地方来。。没有上下文来源是转不起来的。。全靠有个外部上下文供应
    sampeng
        8
    sampeng  
    OP
       20 小时 31 分钟前
    @mydev6666666 补充一下。其实我试了一下。没上下文也能工作。就是在/tdd 的时候要把上下文说清楚。他这个子任务角色很有意思,会传递你的上下文进行分析后給子代理。但有时候会传递错意思或者丢了意思。。要 ctrl+r 看一眼,因为我大部分重要的任务是 gitlab 来传递上下文,就没这个问题。。。可以看到 prompts 里面很多是告诉他 gitlab 的 issues 的结构
    zqguo
        9
    zqguo  
       5 小时 11 分钟前
    很不错的思路,楼主可以说下需要安装哪些 mcp 工具吗 ?如果能给下具体的地址就更好了。
    sampeng
        10
    sampeng  
    OP
       4 小时 28 分钟前 via iPhone
    @zqguo 只能说提供思路了,mcp 是我自己开发的基于 gitlab 进行上下文的传递。可能要找一些 spec 管理的 mcp 吧。
    Philippa
        11
    Philippa  
       2 小时 33 分钟前
    很好的想法,感谢分享

    但 op 有没有想过如何把需求 context 关联和顺序问题?比如说:

    1. 使用 “人和动物 class” 创建一个人物
    2. 使用 “人和动物 class” 创建一只宠物
    3. 让人物去摸宠物

    1. 如果 agent 先读取 issue 时先读了 3 ,会导致奇怪的问题。
    2. 如果 agent 先读取 1 然后马上读取 3 ,可能会导致生成了不符合要求的宠物 code 。
    Philippa
        12
    Philippa  
       2 小时 32 分钟前
    可能要给 issue 和 issue 之间加一个依赖注入,让它能够自动把复杂的需求转化成线性顺序去解决 issues 。
    sampeng
        13
    sampeng  
    OP
       1 小时 58 分钟前
    @Philippa 有一点搞错了。核心并不是上下文,而是 TDD 的流程。
    在 agent 看来。1 ,2 ,3 都是上下文。这是很自然的事。如果是我做。就是一个 issues 是总需求,3 个子需求是 1 ,2 ,3 。
    这样 tdd 的流程就是

    RED 阶段:QA ,知道人和动物的 class 是怎样的,创建人应该预期是什么样,结果是如何。然后针对这个编测试代码。预期失败
    GREE 阶段:Developer ,知道人和动物的 class 是怎样的定义的,行为是什么。根据测试代码。编写实际的创建人的代码。
    重构阶段:QA 和 Developer 交替优化各自的代码,清理临时函数,拆解大函数,检查是不是真的完成了创建人这样的动作。

    这是一个 TDD 循环,再做创建人物的 TDD 循环。最后做人物去摸宠物的 TDD 循环。

    你理解的是一个 agent 干所有事,并不是这样的。agent 是把这些需求作为上下文。目的是什么在创建 context 的时候会明确的说明。

    我尝试这个流程,搞出奇怪 code 的原因基本是自己上下文没说清楚或者说没有 review 。

    AI 是工具,不是魔法。我没打算一个需求給他,就自动 spec+tdd 完事了。这是不可能的,质量没法保障。我要事先 review 上下文的顺序是否合理,内容是否能够指导开发。主控的 prompt 的过程我会先 plan 模式看一眼是不是理解偏差了。

    我这只是方法论。我有个暴论,通过一个工具,一个命令,在人完全不参与的情况下就把需求完全实现并且代码质量都极其好的都是吹牛逼。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5637 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 06:20 · PVG 14:20 · LAX 23:20 · JFK 02:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.