This repository has been archived on 2025-10-29. You can view files and clone it, but cannot push or open issues or pull requests.
Files
docs/llms-full.txt
2025-07-02 15:48:48 +08:00

276 lines
29 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## TOCO知识库
### **1. TOCO 平台概览:**
- **1.1 平台简介:** TOCO是一款重视软件设计及核心代码自动生成的专业研发平台。其基于DDD、分层设计、CQRS等经典研发理论从数据库到API全部覆盖可显著提升开发设计和编程效率帮助开发团队实现更高的质量和生产力
- **1.2 核心价值/目标用户:** 从软件工程理论出发,提供软件设计能力,设计结果可直接转换为标准格式的代码,提升编码一致性及效率
- **1.3 主要特性概览:** 可视化设计、模型关联、多人协作、代码生成器等
### **2. TOCO 设计元素:**
#### **2.1 模块 (Module)**
- **定义与用途:** 在TOCO中我们将系统领域细分为具体的模块映射为Java工程中的module。这些模块代表了系统的叶子子域每个模块负责特定的功能。模块划分有助于系统的可维护性和可扩展性并能提高开发效率和代码质量
#### **2.2 枚举 (Enum)**
- **定义与用途:** Enum用来表达一些常量值的集合可被其他模块使用可被用来做为字段的类型
* **代码产物和修改建议**
* **生成产物**在common模块中生成一个Java类
* **职责:** 表达Enum的数据结构
* **命名规则**类名以Enum结尾
* **类路径:** 位于 ```**.common.enums``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Enum在TOCO中的uuid}|ENUM|DEFINITION
- **生成代码:** Enum会在common层生成Enum文件如StatusEnum
- **修改建议:** 不建议修改
#### **2.3 值对象 (Eo)**
- **定义与用途:** EO为一种POJO对象结构可被其他模块使用可被用来做为实体字段的类型。
* **代码产物和修改建议**
* **生成产物**在persist层生成结构定义类文如AddressEo
* **职责:** 表达POJO数据结构
* **命名规则**类名以Eo结尾
* **类路径:** 位于 ```**.persist.eo``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Eo在TOCO中的uuid}|EO|DEFINITION
- **修改建议:** 不建议修改
#### **2.4 实体关系 (ER / Entity)**
- **定义与用途:** 实体及其关系。一个实体一般对应一个数据库表,关系为实体间的外键依赖关系
- **代码产物和修改建议**
- 结构定义
* **生成产物**Java类按照Mybatis-plus的要求生成
* **职责:** 按照Mybatis-plus的要求生成结构定义类文件
* **类路径:** 位于 ```**.persist.dos``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|ENTITY|DEFINITION
- Mapper
* **生成产物**在persist层生成Mybatis-plus的Mapper类
* **职责:** 提供Mapper给Mybatis-plus框架
* **命名规则**类名以Mapper结尾(${entityName}Mapper)
* **类路径:** 位于 ```**.persist.mapper.mybatis``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Eo在TOCO中的uuid}
- Dao接口
* **生成产物**在persist层生成Dao接口
* **职责:** 提供Entity数据的查询接口为service层提供数据访问入口
* **命名规则**类名以Dao结尾(${entityName}Dao)
* **类路径:** 位于 ```**.persist.mapper``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|ENTITY|IDAO
- Dao实现
* **生成产物**在persist层生成Dao接口的实现类文件
* **职责:** 通过调用Mapper实现实现Dao接口
* **命名规则**类名以DaoImpl结尾(${entityName}DaoImpl)
* **类路径:** 位于 ```**.persist.mapper``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|ENTITY|DAO
- **修改建议:** 不建议修改
#### **2.5 聚合对象 (BO/业务对象)**
- **定义与用途:** 在TOCO中聚合对象是对一组密切关联的实体的封装。聚合对象从单一实体开始这个实体我们称为聚合根通过实体间关系不断的顺序将其他实体按层级关系组装进这个聚合对象。聚合对象可以按实体表达为树形结构。聚合对象提供了这组实体的内存一致性视图提供数据操作入口。由于写操作的内聚性聚合对象只能在单一模块中组合而且一个实体只能属于一个对象。同样如果有实体不在任何一个聚合对象中TOCO将无法提供与之相关的写方法。
- **代码产物和修改建议**
- 综述
- 业务对象包含多个Entity通过业务对象的嵌套组合表达了Entity之间的关系如果一个业务对象包含了子对象则会生成BO和BaseBO,BaseBO封装实体属性和关系子类留给业务扩展逻辑
如果是叶子节点不存在子对象的BO则直接生成BO类文件不生成BaseBO类文件
- BO
* **生成产物**在Manager层生成聚合对象类文件符合Hibernate的标准
* **职责:** 定义聚合对象,多个聚合对象组合成层级结构实现充血模型,支持写链路上的数据变更,监听数据变更,支持数据校验
* **命名规则**类名以BO结尾(${entityName}BO)
* **类路径:** 位于 ```**.manager.bo``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|BO|DEFINITION
- **修改建议:** 建议修改BO中的validateAggregate或valid方法。不建议修改检验方法以外的其他代码如果发现需求中有业务不变性校验**注意** 上述的校验方法,在写方案内部由框架触发调用,而不是业务代码显式调用
- BaseBO
* **生成产物**对于存在子BO的聚合对象封装不变的代码部分
* **职责:** 定义聚合对象,多个聚合对象组合成层级结构实现充血模型,支持写链路上的数据变更,监听数据变更,支持数据校验
* **命名规则**类名以BO结尾(${entityName}BO)
* **类路径:** 位于 ```**.manager.bo``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|BO|DEFINITION
- **修改建议:** 建议修改BO中的validateAggregate或valid方法如果发现需求中有业务不变性校验;不建议修改检验方法以外的其他代码
#### **2.6 数据传输对象 (DTO)**
- **定义与用途:** 在TOCO中DTO表达某个Entity为基本通过外键关系不断关联多个Entity的数据结构。DTO还隐式表达了数据的取数拼装这种拼装符合外键关系。往往被当做RPC的返回值、或读方案的返回值使用不建议把DTO作为入参。注意DTO不能作为HTTP API的返回值。DTO分为BaseDTO和普通DTOBaseDTO派生自Entity包含Entity的所有字段每个Entity有且仅有一个BaseDTO普通DTO派生自BaseDTO包含BaseDTO的所有字段且可以增加扩展字段或自定义字段
- **代码产物和修改建议**
- 结构定义
* **生成产物**一个Java类
* **职责:** 表达DTO的数据结构
* **命名规则**类名以Dto结尾
* **类路径:** 位于 ```**.manager.dto``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|DEFINITION
- **Manager**
* **生成产物:** Java接口以及实现类
* **命名规则:** 接口类名以Manager结尾、实现类名以ManagerImpl结尾(${DtoName}Manager)、基类以名ManagerBaseImpl结尾(${DtoName}ManagerImpl)
* **职责:** 提供了DTO数据的获取的接口包括根据id单个、id列表批量获取、以及根据DTO对应的实体的数据库索引获取
* **类路径:** 位于 ```**.manager``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|MANAGER
- **Converter**
* **生成产物:** Java实现类以及基类
* **命名规则:** 实现类名以Converter结尾(${DtoName}Converter)、基类名以BaseConverter结尾(${DtoName}BaseConverter)
* **职责:** Entity转换到BaseDTO或则BaseDTO转化为普通DTO从Entity转为BaseDTO的方法命名为convert${EntityName}To${DtoName}从BaseDTO转换为DTO的方法命名为convert${BaseDtoName}To${DtoName}
* **类路径:** 位于 ```**.manager.converter``` 包路径下
* **唯一标识符位置:**
* 实现类Converter 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|CONVERTER
* 基类BaseConverter 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|BASE_CONVERTER
- **例子:**
* 如UserDto、UserDtoManager、UserDtoConverter extends UserDtoBaseConverter、UserDtoService或名称为${DtoName}Service内部包含getById,getByIds等方法。如果Dto为UserBaseDto则生成的类名为UserBaseDtoService
- **修改建议:**
- 建议在Service与BaseConverter中进行代码扩展不建议修改结构定义文件和Manager文件。其中DTO的**自定义字段**由于不直接派生自Entity所以一般会对应取数逻辑代码。通常如果涉及到数据获取、计算和拼装批量处理的性能最好所以代码位置**必须**放在BaseConverter中已经自动生成的**列表**转换方法中批量取数组装如UserBaseDtoBaseConverter.convertUserToUserBaseDto(List<User>)或UserDtoBaseConverter.convertUserBaseDtoToUserDto(List<UserBaseDto>)
#### **2.7 视图对象 (VO)**
- **定义与用途:** 在TOCO中VO表达某个BaseDTO(如果用户指明派生源也可使用其他DTO)为派生源通过外键关系不断关联多个BaseDTO的数据结构。VO用于在视图层与前端之间进行数据传输往往被当做HTTP API的返回值、或读方案的返回值使用由服务端返回至前端。注意VO不能作为RPC的返回值。
- **代码产物和修改建议**
- **结构定义**
* **生成产物:** 在controller层生成一个Java类
* **命名规则:** 类名以Vo结尾
* **职责:** 表达VO的数据结构
* **类路径:** 位于 ```**.entrance.web.vo``` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${VO在TOCO中的uuid}|VO|DEFINITION
- **Converter**
* **生成产物:** 在controller层生成一个Java类(**有派生源**的VO才有Converter)和基类
* **命名规则:** 实现类名以Converter结尾(${VoName}Converter)基类名以BaseConverter结尾(${VoName}BaseConverter)
* **类路径:** 位于 ```**.entrance.web.converter``` 包路径下
* **职责:** 把DTO转换成VOConverter中包含2种convert方法1.基础convert方法从DTO转换为VO仅转换结构方法命名为convertTo${VoName}、convertTo${VoName}List、convertTo${VoName}Map其中**Map转换方法**为底层批量方法单个和列表convert方法都通过**调用Map方法**来实现;2.带数据拼装逻辑的convert方法内部会调用基础convert方法从DTO转换为VO然后再根据外键获取拼装最终数据方法命名为convertAndAssembleData、convertAndAssembleDataList)
* **唯一标识符位置:**
* 实现类Converter其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${VO在TOCO中的uuid}|VO|CONVERTER
* 基类BaseConverter其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|BASE_CONVERTER
* **例子:**
* 如UserDetailVo、UserDetailVoConverter包含convertToUserDetailVo、convertToUserDetailVoList、convertToUserDetailVoMap、convertAndAssembleData、convertAndAssembleDataList方法
- **修改建议:**
- 建议在Converter中进行代码扩展不建议修改结构定义文件。其中VO的**自定义字段**由于不直接派生自DTO所以一般会对应取数逻辑代码。通常如果涉及到数据获取、计算和拼装批量处理的性能最好所以自定义字段对应的代码位置**必须**放在Converter的**Map**基础转换方法convertTo${VoName}Map中批量取数组装如UserVoConverter.convertToUserVoMap
#### **2.8 查询对象(WO)**
- **定义与用途:** 在TOCO中WO表达某个Entity为基本通过外键关系不断关联多个Entity的数据结构。WO还隐式表达了数据的取数拼装这种拼装符合外键关系. WO作为ReadPlan的查询上下文使用所以在创建ReadPlan之前需要先创建WO对象。在理解一个ReadPlan的语义的时候需要以WO作为上下文。
#### **2.9 读方案 (ReadPlan)**
- **定义与用途:** 在TOCO中读方案描述了一种数据库查询方案查询条件为一个面向对象的查询语句其中可以包含存在外键关系的多个实体的字段(如age=18 and name like #nameLike and school.name like #schoolNameLike其中以#开头的是自定义参数会自动生成一个QTO结构由查询调用方动态传入),结果为符合查询条件的**一种**DTO或VO列表。读方案内部会将该面向对象的查询条件转化为复杂的join sql语句来实现对数据库的查询以及返回的复杂DTO和VO数据的组装。读方案可以指定其分页方式不分页、页码分页、瀑布流分页以及是否生成计数方法(用于返回符合条件的记录数量)。
- **代码产物和修改建议**
- **Service**
* **生成产物:** 在Service层生成一个Java类
* **命名规则:** 类名以QtoService结尾(${ReadPlanName}QtoService)
* **类路径:** 位于 ```**.service.index.entity```包路径下
* **职责:** 提供查询入口返回符合查询条件的DTO或VO的id列表分页、全部、或则瀑布流,以及返回符合条件的总数。 在TOCO的读链路中数据查询分2步骤1. 获取符合查询条件的DTO或VO的id列表2. 根据id列表组装DTO或VO列表。
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定uuid规则: ${ReadPlan在TOCO中的uuid}|QTO|SERVICE
- **查询传输对象(QTO)**
* **生成产物:** 在Service层生成一个Java类
* **命名规则:** 类名以Qto结尾(${ReadPlanName}Qto)
* **类路径:** 位于 ```**.persist.qto```包路径下
* **职责:** 读方案的查询参数结构,通常可作为API的参数API接收到参数后可直接透传给内部的RPC进行调用
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${ReadPlan在TOCO中的uuid}|QTO|DEFINITION
- **Dao**
- **生成产物:** 在Dao层生成一个Java类
- **命名规则:** 类名以Dao结尾(${ReadPlanName}Dao)
- **类路径:** 位于 ```**.persist.mapper```包路径下
- **职责:** 读方案对应的数据库查询方法
- **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${ReadPlan在TOCO中的uuid}|QTO|DAO
- **QueryExecutor**
- **生成产物** 对于返回**VO**的查询方案在controller层生成一个Java类
- **命名规则:** 类名以QueryExecutor结尾(${WritePlanName}QueryExecutor)
- **类路径:** 位于 ```**.entrance.web.query.executor```包路径下
- **职责:** 把QtoService返回的id数据转化成目标**VO**
- **QueryService**
- **生成产物** 对于返回**DTO**的查询方案在service层生成一个Java类
- **命名规则:** 类名以QueryService结尾(${WritePlanName}QueryService)
- **类路径:** 位于 ```**.service.index.entity```包路径下
- **职责:** 把QtoService返回的id数据转化成目标**DTO**
- **例子:**
* 根据用户名称查询用户列表返回UserDTO则生成UserNameQto、UserNameQtoService、UserNameQtoDao、UserNameQueryService; UserNameQueryService调用UserNameQtoServiceUserNameQtoService调用UserNameQtoDao
- **修改建议:**
- 如果有对结果的数据二次处理建议在QueryService和QueryExecutor中进行代码扩展不建议修改QTO文件
#### **2.10 查询传输对象(QTO)**
- **定义与用途:** 在TOCO中QTO为读方案的查询参数结构每个读方案会对应一个QTO写方案调用方按照QTO的结构向读方案生成的RPC方法传入需要查询的实体字段值完成对数据库的查询
- **如何创建/生成:** 在创建读方案后TOCO会自动生成QTO作为该读方案传入的查询参数结构无需单独创建
- **关键配置:** 名称(${ReadPlanNameQto},驼峰展示),查询字段列表(如idIsnameLike, schoolNameLike等)
- **与API的关系:** QTO通常可作为API的参数API接收到参数后可直接透传给内部的RPC进行调用
#### **2.11 写方案 (WritePlan)**
- **定义与用途:** TOCO针对写场景定义了一种写方案所有对数据库的写操作都只能通过写方案实现。写方案包含了对数据库表的写操作。每个写方案只能操作一个聚合内部的表同时对一个聚合内表的操作尽量合并至一个写方案中根据复用性、内聚性等方面具体情况具体分析。注意写方案可以一次操作聚合内的多张表如location和storey是同一个聚合并且location和storey是**1:N**关系location是父对象聚合根storey是子对象那么我们可以创建一个写方案同时更新单个聚合根location中的信息以及操作其下的子表storey**列表**信息如新增、删除、修改storey等也可以创建一个写方案单独更新单个子表storey对象信息。
- **代码产物和修改建议**
- **Service:**
* **生成产物:** 在对应的聚合服务BoService里生成一个函数
* **函数命名规则:** 和写方案同名
* **职责:** 按需对入参进行转换调用BaseBOService里的函数完成对聚合对象的操作, 实现对数据库的写操作;
* **BoService的类路径:** ```**.service```
* **唯一标识符位置:** 其对应的标识符在函数的注解@AutoGenerated中指定, uuid规则: ${WritePlan在TOCO中的uuid}
- **BaseBoService**
- **生成产物:** 在对应的聚合的BaseBoService里生成一系列函数根据入参完成对聚合对象的变更
- **职责** 增对每个实体的生成增删改的函数,并且根据参数的结构以及聚合的结构,构建嵌套的调用逻辑,完成对一个聚合对象的变更,记录并且返回对应的变更情况
- **类路径:** ```**.service.base```
- **BTO (业务变更传输对象)**
* **生成产物:** 一个Java类以内部类的方式表示层级结构
* **命名规则:** 一个Bto结尾(${WritePlanName}Bto驼峰展示)
* **类路径:** 位于```**.service.bto```包路径下
* **职责:** 在**TOCO**中BTO为写方案的参数结构每个写方案会对应一个BTO写方案调用方按照BTO的结构向写方案生成的RPC方法传入需要查询的实体字段值完成对数据库的变更
* **唯一标识符位置:** 其对应的唯一标识符在类注解@AutoGenerated中指定, uuid规则: ${WritePlan在TOCO中的uuid}|BTO|DEFINITION
- **例子:**
- 创建用户以及用户设置的写方案create_user_and_setting生成CreateUserAndSettingBto, 在用户的聚合(UserBO)对应的UserBOService中生成函数createUserAndSetting该函数调用BaseUserBOService中生成的createUserAndSetting, 其中在BaseUserBOService中还生成了createUser和createSetting的函数, 一起完成了用户的创建和设置创建的逻辑。
- **修改建议:**
- 不能修改BaseBoService中的函数不建议修改BTO文件。建议在BOService中进行手动代码扩展处理可能被复用的修改前后的逻辑如修改数据库的前后值对比、或常被复用的校验逻辑业务不变性校验逻辑除外、需要经常在一个事务内执行的其他写操作等。
#### **2.12 业务变更传输对象(BTO)**
- **定义与用途:** 在TOCO中BTO为写方案自动生成的参数结构每个写方案会生成一个BTO。BTO为写方案选定的操作实体根据关系形成的树形集合最外层为聚合根。写方案调用方按照BTO的结构向写方案生成的RPC方法传入需要操作的实体字段值完成对数据库的写操作
- **与API的关系:** BTO通常可作为API的参数API接收到参数后可直接透传给内部的RPC进行调用
#### **2.13 服务层方法 (RPC)**
- **定义与用途:** 在TOCO中RPC为服务层的方法。RPC按照可见性可以分为两种一种是公开RPC可以被其他模块订阅订阅后可以通过RPC适配器进行调用另一种是非公开RPC只能被当前模块调用。非公开RPC可以被公开从而被其他模块订阅并调用
- **代码产物和修改建议**
- **生成代码:** RPC会在service层中生成类文件及实现函数包含DTO自动生成的RPC如UserDtoService.getById或UserBaseDtoService.getById、读写方案自动生成的RPC如UserDtoQueryService.queryByListQto、UserBOService.createUser、自定义RPC如UserCustomService.customMethod。特别注意公开的RPC才可被其他模块使用RPC被订阅后会生成RpcAdapter适配器其他模块通过RpcAdapter才可调用该方法。如Order模块订阅了User模块的UserDtoService.getById则会在Order模块中生成UserDtoServiceInOrderRpcAdapter.getById方法Order模块中的代码必须通过@Resource private UserDtoServiceInOrderRpcAdapter userDtoServiceInOrderRpcAdapter;注入适配器后才可进行方法调用
- **修改建议:** 建议修改RPC方法不建议修改RPC方法签名、适配器中的内容
#### **2.14 应用程序接口 (API)**
- **定义与用途:** 在TOCO中API用于定义对外暴露的HTTP接口
- **代码产物和修改建议**
- **生成代码:** API会在entrance层生成Controller以及对应的API方法
- **修改建议:** 建议修改API方法的实现内容不建议修改API方法签名、URI
### **3 生成代码产物补充说明**
- **3.1.1 支持的语言/框架**
Java、SpringBoot、MyBatis-plus(读)、Hibernate(写),具体的项目架构如下
```
TOCO生成的项目是一个多模块的SpringBoot项目,包括主模块和子模块
|──main_module
│ ├── common # 项目级别公共的基础模块
│ │ ├──config/ # 中间件配置
│ │ ├──constants/ # 项目级别常量
│ │ ├──enums/ # 项目级别枚举
│ │ ├──redis/ # Redis配置
│ │ ├──response/ # 返回结果封装
│ │ └──utils/ # 项目级别工具类
└── └── entrance/ # 项目入口
│ └──AppApplication.java # 项目启动类
└── modules # 子模块列表
└── module1/ # 子模块1
├── common/
│ ├──constants/ # 模块常量
│ ├──utils/ #模块级别工具类
│ └──enums/ # 枚举
├── entrance/
│ ├── controller/ # api 定义
│ ├──converter/ # 把DTO转化成VO
│ ├──vo/ # VO结构定义
│ └── query/ # 把读方案返回的数据转成成VO
│ ├── assembler/ # VO的数据填充
│ ├── collector/ # 读方案返回的id数据展开成完成对象数据
│ └── executor/ # 调用Service的度方案实现同时调用collector和assembler返回最终的VO
├── manager/ # Dto的查询接口定义
│ ├── bo/ # 聚合对象定义
│ ├── dto/ # 数据传输对象定义以及RPC引用的外模块的DTO定义
│ ├── converter/ # 复杂Dto非BaseDto)组装
│ ├── facade/ # 调用其他模块的RPC适配器包含RpcAdapter如UserDtoServiceInMeetingRpcAdapter表示从meeting模块调用user模块中方法
│ └── impl/ # Dto的查询接口的实现
├── persist/
│ ├── dos/ # 数据库单表结构的映射
│ ├── qto/ # 读方案的数据库查询实现
│ └── mapper/ # MyBatis的Mapper定义
└── service/ # BoService包含某个聚合下所有写方案生成的方法、 DtoService包含DTO生成的预定义方法
├── bto/ # 写方案入参的定义
├── converter/ # 对返回的BaseDto按需进行二次扩展
├── query/ # 查询方案的service层入口调用persist层的查询实现
└── base/ # 每个BoService对应的基类
在一个子模块的内它的依赖层级为entrance -> service -> manager -> persist, 同时各个层都依赖 common
```
- **3.1.2 特殊注解及含义**
TOC自动生成的类和方法会带有@AutoGenerated注解注解中有2个属性:locked为boolean类型如果locked=true则代表该文件或方法不建议修改;uuid为String类型表示该类或方法的唯一标识如果uuid中包含|字符则说明该uuid为特殊格式由不同类型的数据拼装而成(见**[3.2 设计元素到代码的映射规则及修改建议]**中每种设计元素的代码说明)。
### 4. 本地代码阅读和编写指南
#### 4.1 代码阅读
- 根据**设计元素到代码的映射规则及修改建议**在约读代码的时候你可以识别出对应的TOCO设计元素通过工具获取TOCO设计元素信息辅助理解代码语义特别是对于ReadPlanWritePlan的设计元素
- 读取类文件时应该同时读取继承的基类文件但注意不要去阅读BaseBOService里的代码
- 不要去读VoConverter、DtoConverter、 BaseDtoConverter、BaseVoConverter的代码
#### 4.2 代码编写
- 对于校验规则先判断是否为业务不变性规则如果是则将代码写在BO对象的聚合校验函数中即可实现校验功能不需要在Controller或Service中单独调用校验方法。聚合校验函数中适合做内存中数据的规则校验不适合做很重的外部存储数据的获取或RPC调用乐观锁字段由系统维护无需校验
- 需要着重考虑单一职责原则、复用性如Controller中更适合做参数校验及简单的不可复用的逻辑分支处理不适合实现复杂的或通用的业务逻辑
- 在循环中需要尽量避免执行调用数据库的操作,如查询数据库、写数据库等,尽量在循环外层先获取数据,在循环里面进行数据处理或读取
- 提高代码的可以读性复杂的业务逻辑需要拆解成多个函数一个函数的代码一般不要超过30行
- 如果代码中需要抛出异常则统一抛出IgnoredException(code, "message")异常如throw new IgnoredException(400, "xxx");code=400一般表示参数错误code=500一般表示处理出现错误。同时增加import com.vs.ox.common.exception.IgnoredException;
- 写代码时请注意BOService一般是用于写QueryService一般是用于读
- 输出代码前请仔细检查是否有错误的import如果有则将其修正
- 对于无法识别或直接生成的参数和逻辑,请增加一个相关的//TODO注释把从需求中解析到的可能的处理逻辑以java伪代码的形式写在注释中
- BoService 函数中的 boResult.getRootBo() 一定存在不要添加判断null的情况的代码; 不要添加调用rootBo.persist()的代码该方法的触发由生成的代码负责在BoService的函数中不要修改和注销系统生成的代码通过/** This block is generated by vs **/注释标注部分)
- 在函数中的不同片段逻辑,使用 {} 标注分块,附上注释,提升代码的可读性
- 以准确性作为第一优先级(不产生编译错误),不要直接生成不存在的函数、字段的调用; 如果逻辑上必须依赖,可以使用注释来表达
- 写代码时,如果发现有用户指定的上下文,则优先判断是否有可用的代码;如果用户有编写代码的特殊要求,则优先满足用户需求;如果前面已经有过规划信息,则尽量按照之前的规划来做,比如业务不变性的分析等
- 对于写服务的代码插入遵循如下规则: 1、 controller里插入入参的校验部分逻辑和参数重组逻辑 2、其他的逻辑在主BoService的主函数里为了增加代码可读性可以在BoService里新增函数
- 请在最后对所有你新增或修改的代码进行一次review重点关注是否存在编译错误代码可读性是否需要对大的函数进行拆分重构