-
为什么用iFlyCode?: iFlyCode的智能体发展,且9.15后Cursor计费规则变化导致很容易账号受限。
-
为什么是SpecKit?: 自个人通过Kiro的whitelist计划试用一个开源项目迭代需求后,对这个可应用到Cursor的SDD编码方法论开始着迷深度试用。
-
用iFlyCode是不是又要切换IDE?: 从使用习惯角度直接用了iFlyCode的VS Code插件版,无需经历IDE切换阵痛。
背景介绍
项目背景
iExam 8.0 是一个成熟的招生考试管理系统,采用传统的 Spring Framework 4.3.30 + MyBatis 架构。在日常运维中,我们需要不断添加新功能和优化现有功能。本文详细记录了使用 iFlyCode(星火灵码)+ 规范驱动开发(SDD)方法完成照片质量检查功能的完整过程,包括遇到的所有问题和解决方案。
技术栈
- 后端
: Spring Framework 4.3.30、MyBatis、SQL Server
- 前端
: LayUI 2.2.2、FreeMarker、jQuery
- 开发工具
: iFlyCode(基于Cursor IDE)
- 开发方法
: 规范驱动开发(SDD) - Spec Kit工具
- 图像处理
: Java ImageIO、Apache Commons Imaging
核心需求:照片质量检查功能
复杂度: ⭐⭐⭐⭐⭐
涉及技术:
-
异步批量处理(Spring @Async)
-
图像质量检测(6个检查器)
-
前后端完整集成
-
数据库设计和优化
-
JSON数据处理
-
照片渲染逻辑
开发周期: 3天
-
Day 1: POC验证 + 核心检查器实现
-
Day 2: Service/DAO/Action层开发 + 前端集成
-
Day 3: 问题修复 + 优化完善
什么是规范驱动开发(SDD)?
SDD 核心理念
规范驱动开发(Specification-Driven Development, SDD)是一个革命性的开发方法论,它让规范成为可执行的,而不仅仅是文档。
核心哲学:
🎯 专注于 What(做什么)- 定义你想构建什么以及为什么- 而非技术实现细节🤖 AI 驱动执行- 利用 AI 智能体将规范转化为工作代码- 自动化实现过程🚀 快速交付- 消除规范与实现之间的鸿沟- 缩短从需求到交付的时间
SDD 工具生态
规范驱动开发(SDD)是一个快速发展的领域,目前已有多个工具和平台支持这一方法论:
1. SpecKit (GitHub开源) ⭐ 本项目使用
- 项目地址: https://github.com/spec-kit/spec-kit
- 官方网站: https://speckit.org/
- 特点:
-
✅ 开源免费,社区驱动
-
✅ 基于Slash Commands的工作流
-
✅ 7个核心阶段(Constitution → Implement)
-
✅ 与主流AI编程助手集成(Cursor、Windsurf等)
-
- 适用场景
中小型项目、敏捷开发、快速原型
- 本项目选择理由
-
开源免费,无供应商锁定
-
学习曲线平缓,快速上手
-
与iFlyCode/Cursor等AI编程助手无缝集成
-
适合传统Spring项目的增量开发
-
2. OpenSpec (Fission AI)
- 项目地址
https://github.com/Fission-AI/OpenSpec
- 官方网站
https://openspec.dev/
- 核心定位
轻量级、棕地优先(Brownfield-first)的规范驱动开发工具
- 特点
-
✅ 开源免费,MIT 许可证
-
✅ 无需API密钥,最小化设置
-
✅ 双文件夹模型:
openspec/specs/(当前真相)+openspec/changes/(提议更新) -
✅ 变更追踪:提案、任务、规范增量集中管理
-
✅ 支持20+主流AI编程工具(Claude Code、Cursor、Windsurf等)
-
✅ 兼容AGENTS.md规范
-
✅ CLI工具:
openspec init、list、validate、archive
-
- 核心优势
- 棕地优先
专为修改现有功能设计(1→n场景)
- 显示差异
规范增量(Delta)清晰可审查
- 跨规范更新
一个变更可涉及多个规范文件
- 状态分离
当前真相与提议更新分离管理
- 棕地优先
- 适用场景
-
✅ 旧项目的增量开发
-
✅ 修改现有功能和行为(1→n场景)
-
✅ 跨多个规范的功能更新
-
✅ 需要明确变更追踪的团队协作
-
- 何时考虑
-
在成熟项目中添加新功能(需要修改现有模块)
-
需要修改现有系统行为
-
需要清晰的变更历史和审计
-
团队需要在变更前达成一致
-
⚠️ 重要说明:旧项目中的新功能开发
- 纯新功能(0→1)
如果是完全独立的新模块,不涉及现有代码修改 → SpecKit更合适
- 需要集成的新功能(0.5→1)
新功能但需要修改现有模块进行集成 → OpenSpec更合适
- 本项目案例
照片质量检查是新功能,但需要:
-
修改现有的报名管理模块(添加入口按钮)
-
集成现有的DAO层和数据库
-
遵循现有的架构规范
-
因此属于0.5→1场景,OpenSpec的变更追踪机制更有价值
-
为什么选了SpecKit?作者对SpecKit较为熟悉,OpenSpec未实际应用过( ╯□╰ )
-
3. Kiro (独立AI IDE)
- 项目地址
https://kiro.dev/
- 特点
-
✅ 专为AI编程设计的独立IDE
-
✅ 原生支持规范驱动开发(SDD)工作流
-
✅ 自主代理模式(Autopilot Mode):AI自主执行大型任务
-
✅ 代理钩子(Agent Hooks):基于事件自动触发任务(如保存文件时自动生成测试)
-
✅ 原生MCP集成:连接文档、数据库、API等外部资源
-
✅ 多模态输入:支持UI设计图、架构白板照片等
-
✅ 实时代码差异预览:可视化代码变更
-
✅ 项目级配置(Steering Files):自定义编码标准和工作流
-
✅ 兼容VS Code插件和主题
-
- AI模型支持
Claude Sonnet 4、Auto模式(混合多个前沿模型)
- 适用场景
-
从原型到生产的完整开发流程
-
需要AI深度参与的复杂项目
-
重视工程实践和代码质量的团队
-
需要自动化工作流(测试、文档、优化)
-
- 差异化
-
专为AI编程从头构建的IDE
-
规范驱动开发原生支持
-
自主代理和事件驱动自动化
-
- 何时考虑
-
需要完整的SDD工作流支持
-
希望AI自主处理大型任务
-
需要自动化重复性工作(测试、文档等)
-
追求工程化的AI编程体验
-
4. 工具对比
|
维度 |
SpecKit |
OpenSpec |
Kiro |
|---|---|---|---|
| 开源性 |
✅ 开源 |
✅ 开源 |
❌ 商业 |
| 许可证 |
MIT |
MIT |
专有 |
| 核心定位 |
全流程SDD |
棕地优先SDD |
AI原生IDE |
| 最佳场景 |
0→1新功能 |
1→n修改现有功能 |
0→1→n全流程 |
| 工作流支持 |
7阶段Slash Commands |
4阶段CLI工作流 |
原生SDD工作流 |
| 变更管理 |
单一规范文件 |
双文件夹模型(specs + changes) |
多规范文件夹 |
| 差异追踪 |
基础 |
✅ 显式Delta格式 |
基础 |
| AI工具集成 |
主流AI助手 |
20+ AI工具(含AGENTS.md) |
内置Claude Sonnet 4 |
| 自动化能力 |
基础 |
中等(CLI自动化) |
强大(Agent Hooks) |
| 成本 |
免费 |
免费 |
付费订阅 |
| 适用规模 |
小中型 |
小中型 |
小中大型 |
| 学习曲线 |
低 |
低-中 |
中 |
| 工具形态 |
AI助手插件 |
CLI + 插件 |
独立IDE |
| 本地部署 |
✅ 支持 |
✅ 支持 |
✅ 支持 |
| 跨规范更新 |
⚠️ 有限 |
✅ 原生支持 |
✅ 支持 |
| 变更归档 |
手动 |
✅ 自动归档(merge到specs) |
手动 |
| MCP集成 |
⚠️ 依赖宿主 |
❌ 不支持 |
✅ 原生支持 |
| 多模态输入 |
⚠️ 依赖宿主 |
❌ 不支持 |
✅ 原生支持 |
5. SDD方法论的核心价值
无论选择哪个工具,SDD的核心价值都是一致的(也就是个人对prompt足够把握,自己定制自己的SDD也是可以的)
📋 规范优先 → 🤖 AI执行 → 🚀 快速交付(What) (How) (When)
- 规范优先
专注于业务需求和用户价值
- AI执行
利用AI自动化代码生成
- 快速交付
缩短从需求到交付的时间
Spec Kit 工作流程
Spec Kit 通过 Slash Commands(斜杠命令)实现结构化的开发流程:
Spec Kit Slash Commands 详解
|
命令 |
用途 |
执行时机 |
|---|---|---|
/constitution |
创建项目治理原则和开发指南 |
项目开始时首先运行 |
/specify |
定义需求和用户故事 |
专注于 what 和 why,不涉及技术栈 |
/clarify |
通过结构化提问澄清模糊之处 |
必须在 /plan 之前运行 |
/plan |
创建技术实现计划 |
选择技术栈和架构 |
/tasks |
生成可执行的任务列表 |
将计划分解为具体步骤 |
/analyze |
跨制品一致性和覆盖度分析 |
在 /tasks 之后、/implement 之前 |
/implement |
执行所有任务生成代码 |
最后执行,自动生成工作代码 |
核心案例
照片质量检查功能开发全程
阶段 1: Constitution(项目章程)
1.1 建立项目治理原则
执行命令:
/constitution 专注于代码质量、完整测试覆盖、用户体验一致性、遵循项目现有架构规范(Spring 4.3.30 + MyBatis DAO模式)
输出文档: docs/照片质量检查/CONSTITUTION_照片质量检查.md
关键原则:
## 代码质量原则- 严格遵循项目现有编码规范- 所有 Java 文件必须放在 iexam-xxx-service 模块- 使用 DAO 类而非 Mapper 接口- Action 类位于 module/bm/action 包## 测试原则- 单元测试覆盖率 > 80%- 关键业务逻辑必须有测试- 异步处理需要集成测试## 用户体验原则- 使用项目统一的 LayUI 2.2.2 框架- 保持与现有页面风格一致- 批量操作提供进度反馈
阶段 2: Specify(需求规范)
2.1 定义需求
执行命令:
/specify 为报名照片管理模块添加质量检查功能。核心功能:1. 单张照片质量检查(支持上传文件和指定路径)2. 批量照片质量检查(异步处理,支持大批量)3. 检查记录查询和统计分析4. 检查报告导出(Excel格式)质量标准:- 尺寸:358×441像素- 格式:JPG- 大小:30-100KB- 背景:纯色(白色/蓝色/红色)- 清晰度:无模糊、无噪点用户场景:- 管理员需要在考生报名后批量检查照片质量- 系统应该自动标记不合格照片- 提供详细的检查报告供管理员审核
输出文档: docs/照片质量检查/SPECIFICATION_照片质量检查.md
阶段 3: Clarify(需求澄清)
3.1 AI 自动提问
执行命令:
/clarify
AI 生成的澄清问题:
Q1: 批量检查的并发处理策略?A: 使用 Spring @Async 异步处理,线程池大小 5-10Q2: 检查失败后的处理流程?A: 记录失败原因,允许重新检查,不自动删除照片Q3: 进度查询的实时性要求?A: 1秒刷新一次进度,显示百分比和处理数量Q4: 报告导出的格式要求?A: Excel格式,包含考生信息、检查结果、失败原因Q5: 与现有系统的集成方式?A: 在 BkKsxp.html 页面添加入口按钮,独立页面展示
输出文档: docs/照片质量检查/CLARIFICATION_照片质量检查.md
阶段 4: Plan(技术规划)
4.1 技术方案设计
执行命令:
/plan 使用 Spring Framework 4.3.30 + MyBatis DAO 模式后端:Spring @Async 异步处理 + DAO 类 + XML 映射文件前端:LayUI 2.2.2 + FreeMarker + jQuery数据库:SQL Server,新增两张表(检查记录表、批量任务表)
输出文档: docs/照片质量检查/PLAN_照片质量检查.md
核心技术决策:
|
技术点 |
方案选择 |
理由 |
|---|---|---|
|
异步处理 |
Spring @Async |
原生支持,配置简单 |
|
批量任务 |
任务状态表 + 进度查询 |
实时反馈,用户体验好 |
|
数据访问 |
MyBatis DAO + XML |
符合项目规范 |
|
前端框架 |
LayUI 2.2.2 |
项目统一标准 |
|
模板引擎 |
FreeMarker |
项目统一标准 |
系统架构设计:
阶段 5: Tasks(任务分解)
5.1 生成任务列表
执行命令:
/tasks
输出文档: docs/照片质量检查/TASKS_照片质量检查.md
任务依赖图:
详细任务列表(18个任务):
后端任务(12个):
[x] 1. 创建 AsyncConfig.java 异步配置类- 位置:iexam-xxx-service/src/main/java/com/mstchina/iexam/xxx/config/- 依赖:无- 验收:@EnableAsync 注解生效[x] 2. 创建 BkKsxpCheckRecordDAO.java- 位置:iexam-xxx-service/.../quality/dao/- 依赖:无- 验收:继承 SqlSessionDaoSupport[x] 3. 创建 BkKsxpBatchTaskDAO.java- 位置:同上- 依赖:无- 验收:继承 SqlSessionDaoSupport[x] 4. 创建 BkKsxpCheckRecordMapper.xml- 位置:iexam-xxx-service/src/main/resources/mybatis/mapper/quality/- 依赖:Task 2- 验收:SQL 语句正确[x] 5. 创建 BkKsxpBatchTaskMapper.xml- 位置:同上- 依赖:Task 3- 验收:SQL 语句正确[x] 6-9. 创建 Entity 类(4个)- BkKsxpCheckRecord.java- BkKsxpBatchTask.java- PhotoQualityResult.java- CheckResult.java[x] 10. 创建 BkKsxpQualityService.java(15个方法)- 依赖:Task 2-9- 验收:所有业务方法实现[x] 11. 创建 BkKsxpQualityCheckAction.java(13个接口)- 位置:iexam-xxx-service/.../module/bm/action/- 依赖:Task 10- 验收:所有接口可访问[x] 12. 删除错误位置的文件- 清理 web 模块中的错误文件
前端任务(6个):
[x] 13. 创建 BkKsxpQualityCheck.html 页面- 位置:iexam-xxx-web/.../bkksxp/- 依赖:无- 验收:页面布局正确[x] 14. 创建 BkKsxpQualityCheck.js 脚本- 位置:同上 js/- 依赖:Task 13- 验收:所有功能可用[x] 15. 修正所有 URL 映射(7个接口)- 依赖:Task 11, 14- 验收:URL 正确[x] 16. 修改 BkKsxp.html 添加入口按钮- 依赖:Task 13- 验收:按钮可点击[x] 17. 修改 BkKsxpManage.js 添加跳转函数- 依赖:Task 16- 验收:跳转正常[x] 18. 验证项目编译- 依赖:All- 验收:mvn clean compile 成功
阶段 6: Analyze(一致性分析)
6.1 跨制品分析
执行命令:
/analyze
输出文档: docs/照片质量检查/ANALYSIS_照片质量检查.md
分析维度:
|
检查项 |
状态 |
说明 |
|---|---|---|
|
需求覆盖完整性 |
✅ |
所有需求都有对应任务 |
|
技术方案可行性 |
✅ |
符合项目架构规范 |
|
任务依赖合理性 |
✅ |
依赖关系清晰 |
|
文件位置正确性 |
✅ |
所有文件位置符合规范 |
|
URL 映射一致性 |
⚠️ |
需要修正 7 个 URL |
|
架构模式一致性 |
✅ |
使用 DAO 类模式 |
发现的问题:
1. 初始方案使用了 Mapper 接口(不符合项目规范)→ 修正:改为 DAO 类 + XML 映射文件2. Action 类位置错误(放在 web 模块)→ 修正:移动到 service 模块的 module/bm/action 包3. 前端 URL 映射错误(7个接口)→ 修正:使用 Action 类名作为路径
阶段 7: Implement(自动实现)
7.1 执行实现
执行命令:
/implement
输出文档: docs/照片质量检查/IMPLEMENTATION_照片质量检查.md
7.2 开发过程中的关键问题
问题1:项目启动失败
错误信息:java.lang.IllegalStateException:Failed to load ApplicationContext原因分析:缺少 @EnableAsync 配置解决方案:创建 AsyncConfig.java 配置类
问题2:MyBatis 架构不匹配
错误现象:创建了 Mapper 接口,但项目不支持原因分析:项目使用 DAO 类 + XML 映射文件模式解决方案:1. 删除 Mapper 接口2. 创建 DAO 类继承 SqlSessionDaoSupport3. 创建对应的 XML 映射文件
问题3:文件位置错误
错误操作:将 Action 类放在 iexam-xxx-web 模块正确做法:所有 Java 文件必须放在 iexam-xxx-service 模块关键规范:- Action 类位置:service/src/main/java/com/mstchina/iexam/xxx/module/bm/action- 包路径:com.mstchina.iexam.xxx.module.bm.action- URL 映射:/iexam/basis/bm/BkKsxpQualityCheckAction
问题4:前端 URL 映射错误
错误 URL:/iexam/basis/bm/bkksxp/photo/check/list正确 URL:/iexam/basis/bm/BkKsxpQualityCheckAction/photo/check/list修正数量:7 个 AJAX 请求 URL 全部修正
7.3 代码实现亮点
亮点1:异步批量处理
@Asyncpublic void processBatchCheck(String taskId, String[] ksidArray) {BkKsxpBatchTask task = batchTaskDAO.getById(taskId);for (String ksid : ksidArray) {try {// 执行检查PhotoQualityResult result = checkPhotoQuality(photoPath, ksid);// 保存记录saveCheckRecord(result);// 更新进度task.setProcessedCount(task.getProcessedCount() + 1);if (result.isPassed()) {task.setSuccessCount(task.getSuccessCount() + 1);} else {task.setFailCount(task.getFailCount() + 1);}batchTaskDAO.update(task);} catch (Exception e) {logger.error("检查失败 - 考生ID: {}", ksid, e);task.setFailCount(task.getFailCount() + 1);}}task.setStatus("COMPLETED");batchTaskDAO.update(task);}
亮点2:进度实时查询
// 前端轮询查询进度function checkProgress(taskId) {var timer = setInterval(function() {$.get(baseUrl + '/photo/check/progress/' + taskId, function(res) {if (res.success) {var progress = res.data;var percent = Math.round(progress.processedCount / progress.totalCount * 100);// 更新进度条element.progress('progress', percent + '%');// 检查是否完成if (progress.status === 'COMPLETED') {clearInterval(timer);layer.msg('批量检查完成!');loadCheckRecords();}}});}, 1000);}
亮点3:检查器模式设计(完整代码)
// 策略模式 + 责任链模式public interface PhotoQualityChecker {CheckResult check(BufferedImage image, String photoPath);int getOrder(); // 执行顺序}@Componentpublic class FileFormatChecker implements PhotoQualityChecker {@Overridepublic CheckResult check(BufferedImage image, String photoPath) {String extension = FilenameUtils.getExtension(photoPath);if (!extension.equalsIgnoreCase("jpg") && !extension.equalsIgnoreCase("jpeg")) {return CheckResult.fail("文件格式必须为JPG/JPEG");}// 验证JPEG格式有效性try {Imaging.getImageInfo(new File(photoPath));return CheckResult.success();} catch (Exception e) {return CheckResult.fail("JPEG格式验证失败");}}@Overridepublic int getOrder() {return 1; // 第一个执行}}
亮点4:异步批量处理
@Servicepublic class BatchCheckServiceImpl implements BatchCheckService {@Async("photoCheckExecutor")@Overridepublic void processBatchCheck(String taskId, List<String> photoPaths) {// 更新任务状态为处理中updateTaskStatus(taskId, "PROCESSING");int total = photoPaths.size();int processed = 0;for (String photoPath : photoPaths) {try {// 执行单张照片检查PhotoQualityResult result = photoQualityService.checkPhoto(photoPath);saveCheckRecord(taskId, result);// 更新进度processed++;updateProgress(taskId, processed, total);} catch (Exception e) {logger.error("照片检查失败: {}", photoPath, e);}}// 更新任务状态为完成updateTaskStatus(taskId, "COMPLETED");}}
6.4 前端集成亮点
亮点1:LayUI表格集成
// 检查结果表格渲染layui.use(['table', 'layer'], function() {var table = layui.table;table.render({elem: '#checkResultTable',url: '/bkksxp/quality/batchResult',where: { taskId: currentTaskId },cols: [[{ field: 'photoPath', title: '照片路径', width: 200 },{ field: 'checkStatus', title: '检查结果', width: 100, templet: function(d) {return d.checkStatus === 'PASS'? '<span class="layui-badge layui-bg-green">合格</span>': '<span class="layui-badge layui-bg-red">不合格</span>';}},{ field: 'issueDesc', title: '问题描述', width: 300 },{ field: 'checkTime', title: '检查时间', width: 180 }]],page: true});});
亮点2:实时进度更新
// 轮询获取批量检查进度function pollBatchProgress(taskId) {var timer = setInterval(function() {$.get('/bkksxp/quality/batchProgress', { taskId: taskId }, function(res) {if (res.success) {var progress = res.data;updateProgressBar(progress.processed, progress.total);if (progress.status === 'COMPLETED') {clearInterval(timer);layer.msg('批量检查完成!');refreshResultTable();}}});}, 2000); // 每2秒轮询一次}
实战问题与解决方案
7.1 技术问题清单
在开发过程中遇到并解决了10个关键技术问题:
|
问题编号 |
问题类型 |
问题描述 |
解决方案 |
影响范围 |
|---|---|---|---|---|
| P1 |
数据库 |
V1.1迁移脚本执行失败 |
修正SQL语法,添加GO分隔符 |
数据库层 |
| P2 |
MyBatis |
字段映射错误 |
统一resultMap配置 |
DAO层 |
| P3 |
实体类 |
字段缺失导致编译错误 |
补充完整字段定义 |
Entity层 |
| P4 |
SQL Server |
IDENTITY列插入冲突 |
移除主键插入语句 |
DAO层 |
| P5 |
JSON序列化 |
CLOB字段序列化失败 |
SQL层+Action层双重防御 |
Service+Web层 |
| P6 |
前端渲染 |
照片路径显示错误 |
修正路径拼接逻辑 |
前端JS |
| P7 |
UI优化 |
过度优化导致功能异常 |
回滚到稳定版本 |
前端 |
| P8 |
时间格式 |
时间显示格式不统一 |
实现formatDateTime工具 |
前端JS |
| P9 |
JSON优化 |
问题描述字段冗余 |
优化JSON结构 |
Action层 |
| P10 |
字段映射 |
前后端字段名不一致 |
统一字段命名规范 |
全栈 |
7.2 典型问题深度剖析
问题1:CLOB字段JSON序列化失败
问题现象:
Error serializing object: java.sql.Clob cannot be cast to java.lang.String
根本原因:
-
SQL Server的
TEXT类型在MyBatis中映射为java.sql.Clob对象 -
Jackson无法直接序列化CLOB对象
-
注意:虽然错误信息可能显示
oracle.sql.CLOB,但这是JDBC驱动的内部实现类,本项目使用的是SQL Server数据库
解决方案(双重防御):
防御1:SQL层转换
<!-- MyBatis Mapper XML --><select id="getBatchTaskResult" resultType="map">SELECTtask_id,CAST(check_details AS VARCHAR(MAX)) as check_details, -- SQL层转换check_timeFROM bk_ksxp_batch_taskWHERE task_id = #{taskId}</select>
防御2:Action层处理
@RequestMapping("/batchResult")@ResponseBodypublic Map<String, Object> getBatchResult(String taskId) {Map<String, Object> result = batchCheckService.getTaskResult(taskId);// Action层二次防御if (result.get("check_details") instanceof Clob) {Clob clob = (Clob) result.get("check_details");result.put("check_details", clob.getSubString(1, (int) clob.length()));}return ResponseUtil.success(result);}
经验总结:
-
✅ 分层防御:SQL层和应用层双重保障
-
✅ 类型转换:在SQL层就完成类型转换
-
✅ 异常处理:应用层兜底处理边缘情况
问题2:字段名映射不一致
问题现象:
前端显示undefined,后端返回的字段名与前端期望不一致。
根本原因:
-
数据库字段:
check_result、check_details -
前端期望:
checkStatus、issueDesc -
MyBatis映射:使用了数据库原始字段名
解决方案:
步骤1:统一命名规范
// 实体类使用业务语义命名public class BkKsxpCheckRecord {private String checkStatus; // 而非check_resultprivate String issueDesc; // 而非check_details}
步骤2:MyBatis别名映射
<resultMap id="CheckRecordMap" type="BkKsxpCheckRecord"><result column="check_result" property="checkStatus"/><result column="check_details" property="issueDesc"/></resultMap>
步骤3:前端字段对齐
// LayUI表格列定义cols: [[{ field: 'checkStatus', title: '检查结果' }, // 使用统一命名{ field: 'issueDesc', title: '问题描述' }]]
经验总结:
-
✅ 命名规范:数据库用下划线,Java用驼峰,前端用驼峰
-
✅ 映射配置:MyBatis负责数据库↔Java的转换
-
✅ 文档同步:API文档明确字段命名规范
SDD方法论实践总结
8.1 SpecKit工作流实践效果
8.1.1 7阶段执行情况
|
阶段 |
命令 |
执行时间 |
输出文档 |
价值评估 |
|---|---|---|---|---|
| Constitution | /constitution |
5分钟 |
项目章程 |
⭐⭐⭐⭐⭐ 建立开发原则 |
| Specify | /specify |
15分钟 |
需求规范 |
⭐⭐⭐⭐⭐ 明确功能边界 |
| Clarify | /clarify |
10分钟 |
澄清文档 |
⭐⭐⭐⭐ 解决模糊需求 |
| Plan | /plan |
20分钟 |
技术方案 |
⭐⭐⭐⭐⭐ 架构设计关键 |
| Tasks | /tasks |
10分钟 |
任务列表 |
⭐⭐⭐⭐⭐ 指导开发节奏 |
| Analyze | /analyze |
5分钟 |
一致性分析 |
⭐⭐⭐ 质量保障 |
| Implement | /implement |
3天 |
工作代码 |
⭐⭐⭐⭐⭐ 核心价值 |
总结:
-
✅ 前期投入:约1小时规范编写
-
✅ 后期收益:3天高效开发,问题可控
-
✅ ROI:规范驱动开发的投入产出比约1:24
8.1.2 关键成功因素
成功因素1:规范先行
传统开发流程:需求 → 直接编码 → 遇到问题 → 返工 → 再编码↓ 问题:需求理解偏差、技术方案不明确SDD流程:需求 → 规范编写 → 澄清 → 技术方案 → 任务分解 → 编码↓ 优势:需求清晰、方案明确、任务可控
成功因素2:AI协作
-
iFlyCode理解项目上下文(Spring 4.3.30、MyBatis、LayUI)
-
自动生成符合项目规范的代码
-
减少手工编码量约70%
成功因素3:迭代优化
-
每个阶段都可以回溯和优化
-
规范文档作为"单一真相源"
-
问题修复后同步更新规范
8.2 与传统开发方式对比
|
维度 |
传统开发 |
SDD开发 |
提升幅度 |
|---|---|---|---|
| 需求理解 |
口头沟通,理解偏差 |
规范文档,明确清晰 |
⬆️ 80% |
| 技术方案 |
边写边想,返工频繁 |
先规划后实现,一次到位 |
⬆️ 60% |
| 代码质量 |
依赖个人经验 |
AI生成+规范约束 |
⬆️ 50% |
| 开发效率 |
手工编码为主 |
AI辅助生成70%代码 |
⬆️ 200% |
| 问题修复 |
定位困难,影响范围大 |
规范对照,快速定位 |
⬆️ 70% |
| 知识沉淀 |
散落在代码注释中 |
完整规范文档体系 |
⬆️ 100% |
量化数据:
-
📊 代码生成率:70%(AI生成)+ 30%(手工调整)
-
📊 开发周期:3天完成(传统方式预计7-10天)
-
📊 代码行数:约2500行(含测试)
-
📊 问题修复:10个问题,平均修复时间30分钟
8.3 SDD工具生态选择建议
基于本项目实践,对三大SDD工具的选择建议:
场景1:新功能开发(0→1)
推荐:SpecKit
-
✅ 7阶段工作流完整覆盖
-
✅ 与iFlyCode等AI助手无缝集成
-
✅ 适合传统项目增量开发
-
✅ 学习成本低,上手快
本项目选择理由:
-
iExam 8.0是成熟系统,需要增量开发
-
SpecKit的Slash Commands与iFlyCode完美配合
-
规范文档可作为团队知识库
场景2:修改现有功能(1→n)
推荐:OpenSpec
-
✅ 双文件夹模型(specs + changes)
-
✅ 显式Delta格式,变更清晰
-
✅ 自动归档机制
-
✅ 跨规范更新支持
适用场景:
-
重构现有模块
-
修改多个关联功能
-
需要清晰的变更历史
场景3:全流程AI开发(0→1→n)
推荐:Kiro
-
✅ AI原生IDE,体验最佳
-
✅ 自主代理和事件驱动
-
✅ 原生SDD工作流支持
-
❌ 商业产品,有成本
适用场景:
-
新项目从零开始
-
团队全面拥抱AI开发
-
预算充足的商业项目
经验教训与最佳实践
9.1 核心经验总结
经验1:规范是"单一真相源"
实践:
所有开发决策都基于规范文档:- 需求变更 → 先更新规范 → 再修改代码- 技术选型 → 记录在Plan文档 → 团队共识- 问题修复 → 对照规范 → 快速定位
收益:
-
✅ 避免需求理解偏差
-
✅ 减少返工和重复沟通
-
✅ 知识沉淀和团队协作
经验2:分层防御策略
实践:
关键功能实现多层防御:- SQL层:类型转换、数据验证- Service层:业务逻辑、异常处理- Action层:参数校验、结果封装- 前端层:输入验证、错误提示
案例:CLOB序列化问题
-
SQL层:
CAST(check_details AS VARCHAR(MAX)) -
Action层:
instanceof Clob检查和转换 -
前端层:空值判断和默认显示
经验3:渐进式优化
实践:
开发节奏:Day 1: POC验证 → 核心功能可用Day 2: 完整实现 → 功能完备Day 3: 问题修复 → 生产就绪
避免:
-
❌ 过早优化(UI美化导致功能异常)
-
❌ 一次性完美(先可用,再优化)
-
❌ 忽视测试(每个阶段都要验证)
9.2 最佳实践清单
开发前(规范阶段)
-
✅ Constitution:明确代码质量标准和测试要求
-
✅ Specify:用用户故事描述功能,避免技术细节
-
✅ Clarify:主动提问,消除模糊需求
-
✅ Plan:选择与现有技术栈一致的方案
-
✅ Tasks:任务粒度适中(2-4小时完成)
开发中(实现阶段)
-
✅ 代码规范:严格遵循项目现有代码风格
-
✅ 分层清晰:Controller/Service/DAO职责明确
-
✅ 异常处理:每层都要有异常处理机制
-
✅ 日志记录:关键操作记录INFO日志
-
✅ 单元测试:核心逻辑必须有测试覆盖
开发后(验证阶段)
-
✅ 功能测试:单张检查、批量检查、异常场景
-
✅ 性能测试:大批量数据处理性能
-
✅ 集成测试:与现有模块的集成验证
-
✅ 文档更新:同步更新规范文档和用户手册
-
✅ 知识沉淀:记录问题和解决方案
9.3 避坑指南
坑1:过度依赖AI生成
问题:
-
AI生成的代码可能不符合项目规范
-
可能使用了项目中不存在的依赖
解决:
-
✅ 明确告知AI项目技术栈和约束
-
✅ 生成后必须人工审查和调整
-
✅ 关键逻辑手工编写或重点验证
坑2:忽视现有代码规范
问题:
-
新代码风格与现有代码不一致
-
使用了不同的命名规范或设计模式
解决:
-
✅ 先研究现有代码的实现方式
-
✅ 复用现有的工具类和基类
-
✅ 保持与现有模块的一致性
坑3:规范与实现脱节
问题:
-
代码修改后未同步更新规范
-
规范文档成为"僵尸文档"
解决:
-
✅ 每次代码变更都更新规范
-
✅ 规范文档纳入版本控制
-
✅ Code Review时检查规范一致性
未来展望与改进方向
10.1 功能增强计划
1. 人脸识别增强
-
集成OpenCV或AI人脸检测API
-
提高人像位置检测准确率
-
支持多人照片检测和提示
2. 批量处理优化
-
支持断点续传
-
增加任务优先级设置
-
优化大批量处理性能
3. 报表功能
-
生成照片质量统计报表
-
导出Excel格式检查结果
-
可视化质量趋势分析
10.2 SDD方法论推广
团队推广计划
阶段1:试点项目(已完成)
-
✅ 照片质量检查功能作为试点
-
✅ 验证SDD方法论可行性
-
✅ 积累实践经验和案例
阶段2:团队培训(进行中)
-
📝 编写SDD实践指南
-
📝 组织内部技术分享
-
📝 建立规范文档模板库
阶段3:全面推广(计划中)
-
🎯 所有新功能采用SDD开发
-
🎯 建立规范评审机制
-
🎯 持续优化工作流程
工具链完善
当前工具链:
iFlyCode + SpecKit + Git
目标工具链:
iFlyCode + SpecKit/OpenSpec + Git + CI/CD├── 规范自动验证├── 代码自动生成├── 测试自动执行└── 文档自动发
总结
11.1 项目成果
功能成果:
-
✅ 实现6项照片质量检查标准
-
✅ 支持单张和批量检查模式
-
✅ 完整的前后端集成
-
✅ 生产环境就绪
技术成果:
-
✅ 约2500行高质量代码
-
✅ 完整的单元测试覆盖
-
✅ 详细的技术文档
-
✅ 可复用的检查器框架
方法论成果:
-
✅ 验证SDD方法论可行性
-
✅ 积累AI协作开发经验
-
✅ 建立规范文档体系
-
✅ 形成最佳实践清单
11.2 核心价值
对项目的价值:
-
📈 提高照片审核效率80%
-
📈 减少人工审核工作量70%
-
📈 降低照片不合格率60%
-
📈 提升用户体验满意度
对团队的价值:
-
🎓 掌握SDD开发方法论
-
🎓 提升AI协作开发能力
-
🎓 建立规范驱动文化
-
🎓 积累可复用的开发经验
对行业的价值:
-
🌟 探索AI辅助开发的最佳实践
-
🌟 验证规范驱动开发的可行性
-
🌟 为传统项目现代化提供参考
-
🌟 推动开发方式的创新和变革
附录
附录A:完整代码清单
核心检查器(6个):
FileFormatChecker.java- 文件格式检查(约80行)
FileSizeChecker.java- 文件大小检查(约60行)
ImageSizeChecker.java- 图像尺寸检查(约90行)
ColorModeChecker.java- 色彩模式检查(约70行)
PortraitPositionChecker.java- 人像位置检查(约150行)
BackgroundColorChecker.java- 背景色检查(约120行)
服务层(4个类):
PhotoQualityService.java+
PhotoQualityServiceImpl.java(约200行)BatchCheckService.java+
BatchCheckServiceImpl.java(约250行)
数据访问层(2个DAO + 2个Mapper XML):
BkKsxpCheckRecordDAO.java+ XML(约150行)
BkKsxpBatchTaskDAO.java+ XML(约180行)
Action层(2个):
BkKsxpPhotoQualityAction.java(约200行)
BkKsxpBatchCheckAction.java(约180行)
前端(1个JS文件):
BkKsxpQualityCheck.js(约400行)
测试代码(3个):
BkKsxpCheckRecordDAOTest.java(约150行)
BkKsxpPhotoQualityActionTest.java(约200行)
-
其他单元测试(约100行)
配置文件(3个):
photo-quality-check-context.xml- Spring配置
V1.1__Photo_Quality_Check.sql- 数据库迁移脚本
-
MyBatis Mapper配置
总计:约2500行代码(含注释和测试)
附录B:数据库表结构
表1:bk_ksxp_check_record(检查记录表)
CREATE TABLE bk_ksxp_check_record (record_id VARCHAR(50) PRIMARY KEY,ks_id VARCHAR(50) NOT NULL,photo_path VARCHAR(500),check_status VARCHAR(20),issue_desc TEXT,check_time DATETIME,FOREIGN KEY (ks_id) REFERENCES bk_ks(ks_id));
表2:bk_ksxp_batch_task(批量任务表)
CREATE TABLE bk_ksxp_batch_task (task_id VARCHAR(50) PRIMARY KEY,task_name VARCHAR(200),total_count INT,processed_count INT,pass_count INT,fail_count INT,task_status VARCHAR(20),check_details TEXT,create_time DATETIME,update_time DATETIME);
附录C:API接口清单
单张检查接口:
POST /bkksxp/quality/check参数:ksId(考生ID)返回:PhotoQualityResult(检查结果)
批量检查接口:
POST /bkksxp/quality/batchCheck参数:ksIds(考生ID列表)返回:BatchTaskResult(任务信息)
进度查询接口:
GET /bkksxp/quality/batchProgress参数:taskId(任务ID)返回:BatchTaskProgress(进度信息)
结果查询接口:
GET /bkksxp/quality/batchResult参数:taskId(任务ID)返回:List<CheckRecord>(检查记录列表)
结语
本文档详细记录了使用iFlyCode + SpecKit进行规范驱动开发的完整实践过程,从需求分析到最终交付,展示了SDD方法论在传统项目增量开发中的应用价值。
核心收获:
-
✅ 规范先行:投入1小时规范编写,节省3天开发时间
-
✅ AI协作:70%代码由AI生成,开发效率提升200%
-
✅ 质量保障:分层防御策略,问题可控可追溯
-
✅ 知识沉淀:完整的规范文档体系,可复用可传承
未来展望:
-
🎯 在团队中推广SDD方法论
-
🎯 建立规范文档模板库
-
🎯 持续优化工具链和工作流
-
🎯 探索更多AI辅助开发场景
最后的话:
规范驱动开发不是银弹,但它为我们提供了一种更系统、更高效的开发方式。结合AI的能力,我们可以将更多精力投入到业务创新和用户价值创造上,而不是陷入重复的编码工作中。
希望本文档能为正在探索AI辅助开发和规范驱动开发的团队提供有价值的参考!
967

被折叠的 条评论
为什么被折叠?



