diff --git a/llms-full.txt b/llms-full.txt index cb7c8db..627b261 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,30 +1,31 @@ -# TOCO知识库 -## **1. TOCO 平台概览:** + +## TOCO知识库 +### **1. TOCO 平台概览:** - **1.1 平台简介:** TOCO是一款重视软件设计及核心代码自动生成的专业研发平台。其基于DDD、分层设计、CQRS等经典研发理论,从数据库到API全部覆盖,可显著提升开发设计和编程效率,帮助开发团队实现更高的质量和生产力 - **1.2 核心价值/目标用户:** 从软件工程理论出发,提供软件设计能力,设计结果可直接转换为标准格式的代码,提升编码一致性及效率 - **1.3 主要特性概览:** 可视化设计、模型关联、多人协作、代码生成器等 -## **2. TOCO 设计元素:** -### **2.1 模块 (Module)** +### **2. TOCO 设计元素:** +#### **2.1 模块 (Module)** - **定义与用途:** 在TOCO中,我们将系统领域细分为具体的模块,映射为Java工程中的module。这些模块代表了系统的叶子子域,每个模块负责特定的功能。模块划分有助于系统的可维护性和可扩展性,并能提高开发效率和代码质量 - **关键配置:** 名称(小写英文字母+下划线,如meeting,user_detail,禁止加任何固定后缀),描述 - **与其他元素关系:** 下面的每种设计元素都属于一个模块 -### **2.2 枚举 (Enum)** +#### **2.2 枚举 (Enum)** - **定义与用途:** Enum用来表达一些常量值的集合,可被其他模块使用,可被用来做为字段的类型 - **关键属性/配置:** 名称(以_enum结尾),枚举值列表(全大写字母+下划线) -### **2.3 值对象 (Eo)** +#### **2.3 值对象 (Eo)** - **定义与用途:** EO为一种POJO对象结构,可被其他模块使用,可被用来做为实体字段的类型 - **关键属性/配置:** 名称(以_eo结尾),字段列表。EO的字段类型只能为基本类型(含List)、EO、Enum,其他类型不允许 -### **2.4 实体关系 (ER / Entity)** +#### **2.4 实体关系 (ER / Entity)** - **定义与用途:** 实体及其关系。一个实体一般对应一个数据库表,关系为实体间的外键依赖关系 - **关键属性/配置:** 实体中包含名称、字段、字段类型、主键、索引等,关系分为1:1和1:N关系 - **与其他元素关系:** 实体关系是聚合的基础,也是DTO和VO的派生基础 -### **2.5 聚合对象 (BO/业务对象)** +#### **2.5 聚合对象 (BO/业务对象)** - **定义与用途:** 在TOCO中,聚合对象是对一组密切关联的实体的封装。聚合对象从单一实体开始,这个实体我们称为聚合根,通过实体间关系,不断的顺序将其他实体按层级关系组装进这个聚合对象。聚合对象可以按实体表达为树形结构。聚合对象提供了这组实体的内存一致性视图,提供数据操作入口。由于写操作的内聚性,聚合对象只能在单一模块中组合,而且一个实体只能属于一个对象。同样如果有实体不在任何一个聚合对象中,TOCO将无法提供与之相关的写方法。 - **包含元素:** 聚合对象包括聚合根及其聚合下的其他子实体对象,例如,商品聚合ProductBO中,商品基本信息实体是ProductBO的聚合根,商品SKU实体、商品库存实体是ProductBO的子聚合对象。 - **关键配置:** 名称(${EntityName驼峰}BO结尾,如StaffBO),聚合根实体,聚合子对象实体。每个聚合必须包含一个聚合根 - **与其他元素关系:** 聚合是写方案的基础 -### **2.6 数据传输对象 (DTO)** +#### **2.6 数据传输对象 (DTO)** - **定义与用途:** 在TOCO中,DTO表达某个Entity为基本,通过外键关系不断关联多个Entity的数据结构。DTO还隐式表达了数据的取数拼装,这种拼装符合外键关系。往往被当做RPC的返回值、或读方案的返回值使用,不建议把DTO作为入参。注意DTO不能作为HTTP API的返回值。DTO分为BaseDTO和普通DTO,BaseDTO派生自Entity,包含Entity的所有字段,每个Entity有且仅有一个BaseDTO;普通DTO派生自BaseDTO,包含BaseDTO的所有字段,且可以增加扩展字段或自定义字段 - **如何创建/生成:** 对于每个Entity,TOCO会自动生成一个BaseDTO,命名为${Entity名字}BaseDto,如UserBaseDto,该BaseDTO包含了Entity的全部字段。除了BaseDTO,其他的DTO均需要手动以BaseDTO为根来创建。在TOCO中,必须要先判断需要的DTO是否为BaseDTO,如果是BaseDTO,则可通过Entity名称获取BaseDTO;如果不是BaseDTO,则需要通过DTO要表达的信息来创建DTO,如:会议及其议程信息。 - **关键配置:** 名称(BaseDTO以BaseDto结尾,其他DTO以Dto结尾)、根Entity、字段列表。DTO中的字段分为三种:a.继承Entity或BaseDTO的字段,和Entity及BaseDTO的字段类型一样;b.扩展字段,含正向替换和反向注入字段,类型为DTO或List;c.自定义字段,类型为基本类型、Eo、Enum、DTO类型。BaseDTO中一般包含Entity的全部字段,DTO中一般包含BaseDTO中的全部字段,不进行字段裁剪,可以根据外键关系扩展其他Entity(详见**字段扩展方式**),在明确无法扩展外部Entity的情况下,可增加对应的自定义字段。 @@ -90,7 +91,7 @@ DateTime endTime; //会议结束时间 - b. 如果通过其他复杂查询条件,则可以采用第2种方式 注意判断使用哪种方式时,只能根据查询条件判断是否使用读方案,绝对禁止使用返回值是否需要数据拼装来判断!**如果现实中的代码和TOCO中的步骤有冲突时,只能使用TOCO的定义!** -### **2.7 视图对象 (VO)** +#### **2.7 视图对象 (VO)** - **定义与用途:** 在TOCO中,VO表达某个BaseDTO(如果用户指明派生源,也可使用其他DTO)为派生源,通过外键关系不断关联多个BaseDTO的数据结构。VO用于在视图层与前端之间进行数据传输,往往被当做HTTP API的返回值、或读方案的返回值使用,由服务端返回至前端。注意VO不能作为RPC的返回值。 - **关键配置:** 名称(以Vo结尾)、根Entity、派生源、字段列表。VO中的字段分为三种:a.继承DTO的字段,和DTO的字段类型一样;b.扩展字段,含正向替换和反向注入字段,类型为VO或List;c.自定义字段,类型为基本类型或VO类型。VO中的字段来源于DTO,可以根据页面需要进行裁剪,可以根据外键关系扩展其他BaseDto(详见**字段扩展方式**)。如果在派生源中没有合适字段,且明确无法通过外键扩展外部BaseDto的情况下,可增加对应的自定义字段 - **与DTO的区别 (在TOCO语境下): **DTO用于服务层传输,通常作为RPC的返回值,与数据模型更近,复用性较强;VO用于视图层传输,通常作为API的返回值,与UI展示更为接近,复用性较弱。 @@ -156,7 +157,7 @@ DateTime endTime; //会议结束时间 - c. 如果用户上下文中有指定的返回DTO的读方案符合条件,则使用第2种,否则使用第3种 注意判断使用哪种方式时,只能根据查询条件判断是否使用读方案,绝对禁止使用返回值是否需要数据拼装来判断!**如果现实中的代码编写方式和TOCO中的步骤有冲突时,只能使用TOCO的定义!** -### **2.8 读方案 (ReadPlan)** +#### **2.8 读方案 (ReadPlan)** - **定义与用途:** 在TOCO中,读方案描述了一种数据库查询方案,查询条件为一个面向对象的查询语句,其中可以包含存在外键关系的多个实体的字段(如age=18 and name like #nameLike and school.name like #schoolNameLike,其中以#开头的是自定义参数,会自动生成一个QTO结构,由查询调用方动态传入),结果为符合查询条件的**一种**DTO或VO列表。读方案内部会将该面向对象的查询条件转化为复杂的join sql语句,来实现对数据库的查询,以及返回的复杂DTO和VO数据的组装。读方案可以指定其分页方式(不分页、页码分页、瀑布流分页),以及是否生成计数方法(用于返回符合条件的记录数量)。 - **使用建议:** 如果查询条件只有主键,则建议使用预定义的getBy${PrimaryKey}或getBy${PrimaryKey}s方法来获取DTO(参照DTO的**预定义方法**)或VO(参照**复杂嵌套VO获取流程**),不建议使用读方案。非主键查询或多条件查询建议使用读方案。 - **关键配置:** 名称(小写字母+下划线,不要以read_plan结尾)、返回结构(DTO/VO,一个读方案**不能**同时返回多种DTO或VO)、查询条件的自然语言描述、是否生成计数方法、排序字段(如果选择不分页,则不需要) @@ -356,12 +357,12 @@ DateTime endTime; //会议结束时间 } } ``` -### **2.9 查询传输对象(QTO)** +#### **2.9 查询传输对象(QTO)** - **定义与用途:** 在TOCO中,QTO为读方案的查询参数结构,每个读方案会对应一个QTO,写方案调用方按照QTO的结构向读方案生成的RPC方法传入需要查询的实体字段值,完成对数据库的查询 - **如何创建/生成:** 在创建读方案后,TOCO会自动生成QTO作为该读方案传入的查询参数结构,无需单独创建 - **关键配置:** 名称(${ReadPlanNameQto},驼峰展示),查询字段列表(如idIs,nameLike, schoolNameLike等) - **与API的关系:** QTO通常可作为API的参数,API接收到参数后可直接透传给内部的RPC进行调用 -### **2.10 写方案 (WritePlan)** +#### **2.10 写方案 (WritePlan)** - **定义与用途:** TOCO针对写场景定义了一种写方案,所有对数据库的写操作都只能通过写方案实现。写方案包含了对数据库表的写操作。每个写方案只能操作一个聚合内部的表,同时对一个聚合内表的操作尽量合并至一个写方案中(根据复用性、内聚性等方面具体情况具体分析)。注意写方案可以一次操作聚合内的多张表,如location和storey是同一个聚合,并且location和storey是**1:N**关系,location是父对象(聚合根),storey是子对象,那么我们可以创建一个写方案,同时更新单个聚合根location中的信息,以及操作其下的子表storey**列表**信息,如新增、删除、修改storey等;也可以创建一个写方案单独更新单个子表storey对象信息。 - **关键配置:** 名称(小写字母+下划线,不要以write_plan结尾),操作的聚合,聚合内的实体和字段,对每个实体的操作类型:CREATE(创建**单个**实体),UPDATE(更新**单个**实体), DELETE(删除**单个**实体), CREATE_ON_DUPLICATE_UPDATE(创建或者更新**单个**实体),FULL_MERGE( 批量更新**列表**数据,根据传入的列表数据,一条一条执行CREATE_ON_DUPLICATE_UPDATE的操作;并且删除掉老的列表中不在传入列表数据中的部分), PARTIAL_MERGE(批量更新**列表**数据,根据传入的列表数据,一条一条执行) - **与RPC的关系:** 对于每一个写方案,TOCO会自动生成一个RPC方法,其参数为写方案对应的BTO,返回值为本次操作的聚合根实体的主键值,内部只实现了对当前聚合的数据库操作 @@ -489,7 +490,7 @@ DateTime endTime; //会议结束时间 ] } ``` -### **2.11 业务变更传输对象(BTO)** +#### **2.11 业务变更传输对象(BTO)** - **定义与用途:** 在TOCO中,BTO为写方案自动生成的参数结构,每个写方案会生成一个BTO。BTO为写方案选定的操作实体根据关系形成的树形集合,最外层为聚合根。写方案调用方按照BTO的结构向写方案生成的RPC方法传入需要操作的实体字段值,完成对数据库的写操作 - **如何创建/生成:** 在创建写方案后,TOCO会自动生成一个BTO作为该写方案传入的参数结构,无需通过TOCO创建。 - **关键配置:** 名称(${WritePlanName}Bto,驼峰展示),嵌套的树形实体和字段列表,BTO内部的字段全部都来自Entity。以下为一个示例: @@ -504,7 +505,7 @@ DateTime endTime; //会议结束时间 } ``` - **与API的关系:** BTO通常可作为API的参数,API接收到参数后可直接透传给内部的RPC进行调用 -### **2.12 服务层方法 (RPC)** +#### **2.12 服务层方法 (RPC)** - **定义与用途:** 在TOCO中,RPC为服务层的方法。RPC按照可见性可以分为两种,一种是公开RPC,可以被其他模块订阅,订阅后可以通过RPC适配器进行调用;另一种是非公开RPC,只能被当前模块调用。非公开RPC可以被公开,从而被其他模块订阅并调用 - **如何创建/生成:** RPC有4种创建方式:a.DTO创建后会自动创建RPC,RPC的公开性与DTO的公开性保持一致;b.返回DTO的读方案会根据分页情况、以及是否生成计数函数的配置自动生成非公开的RPC c.写方案创建后会自动生成非公开的RPC d.如果上述三种RPC无法满足需求,则可以通过TOCO创建自定义RPC完整指定功能,需指定具体的参数和返回值以及公开性等。 - **优先复用:** 当用户需要创建一个RPC时,如果用户有明确要求创建的方式,则按照用户的要求来创建。如果没有明确要求,则通常先判断是否可以通过创建读方案、写方案、DTO来使TOCO自动创建出对应的RPC,最后再考虑通过TOCO创建自定义RPC @@ -566,7 +567,7 @@ requestParams为请求参数列表,response为返回结构,requestParams中 ``` 结构中一些关键字段描述如下: requestParams为请求参数列表,response为返回结构,requestParams中每个参数和response的结构相同,其中:name为参数名;type为参数类型,参数类型取值范围为Boolean,String,Integer,Long,Float,Double,BigDecimal,Date,ByteArray,Enum,Eo,List,Vo,Qto,Bto,Void,其中参数不能为Void,如果不需要返回值,则type设置为Void;description为描述;uuid为参数对应类结构的UUID,当type为Enum、Eo、Vo、Qto、Bto时包含该字段;innerType为List内部类型,当type为List时包含该字段;innerUuid为List内部类结构的UUID,当type为List且innerType为Enum、Eo、Vo、Qto、Bto时包含该字段。 -### **2.14 流程服务(Function_Flow)** +#### **2.14 流程服务(Function_Flow)** - **定义与用途:** TOCO针对复杂业务拆解,定义了流程服务,把一个复杂的业务过程,根据业务逻辑的内聚性,合并逻辑功能,把流程分解成流程节点,最终构造出一个类似工作流的逻辑流程;最终实现复杂业务流程分解,提升代码的可维护性。TOCO内嵌了流程引擎,在Function_Flow生成代码后,可以在流程引擎中执行 - **何时使用:** - 如果一个API/RPC中涉及的写服务超过3个,则推荐使用流程服务 @@ -651,16 +652,16 @@ requestParams为请求参数列表,response为返回结构,requestParams中 } ``` -## **3. TOCO 代码生成说明** -### **3.1 生成代码产物说明** +### **3. TOCO 代码生成说明** +#### **3.1 生成代码产物说明** - **3.1.1 支持的语言/框架** Java、SpringBoot、MyBatis-plus(读)、Hibernate(写) - **3.1.2 特殊注解及含义** TOC自动生成的类和方法会带有@AutoGenerated注解,注解中有2个属性:locked为boolean类型,如果locked=true,则代表该文件或方法不建议修改;uuid为String类型,表示该类或方法的唯一标识,如果uuid中包含|字符,则说明该uuid为特殊格式,由不同类型的数据拼装而成(见**[3.2 设计元素到代码的映射规则及修改建议]**中每种设计元素的代码说明)。 -### **3.2 设计元素到代码的映射规则及修改建议** -#### 3.2.1 Module +#### **3.2 设计元素到代码的映射规则及修改建议** +##### 3.2.1 Module - **生成代码:** 每个Module会单独生成一个Java Module:项目路径/modules/模块名,内部采用了entrance、service、manager、persist、common分层结构 -#### 3.2.2 Enum +##### 3.2.2 Enum * **生成产物**:在common模块中生成一个Java类 * **职责:** 表达Enum的数据结构 * **命名规则**:类名以Enum结尾 @@ -668,14 +669,14 @@ requestParams为请求参数列表,response为返回结构,requestParams中 * **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Enum在TOCO中的uuid}|ENUM|DEFINITION - **生成代码:** Enum会在common层生成Enum文件,如StatusEnum - **修改建议:** 不建议修改 -#### 3.2.3 EO +##### 3.2.3 EO * **生成产物**:在persist层生成结构定义类文,如AddressEo * **职责:** 表达POJO数据结构 * **命名规则**:类名以Eo结尾 * **类路径:** 位于 ```**.persist.eo``` 包路径下 * **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Eo在TOCO中的uuid}|EO|DEFINITION - **修改建议:** 不建议修改 -#### 3.2.4 Entity +##### 3.2.4 Entity - 结构定义 * **生成产物**:Java类,按照Mybatis-plus的要求生成 * **职责:** 按照Mybatis-plus的要求生成结构定义类文件 @@ -700,7 +701,7 @@ requestParams为请求参数列表,response为返回结构,requestParams中 * **类路径:** 位于 ```**.persist.mapper``` 包路径下 * **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|ENTITY|DAO - **修改建议:** 不建议修改 -#### 3.2.5 业务对象 (BO) +##### 3.2.5 业务对象 (BO) - 综述 - 业务对象包含多个Entity,通过业务对象的嵌套组合表达了Entity之间的关系,如果一个业务对象包含了子对象,则会生成BO和BaseBO,BaseBO封装实体属性和关系,子类留给业务扩展逻辑; 如果是叶子节点(不存在子对象)的BO,则直接生成BO类文件,不生成BaseBO类文件 @@ -718,7 +719,7 @@ requestParams为请求参数列表,response为返回结构,requestParams中 * **类路径:** 位于 ```**.manager.bo``` 包路径下 * **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|BO|DEFINITION - **修改建议:** 建议修改BO中的validateAggregate或valid方法,如果发现需求中有业务不变性校验;不建议修改检验方法以外的其他代码 -#### 3.2.6 数据传输对象 (DTO) +##### 3.2.6 数据传输对象 (DTO) - 结构定义 * **生成产物**:一个Java类 * **职责:** 表达DTO的数据结构 @@ -743,7 +744,7 @@ requestParams为请求参数列表,response为返回结构,requestParams中 * 如UserDto、UserDtoManager、UserDtoConverter extends UserDtoBaseConverter、UserDtoService或(名称为${DtoName}Service,内部包含getById,getByIds等方法)。如果Dto为UserBaseDto,则生成的类名为UserBaseDtoService - **修改建议:** - 建议在Service与BaseConverter中进行代码扩展,不建议修改结构定义文件和Manager文件。其中DTO的**自定义字段**由于不直接派生自Entity,所以一般会对应取数逻辑代码。通常如果涉及到数据获取、计算和拼装,批量处理的性能最好,所以代码位置**必须**放在BaseConverter中已经自动生成的**列表**转换方法中,批量取数组装,如UserBaseDtoBaseConverter.convertUserToUserBaseDto(List)或UserDtoBaseConverter.convertUserBaseDtoToUserDto(List) -#### 3.2.7 视图对象 (VO) +##### 3.2.7 视图对象 (VO) - **结构定义** * **生成产物:** 在controller层生成一个Java类 * **命名规则:** 类名以Vo结尾 @@ -762,7 +763,7 @@ requestParams为请求参数列表,response为返回结构,requestParams中 * 如UserDetailVo、UserDetailVoConverter(包含convertToUserDetailVo、convertToUserDetailVoList、convertToUserDetailVoMap、convertAndAssembleData、convertAndAssembleDataList方法) - **修改建议:** - 建议在Converter中进行代码扩展,不建议修改结构定义文件。其中VO的**自定义字段**由于不直接派生自DTO,所以一般会对应取数逻辑代码。通常如果涉及到数据获取、计算和拼装,批量处理的性能最好,所以自定义字段对应的代码位置**必须**放在Converter的**Map**基础转换方法convertTo${VoName}Map中,批量取数组装,如UserVoConverter.convertToUserVoMap -#### 3.2.8 读方案 (ReadPlan) +##### 3.2.8 读方案 (ReadPlan) - **Service** * **生成产物:** 在Service层生成一个Java类 * **命名规则:** 类名以QtoService结尾(${ReadPlanName}QtoService) @@ -795,7 +796,7 @@ requestParams为请求参数列表,response为返回结构,requestParams中 * 根据用户名称查询用户列表返回UserDTO,则生成UserNameQto、UserNameQtoService、UserNameQtoDao、UserNameQueryService; UserNameQueryService调用UserNameQtoService,UserNameQtoService调用UserNameQtoDao - **修改建议:** - 如果有对结果的数据二次处理,建议在QueryService和QueryExecutor中进行代码扩展,不建议修改QTO文件 -#### 3.2.9 写方案 (WritePlan) +##### 3.2.9 写方案 (WritePlan) - **Service:** * **生成产物:** 在对应的聚合服务BoService里生成一个函数 * **函数命名规则:** 和写方案同名 @@ -816,13 +817,13 @@ requestParams为请求参数列表,response为返回结构,requestParams中 - 创建用户以及用户设置的写方案create_user_and_setting,生成CreateUserAndSettingBto, 在用户的聚合(UserBO)对应的UserBOService中生成函数createUserAndSetting,该函数调用BaseUserBOService中生成的createUserAndSetting, 其中在BaseUserBOService中还生成了createUser和createSetting的函数, 一起完成了用户的创建和设置创建的逻辑。 - **修改建议:** - 不能修改BaseBoService中的函数,不建议修改BTO文件。建议在BOService中进行手动代码扩展,处理可能被复用的修改前后的逻辑,如修改数据库的前后值对比、或常被复用的校验逻辑(业务不变性校验逻辑除外)、需要经常在一个事务内执行的其他写操作等。 -#### 3.2.10 RPC +##### 3.2.10 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方法签名、适配器中的内容 -#### 3.2.11 API +##### 3.2.11 API - **生成代码:** API会在entrance层生成Controller以及对应的API方法 - **修改建议:** 建议修改API方法的实现内容,不建议修改API方法签名、URI -#### 3.2.12 流程服务(FunctionFlow) +##### 3.2.12 流程服务(FunctionFlow) - **FlowConfig** * **生成产物:** 每个模块在service层的生成一个Java类,负责注册模块下的所有流程到执行器 * **命名规则:** 类名为${moduleName}FlowConfig @@ -849,12 +850,33 @@ requestParams为请求参数列表,response为返回结构,requestParams中 - 用户登录,在UserFlowService中生成一个函数invokeLoginFlow,该函数通过流程框架根据流程定义调用LoginNode,LoginNode中封装了用户登录的逻辑,LoginFlowContext中封装了用户登录的参数和结果。 - **修改建议:** 不修改 service 中的函数, 不修改FlowConfig, 可以修改FlowContext, 添加/修改出入参数, 修改FlowNode中的具体业务逻辑。 -## 4. TOCO 最佳实践 -### 4.1 设计分析结果应用(Design analysis results application): +### 4. TOCO 最佳实践 +#### 4.1 设计分析结果应用(Design analysis results application): 在TOCO中,设计分析(designAnalyze工具)的结果按照用户的要求或需求的复杂度分为2种,你需要分辨流程分析的结果类型,然后根据不同类型做出不同的后续工具调用规划: - 1.**细节设计分析**:针对简单或短流程需求,会直接进行读写方案、接口等分析、代码编写等结果。此时需要根据工具规划后续的调用。 - 2.**流程拆解设计分析**:针对复杂需求,不会直接分析细节的设计元素,而是根据内聚、解耦、复用等原则,参考**流程服务(Function_Flow)**对业务需求拆解为多个短流程并返回结果。后续需要针对整体的API的定义、流程服务定义、**所有**流程节点中涉及的**所有**DTO、VO、读写方案、RPC等来进行对应的工具调用。注意此时**必须**调用createFunctionFlow工具来创建流程服务。 -### 4.2 为所有的写场景都创建写方案(Create WritePlan For All Write Scenarios): +#### 4.2 为所有的写场景都创建写方案(Create WritePlan For All Write Scenarios): 通常在分析业务需求时,需要分析出**所有**写数据的场景,并按照**聚合维度**进行分组,然后针对每个写场景**都需要**创建对应的写方案,不能有遗漏。写方案可以按需根据聚合进行合并。 -### 4.3 接口参数类型和返回值选择(Interface Parameter & Return Type Definition): +#### 4.3 接口参数类型和返回值选择(Interface Parameter & Return Type Definition): 在做TOCO接口(API、RPC)设计时,通常会先判断接口的主要功能是读数据库或写数据库,并分析相关的读写方案以及对应的QTO和BTO。如果是读场景,则参数会**优先使**用相关的QTO;如果是写场景,则参数会**优先**使用相关的BTO,如果BTO和QTO无法满足要求,则可以再增加基本类型或Enum、EO等类型参数。参数类型选择时必须遵循以下要求:a.DTO、VO不能作为参数类型;b.QTO、BTO不能作为返回值类型 + +### 5. 本地代码阅读和编写指南 +#### 5.1 代码阅读 +- 根据**设计元素到代码的映射规则及修改建议**,在约读代码的时候,你可以识别出对应的TOCO设计元素,通过工具获取TOCO设计元素信息,辅助理解代码语义,特别是对于ReadPlan,WritePlan的设计元素 +- 读取类文件时,应该同时读取继承的基类文件(但注意不要去阅读BaseBOService里的代码) +- 不要去读VoConverter、DtoConverter、 BaseDtoConverter、BaseVoConverter的代码 +#### 5.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,重点关注是否存在编译错误;代码可读性(是否需要对大的函数进行拆分重构)