# MyBatis Output Layout Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 通过项目根目录推导 MyBatis 生成目录,并提供生成前风险摘要与生成后文件差异。 **Architecture:** `OutputLayoutPolicy` 只负责纯路径推导;`GenerationPlanner` 负责目录状态与已有文件统计;`OutputSnapshot` 负责前后文件差异;`GenerateArtifactsUseCase` 编排计划、快照和网关执行。JavaFX Window 只绑定根目录、自定义开关、摘要和结果。 **Tech Stack:** Java 17、Java NIO、JavaFX、JUnit 5、Maven ## Global Constraints - 默认 Model/Mapper 为 `/src/main/java`,XML 为 `/src/main/resources`。 - 不改变 `MyBatisGeneratorService` 的覆盖行为。 - 不连接数据库或在 UI 验收中执行生成。 - Git 评审不参与修改。 - 所有新增领域对象不可变且不依赖 JavaFX。 --- ### Task 1: 输出布局策略 **Files:** - Create: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/OutputLayout.java` - Create: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/OutputLayoutPolicy.java` - Test: `src/test/java/com/example/workutils/biz/mybatisgenerator/application/OutputLayoutPolicyTest.java` **Interfaces:** - Produces: `OutputLayout derive(Path projectRoot)`、`OutputLayout custom(Path root, Path model, Path xml, Path mapper)` - [ ] 写测试:标准推导返回规范化绝对路径,空值和普通文件被拒绝,自定义目录保持明确映射。 - [ ] 运行 `-Dtest=OutputLayoutPolicyTest` 并确认因类型不存在而失败。 - [ ] 实现不可变 record 和无状态策略。 - [ ] 重跑测试并确认通过。 ### Task 2: 生成前风险计划 **Files:** - Create: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/DirectoryRisk.java` - Create: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/GenerationPlan.java` - Create: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/GenerationPlanner.java` - Test: `src/test/java/com/example/workutils/biz/mybatisgenerator/application/GenerationPlannerTest.java` **Interfaces:** - Consumes: `OutputLayout`、表名列表 - Produces: `GenerationPlan plan(List tables, OutputLayout layout)` - [ ] 写测试:待创建目录、可写目录、已有 Java/XML 文件数及不可写目录验证。 - [ ] 运行测试并确认失败。 - [ ] 用 `Files.walk` 实现扩展名计数,去重相同的 Java 输出根目录。 - [ ] 重跑测试并确认通过。 ### Task 3: 输出文件快照与结果 **Files:** - Create: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/OutputSnapshot.java` - Create: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/GenerationResult.java` - Test: `src/test/java/com/example/workutils/biz/mybatisgenerator/application/OutputSnapshotTest.java` **Interfaces:** - Produces: `OutputSnapshot capture(OutputLayout layout)`、`GenerationResult compare(OutputSnapshot after, String message)` - [ ] 写测试:区分新增、更新和未变化文件,并保留 warning 与原始消息。 - [ ] 运行测试并确认失败。 - [ ] 以路径、大小、最后修改时间保存不可变指纹并实现差异比较。 - [ ] 重跑测试并确认通过。 ### Task 4: 生成用例编排 **Files:** - Modify: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/GenerateArtifactsRequest.java` - Modify: `src/main/java/com/example/workutils/biz/mybatisgenerator/application/GenerateArtifactsUseCase.java` - Modify: `src/test/java/com/example/workutils/biz/mybatisgenerator/application/GeneratorRequestTest.java` - Modify: `src/test/java/com/example/workutils/biz/mybatisgenerator/application/GeneratorUseCaseTest.java` **Interfaces:** - Request consumes: `List tables, OutputLayout layout` - UseCase produces: `GenerationResult execute(GenerateArtifactsRequest request)` - [ ] 先更新测试,要求网关接收布局目录且用例返回文件差异。 - [ ] 运行两组测试并确认旧接口导致失败。 - [ ] 最小修改请求与用例,执行前后快照,网关仍接收三个字符串目录。 - [ ] 重跑测试并确认通过。 ### Task 5: JavaFX 表单与结果反馈 **Files:** - Modify: `src/main/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindow.java` - Create: `src/test/java/com/example/workutils/biz/mybatisgenerator/MyBatisGeneratorWindowArchitectureTest.java` **Interfaces:** - Consumes: `OutputLayoutPolicy`、`GenerationPlanner`、`GenerationResult` - Produces: 根目录输入、只读派生目录、自定义开关、生成前摘要和结构化结果文本 - [ ] 写源码结构测试:一个根目录字段、一个自定义开关、三字段只读切换、Window 不调用 `Files.walk`。 - [ ] 运行测试并确认失败。 - [ ] 改造目录区域,根目录变化时刷新预览;自定义模式才允许编辑。 - [ ] 生成前显示确认摘要;确认后提交请求;完成后显示新增/更新/未变化文件。 - [ ] 重置恢复标准推导模式。 - [ ] 重跑窗口结构测试和 MyBatis generator 全部测试。 ### Task 6: 完整验证 **Files:** - Verify only - [ ] 运行 `\.\mvnw.cmd -q test`。 - [ ] 运行 `\.\mvnw.cmd -q -DskipTests compile`。 - [ ] 运行 `git diff --check`。 - [ ] 启动应用做只读 UI 验收,不查询数据库、不生成文件。 - [ ] 提交 P0 重构。