這是蒼何的第 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 圖,來幫助了解。
prompt:基于該 sql 文件,生成實體-關系圖,并按照業務域對數據庫表進行分類 這里有個細節,由于 sql 文件非常大,在 Chat 界面可以看到,JoyCode 會對整個上下文進行合理壓縮,然后制定該任務的 todolist,agent 會執行任務。
![]()
先看下稍微簡單一些的任務,將表按照業務域做分類,這個完全沒啥問題。
![]()
到了畫圖這,由于表過多,我本就沒打算它能一次成,在一番處理后,終于生成好了。
![]()
說實話,這和我理想中的 ER 圖有些距離,不過用來做項目輔助理解,多少有些用。
有了清晰的數據結構,對于有些復雜的業務邏輯,可以借助 AI 來進行代碼脈絡查看,可以通過流程圖來輔助理解。
比如 PmHub 項目中的這串代碼:
/**
* 任務待逾期提醒
*/
@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 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 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 接口文檔地址:https://laigeoffer-pmhub.apifox.cn
給到如下提示詞:
基于該API文檔:https://laigeoffer-pmhub.apifox.cn 中的"我的項目"模塊進行開發,請嚴格遵循開發規范和接口定義,前后端分離,保證項目可運行。他會先根據 API 文檔創建需求文檔、設計文檔和任務文檔。
![]()
然后就開始吭哧吭哧的由前端到后端的開發。我這里選的是 JoyCode 的規約編程模式。
一句話解釋規約編程:你不用手把手教 AI 怎么做,你只管用規則(規約)把“要什么”和“標準是什么”定義清楚,AI 就能自己寫出 100% 滿足你要求的代碼。
在任務列表中可以分解了 22 個任務,等待執行,我們點擊確認全部執行。
![]()
在任務隊列中就可看到所有任務,JoyCode 會按照任務順序依次執行。
![]()
這里我發現了一處小細節,在 JoyCode 中多個任務是可以并行的,比如這個命令:
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 就能自己寫出滿足你要求的代碼。
以后接手沒有注釋和文檔的屎山項目時,也許我們終于不用再戴上痛苦面具了。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.