这是苍何的第 445 篇原创!
大家好,我是刷 GitHub 停不下来的苍何。
刷了很久的 GitHub,发现个有意思的开源项目。

看了下,这是京东开源的 joycode-agent,目前在 SWE-Bench Verified 基准测试中凭借 74.6% 的高通过率位居榜单全球 Top3。

SWE-Bench Verified 是通过使用真实世界开源项目中的 Bug 报告和 Issue 来测试 Agent 从理解问题到自主生成、集成和验证修复代码的完整端到端能力,是 AI Coding 技术走向和产品落地的行业风向标之一。
从跑分和能力上来看,JoyCode 针对的应该是企业级研发场景。
我点进去他们官网,就可以直接下载 JoyCode 这款智能编码工具。

进入后,导入 vscode 配置,做下简单设置,然后用京东账号登录。

可以看到,JoyCode 内置了很多的资源和 MCP 工具。

也内置了很多主流的大模型,都可以直接使用,也可自定义添加模型,集成了 Git 做代码的版本管理,自动生成 commit message 信息。
看了 JoyCode 设置,可以开启代码评审,针对每次提交的代码,自动进行质量、安全、编码规范、逻辑错误等多维度的扫描,并提供修复建议。

稍微总结下它的核心能力:
1、多智能体架构:可定制智能体,通过"先规划、后执行"的策略,以团队协作方式智能拆解复杂任务。
2、支持规约编程:基于需求、设计、实施的三阶段工作流程,可实现从需求到交付的端到端覆盖。
3、CSR上下文引擎:通过对代码仓库的深度解析,全面理解代码仓库上下文等集成开发环境信息。
4、可一键云端部署。
看了京东云官方公众号消息,说是 JoyCode 已服务京东上万名研发人员,支撑数亿级用户产品研发,生成代码采纳率超 50%,开发周期缩短 40%。

于是乎,我又开始了一顿测试,来看看 JoyCode 实际能力如何。
既然主打的是企业级智能编码工具,那就来几个企业级开发最为关心的几大问题。

快速上手老项目
大部分时间,企业中并不总是在开发新项目,而是在原有项目上做些功能的迭代或者业务的更新。
特别是对于新人,新加入项目团队后,要快速掌握整个项目,绝非一件容易的事,稍微规范点的团队会有相关文档,但很多团队项目,就真的只有一份代码。
最让人痛苦的是,这份代码,连个注释都没有,业务逻辑和数据结构,要人肉去理解,花费时间及其漫长,痛苦面具+1。
我尝试用 JoyCode 来做这方面的工作,就拿我的真实企业级开源项目 PmHub 来测试吧。
先让 JoyCode 基于项目源码帮我生成项目架构图。

可以看到 JoyCode 自动切换到架构图设计模式,然后上来就先分析了项目中的 pom. xml 依赖文件及 Readme 文件,以及对整个项目理解就开始吭哧吭哧自动调用 draw. io 帮画项目架构图了。
这里我等了不少时间,中途甚至有些想放弃,骂一句辣鸡,然后滚去睡觉。但最后出来的结果,让人很惊喜。

除了还原了整个项目的技术架构,还把各个层的流转用流动箭头做了标记。可以说,这是目前为止,我最满意的一次架构图设计实验。
JoyCode 生成. drawio 文件后,通过插件或者 draw.io 就能打开了。
了解了整个项目架构,还需要根据数据结构来从数据层面了解业务。可以让它生成对应的 ER 图,来帮助了解。
sql
prompt:基于该 sql 文件,生成实体-关系图,并按照业务域对数据库表进行分类
这里有个细节,由于 sql 文件非常大,在 Chat 界面可以看到,JoyCode 会对整个上下文进行合理压缩,然后制定该任务的 todolist,agent 会执行任务。

先看下稍微简单一些的任务,将表按照业务域做分类,这个完全没啥问题。

到了画图这,由于表过多,我本就没打算它能一次成,在一番处理后,终于生成好了。

说实话,这和我理想中的 ER 图有些距离,不过用来做项目辅助理解,多少有些用。
有了清晰的数据结构,对于有些复杂的业务逻辑,可以借助 AI 来进行代码脉络查看,可以通过流程图来辅助理解。
比如 PmHub 项目中的这串代码:
less
/**
* 任务待逾期提醒
*/
@Component
@Slf4j
publicclass TaskNotifyJob {
@Autowired
private ProjectTaskMapper projectTaskMapper;
@Autowired
private ProjectTaskNotifyMapper projectTaskNotifyMapper;
@Scheduled(cron = "0 0 9 * * ?")
@Transactional(rollbackFor = Exception.class)
public void taskNotify() {
List<TaskNotifyDTO> tasks = projectTaskMapper.queryTaskNotifyJob();
// 当前时间
LocalDate localDate = LocalDate.now();
tasks.stream().filter(taskNotifyDTO -> StringUtils.isNotBlank(taskNotifyDTO.getUserWxName()) && taskNotifyDTO.getCloseTime() != null)
.forEach(taskNotifyDTO -> {
if (ProjectStatusEnum.PAUSE.getStatus().equals(taskNotifyDTO.getStatus())) {
return;
}
LocalDate closeDate = taskNotifyDTO.getCloseTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
if (ChronoUnit.DAYS.between(localDate, closeDate) == taskNotifyDTO.getNotifyDay()) {
log.info("待逾期任务提醒开始, 用户id:{}, 企微id:{}, 任务id:{}", taskNotifyDTO.getUserId(), taskNotifyDTO.getUserWxName(), taskNotifyDTO.getTaskId());
// 进行待逾期消息提醒
TaskOverdueRemindDTO taskOverdueRemindDTO = new TaskOverdueRemindDTO();
// 设置任务名称
taskOverdueRemindDTO.setTaskName(taskNotifyDTO.getTaskName());
// 设置通知用户id
taskOverdueRemindDTO.setUserIds(Collections.singletonList(taskNotifyDTO.getUserWxName()));
// 设置天数
taskOverdueRemindDTO.setNum(taskNotifyDTO.getNotifyDay());
// 设置任务详情地址
String url = SsoUrlUtils.ssoCreate(appid, agentid, host + path + ssoPath + URLEncoder.encode(host + "/pmhub-project/my-task/info?taskId=" + taskNotifyDTO.getTaskId()));
taskOverdueRemindDTO.setDetailUrl(url);
taskOverdueRemindDTO.setOaTitle("任务即将逾期提醒");
taskOverdueRemindDTO.setOaContext("您的任务【" + taskNotifyDTO.getTaskName() + "】还有【" + taskNotifyDTO.getNotifyDay() + "】天到期,请及时处理!");
taskOverdueRemindDTO.setUserName(taskNotifyDTO.getUserName());
taskOverdueRemindDTO.setLinkUrl(OAUtils.ssoCreate(host + "/pmhub-project/my-task/info?taskId=" + taskNotifyDTO.getTaskId()));
RocketMqUtils.push2Wx(taskOverdueRemindDTO);
// 进行查询 如果数据库不存在记录 则就插入记录
LambdaQueryWrapper<ProjectTaskNotify> qw = Wrappers.lambdaQuery(ProjectTaskNotify.class).eq(ProjectTaskNotify::getTaskId, taskNotifyDTO.getTaskId()).eq(ProjectTaskNotify::getOverdue, 0);
if (projectTaskNotifyMapper.selectOne(qw) == null) {
// 插入记录
ProjectTaskNotify projectTaskNotify = new ProjectTaskNotify();
projectTaskNotify.setProjectId(taskNotifyDTO.getProjectId());
projectTaskNotify.setTaskId(taskNotifyDTO.getTaskId());
projectTaskNotify.setOverdue(0);
projectTaskNotify.setUserId(taskNotifyDTO.getUserId());
projectTaskNotify.setUserWxName(taskNotifyDTO.getUserWxName());
projectTaskNotify.setCloseTime(taskNotifyDTO.getCloseTime());
projectTaskNotify.setTaskName(taskNotifyDTO.getTaskName());
projectTaskNotifyMapper.insert(projectTaskNotify);
}
log.info("待逾期任务提醒结束");
}
});
}
}
可以选中这段代码后,解释该代码。

然后让 JoyCode 生成流程图。

代码评审
在团队开发中,开发完代码通常需要进行代码评审,也简称为 CR,这个工作通常会团队内交叉进行,最终上线需要技术 leader 进行最终 CR。
现在就可以把这个工作先交给 AI 来做一轮前置评审,识别出相关风险,保证代码质量。

JoyCode 会给出一份评审报告,并列出改进建议和优先级排序。

在完成开发后,做代码提交,JoyCode 能够自动添加 git commit 信息。

接口变生产代码
在实际企业级开发中,前后端会同步开发,往往是先定义好接口,然后前后端都基于该接口进行开发。
所以如何将定义好的接口(API 文档)转化为生产级代码,就显得很重要。
我尝试在 JoyCode 中测试该功能,比如照着我们开源的 PmHub 项目的接口文档,我们尝试做点有意思的事情。
PmHub 接口文档地址:laigeoffer-pmhub.apifox.cn
给到如下提示词:
bash
基于该API文档:https://laigeoffer-pmhub.apifox.cn 中的"我的项目"模块进行开发,请严格遵循开发规范和接口定义,前后端分离,保证项目可运行。
他会先根据 API 文档创建需求文档、设计文档和任务文档。

然后就开始吭哧吭哧的由前端到后端的开发。我这里选的是 JoyCode 的规约编程模式。
一句话解释规约编程:你不用手把手教 AI 怎么做,你只管用规则(规约)把"要什么"和"标准是什么"定义清楚,AI 就能自己写出 100% 满足你要求的代码。
在任务列表中可以分解了 22 个任务,等待执行,我们点击确认全部执行。

在任务队列中就可看到所有任务,JoyCode 会按照任务顺序依次执行。

这里我发现了一处小细节,在 JoyCode 中多个任务是可以并行的,比如这个命令:
bash
cd pmhub-ui && npm install
它就能在终端自己并行执行,在 Chat 中的代码任务也在同步执行。
在生成前端代码这个任务中,可以看到无论是使用的框架还是文件类命名的风格都出奇的和规范保持一致,甚至还学习了命名风格,环境配置。
我列了一张对比图:

出奇的相似。前端页面也完全可用。

登录进来后就可以看到项目管理功能模块了。

这是一个基于 API 文档利用 JoyCode 生成的项目管理系统,全程我唯一要做的是把 API 丢给 JoyCode,然后让他规划任务,按照指定的规约进行编程。
JoyCode 的表现还不错👍,在严肃的企业级场景中,不会瞎搞,像是个憨实的程序员。
一句话需求到 PRD
我从 GitHub 了解到,JoyCode 内置了一些工具,能将一句话需求快速转变为专业产研翻译,生成 PRD 文档。
来测试下效果。
提示词:帮我生成专业的PRD文档,我需要开发一个项目管理系统,支持新建项目、项目中新建任务。

可以看到将口语的一句话需求转化为了专业的业务语言。
全栈开发
我也蛮想试试在 JoyCode 中进行全栈开发,
这里我直接利用原先 PmHub 的 PRD 文档和设计原型文档,进行全栈开发。
ps:这也是规约编程的执行标准,不建议直接上手开发,在开发前定义好相应需求和设计,才能让 AI 更好的完成任务。
我的目的很简单,帮我一比一复刻一个 PmHub 出来。
但由于 PmHub 功能很多,完全复刻需要时间,这里我就以基础的能力来做了复刻。下面是我整体的实现流程。

第一步,PRD 分析。
PmHub 的需求分析长这样:

提示词:你是一名全栈架构师,以上是项目管理系统的prd,帮我根据这个prd,
生成一个关键设计说明。并生成系统整体交互流程UML时序图

生成的时序图,经过调整和样式简单优化得到如下:

这里的 UML 逻辑需要多次核对,Chat 修改,最终能得到符合的效果,稍微有些花时间。
第二步,设计原型文档分析。
这是 PmHub 的原型设计图,直接将他丢给 JoyCode。

以上是项目管理系统的原型设计文档「URL链接」,请基于此进行技术方案设计。
可以看到结果会更偏向设计需求:

第三步、生成 API 接口文档
接口先行,并行开发,是敏捷开发的必要点,这里我创新性的让 JoyCode 先根据以上信息生成 API 接口文档,然后根据上面的步骤再依次生成前后端代码及数据库代码。
由于模块很多,建议区分单个模块生成。
基于以上信息及文档,帮我生成项目管理模块中的项目列表和添加项目的 api 接口文档,我要能直接导入到apifox中。

然后还生成了 api 文档说明。

这里需要导入到 Apifox 中进行 check,确保符合后继续接下来的操作。
第四步,生成代码。
这里我的经验是根据 api 文档以及原型设计稿会有很好的效果,AI 不会瞎搞,样式和接口都是按照预定的来。
包括技术设计、架构设计,这些在规约中已经指定,这就是规约编程的魅力吧。
和之前一样,JoyCode 会根据要求,老老实实写代码。
由于时间关系,我就只让开发了登录页面、项目列表页和新建项目,包括整个框架这次我也让生成好了,这样下次单模块开发就能直接使用。
登录页:

这是项目列表页:

这是添加项目页面:

可以说,98%以上还原了我 PmHub,包括页面组件样式和功能。
虽然,过程中会有一些问题需要调整,但在 JoyCode 中也能方便的处理。
我体验下来,JoyCode 对于复杂任务的理解和处理效果是很好的,如果给的足够详细,比如原型设计,基于 API 接口开发等。
更能发挥出好的效果。
还可以在 JoyCode 中一键部署,不过我的功能还没开发完全,就先不部署了,到时再多调调,看下能否完全复刻出一个 PmHub 出来。
呼,现在真方便了。有了 AI 规约编程,你不用手把手教 AI 怎么做,你只管用规则(规约)把"要什么"和"标准是什么"定义清楚,AI 就能自己写出满足你要求的代码。
以后接手没有注释和文档的屎山项目时,也许我们终于不用再戴上痛苦面具了。