解密AI写代码的“上下文陷阱”:一套系统化协作方案

揭秘AI编程上下文陷阱,提出系统化记忆管理和高效AI协作策略,助攻开发者提升智能编码效率。

原文标题:AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

原文作者:阿里云开发者

冷月清谈:

文章深入探讨了AI在代码生成过程中常遇到的“上下文陷阱”问题,即AI因获取的上下文信息不完整、不精确或不聚焦而导致输出错误代码的情况。为系统性解决这一挑战,作者提出了两个核心方法。

首先是**充分利用模型能力**,关键在于构建“完整+精确+聚焦”的上下文。这包括合理分解任务以适配模型的有限上下文宽度,提供完整的系统架构、业务需求和代码实现路径等背景信息,使用清晰无歧义的指令描述,并通过有效的验证和反馈机制来纠偏。文章强调,上下文的细致程度需随模型能力的提升而动态调整。

其次是**AI协作编程的方法**,核心是像设计系统架构一样设计上下文架构,即“上下文工程”。这通过建立三层记忆结构实现:“应用基础记忆”作为长期稳定的通用信息(如技术栈、规范),“功能模块记忆”是对具体功能的完整描述,以及“需求迭代记忆”承载基于项目迭代产出的技术方案。文章还详细阐述了如何利用AI辅助记忆的构建、维护和更新,包括冷启动、基于代码入口的检索、依照需求生成技术方案,以及在开发过程中持续迭代和回写经验。为了平衡效率与质量,建议将大任务拆解为子任务,让AI辅助生成测试代码并进行自我审查,同时明确对AI的约束以防止“作弊”和“超额输出”行为。

最后,文章指出工程师需具备对AI能力的动态认知、管理多种AI编程工具的能力,以及持续扎实的软件架构设计和业务理解表达能力。文末对比了Cursor和Claude Code两款当前热门的编程工具,并强调了后者在原生任务规划和Agent并行开发方面的优势,但也提及其高昂费用和AI自主运行仍需人工监督的现状。

怜星夜思:

1、文章详细介绍了AI在代码生成时‘上下文陷阱’的解决方案,但除了技术层面的上下文管理,大家觉得在实际团队或企业协作中,推广和应用AI编程工具还会遇到哪些非技术性的‘陷阱’?比如信任问题、工作流程摩擦、数据安全合规等?
2、文章提到Claude Code拥有原生的Agent功能,并且Devin这类端到端异步Agent目前表现不佳。那么,大家认为要实现真正的、能独立完成复杂开发任务的“AI编程Agent”,目前还缺少哪些关键能力或者需要克服哪些障碍?
3、文章最后强调了工程师需要培养对AI能力的动态认知、管理多种AI工具以及软件架构设计能力。在AI辅助编程日益普及的今天,作为开发者,大家认为我们目前最应该优先培养哪些新的技能或思维方式,才能更好地与AI协作,甚至引领未来?

原文内容


一、如何充分使用模型能力

关键要点完整+精确+聚焦的上下文是充分使用模型能力的关键。在这个认知之下思考如何系统性的构建满足这个条件的上下文?

  • 合理的任务分解:本质上是在有限上下文宽度和注意力的约束下,怎么恰当的把握任务的复杂度边界,让模型能够在一个聚焦的任务上作业。

  • 完整的背景信息:在一个真实的项目中写代码,需要理解系统架构和规范、了解业务需求、清楚关键代码实现路径、知道如何修改代码满足新的需求,完整了解这些背景信息才能真正的写代码,这对于人类和AI来说是一样的。

  • 精确的指令描述:使用能够让AI更容易理解的方式,清晰无歧义的表达要完成的任务,如强调语法**、mermaid画图等。

  • 有效的验证和反馈:信息从我们表达出来->AI理解->生成代码,每一层都会有损失,而且往往我们自己也会遗漏一些细节,这一步的关键是自己要根据AI的产出验证和思考,将错漏的内容反馈AI自行反思、纠偏。

这4个关键点的应用中还涉及到尺度的把握(信息的细致程度),而这个尺度会随着模型的能力提升而变化。如早期的模型需要非常详尽的内容输入,当模型能力提升后可以自主从代码中获得足够的背景知识。

二、AI协作编程的方法

2.1. 应用级记忆结构

关键要点像设计系统架构一样设计上下文架构,暗合近期讨论比较多的上下文工程(context engineering)的概念。在这个认知之下思考如何高效、准确的维护这个上下文工程?

  • 第一层-应用基础记忆:是应用比较基础的架构、技术栈、规范、通用工具等长期稳定记忆,是与AI交互的System Prompt,就像系统架构中的基础组件。

  • 第二层-功能模块记忆:是对某个具体功能的完整描述,包括链路图、代码入口、关键逻辑、依赖关系等相对稳定的功能记忆,是与AI交互关键背景知识,就像系统架构中由基础组件+业务需求组成的具体功能。

  • 第三层-需求迭代记忆:是AI基于项目迭代中业务需求+功能模块背景知识+项目系统架构产出的技术方案,包括明确的业务需求、代码改造范围、约束条件、边界情况等,是作为提供给AI进行代码生成的最终输入。

2.2. AI辅助记忆维护

记忆维护关键点向AI提供的输入内容和产出验收,本身也可以由AI来辅助生成和验证,同时记忆的维护是渐进的,可跟随实际项目逐步完善。

  • 应用基础记忆构建:一般AI编程工具都有生成项目顶层记忆文档的功能,如Cursor/Generate Cursor RulesClaudeCode/init,在某个应用没有任何记忆时,可以作为冷启动的快速建立记忆的方法,生成初始记忆后,可以根据自己的要求让AI辅助调整。

  • 功能模块记忆构建:由人类提供提供简洁的功能描述和关键代码入口,让AI自动根据代码入口作为线索去检索,建立完整链路的记忆文档,再根据自己的要求让AI辅助调整。

  • 需求迭代记忆构建:引用与需求相关的背景知识记忆,并且以Markdown格式描述本次需求内容,要求其生成技术方案,就产出了需求迭代记忆。需求开发完成后反向更新功能模块记忆。

  • 记忆文档的规范:建立一些基础的记忆文档规范,如应用记忆保持整洁、功能模块记忆需要有链路图、需求迭代记忆需要建立在指定目录等。

  • 要求AI辅助检查和反思:每一层的记忆文档生成后,都可以要求AI进行自我检查和反思,是否有错漏的地方。

  • 通用的记忆格式:统一以.md作为记忆格式,未来使用任何AI编程工具都可以无缝切换。(cursor的.mdc本质上也是.md)

总结:核心是系统性的分层分模块管理上下文,最大程度让AI辅助维护上下文,每次变更的知识负担就可以大幅度下降(输入具体需求即可),配合渐进式的更新维护,使用AI编程工具的效率正循环就形成了。

2.2.1. 记忆示例

功能模块基于、需求迭代记忆的示例涉及到敏感业务代码,不再此处展示

项目结构和技术栈

---
description: 
globs: 
alwaysApply: true
---
# AE评测系统开发指南

项目结构

demo-start: 项目启动模块,这个模块中没有业务逻辑, 在我没有明确指令是不要修改此模块中的代码
demo-api: HSF API接口定义模块, 对于Demo系统的开发,只关心 demo package下的内容, 其他package内容忽略
  - demo/api: Demo系统的HSF API的interface均在这个package下定义, 命名后缀为Service
  - demo/model: Demo系统的HSF API的model均保存在这个package, 命名后缀为Request、DTO
  - demo/common: Demo系统的HSF API的enum均保存在这个package下, 命名后缀为Enum
  - demo/base: Demo系统的HSF API的model的基类均保存在这个package下
demo-biz: 业务逻辑实现模块, 对于Demo系统的开发,只关心 demo package下的内容, 其他package内容忽略
  - demo/api: Demo系统的HSF API的实现类均在这个package下定义, 命名后缀为ServiceImpl
    - demo/api/converter: Demo系统的HSF API的实现类使用的Converter类均保存在这个package下, 命名后缀为Converter
    - demo/api/validate: Demo系统的HSF API的实现类使用的校验类均保存在这个package下, 命名后缀为Validate
  - demo/common: Demo系统的内部的公共类均保存在这个package下, 命名后缀为Enum、Constant
  - demo/config: Demo系统的内部的Diamond、HSF配置类均保存在这个package下, 命名后缀为Config、Configuration
  - demo/consumer: Demo系统的MetaQ Consumer类均保存在这个package下, 命名后缀为Consumer(消费MetaQ)
    - demo/consumer/listener: Demo系统的Consumer的消费逻辑实现类均保存在这个package下, 命名后缀为Listener(实现消费逻辑)
  - demo/demouator: Demo系统的评估器实现类均保存在这个package下, 命名后缀为demouator, 此处的代码相对比较稳定,在我没有明确指令时不要自行修改
  - demo/executor: Demo系统的通用业务逻辑实现类均保存在这个package下, 命名后缀为Executor
  - demo/invoker: Demo系统的调用AI应用的通用封装类均保存在这个package下, 此处的代码相对比较稳定,在我没有明确指令时不要自行修改
  - demo/task: Demo系统的任务提交和任务执行的的通用封装类均保存在这个package下, 此处的代码相对比较稳定,在我没有明确指令时不要自行修改
  - demo/util: Demo系统的工具类均保存在这个package下, 此处的代码相对比较稳定,在我没有明确指令时不要自行修改
demo-core: 核心功能模块, 包含基础设施和通用组件, 对于Demo系统的开发, 任何时候都不需要关注这个模块中的内容
demo-job: 定时任务模块, 对于Demo系统的开发, 任何时候都不需要关注这个模块中的内容
demo-workflow: 工作流相关模块, 对于Demo系统的开发, 任何时候都不需要关注这个模块中的内容
demo-infrastructure: 基础设施模块, 包含数据访问、外部服务集成等, 对于Demo系统的开发, 主要关心其中操作数据库的相关代码
  - dao/demo: Demo系统的Mybatis-Plus的Mapper类均保存在这个package下,后缀为Mapper
  - model/demo: Demo系统的Mybatis-Plus的实体类均保存在这个package下,其中PO后缀的是与数据库表直接映射的实体类,其中/model文件夹下的类是和业务层交互的实体类
  - model/convert: Demo系统的Mybatis-Plus的PO与Model之间的转换类均保存在这个package下,后缀为Converter
  - repository: Demo系统的数据库操作类均保存在这个package下,接口后缀为Repository,实现类后缀为RepositoryImpl,核心的作用是调用Mapper与数据库操作、转换PO与Model
demo-provider: 服务提供者模块
  - hsf/provider: 增加新的HSF服务Provider需要在 HsfProviderConfig.java类中增加配置
demo-sdk: Demo系统SDK工具模块,此处的代码相对比较稳定,在我没有明确指令时不要自行修改

主要技术栈

- Pandora Boot: 基于Spring Boot的阿里内部框架
- HSF: 阿里内部的RPC框架
- Diamond: 阿里内部的配置中心
- Tair: 阿里内部的缓存服务
- MetaQ: 阿里内部的消息服务
- MyBatis-Plus: 轻量级的ORM框架

DAO层代码规范

---
description: 根据创建表的SQL生成操作数据库层增删改查代码时引用此文件
globs: 
alwaysApply: false
---
## 操作数据库编码规范
#### 操作DB框架
1. 开发框架:使用MyBatis-Plus进行编码
2. 调用逻辑:上层通过注入的方式调用Repository的实现,在Repository的实现的实现中调用Mapper,调用Mapper后返回的对象是PO,再通过Converter转换成Model后返回为上层调用方。
3. 数据类型的选择:时间字段使用java.util.Date类型
4. 使用MyBatis-Plus方法注意事项:注意不要调用deprecated的方法
5. Repository层的删除方法:统一使用逻辑删除,逻辑删除字段是is_deleted
6. Repository层需操作时需要附加对当前环境的处理:调用 [EnvUtil.java](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/util/EnvUtil.java)的getEnv().getCode()方法
7. Repository层的的分页方法:调用MyBatis-Plus的selectPage方法
   
#### DAO层PO
1. DAO层PO的命名规范为${TableName}PO
2. DAO层PO的存放目录[model](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/model)

#### DAO层Mapper
1. DAO层Mapper命名规范为${TableName}Mapper
2. DAO层Mapper的存放目录dao
   
#### Repository层
1. Repository层interface命名规范为${TableName}Repository
2. Repository层实现命名规范为${TableName}RepositoryImpl
3. Repository层Model命名规范为${TableName}Model
4. Repository层interface的存放目录repository
5. Repository层实现的存放目录repositoryimpl
6. Repository层Model存放目录model

#### Converter层
1. Converter层命名规范位${TableName}Converter
2. Converter层的存放目录convert
3. Converter代码规范:使用字段进行映射,禁止使用json序列化、BeanUtils.copyProperties等方式

参考代码

1. DAO层PO参考代码

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

${必要的引用}

/**
 * @author chigong.zxn
 */
@Data
@Builder
@TableName(value = "${tableName}")
@AllArgsConstructor
@NoArgsConstructor
publicclass ${TableName}PO {
    ${注释}
    ${只可以使用包装类型,禁止使用基础类型}
    ${columnName}
}

2. DAO层Mapper参考代码,【注意:不需要增加增删改查方法,MyBatis-Plus已经默认通过继承BaseMapper提供】

import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author chigong.zxn
 */
@Mapper
public interface ${TableName}Mapper extends BaseMapper<${TableName}PO> {
}

3. Repository层interface参考代码,【注意:生成基础的增删改查方法】

import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;
import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}Model;

/**
 * @author chigong.zxn
 */
@Mapper
public interface ${TableName}Repository {
    ${注释}
    ${增删改查方法}
}

4. Repository层实现参考代码,【注意:继承Repository接口实现基础增删改查方法,调用Mapper生成基础的增删改查方法】

import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;
import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}Model;

/**
 * @author chigong.zxn
 */
@Mapper
public interface ${TableName}RepositoryImpl implements ${TableName}Repository {
    ${注释}
    ${实现Repository增删改查方法}
}

5. Repository层Model参考代码

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

${必要的引用}

/**
 * @author chigong.zxn
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
publicclass ${TableName}Model {
    ${注释}
    ${只可以使用包装类型,禁止使用基础类型}
    ${columnName}
}

6. Converter层参考代码,【注意:生成2个静态方法,PO转Model、Model转PO】

import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;
import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}Model;

/**
 * @author chigong.zxn
 */
publicclass ${TableName}Converter {
    ${注释}
    ${PO转换为Model}

    ${注释}
    ${Model转换为PO}
}

API层代码规范

---
description: 增加HSF接口时引用此文件
globs: 
alwaysApply: false
---
## API开发规范
### 服务实现
* 验证器存放目录:[validate](mdc:task-biz/src/main/java/com/aliexpress/qa/task/biz/eval/api/)
* 实现要求:必须实现服务验证器
* 服务实现代码参考:
``` java
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
publicclass ${服务名}ServiceImpl implements ${服务名}Service {
    privatestaticfinal Logger logger = LoggerFactory.getLogger(${服务名}ServiceImpl.class);
    @Autowired
    private ${服务校验器}Validate validate;
    // 如果需要调用其他bean也可以在此处引入
    // 如:
    // @Autowired
    // private EvalDatasetDetailRepository evalDatasetDetailRepository;
    @Override
    public ${服务方法出参} ${服务方法名}(${服务方法请求体} request) {
        logger.info("${服务名}Service.${服务方法名} request:{}", JSON.toJSONString(request));
        ${服务方法出参} response = new ${服务方法出参}();
        try {
            String validateMsg = validate.${服务方法校验器}Validate(request);
            if (StringUtils.isNotBlank(validateMsg)) {
                return Response.fail(ErrorCode.PARAM_ERROR.name(), validateMsg);
            }
            // 在此处实现业务逻辑
            ${业务逻辑}
        } catch (Exception e) {
            logger.error("${服务名}Service.${服务方法名} error", e);
            response = Response.fail(ErrorCode.SYSTEM_ERROR.name(), e.getMessage());
        }
        logger.info("${服务名}Service.${服务方法名} response:{}", response);
        return response;
    }
}
```
### 服务验证器
* 验证器存放目录:[validate](/task-biz/src/main/java/com/aliexpress/qa/task/biz/eval/api/validate/)
* 验证器代码参考:验证失败则返回失败原因字符串,验证成功则返回空字符串
``` java
import com.aliexpress.qa.task.biz.eval.util.ValidateUtil;
import org.springframework.stereotype.Component;
@Component
publicclass ${服务名}Validate {
    // 如果需要调用其他bean也可以在此处引入
    // 如:
    // @Autowired
    // private EvalDatasetDetailRepository evalDatasetDetailRepository;
    public String ${服务方法名}Validate(${服务方法请求体} request) {
        // 请求体不能为空
        if (request == null) {
            return"请求参数不能为空";
        }
        // 基础校验,使用ValidateUtil校验net.sf.oval annotation
        String validateMsg = ValidateUtil.validate(request);
        if (StringUtils.isNotBlank(validateMsg)) {
            return validateMsg;
        }
        // 写明校验注释
        #{文档要求的其他校验逻辑}
        // 返回空字符串则校验成功
        return StringUtils.EMPTY;
    }
}
```
### 分布式锁使用
* 服务实现代码参考:
``` java
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.aliexpress.qa.task.infrastructure.util.lock.DistributedLockUtil;
@Service
publicclass ${服务名}ServiceImpl implements ${服务名}Service {
    privatestaticfinal Logger logger = LoggerFactory.getLogger(${服务名}ServiceImpl.class);
    @Autowired
    private ${服务校验器}Validate validate;
    @Autowired
    private DistributedLockUtil distributedLockUtil;
    // 如果需要调用其他bean也可以在此处引入
    // 如:
    // @Autowired
    // private EvalDatasetDetailRepository evalDatasetDetailRepository;
    @Override
    public ${服务方法出参} ${服务方法名}(${服务方法请求体} request) {
        logger.info("${服务名}Service.${服务方法名} request:{}", JSON.toJSONString(request));
        ${服务方法出参} response = new ${服务方法出参}();
        try {
            String validateMsg = validate.${服务方法校验器}Validate(request);
            if (StringUtils.isNotBlank(validateMsg)) {
                return Response.fail(ErrorCode.PARAM_ERROR.name(), validateMsg);
            }
            // 根据业务逻辑要求构建lockKey
            String lockKey = ...;
            // 分布式锁,避免并发调度
            DistributedLock lock = distributedLockUtil.getLock(lockKey);
            // 获取分布式锁
            try {
                lock.tryLock(1000L);
            } catch (GetLockErrorException lockException) {
                return Response.fail(ErrorCode.LOCK_ERROR.name(), ErrorCode.LOCK_ERROR.getMessage());
            }
            try {
                // 在此处实现业务逻辑
                ${业务逻辑} 
            } finally {
                lock.unlock();
            }
        } catch (Exception e) {
            logger.error("${服务名}Service.${服务方法名} error", e);
            response = Response.fail(ErrorCode.SYSTEM_ERROR.name(), e.getMessage());
        }
        logger.info("${服务名}Service.${服务方法名} response:{}", response);
        return response;
    }
}
```

单元测试规范

---
description: 
globs: 
alwaysApply: false
---
# 单元测试指南

测试框架

- JUnit Jupiter 5.9.2
- Mockito 4.11.0
- JUnit Platform 1.9.2

严格执行

- 禁止改变被测试方法的任何行为
- private方法测试: 使用反射的方式测试private方法, 禁止改变被测试方法的private
  ```java
  @BeforeEach
  voidsetUp() throws NoSuchMethodException {
      // 获取私有方法
      Method privateMethod = TargetClass.class.getDeclaredMethod(“privateMethodName”, 
          ParameterType1.class, ParameterType2.class);
      privateMethod.setAccessible(true);
  }

  @Test
  voidprivateMethodName_Should_ExpectedBehavior_When_StateUnderTest() throws Exception {
      // given
      // when
      Object result = privateMethod.invoke(targetObject, arg1, arg2);
      // then
      // assertions
  }
  - 静态方法Mock: 使用MockedStatic方式 - staticfinal字段处理: 避免直接测试或mock staticfinal字段(如日志记录器),专注于测试核心业务逻辑和返回值 - Mybatis-Plus初始化实体类元数据: mock Mybatis-Plus的LambdaUpdateWrapper、LambdaQueryWrapper时,在@BeforeEach中使用TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), “”),${实体类名}PO.class);```初始化实体类元数据

测试命名规范

- 使用 @Test 注解标记测试方法
- 测试方法名应该清晰表达测试目的,并且测试方法名必须包含被测试的方法名
- 格式:${被测试方法名}_Should_ExpectedBehavior_When_StateUnderTest
- 示例:buildQuery_Should_ReturnQueryWithEntrustBizId_When_UserHasEntrustPermission

测试最佳实践

Mock策略

- 优先测试核心业务逻辑,避免过度依赖基础设施组件的验证
- 对于不可变的静态组件(如staticfinal字段),采用行为验证而非状态验证
- 当无法直接mock某个组件时,考虑通过测试输出结果来间接验证行为
- Mock对象使用: 只能对mock()创建的对象使用when()进行stub,禁止对真实对象(如通过builder模式创建的对象)使用when()

测试重点

- 专注于方法的返回值、异常抛出、状态变更等核心行为
- 避免测试框架细节、日志输出等非核心功能
- 保持测试的简洁性和可维护性

模块功能文档规范

---
description: 
globs: 
alwaysApply: false
---
## 生成记忆
- 创建记忆文件夹:记忆文件统一存放在 [.cursor/memory](mdc:.cursor/memory) ,如果我提供了指定了文件目录则按照我提供的文件夹存放,如果我没提供则根据需要梳理的链路自动起名创建文件夹
- 创建记忆文件:如果我提供了名字,则按照我提供的名字创建,如果我没有提供,则根据需要梳理的链路自动创建文件,已`.md`格式的文件维护记忆。
- 记忆文件内容要求:必须包含一个完整的链路图,并且将必要的代码入口、核心的代码逻辑放在记忆文档中。


技术方案文档规范
---
description: 
globs: 
alwaysApply: false
---
## 生成开发任务
- 创建任务文件夹:当我要求你创建一个开发任务时,你需要根据`当前分支`的名称在 [.cursor/task](mdc:.cursor/task) 文件中查找是否有对应任务的文件,如果没有则创建一个任务文件夹
- 创建任务文件:在以`当前分支`命名的文件夹中,创建当前任务的详细描述文件,使用`.md`的文件格式生成文档内容,文件名根据我的要求自动生成一个中文名

文档内容规范

- 文档结构:保持简洁,专注技术方案。在没有明确要求时不包含开发计划、风险控制、上线计划等管理内容
- 测试要求:单元测试要求,覆盖率达到80%以上
- 尽量简洁:在满足要求的情况下尽量简洁,如果有需要补充的内容,我会明确的向你表达

代码设计规范

- 枚举使用:新增字符串类型字段时优先考虑枚举定义,避免硬编码
- 历史兼容:新增字段时考虑历史数据兼容性,提供默认值处理



2.3. 代码生成与测试

平衡效率和质量核心是控制单个任务不要过大,当下过大的任务质量和验证过程都会失控。

  • 拆解子任务分步执行:和AI共同完成技术方案后,可以要求其将技术方案分成多个子任务,然后子任务分步执行、验证、调整。

  • 让AI按照技术方案写测试代码:确保核心场景单元测试都能覆盖到,避免我们成为AI的填坑奴隶。更进一步是让AI生成集成测试、端到端测试(尝试中)。

  • AI自Review代码:根据技术方案生成代码之后,可以要求AI根据技术方案检查下当前的代码变更,是否有错漏的。

对AI的约束模型为了获得奖励,有时候会用作弊的方式假装满足用户的要求

  • 作弊问题:当AI反复多次无法完成任务时,就会出现作弊现象,比如硬编码绕开测试、模型自己直接给出结果等。可以在规则中明确禁止,禁止绕开需求直接生成结果,如无法完成时可以明确表示无法完成。

  • 超额输出问题:无论是技术方案还是代码都存在超额输出的问题,AI可能会输出一些不着边际的方案或代码,可以将这个问题尽量在技术方案阶段限制住,在生成技术方案时要求尽量简洁、专注技术方案,不必生成工期之类的内容,在生成代码时要求严格按照技术方案生成代码。

多任务并行开发Cursor本身支持多任务并行开发的能力

  • Cursor多子任务:将技术方案分成多个子任务后,可以在CursorIDE中同一个项目开启多个子任务并行开发,每个子任务分别验证。

  • Cursor Background Agent:异步编程Agent,在云端环境启动虚拟环境执行开发任务,但是需要上传代码到Cursor的云端环境,在团队版的Cursor中强制开启因素模式,无法使用Background Agent。

开发过程持续更新记忆类似上文提到的,记忆是逐步完善的,不是一蹴而就的,需要在过程中持续完善记忆。

  • 记忆与代码不匹配:无论是哪一层的记忆,如果开发过程中发现有缺少或不恰当的,可以直接要求AI根据特定代码修正记忆文档。

  • 经验总结回写记忆:如果在开发过程中,发现有一些规范或场景在规则中没考虑到的,可以完成一个子任务后,要求AI总结经验,并且使用简洁的方式回写到对应记忆文档中。

2.3.1. 对AI的约束示例

AI作弊的CASE:在一个JSON转HTML的任务中,cursor在多轮循环无法解决问题之后,直接生成了一个html的结果文件给我,绕开了使用代码生成html的要求。

严格按照要求执行示例

- 禁止作弊:对于生产代码和测试代码的生成,需要完全遵循框架和需求的要求,**禁止通过硬编码的方式直接生成结果或绕开测试等行为**。
- 严格按照要求写代码:如果我提供了开发任务的.md文档,请严格按照文档要求生成代码,不要擅自发挥。
- 保持简洁:专注按照我的需求生成技术方案。在没有明确要求时不包含开发计划、风险控制、上线计划等冗余内容

2.4. 工程师的基础能力

  • 对模型能力的动态认知清晰的认知当前AI的能力特征和极限,并且随着模型能力的提升,能够快速的形成对新模型的新认知,改变自己的行为模式获得更高的效率、质量。

  • 管理多个AI编程工具通过上下文工程、AI并行开发协作方法驱动多个AI编程工具,放大技术杠杆的效果。如Cursor多子任务、Cursor Background Agent、Claude Code多子Agent实例等并行开发手段。

  • 软件架构设计能力AI已经能帮助我们很好的处理细节,但是在企业级复杂系统中,AI当下依然是个执行角色,我们需要作为软件系统的主导者、控制者、设计者,让系统在预期之内演进。(自己能够处理细节的能力依然重要)

  • 业务理解与表达当AI已经能够处理很多的技术细节时,深入的产品业务理解能力和清晰的表达能力,未来是新的编程技巧。

三、真实的使用案例

3.1. 初始记忆维护

使用示例

Cursor规则描述

Cursor自动生成

应用基础记忆

输入指令:/Generate Cursor Rules 

要求生成特定的规则

基于应用基础记忆

结合代码入口生成

功能模块记忆文档

3.2. 技术方案生成

使用示例

基于功能

模块记忆

生成迭代

技术方案

3.3. 代码开发与测试

使用示例

执行开发任务

执行开发任务

复杂任务拆解

输入指令

将这个方案拆分为多个子任务,并且细化到可供Cursor执行的程度。

任务过程中反思

同项目并行开发

Playwright 

MCP

端到端测试

基础处于不可用状态,执行了5~10分钟,无法处理日期组件等复杂组件。

四、AI编程领域的最新趋势

4.1. 编程工具对比

Cursor依然是当下实用性和性价比较高的编程工具,但Claude Code的高任务完成度和其形态的高可玩性正在快速蚕食Cursor的用户市场。以Devin为代表的端到端异步Agent由于其较低的任务完成度,已经逐渐失去了用户的信任,处在黑暗中挣扎的阶段。(此处仅对比当下有代表性的2款热门工具)

近期Cursor的订阅模式的改变(Pro不限量)也可以侧面感受到来自ClaudeCode的竞争压力,从能力层面上ClaudeCode目前更强一些,但是Cursor放开Pro订阅的使用限制,是从成本和用量上拉开优势进行错位竞争,先留住用户,再追赶能力。(个人理解)

4.2. ClaudeCode使用体验

  • 特点:原生任务规划能力+Claude4任务完成度比Cursor更高,但是费用也更高。

  • 费用:费用高主要体现在20$每个月的订阅版本无法作为主力开发,其额度5小时刷新一次,但是1个额度周期只够开发1小时(真实使用),达到额度后要等下一个5小时周期。解决额度问题需要升级每月100$/200$的MAX版本,或者使用API访问。不过API的费用更加高昂,使用claude 4 sonnet1个任务要花掉2$(opus5倍价格)。

  • 并行开发:Claude Code原生集成Agent功能,在任务分解后可以让其自行启动多个子Agent并行开发,由Claude Code统一管理。

  • 解决复杂问题:在一个真实需求中,需要将格式不固定的JSON转成HTML,在Cursor使用了100次的额度、2-3个小时、尝试了3个方案依然无法符合要求。Claude Code沟通了3-4次完成了可运行的MVP,10次左右达到预期效果。

  • 无监督运行时长:Claude Code跳过权限提示后(--dangerously-skip-permissions),在无额度限制的情况下连续运行的时间远超过Cursor,社区有连续运行数个小时的例子。(Cursor的连续工作最大限制是25个tools)

  • 无监督自主开发的Agent是否具备条件:强如Claude Code,虽然持续执行的时间更长,但是依然很难做到长期无监督的运行。核心的问题是前期输入信息的完备性和后期的代码验收依然是个很大的挑战,执行任务的复杂度越高、无监督时间越长,结果越容易失控。

使用示例

安装和启动

# 安装(需要NPM)
npm install -g @anthropic-ai/claude-code
# 进入项目目录
cd ~/your-project
# 启动
claude


启动视图

使用了claude-code-router介入openrouter api的界面,订阅用户稍有区别

运行模式

创建技术方案

拆解子任务

并行开发

达到限额

ClaudeCode

工具集

ClaudeCode

解决真实问题

通义千问3 + MCP:一切皆有可能


MCP 协议通过标准化交互方式解决 AI 大模型与外部数据源、工具的集成难题;通义千问3 原生支持 MCP 协议,能更精准调用工具;阿里云百炼上线了业界首个全生命周期 MCP 服务,大幅降低 Agent 开发门槛,用户只需 5 分钟即可构建增强型智能体。


点击阅读原文查看详情。


嗯,说了这么多,我觉得核心就一句话:我们不能只当’代码的生产者’,而要升级为’AI的艺术指导’!就像导演和演员的关系,AI是优秀的演员,它能按剧本演得很好,但剧本好不好,演员选得对不对,怎么调度,怎么协调,最终呈现什么效果,都得由我们这些’导演’来把控。所以,培养的就应该是这种高维度的’掌控力’和’审美力’,知道什么时候用AI,用什么AI,以及怎么用它来达到最佳效果。当然,别忘了,保持愉悦的心情,因为你将拥有一个超强的’工具人’!——一位乐观的程序员

我觉得’上下文工程’和’高级提示词设计’(Prompt Engineering)是当务之急。文章里也反复提到了,给AI喂养什么样的信息,直接决定了它的产出质量。这不再是简单的“搜索”技能,而是要学会如何梳理复杂问题,将其结构化、层级化地喂给AI,并根据AI的反馈进行迭代优化。其次,对AI生成代码的’批判性审查’能力也至关重要,你不能完全依赖它,得能快速识别问题、分析深层原因并进行修正。最后,宏观的’系统设计能力’变得更关键,AI可以帮你填细节,但大厦的蓝图还得你来画。——某技术负责人

从技术角度看,最大的障碍在于通用的世界模型和高级推理能力。现有的AI在特定领域表现出色,但缺乏对代码背后“业务逻辑”和“系统架构”的真正理解,它们更多是基于模式识别。要独立完成复杂任务,Agent必须能像人类工程师一样进行高层次的设计、权衡利弊、识别潜在风险,甚至对未知的、抽象的需求进行有效转化和分解。这需要更强的多模态感知能力、长期的记忆整合与学习能力,以及对项目复杂性的持续管理能力,而不仅仅是代码生成。——计算机科学博士

确实,信任问题首当其冲。我们团队刚开始用AI生成代码时,不少同事都表示不放心,觉得AI写出来的代码质量没保证,或者担心自己会“失业”。这种心理上的阻力,比技术集成更难克服。另外,数据安全和知识产权也是大问题,一旦代码涉及到公司核心业务逻辑,谁敢轻易让AI去“学习”?万一数据泄露或者被模型当成训练数据外传,那后果可就大了。这些都得有明确的规章制度和技术保障。——某资深架构师

我觉得是’工程化的鲁棒性’。现在的AI Agent在特定场景下能跑通,但一旦遇到边界情况、异常处理、或者需要高度定制化的逻辑,就很容易露馅。真正的AI编程Agent,不仅要能写出’能跑’的代码,还要能写出’高质量、可维护、可扩展、bug少’的代码。这就要求它能够模拟人类工程师的’批判性思维’和’系统性思维’,对自己的产出进行深度自检和优化。目前来说,很多Agent在连续多步骤任务中容易迷失方向,难以进行有效的自我纠错和长链条规划。——某高级研发工程师

嘿,我觉得是AI需要一颗’好奇心’和’自我驱动力’!你看我们程序员,遇到一个新问题,总想去研究透彻,找各种资料,甚至会主动去优化现有代码。AI现在更多是被动地接收指令并执行,它没有那种‘想把事情做得更好’的内在驱动力。如果AI Agent能主动发现代码中的潜在问题,或者能根据最新的技术趋势反哺代码设计,那才叫真香!当然,还有就是处理’模糊需求’的能力,老板们可不会把需求写得像PRD一样严谨规范,AI得学会从只言片语中领会精神。——一位“懒癌晚期”但热爱技术的程序员

我觉得是工作流程的摩擦。AI介入后,是不是每个PR都得加个“AI生成代码审查”环节?出了bug是怪写需求的,怪AI的上下文没给对,还是怪程序员没仔细改?责任划分不清楚,很容易踢皮球。而且,如果AI生成效率很高,但新人缺乏基础功底,过度依赖AI,那长此以往,团队的整体编程能力可能会下降,这不是一个好现象。——一位在职程序员

除了技术,我认为最重要的能力是’高效学习能力’和’跨领域融合能力’。AI技术本身发展很快,新的模型和工具层出不穷,你必须能快速理解其优势和局限,并将其集成到自己的工作流中。同时,由于AI能处理大量技术细节,我们人类就应该把精力更多地放在业务理解、用户体验、以及多系统间的集成优化上。未来,'懂业务的架构师’可能会比’纯粹的编码机器’更稀缺。——一名年轻的程序员,关注技术趋势