diff --git a/knowledge-brief.md b/knowledge-brief.md index 52e3a51..0e6be45 100644 --- a/knowledge-brief.md +++ b/knowledge-brief.md @@ -2,139 +2,208 @@ ## 平台概述 -TOCO是一款专业的软件研发平台,专注于软件设计和核心代码的自动生成。基于DDD(领域驱动设计)、分层设计、CQRS等经典软件工程理论,提供从数据库到API的全栈开发能力,显著提升开发设计和编程效率。 +TOCO是一个基于DDD、分层设计、CQRS等理论的专业研发平台,主要目标是提供软件设计能力,设计结果可直接转换为标准格式的代码。平台覆盖从数据库到API的全链路,能够显著提升开发设计和编程效率。 -核心价值在于从软件工程理论出发,提供可视化的软件设计能力,设计结果可直接转换为标准格式的代码,提升编码一致性和效率。主要特性包括可视化设计、模型关联、多人协作、代码生成器等。 +## 核心设计理念 -## 核心设计元素 +TOCO采用严格的分层架构: +- **entrance层**:API控制器层 +- **service层**:服务层,处理业务逻辑 +- **manager层**:管理层,处理DTO相关逻辑 +- **persist层**:持久化层,处理数据访问 +- **common层**:公共层,存放枚举、工具类等 + +技术栈:Java + SpringBoot + MyBatis-plus(读)+ Hibernate(写) + +## 重要设计元素详解 ### 1. 模块(Module) -模块是系统领域的具体细分,映射为Java工程中的module,代表系统的叶子子域。 -- **命名规则**:小写英文字母+下划线(如meeting、user_detail),禁止添加固定后缀 -- **代码产物**:生成独立的Java Module,采用entrance、service、manager、persist、common分层结构 +- **作用**:系统领域的具体细分,映射为Java工程中的module +- **命名规则**:小写英文字母+下划线,如`meeting`、`user_detail`,全局唯一 +- **代码结构**:每个Module生成独立的Java Module,采用entrance、service、manager、persist、common分层 ### 2. 枚举(Enum) -表达常量值集合,可被其他模块使用,可作为字段类型。 -- **命名规则**:以_enum结尾 -- **枚举值**:全大写字母+下划线 -- **代码产物**:在common模块生成Java类,类名以Enum结尾,位于common.enums包路径 +- **作用**:表达常量值集合,可被其他模块使用 +- **命名规则**:以`_enum`结尾,全局唯一 +- **生成位置**:`**.common.enums`包路径下 +- **修改建议**:不建议修改 ### 3. 值对象(EO) -POJO对象结构,可被其他模块使用,可作为实体字段类型。 -- **命名规则**:以_eo结尾 -- **字段限制**:只能为基本类型(含List)、EO、Enum -- **代码产物**:在persist层生成,类名以Eo结尾,位于persist.eo包路径 +- **作用**:POJO对象结构,可被其他模块使用 +- **命名规则**:以`_eo`结尾,全局唯一 +- **字段限制**:只能为基本类型、EO、Enum类型 +- **生成位置**:`**.persist.eo`包路径下 -### 4. 实体关系(ER/Entity) -实体及其关系,一个实体对应一个数据库表,关系为实体间的外键依赖关系。包含名称、字段、字段类型、主键、索引等属性。是聚合的基础,也是DTO和VO的派生基础。 +### 4. 实体关系(Entity) +- **作用**:对应数据库表,定义实体间的外键依赖关系 +- **生成产物**: + - 结构定义类:`**.persist.dos` + - Mapper类:`**.persist.mapper.mybatis` + - Dao接口:`**.persist.mapper` + - Dao实现:`**.persist.mapper` -### 5. 聚合对象(BO/业务对象) -对一组密切关联实体的封装,从聚合根开始,通过实体关系按层级组装其他实体。 -- **特点**:提供内存一致性视图和数据操作入口 -- **限制**:只能在单一模块中组合,一个实体只能属于一个聚合对象 -- **代码产物**:生成BO和BaseBO,BaseBO封装实体属性和关系 +### 5. 聚合对象(BO) +- **核心概念**:封装一组密切关联的实体,以聚合根为起点,按层级关系组装其他实体 +- **重要特性**: + - 提供数据操作入口和内存一致性视图 + - 只能在单一模块中组合 + - 一个实体只能属于一个聚合对象 +- **生成位置**:`**.manager.bo`包路径下 +- **修改建议**:建议修改BO中的`validateAggregate`或`valid`方法进行业务不变性校验 ### 6. 数据传输对象(DTO) -表达以某个Entity为基础,通过外键关系关联多个Entity的数据结构。 -- **分类**:BaseDTO(派生自Entity)和普通DTO(派生自BaseDTO) -- **字段扩展**:支持正向替换和反向注入 -- **预定义方法**:根据根Entity的唯一索引自动生成RPC方法 -- **跨模块使用**:公开DTO的预定义RPC可被其他模块订阅调用 - -**获取方式判断原则**: -- 主键或唯一索引查询 → 使用预定义方法 -- 其他复杂查询条件 → 使用读方案 +- **核心概念**:以某个Entity为基础,通过外键关系关联多个Entity的数据结构 +- **分类**: + - **BaseDTO**:每个Entity自动生成一个,包含Entity全部字段 + - **普通DTO**:派生自BaseDTO,可增加扩展字段或自定义字段 +- **字段扩展方式**: + - **正向替换**:将外键字段替换为对应Entity的DTO对象 + - **反向注入**:在当前Entity中注入其他Entity的DTO对象或列表 +- **预定义方法**:TOCO自动为每个DTO生成基于唯一索引的RPC方法 +- **生成产物**: + - 结构定义:`**.manager.dto` + - Manager:`**.manager` + - Converter:`**.manager.converter` ### 7. 视图对象(VO) -基于BaseDTO派生,用于视图层与前端的数据传输。 -- **用途**:作为HTTP API返回值,不能作为RPC返回值 -- **继承规则**:DTO字段为基础类型时保持一致,DTO字段时需转换为对应的VO -- **转换方法**:自动生成基础convert方法和带数据拼装的convert方法 -- **根VO vs 子VO**:根VO有uuid标识可被引用,子VO附属于根VO无uuid - -**获取方式判断原则**: -- 主键或唯一索引查询 → 预定义方法获取DTO后转换 -- 其他复杂查询 → 通过读方案获取DTO后转换,或直接获取VO +- **作用**:用于视图层与前端数据传输,作为HTTP API返回值 +- **派生关系**:通常派生自BaseDTO或其他DTO +- **分类**: + - **根VO**:需要创建,有uuid标识 + - **子VO**:自动创建,附属于根VO +- **与DTO区别**:VO更接近UI展示,可裁剪冗余字段;DTO更接近数据模型,复用性强 +- **转换方法**: + - 基础转换:`convertTo${VoName}` + - 带数据拼装:`convertAndAssembleData` ### 8. 查询对象(WO) -表达以某个Entity为基础,通过外键关系关联多个Entity的查询结构。作为ReadPlan的查询上下文使用,支持数据过滤功能。 +- **作用**:表达以某Entity为基础通过外键关系关联多个Entity的查询结构 +- **用途**:作为ReadPlan的查询上下文使用 ### 9. 读方案(ReadPlan) -描述如何基于查询对象从数据库获取DTO和VO列表数据。 +- **作用**:描述如何基于查询对象从数据库获取DTO/VO列表数据 - **核心能力**: - - 根据查询条件返回符合条件的DTO或VO的id列表 - - 根据字段过滤条件对列表字段数据进行过滤 -- **排序支持**:默认排序和自定义排序两种方式 -- **代码产物**:自动生成RPC方法(返回DTO)或Java方法(返回VO) + - 复杂查询条件组合 + - 数据拼装和过滤 + - 分页和排序 +- **能力边界**: + - 支持等值、模糊、范围、包含查询 + - 支持列表属性过滤 + - 不支持复杂统计和聚合计算 +- **使用原则**:根据主键或唯一索引查询时,优先使用DTO预定义方法,其他复杂查询使用读方案 +- **生成产物**:自动生成RPC方法和对应的QTO -### 10. 查询传输对象(QTO) -读方案的查询参数结构,每个读方案对应一个QTO。调用方按QTO结构传入查询参数。 +### 10. 写方案(WritePlan) +- **重要限制**:一个写方案只能操作一个聚合内的表,无法跨聚合操作 +- **操作类型**: + - `CREATE`:创建单个实体 + - `UPDATE`:更新单个实体 + - `DELETE`:删除单个实体 + - `CREATE_ON_DUPLICATE_UPDATE`:创建或更新单个实体 + - `FULL_MERGE`:批量更新列表数据(全量替换) + - `PARTIAL_MERGE`:批量更新列表数据(部分更新) +- **生成产物**:自动生成RPC方法和对应的BTO -### 11. 写方案(WritePlan) -所有数据库写操作都通过写方案实现,每个写方案只能操作一个聚合内部的表。 -- **操作类型**:CREATE、UPDATE、DELETE、CREATE_ON_DUPLICATE_UPDATE、FULL_MERGE、PARTIAL_MERGE -- **代码产物**:生成对应的RPC方法,参数为BTO,返回聚合根主键 +### 11. 查询传输对象(QTO) +- **作用**:读方案的查询参数结构 +- **使用场景**:作为API参数,禁止用作写参数 ### 12. 业务变更传输对象(BTO) -写方案自动生成的参数结构,按照写方案选定的操作实体根据关系形成树形集合。 +- **作用**:写方案的参数结构 +- **特点**:树形结构,最外层为聚合根 +- **使用场景**:作为API参数,禁止用作查询参数 ### 13. 服务层方法(RPC) -按可见性分为公开RPC(可被其他模块订阅)和非公开RPC(仅当前模块使用)。 -- **参数类型限制**:只能为QTO、BTO、Enum、基本类型 -- **返回值类型限制**:只能为DTO、Enum、基本类型 -- **创建方式**:DTO创建自动生成、读方案自动生成、写方案自动生成、自定义RPC +- **分类**: + - **公开RPC**:可被其他模块订阅调用 + - **非公开RPC**:只能被当前模块调用 +- **创建方式**: + - DTO创建后自动生成 + - 读方案自动生成 + - 写方案自动生成 + - 手动创建自定义RPC +- **参数限制**:只能为QTO、BTO、Enum、基本类型 +- **返回值限制**:只能为DTO、Enum、基本类型 ### 14. 应用程序接口(API) -定义对外暴露的HTTP接口。 -- **参数类型限制**:只能为QTO、BTO、Enum、基本类型 -- **返回值类型限制**:只能为VO、Enum、基本类型 -- **返回包装**:框架自动包装返回值(code、message、data) +- **作用**:定义对外暴露的HTTP接口 +- **URI规范**:一般为`/api/${moduleName}/xxx`格式 +- **参数限制**:只能为QTO、BTO、EO、Enum、基本类型 +- **返回值限制**:只能为VO、Enum、基本类型 +- **分页处理**:框架自动包装返回值(code、message、data) ### 15. 流程服务(FunctionFlow) -针对复杂业务的流程拆解,把业务过程分解成流程节点。 -- **使用场景**:API/RPC涉及写服务超过3个时推荐使用 -- **节点类型**:顺序节点、条件节点、选择节点、开始节点 -- **代码产物**:生成FlowConfig、Service、FlowNode、FlowContext +- **使用场景**: + - API/RPC涉及超过3个写服务时必须使用 + - 用户明确要求时使用 +- **节点类型**: + - 顺序节点:封装业务逻辑 + - 条件节点:封装判断逻辑 + - 选择节点:封装分支选择逻辑 + - 开始节点:流程起点 +- **设计原则**:以数据内聚为首要考虑,每个节点围绕核心写服务 -## 最佳实践原则 +## 数据获取流程 -### 1. 设计分析结果应用 -- **细节设计分析**:针对简单需求直接分析读写方案、接口等 -- **流程拆解设计分析**:针对复杂需求拆解为多个短流程,必须调用createFunctionFlow +### DTO获取流程 +1. **主键/唯一索引查询**:使用预定义方法 +2. **复杂查询条件**:使用读方案 -### 2. 写方案创建原则 -分析出所有写数据场景,按聚合维度分组,每个写场景都需要创建对应的写方案。 +### VO获取流程 +1. **主键/唯一索引查询**:预定义方法获取DTO → convert方法转换为VO +2. **复杂查询(有对应DTO读方案)**:读方案获取DTO → convert方法转换为VO +3. **复杂查询(无对应DTO读方案)**:直接使用VO读方案 -### 3. 接口参数类型选择 -- **读场景**:参数优先使用QTO -- **写场景**:参数优先使用BTO -- **严格限制**:DTO、VO不能作为参数;QTO、BTO不能作为返回值 +## 接口设计最佳实践 -### 4. 数据获取方式判断 -严格按查询条件判断,不能根据返回值是否需要数据拼装判断: -- 主键或唯一索引 → 预定义方法 -- 其他复杂条件 → 读方案 +### 参数类型选择优先级 +1. **读场景**:优先使用QTO +2. **写场景**:优先使用BTO +3. **补充参数**:基本类型、Enum、EO -## 代码编写指南 +### 返回值类型选择 +1. **RPC返回值**:DTO、Enum、基本类型 +2. **API返回值**:VO、Enum、基本类型 -### 基本原则 -- **准确性优先**:不产生编译错误,不调用不存在的函数/字段 -- **单一职责**:Controller做参数校验,Service做业务逻辑 -- **复用性考虑**:复杂逻辑拆分为多个函数,单函数不超过30行 -- **循环优化**:避免在循环中执行数据库操作 +### 绝对禁止的用法 +- DTO、VO不能作为参数类型 +- QTO、BTO不能作为返回值类型 +- Service层不能返回VO +- VO不能作为RPC返回值 -### 特殊规则 -- **异常处理**:统一使用IgnoredException(code, "message") -- **BO校验**:业务不变性规则写在BO的聚合校验函数中 -- **系统代码**:不要修改/** This block is generated by vs **/标注的代码 -- **代码结构**:使用{}和注释分块提升可读性 +## 代码修改指南 -### 注解说明 -- **@AutoGenerated**:标识自动生成的类和方法 - - locked=true:不建议修改 - - uuid:唯一标识,包含|字符表示特殊格式 +### 推荐修改的位置 +1. **BO类**:`validateAggregate`或`valid`方法中添加业务校验 +2. **Converter类**:自定义字段的数据获取逻辑 +3. **Service类**:业务逻辑实现 +4. **API Controller**:接口实现逻辑 -## 技术栈 -- **语言/框架**:Java、SpringBoot -- **数据访问**:MyBatis-plus(读)、Hibernate(写) -- **分层结构**:entrance、service、manager、persist、common +### 禁止修改的内容 +1. 带有`@AutoGenerated(locked=true)`的类和方法 +2. DTO、VO的结构定义 +3. Manager类的系统生成方法 +4. Mapper类的结构定义 + +## 并发控制最佳实践 + +在处理先读后更新的场景时,为避免并发引起的数据脏写: +1. **写方案中使用incr字段** +2. **BoService中添加校验**:如`if(userBo.getBalance() >= 0)` +3. **聚合校验**:在BO的业务不变性校验中添加约束条件 + +## 项目结构导航 + +标准查找流程: +- **API查找**:`modules/{模块名}/entrance/web/controller/` +- **DTO查找**:`modules/{模块名}/manager/dto/` +- **Service查找**:`modules/{模块名}/service/` +- **数据层查找**:`modules/{模块名}/persist/` + +## 重要注意事项 + +1. **跨模块调用**:必须通过订阅RPC,使用RpcAdapter进行调用 +2. **变量命名**:RpcAdapter注入时变量名必须是类名首字母小写 +3. **自定义字段逻辑**:必须在BaseConverter的Map转换方法中实现 +4. **读写分离**:读操作使用MyBatis-plus,写操作使用Hibernate +5. **严格分层**:各层职责明确,不能越层调用 \ No newline at end of file