网站策划书如何做工程建设网站导航图

张小明 2025/12/30 4:40:50
网站策划书如何做,工程建设网站导航图,杭州seo外包,电商网站开发用什么语言表达本文系统回顾了淘特导购团队在AI编码实践中的演进历程#xff0c;从初期的代码智能补全到Agent Coding再到引入Rules约束#xff0c;最终探索SDD#xff08;Specification Driven Development#xff0c;规格驱动开发#xff09;——以自然语言规格#xff08;spec.md从初期的代码智能补全到Agent Coding再到引入Rules约束最终探索SDDSpecification Driven Development规格驱动开发——以自然语言规格spec.md为唯一真理源驱动代码、测试、文档自动生成实现设计先行、可测试性内建与文档永不过期。实践中发现SDD理念先进但落地门槛高、工具链不成熟、历史代码集成难因此团队当前采用融合策略以轻量级技术方案模板为输入 Rules严格约束 Agent Coding高效实现 AI自动汇总架构文档形成兼顾规范性、效率与可维护性的AI辅助编程最佳实践。背景▐1.1 业务背景生成式AI技术的范式突破正驱动智能开发工具进入超线性演进阶段主流代码生成工具的迭代周期已从季度级压缩至周级智能体架构创新推动开发效能持续提升。淘特导购系统承载着商品推荐、会场投放、活动营销等多样化的业务场景技术团队面临着需求迭代频繁、代码腐化及团队协作度高的问题如何提升开发效率、保证代码质量、降低维护成本成为我们面临的重要挑战。正是在这样的背景下我们开始尝试将AI技术融入到日常开发流程中探索从传统编码到AI辅助编程的转变之路。▐1.2 AI编程工具的引入2024年初团队开始探索AI编程工具希望通过AI提升开发效率和代码质量。最初接触的是Aone Copilot阿里内部AI工具的代码智能补全功能后来逐步尝试Agentic Coding、Rules约束、SDDSpecification Driven Development等多种AI编程模式。本文将详细记录我们的探索历程、实践经验以及对AI编程未来的思考。代码智能补全与单方法改写▐2.1 初识AI编程场景1代码自动补全// 开发者输入public ListItemCardVO buildItemCards(ListContentEntity entities) { ListItemCardVO result new ArrayList(); // AI自动补全以下代码 for (ContentEntity entity : entities) { ItemCardVO itemCard new ItemCardVO(); itemCard.setItemId(entity.getItemId()); itemCard.setItemTitle(entity.getTitle()); itemCard.setItemImg(entity.getPicUrl()); result.add(itemCard); } return result;}场景2单方法重构// 原始代码冗长难读public String getDiscountText(Long finalPrice, Long nnPrice) { if (finalPrice null || nnPrice null) { return ; } if (finalPrice nnPrice) { return ; } Long discount finalPrice - nnPrice; if (discount 0) { return ; } String discountYuan String.valueOf(discount / 100.0); return discountYuan 元;}// AI重构后简洁优雅public String getDiscountText(Long finalPrice, Long nnPrice) { if (finalPrice null || nnPrice null || finalPrice nnPrice) { return ; } Money discount Money.ofFen(finalPrice).subtract(Money.ofFen(nnPrice)); if (discount.getCent() 0) { return ; } return String.format(%s元, discount.getYuan());}▐2.2 初步收益效率提升去年某次商详项目中代码补全在对象构建、模型转换中减少70-80%的键盘输入。单方法重构速度提升50%。体验优化减少了查找API文档的时间避免了拼写错误和语法错误让开发者更专注于业务逻辑▐2.3 遇到的问题然而这个阶段也暴露出一些问题局限于局部优化只能帮助完成单个方法或代码片段无法理解整体业务逻辑缺乏上下文理解不了解项目的架构规范和代码风格无法应对复杂需求对于跨多个类、多个模块的需求无能为力Agentic Coding的探索与挑战▐3.1 Agentic Coding的尝试带着上面的问题我们开始尝试Agentic Coding模式通过编写详细的提示词Prompt让AI一次性实现整个功能。AI工具Aone Copilot模型Qwen3-coder。典型的Prompt结构需求实现NN页面红包模块背景- 需要展示用户可用的红包列表- 红包按门槛从小到大排序实现要求1. 创建数据服务类 NnRedPacketDataService查询用户红包2. 创建模块VO NnRedPacketVO包含红包列表、总金额等字段3. 创建模块构建器 NnRedPacketModuleBuilder组装数据技术细节- 数据服务需要实现 DataServiceListFundQueryDTO 接口- 数据服务实现类需要依赖FpProvider并执行红包查询参数请参考已有实现- 模块构建器需要继承 BaseModuleBuilderNnRedPacketVO- 使用 Component 注解标记为Spring Bean- 遵循项目代码规范请生成完整的代码。AI生成的代码示例// 1. 数据服务Componentpublic class NnRedPacketDataService implements DataServiceListFundQueryDTO { Autowired private FpProvider fpProvider; Override public ListFundQueryDTO execute(InvocationContext context, JSONObject req) { // 从配置获取红包池ID String poolIds req.getString(nnRedPacketPoolIds); ListLong fundPoolIds Arrays.stream(poolIds.split(,)) .map(Long::parseLong) .collect(Collectors.toList()); // 查询用户红包 return fpProvider.queryUserFundBuyPoolId( context, fundPoolIds, customRuleId, securityCode ); }}// 2. 模块VODataBuilderpublic class NnRedPacketVO { private ListRedPacketItem redPacketList; private String totalAmount; private String expandText;}// 3. 模块构建器Componentpublic class NnRedPacketModuleBuilder extends BaseModuleBuilderNnRedPacketVO { Override public String getName() { return nnRedPacket; } Override protected NnRedPacketVO doBuild(InvocationContext context) { // 获取红包数据 ListFundQueryDTO funds ContextUtils .ListFundQueryDTOgetBizResult( NnRedPacketDataService.class.getSimpleName(), context, 500 ) .orElse(Collections.emptyList()); if (CollectionUtils.isEmpty(funds)) { return null; } // 构建VO return NnRedPacketVO.builder() .redPacketList(buildRedPacketList(funds)) .totalAmount(calculateTotalAmount(funds)) .build(); } private ListRedPacketItem buildRedPacketList(ListFundQueryDTO funds) { return funds.stream() .map(this::toRedPacketItem) .collect(Collectors.toList()); } // ... 其他方法}▐3.2 显著的效率提升Agentic Coding实现了开发效率的显著优化通过提示词驱动的自动代码生成替代了传统手动编写虽然Prompt设计需要额外时间但综合效率提升效果明显。▐3.3 快速暴露的问题然而在后续的需求迭代中我们发现了严重的问题问题1代码延续性差现象 同样的NN业务第二次让AI实现时生成的代码风格完全不同// 第一次生成简洁风格private String buildDiscountText(Money discount) { return String.format(省%s元, discount.getYuan());}// 第二次生成冗长风格 private String buildDiscountText(Money discount) { BigDecimal yuan BigDecimal.valueOf(discount.getCent()) .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); String yuanStr yuan.stripTrailingZeros().toPlainString(); return 省 yuanStr 元;}影响 同一个项目内类似功能的实现方式五花八门维护成本高问题2代码风格不一致现象 AI不了解项目的代码规范导致生成的代码风格和存量代码不一致。问题3团队协同性差现象 不同开发者写的Prompt差异大生成的代码质量参差不齐新手写的Prompt过于简单AI生成的代码质量差老手写的Prompt详细但冗长难以复用缺乏统一的Prompt模板和最佳实践▐3.4 原因分析这些问题的根本原因在于AI缺乏项目特定的上下文和约束没有项目规范AI不知道项目的代码风格、架构模式、命名规范没有领域知识AI不了解淘特导购业务的特定术语和设计模式没有历史经验每次都是零基础生成代码无法从历史代码中学习这让我们意识到需要给AI建立项目规范和领域知识。Rules约束 - 建立AI的项目规范▐4.1 引入Rules文件我们开始尝试用Rules文件来约束AI的行为将项目规范、架构模式、领域知识固化下来。Rules文件体系.aone_copilot/├── rules/│ ├── code-style.aonerule # 代码风格规范│ ├── project-structure.aonerule # 项目结构规范│ └── features.aonerule # 功能实现规范└── tech/ ├── xx秒杀-技术方案.md # 具体需求的技术方案 └── xx红包模块-技术方案.md▐4.2 Rules文件内容示例代码风格规范code-style.aonerule# 代码风格规范 ## Java代码规范- 类名使用大驼峰命名法PascalCase- 方法名和变量名使用小驼峰命名法camelCase- 常量使用全大写单词间用下划线分隔CONSTANT_CASE ## 空值判断- 集合判空统一使用CollectionUtils.isEmpty() 或 isNotEmpty()- 字符串判空统一使用StringUtils.isBlank() 或 isNotBlank()- 对象判空统一使用Objects.isNull() 或 Objects.nonNull() ## 日志规范- 使用 LogUtil 工具类记录日志- 错误日志格式LogUtil.error(类名, 方法名, 错误描述, 关键参数{}, param, exception) ## 注解使用- Service类使用 Component 注解- 数据服务实现 DataServiceT 接口- 模块构建器继承 BaseModuleBuilderT项目结构规范# 项目结构规范## 包结构com.alibaba.aladdin.app/├── module/ # 模块构建器│ ├── nn/ # NN业务模块│ ├── seckill/ # 秒杀业务模块│ └── common/ # 通用模块├── domain/ # 领域对象│ ├── module/ # 模块VO继承ModuleObject│ └── [业务名]/ # 业务领域对象BO、DTO├── dataservice/impl/ # 数据服务实现└── provider/ # 外部服务提供者## 命名规范- 数据服务[业务名]DataService如 NnRedPacketDataService- 模块构建器[业务名]ModuleBuilder如 NnFeedsModuleBuilder- 模块VO[业务名]VO如 NnRedPacketVO- 业务BO[业务名]BO如 NnRoundFeatureBO功能实现规范# 功能实现规范## 数据服务层- 必须实现 DataServiceT 接口- 使用 Component 注解- execute方法的第一个参数是 InvocationContext- execute方法的第二个参数是 JSONObject businessReq示例javaComponentpublic class NnRedPacketDataService implements DataServiceListFundQueryDTO { Override public ListFundQueryDTO execute(InvocationContext context, JSONObject businessReq) { // 实现逻辑 }}## 模块构建器- 必须继承 BaseModuleBuilder- 使用 Component 注解- 实现 getName()、doBuild()、bottomTransform() 三个方法- 通过 ContextUtils.getBizResult() 获取数据服务结果示例Componentpublic class NnRedPacketModuleBuilder extends BaseModuleBuilderNnRedPacketVO { Override public String getName() { return nnRedPacket; } Override protected NnRedPacketVO doBuild(InvocationContext context) { ListFundQueryDTO funds ContextUtils .ListFundQueryDTOgetBizResult( NnRedPacketDataService.class.getSimpleName(), context, 500 ) .orElse(Collections.emptyList()); // 构建逻辑 }}▐4.3 技术方案模板除了Rules文件我们还为每个需求创建技术方案文档明确定义需要生成的代码技术方案示例NN红包模块-技术方案.md## 业务定义NN红包模块用于展示用户在NN业务场景下可用的红包列表。## 业务领域对象无复用 FundQueryDTO## 模块领域对象| 对象含义 | 实现方案 | 属性及类型 ||---------|---------|-----------|| NN红包模块VO | 新增 | 1. redPacketListListRedPacketItem - 红包列表br2. totalAmountString - 总金额br3. expandTextString - 展开文案 |## 数据服务层| 数据服务定义 | 实现方案 | execute ||------------|---------|---------|| NN红包查询服务 | 新增 | 1. 从配置获取红包池ID列表br2. 调用FpProvider查询用户红包br3. 过滤可用红包状态2未过期br4. 返回红包列表 |## 模块构建器| 模块构建器定义 | 实现方案 | doBuild逻辑 ||--------------|---------|-------------|| NN红包模块构建器 | 新增 | 1. 获取红包数据br2. 过滤门槛20元的红包br3. 按门槛从小到大排序br4. 构建VO |▐4.4 显著改善的效果引入Rules文件后我们看到了明显的改善代码一致性所有生成的代码都遵循统一的命名规范项目结构清晰模块划分明确代码风格保持一致开发效率技术方案填写时间从2小时降低到20分钟代码实现时间从1天降低到2小时需要人工收尾团队协作技术方案成为团队共同语言Code Review效率提升50%新人上手时间从1周降低到2天▐4.5 依然存在的问题虽然Rules带来了显著改善但仍存在一些问题需求理解不够深入AI仍然是基于技术方案翻译成代码对业务语义理解有限测试质量参差不齐虽然能生成单测但测试用例的通过率和覆盖度仍需人工把关文档滞后代码变更后文档更新容易遗漏依赖关系管理对于复杂的模块依赖关系AI处理不够优雅这些问题让我们思考能否找到一种方式让AI能更加规范和延续的codingSDD探索 - 规格驱动开发▐5.1 SDD的引入近期我们开始初步尝试SDDSpecification Driven Development规格驱动开发使用了Spec Kit工具链。SDD的核心理念规格是唯一真理源Single Source of Truth所有的代码、测试、文档都从规格生成规格即文档文档永不过期设计先于实现先用自然语言描述做什么规格再让AI生成怎么做代码可测试性内建规格中明确定义测试用例自动生成完整的单元测试▐5.2 Speckit执行流程5.2.1 环境准备我们主要使用了两种工具iflow qwen3 coder plus spec kitqwen qwen3 coder plus spec kit文件体系├── .specify/│ ├── memory/│ │ └── constitution.md│ ├── scripts/│ └── templates/├── specs/│ └── 001-nn-redpacket-module/│ ├── checklists/│ │ └── requirements.md│ ├── contracts/│ │ └── api-contract.md│ ├──>5.2.2 speckit.constitution—制定整个项目的原则这一步会生成项目全局的宪章constitution.md以下是部分节选## 核心原则 ### I. 模块化服务架构所有服务必须遵循模块化设计原则具有明确的关注点分离和定义良好的接口。每个模块应具有单一职责并可独立部署。模块必须以松耦合和高内聚的方式设计以增强可维护性和可扩展性遵循最小依赖原则。### II. 阿里巴巴开发标准所有代码必须遵循阿里巴巴Java开发指南基于阿里巴巴Java编码规范。这包括命名约定、异常处理实践、日志标准、安全最佳实践和性能优化模式。代码必须遵守样式一致性要求以保持代码库的统一性。### III. 质量保证实践全面测试是强制性的对所有业务逻辑进行单元测试对服务交互进行集成测试对API兼容性进行合同测试。代码覆盖率必须保持在80以上特别关注关键业务路径。代码质量工具必须集成到CI/CD管道中以执行标准遵循阿里巴巴开发规范以确保质量和可靠性。### IV. 模块设计原则遵循单一职责原则每个模块都有一个明确的目的。模块必须以松耦合和高内聚的方式设计遵循关注点分离原则。模块边界应与业务能力和领域上下文对齐。所有模块都遵循最小依赖原则仅导入必要的依赖项以减少系统复杂性。### V. 项目架构设计原则本项目采用分层架构设计通过模块化组织代码支持淘特投放业务的各种场景需求。架构层次包括1. **接入层**处理请求接入和协议转换2. **解决方案层**业务解决方案的统一入口3. **子解决方案层**细粒度的业务处理能力4. **模块构建层**按业务功能划分的模块构建器5. **数据服务层**负责各种业务数据的获取、处理和封装6. **外部服务层**负责调用外部服务并进行模型转换7. **领域模型层**定义核心业务对象和数据传输对象8. **基础设施层**包含基础组件和框架封装9. **通用模块层**公共组件和工具类### VI. 依赖管理遵循最小依赖原则每个模块应只拥有其实际需要的依赖项。避免模块之间的循环依赖。使用依赖注入实现松耦合。定期审核和更新依赖项以最小化安全漏洞。这确保了可维护和高效的代码结构。### VII. 代码风格一致性在整个项目中保持一致的代码风格使用标准化的格式化规则。所有代码在合并前必须通过静态分析检查。一致地遵循设计模式并对与标准实践的任何偏差提供清晰的证明。这确保了统一的代码规范和样式符合项目标准。### VIII. Speckit中文本地化所有speckit相关文件、文档和配置都应使用中文以支持本地开发团队。.specify/和specs/目录中的文件和相关speckit构件必须使用中文以便本地开发人员更好地理解和维护同时应为可能服务国际市场面向用户的组件保留国际化支持。## 安全和合规要求所有代码必须符合阿里巴巴的安全标准并在部署前进行强制性安全审查。必须为所有暴露的端点实现适当的身份验证和授权。敏感数据必须根据内部合规要求进行处理。必须扫描依赖项中的安全漏洞。## 开发工作流程1. 所有代码更改必须遵循标准的阿里巴巴开发工作流程功能分支、代码审查、自动化测试和CI/CD管道验证。拉取请求必须通过所有测试并获得指定审阅者的批准后才能合并。除非明确批准进行具有迁移计划的破坏性更改否则所有更改必须向后兼容。每次更改都必须遵循模块设计原则并保持代码风格一致性。2. 所有操作不要创建新分支而是在当前分支下进行3. 代码生成必须遵循code-generation-prompt.aonerule文件## 治理本宪法凌驾于所有其他开发实践之上必须在存储库中的所有工作中遵循。对本宪法的任何修改都需要正式文档、团队批准和迁移计划。所有PR和代码审查必须验证是否符合这些原则。5.2.3 speckit.specify—编写规格说明这一步会新建一个分支创建spec.md、requirements.md等文件这里反复修改了多次主要还是后续的执行不理想的返工。NN红包模块规格说明spec.md# NN红包模块规格说明## 功能概述NN红包模块用于在NN频道页面展示用户可用的红包列表帮助用户了解可以使用的优惠。## 功能需求### FR-1: 红包数据获取**描述** 系统应该能够查询用户在当前NN业务场景下可用的红包**前置条件**- 用户已登录- 配置了红包池IDfundPoolIds- 配置了规则idcustomRuleId- 配置了securityCode**输入**- userId用户ID- fundPoolIds红包池ID列表- customRuleId自定义规则ID- securityCode安全码**处理逻辑**1. 调用FpProvider.queryUserFundBuyPoolId()查询红包2. 过滤条件 - 红包状态payStatus 2可使用 - 红包未过期当前时间在startTime和endTime之间 - 红包门槛 配置的amountThreshold默认20元**输出**- 返回符合条件的红包列表**异常处理**- 如果FpProvider调用失败返回空列表- 如果用户未登录返回空列表.........**处理逻辑**1. 如果红包列表为空不展示模块返回null2. 构建NnRedPacketVO - redPacketList转换每个红包为RedPacketItem - totalAmount计算所有红包金额总和 - expandText从配置获取展开文案**输出** NnRedPacketVO## 非功能需求### NFR-1: 性能要求- 红包查询超时时间500ms- 如果超时返回空列表不影响页面其他模块### NFR-2: 可扩展性- 支持配置不同的红包池ID- 支持配置不同的门槛限制## 测试用例### TC-1: 正常流程 - 有可用红包**前置条件**- 用户ID123456- 配置的红包池ID[1001, 1002]- FpProvider返回2个可用红包 - 红包1金额5元门槛15元 - 红包2金额10元门槛25元**执行步骤**1. 调用 doBuild(context)**预期结果**- 返回的VO不为null- redPacketList包含2个红包- totalAmount 15.005 10- 红包按门槛排序红包1在前### TC-2: 边界条件 - 红包门槛超限**前置条件**- FpProvider返回1个红包门槛25元- 配置的amountThreshold 20元2000分**预期结果**- 返回null因为门槛超限红包被过滤......5.2.4 speckit.plan—制定实施计划这一步会生成data-model.md、api.md等几个文件最重要的是plan.md5.2.5 speckit.tasks—任务分解生成task.md5.2.6 speckit.implement—实现代码数据服务实现Componentpublic class NnRedPacketDataService implements DataServiceListFundQueryDTO { Autowired private FpProvider fpProvider; Override public ListFundQueryDTO execute(InvocationContext context, JSONObject businessReq) { long userId context.getUserId(); if (userId 0) { return Collections.emptyList(); } // 获取配置 String poolIdsStr businessReq.getString(nnRedPacketPoolIds); ListLong fundPoolIds parsePoolIds(poolIdsStr); Long customRuleId businessReq.getLong(customRuleId); String securityCode businessReq.getString(securityCode); // 查询红包 ListFundQueryDTO funds fpProvider.queryUserFundBuyPoolId( context, fundPoolIds, customRuleId, securityCode ); if (CollectionUtils.isEmpty(funds)) { return Collections.emptyList(); } // 过滤可用红包按规格FR-1的过滤条件 Long amountThreshold businessReq.getLong(amountThreshold, 2000L); return funds.stream() .filter(fund - fund.getPayStatus() 2) // 可使用状态 .filter(fund - isNotExpired(fund)) // 未过期 .filter(fund - fund.getAmountThreshold() amountThreshold) // 门槛限制 .collect(Collectors.toList()); } private boolean isNotExpired(FundQueryDTO fund) { long now System.currentTimeMillis(); return fund.getStartTime() now now fund.getEndTime(); } // ... 其他方法}模块构建器实现Componentpublic class NnRedPacketModuleBuilder extends BaseModuleBuilderNnRedPacketVO { Override public String getName() { return nnRedPacket; } Override protected NnRedPacketVO doBuild(InvocationContext context) { // 获取红包数据FR-1 ListFundQueryDTO funds ContextUtils .ListFundQueryDTOgetBizResult( NnRedPacketDataService.class.getSimpleName(), context, 500 ) .orElse(Collections.emptyList()); // 如果无可用红包不展示模块FR-3 if (CollectionUtils.isEmpty(funds)) { return null; } // 红包排序FR-2 ListFundQueryDTO sortedFunds sortFunds(funds, context); // 构建VOFR-3 return NnRedPacketVO.builder() .redPacketList(buildRedPacketList(sortedFunds)) .totalAmount(calculateTotalAmount(sortedFunds)) .expandText(getExpandText(context)) .build(); } /** * 红包排序NN专属红包优先其次按门槛从小到大 * 对应规格 FR-2 */ private ListFundQueryDTO sortFunds(ListFundQueryDTO funds, InvocationContext context) { JSONObject extraParams getExtraParams(context); String nnPoolIdsStr extraParams.getString(nnRedPacketPoolIds); SetLong nnPoolIds parsePoolIds(nnPoolIdsStr).stream() .collect(Collectors.toSet()); return funds.stream() .sorted(Comparator .comparing((FundQueryDTO fund) - nnPoolIds.contains(fund.getFromFundId()) ? 0 : 1) .thenComparing(FundQueryDTO::getAmountThreshold)) .collect(Collectors.toList()); } // ... 其他方法}完整的单元测试RunWith(MockitoJUnitRunner.class)public class NnRedPacketModuleBuilderTest { Mock private InvocationContext context; Mock private NnRedPacketDataService dataService; InjectMocks private NnRedPacketModuleBuilder builder; /** * 测试用例 TC-1: 正常流程 - 有可用红包 */ Test public void testBuild_WithAvailableFunds_ShouldReturnVO() { // 准备数据 ListFundQueryDTO mockFunds Arrays.asList( createFund(1L, 500L, 1500L), // 5元门槛15元 createFund(2L, 1000L, 2500L) // 10元门槛25元 ); // Mock when(dataService.execute(any(), any())).thenReturn(mockFunds); mockContext(context, nnRedPacketPoolIds, 1,2); mockBizResult(context, NnRedPacketDataService.class.getSimpleName(), mockFunds); // 执行 NnRedPacketVO result builder.doBuild(context); // 验证按规格预期结果 assertNotNull(result); assertEquals(2, result.getRedPacketList().size()); assertEquals(15.00, result.getTotalAmount()); // 验证排序门槛低的在前 assertEquals(1500L, result.getRedPacketList().get(0).getAmountThreshold()); } /** * 测试用例 TC-2: 边界条件 - 红包门槛超限 */ Test public void testBuild_ThresholdExceeded_ShouldReturnNull() { // 准备数据门槛25元超过配置的20元 ListFundQueryDTO mockFunds Arrays.asList( createFund(1L, 500L, 2500L) ); // Mock配置amountThreshold2000即20元 JSONObject businessReq new JSONObject(); businessReq.put(amountThreshold, 2000L); when(dataService.execute(any(), eq(businessReq))).thenReturn(Collections.emptyList()); mockBizResult(context, NnRedPacketDataService.class.getSimpleName(), Collections.emptyList()); // 执行 NnRedPacketVO result builder.doBuild(context); // 验证按规格预期结果 assertNull(result); } /** * 测试用例 TC-3: 异常场景 - FpProvider返回null */ Test public void testBuild_ProviderReturnsNull_ShouldReturnNull() { // Mock when(dataService.execute(any(), any())).thenReturn(null); mockBizResult(context, NnRedPacketDataService.class.getSimpleName(), null); // 执行 NnRedPacketVO result builder.doBuild(context); // 验证按规格预期结果 assertNull(result); } /** * 测试用例 TC-4: 异常场景 - 用户未登录 */ Test public void testBuild_UserNotLogin_ShouldReturnNull() { // MockuserId 0 when(context.getUserId()).thenReturn(0L); when(dataService.execute(any(), any())).thenReturn(Collections.emptyList()); mockBizResult(context, NnRedPacketDataService.class.getSimpleName(), Collections.emptyList()); // 执行 NnRedPacketVO result builder.doBuild(context); // 验证按规格预期结果 assertNull(result); } // 辅助方法 private FundQueryDTO createFund(Long id, Long amount, Long threshold) { FundQueryDTO fund new FundQueryDTO(); fund.setFundId(id); fund.setAvailableAmount(amount); fund.setAmountThreshold(threshold); fund.setPayStatus(2); // 可使用 fund.setStartTime(System.currentTimeMillis() - 3600000); // 1小时前开始 fund.setEndTime(System.currentTimeMillis() 3600000); // 1小时后结束 return fund; }}▐5.3 SDD带来的改进5.3.1 一致性显著提升代码层面所有代码都严格遵循规格说明消除了理解偏差不同开发者实现相同规格代码风格完全一致代码变更时必须先更新规格保证文档与代码同步业务层面产品、开发、测试对需求的理解高度一致减少了需求理解偏差导致的返工5.3.2 可测试性大幅提升测试覆盖自动生成的测试用例覆盖了所有正常和异常流程测试用例与规格说明一一对应确保完整性边界条件和异常场景都有明确的测试用例测试质量Mock方式规范统一符合项目最佳实践断言准确全面不会遗漏关键验证点测试代码可读性好易于维护5.3.3 可维护性显著改善文档永不过期规格说明就是最准确的文档任何变更都先更新规格再同步代码新人通过阅读规格说明就能快速理解功能变更影响分析修改规格时清晰知道影响哪些代码模块依赖关系在规格中明确定义重构时可以基于规格验证正确性代码可读性代码结构清晰层次分明注释完整准确与规格保持一致命名规范统一易于理解5.3.4 团队协作效率提升新人通过阅读规格说明快速上手跨团队协作时规格成为统一语言历史需求回溯更容易规格即完整记录▐5.4 SDD的问题与挑战虽然SDD带来了价值但在实践中也遇到了一些明显的问题问题1规格编写门槛高现象 编写高质量的规格说明需要较强的抽象能力和文档编写能力新手往往写不好规格过于技术化或过于模糊规格模板虽然有但如何填写仍需要经验不合格的规格对后面的代码实现影响影响 对于简单需求写规格的时间甚至超过直接写代码问题2Spec Kit工具链不成熟遇到的具体问题规格解析不准确AI有时无法正确理解规格中的复杂逻辑需要用非常精确的语言描述稍有歧义就可能理解错误代码生成质量不稳定相同的规格不同时间生成的代码质量差异大有时生成的代码过于冗长有时又过于简化增量更新困难规格修改后很难做到只更新变化的部分往往需要重新生成整个文件导致手工修改的部分丢失问题3与现有代码库集成困难现象 我们的代码库已经有大量历史代码SDD更适合从零开始的新项目历史代码缺乏规格说明无法纳入SDD体系新老代码风格混杂维护成本反而增加团队一部分人用SDD一部分人用传统方式协作困难问题4学习成本高数据写出合格的第一份规格说明平均需要3-5次迭代老员工接受度较低认为还不如直接写代码快▐5.5 SDD适用场景分析经过3个月的实践我们总结出SDD的适用场景适合使用SDD✅ 全新的项目或模块✅ 核心业务逻辑需要长期维护✅ 复杂度高需要详细设计的功能✅ 多人协作的大型需求✅ 对质量要求极高的场景不适合使用SDD❌ 简单的工具函数或配置修改❌ 快速验证的实验性功能❌ 一次性的临时需求❌ 对现有代码的小修改当前最佳实践 -Rules Agentic Coding AI文档汇总▐6.1 融合各阶段优势核心思路用Rules约束AI用技术方案指导实现用Agentic Coding快速迭代用AI汇总文档保持同步▐6.2 技术方案模板优化我们优化了技术方案模板更加轻量级# [需求名称]-技术方案## 业务定义[简要描述业务背景和目标1-2句话]## 业务领域对象[如果需要新增/修改BO或DTO在此说明]## 模块领域对象[需要新增/修改的VO对象]| 对象含义 | 实现方案 | 属性及类型 ||---------|---------|-----------|| [对象名] | 新增/修改 | 1. 字段1类型 - 说明br2. 字段2类型 - 说明 |## 数据服务层[需要新增/修改的数据服务]| 数据服务定义 | 实现方案 | execute逻辑 ||------------|---------|-----------|| [服务名] | 新增/复用 | 1. 步骤1br2. 步骤2 |## 模块构建器[需要新增/修改的模块构建器]| 模块构建器定义 | 实现方案 | doBuild逻辑 ||--------------|---------|-------------|| [构建器名] | 新增/修改 | 1. 获取数据br2. 处理逻辑br3. 构建VO |特点比SDD规格更轻量编写时间从2小时降低到30分钟比纯Agentic Coding更规范有明确的结构约束聚焦于做什么而非怎么做实现细节交给AI▐6.3 AI文档汇总机制即让AI自动维护整体架构与业务逻辑文档6.3.1 文档汇总流程完成需求开发 → 提交AI将本次代码逻辑汇总到汇总文档 → AI分析代码 → AI更新文档Prompt示例我刚完成了NN红包模块的开发请分析以下代码- NnRedPacketDataService.java- NnRedPacketModuleBuilder.java- NnRedPacketVO.java然后将其业务逻辑汇总到NN业务整体架构与逻辑文档.md中确保1. 描述模块的核心功能和业务价值2. 说明数据流转过程3. 列出关键的业务规则和判断逻辑4. 保持与现有文档的风格一致6.3.2 架构文档结构# NN业务整体架构与逻辑文档## 一、业务概述[业务背景、目标、核心价值]## 二、整体架构### 2.1 技术架构[分层架构图、技术栈]### 2.2 模块组成[各个模块的功能和关系]## 三、核心模块详解### 3.1 NN Feeds模块#### 3.1.1 功能说明[模块的核心功能]#### 3.1.2 数据流转[数据从哪里来经过哪些处理最终输出什么]#### 3.1.3 关键逻辑[重要的业务规则、计算逻辑、判断条件]#### 3.1.4 代码位置[对应的类和方法]### 3.2 NN红包模块[类似结构]### 3.3 NN吊钩层模块[类似结构]## 四、数据服务层[各个数据服务的功能和依赖]## 五、关键流程[重要的业务流程时序图]## 六、配置说明[配置项说明]## 七、扩展点[未来可能的扩展方向]6.3.3 AI汇总效果示例AI生成的文档片段### 3.2 NN红包模块#### 3.2.1 功能说明NN红包模块用于在NN频道页面展示用户可用的红包列表帮助用户了解可以使用的优惠提升转化率。#### 3.2.2 数据流转用户请求 → NnRedPacketDataService → 调用FpProvider查询用户红包 → 过滤可用红包状态2未过期门槛20元 → 返回红包列表 ↓NnRedPacketModuleBuilder → 获取红包数据 → 红包排序NN专属优先门槛从小到大 → 构建NnRedPacketVO → 返回前端#### 3.2.3 关键逻辑**1. 红包过滤规则**java// 只展示满足以下条件的红包// 1. 状态为可使用payStatus 2// 2. 未过期当前时间在startTime和endTime之间// 3. 门槛 配置的amountThreshold默认20元if (fund.getPayStatus() ! 2) return false;if (fund.getStartTime() now || now fund.getEndTime()) return false;if (fund.getAmountThreshold() amountThreshold) return false;**2. 红包排序规则**java// 排序规则// 1. NN专属红包配置的nnRedPacketPoolIds优先// 2. 其次按门槛从小到大排序funds.stream() .sorted(Comparator .comparing(fund - nnPoolIds.contains(fund.getFromFundId()) ? 0 : 1) .thenComparing(FundQueryDTO::getAmountThreshold))**3. 总金额计算**java// 计算所有可用红包的金额总和String totalAmount funds.stream() .map(FundQueryDTO::getAvailableAmount) .reduce(0L, Long::sum) .map(PriceUtils::getPriceFenToYuan) .orElse(0.00);#### 3.2.4 代码位置- 数据服务NnRedPacketDataService - 位置dataservice/impl/nn/NnRedPacketDataService.java - 核心方法execute(InvocationContext, JSONObject)- 模块构建器NnRedPacketModuleBuilder - 位置module/nn/NnRedPacketModuleBuilder.java - 核心方法doBuild(InvocationContext)、sortFunds(ListFundQueryDTO)- 模块VONnRedPacketVO - 位置domain/module/nn/NnRedPacketVO.java#### 3.2.5 配置项json{ nnRedPacketPoolIds: 1001,1002,1003, // NN专属红包池ID amountThreshold: 2000, // 红包门槛上限分 expandText: 展开查看更多 // 展开文案}思考总结在淘特导购业务的AIcoding实践中我们经历了从简单代码补全到Agentic Coding再到基于规则和SDD的编程模式的演进过程。每个阶段都有其价值和局限性初期探索让我们认识到AI在编码辅助方面的潜力但也暴露了缺乏规范指导的问题Agentic Coding提升了功能实现的完整性但可延续性和一致性仍有不足基于规则的模式有效解决了代码规范和架构一致性问题成为当前的主要实践方式SDD尝试虽然在理念上很有价值但在实际应用中还需要进一步完善。虽然在SDD编程方面遇到了一些挑战但我们认为AI规范化编程是未来发展的方向。团队中的同学正在持续探索和优化完善工具链改进Spec Kit等工具提升自动化能力优化流程整合更好地将SDD模式与现有开发流程结合降低学习成本通过培训和实践案例帮助团队成员适应新模式持续改进规则根据实践经验不断完善规则定义我们相信通过持续的探索和实践一定能找到更适合团队的AI辅助编程模式进一步提升开发效率和代码质量。▐最后本文大部分内容由AI根据代码及配置生成。团队介绍本文作者式遂来自淘天集团-淘特用户技术团队。团队主要负责淘宝行业淘特C端链路的研发工作包含搜索推荐、互动游戏、导购、交易等基础服务及创新业务。当下我们积极拥抱AI时代探索智能化在研发提效和业务场景中的无限可能。技术不只是工具更是为用户创造价值的力量。¤拓展阅读¤3DXR技术 | 终端技术 | 音视频技术服务端技术 | 技术质量 | 数据算法
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

西宁网站系统建设百度热门关键词

Nexe完整指南:将Node.js应用打包成单文件可执行程序 【免费下载链接】nexe 🎉 create a single executable out of your node.js apps 项目地址: https://gitcode.com/gh_mirrors/ne/nexe 在Node.js应用部署过程中,开发者常常面临依赖…

张小明 2025/12/27 8:30:18 网站建设

网站开发word外国老头做中文网站

轻松下载3D模型的完整实用指南 【免费下载链接】sketchfab sketchfab download userscipt for Tampermonkey by firefox only 项目地址: https://gitcode.com/gh_mirrors/sk/sketchfab 在当今数字创意蓬勃发展的时代,3D模型下载已经成为设计师、开发者和创作…

张小明 2025/12/27 8:29:12 网站建设

做方案收集图片的网站开源官网

当机器学习"看懂"时间:时间序列分析与预测完全指南 数据会随着时间讲故事,而时间序列分析就是让我们听懂这个故事的方法。 📖 文章目录(Table of Contents) 🔍 什么是时间序列?&…

张小明 2025/12/27 8:28:38 网站建设

中企动力是怎么建设网站的dedecms中英文网站开发

📝 博客主页:Jax的CSDN主页 目录当AI变成我的私人医生:那些年我们一起追过的健康革命 我和AI医生的第一次约会 医疗AI的"中年危机" 当AI遇上中医:玄学还是科学? 医疗AI的"社交尴尬" 给AI医生的忠告…

张小明 2025/12/27 8:28:06 网站建设

视频网站数据库设计win2003搭建php网站

UI-TARS-7B-DPO:智能GUI代理的终极指南与完整解析 【免费下载链接】UI-TARS-7B-DPO 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/UI-TARS-7B-DPO 在数字化转型加速推进的当下,图形用户界面(GUI)作为人机…

张小明 2025/12/27 8:27:33 网站建设

网站安全建设总结报告网站排名快速上升

MegSpot:专业级图片视频对比工具全方位使用指南 【免费下载链接】MegSpot MegSpot是一款高效、专业、跨平台的图片&视频对比应用 项目地址: https://gitcode.com/gh_mirrors/me/MegSpot MegSpot是一款免费免登录、高效专业的跨平台图片视频对比应用&…

张小明 2025/12/27 8:26:29 网站建设