当前位置: 首页 > news >正文

福田网站-建设深圳信科企业网站建设太原网站建设

福田网站-建设深圳信科,企业网站建设太原网站建设,网站设计一般多长时间,怎么注销建设银行网站用户名1. 关于DDD项目结构约定 1.1 项目结构使用DDD整洁架构进行分包 maven项目结构遵从DDD整洁架构分为如下四个顶级包#xff1a; application - 应用层代码#xff0c;一般为接口层定义API的实现类和一些结构转化#xff0c;application不应该承载业务逻辑 domain - 领域层 application - 应用层代码一般为接口层定义API的实现类和一些结构转化application不应该承载业务逻辑 domain - 领域层包含应用的业务模型定义全部业务逻辑可以细分实体entity和领域服务service等子包 infrastructure - 基础设施层包含配置、基础工具、切面、枚举、外部服务调用、消息、缓存等中间件 interfaces - 服务自身API的定义以及与API定义相关的API结构DTO定义 单模块工程结构示例 assignment-service – src/main/java ---- com.huawei.it.hr.assignment ------ application ------ domain ------ infrastructure ------ interfaces ------ AssignmentApp.java 启动类 – pom.xml 多模块工程结构示例 MetadaPayrollCalculation – PayrollCalcService ---- src/main/java ------ com.huawei.it.hr.payroll ------ application ------ domain ------ infrastructure ------ interfaces ---- pom.xml 子模块构建配置文件 – PayrollCalcBase ---- src/main/java ------ com.huawei.it.hr.payroll ------ application ------ domain ------ infrastructure ------ interfaces ---- pom.xml 子模块构建配置文件 – pom.xml 父模块构建配置文件 各层级依赖关系为 接口层通常不依赖应用层/领域层可以依赖部分基础设施层工具、类型 应用层依赖接口层的API接口定义并依据接口定义提供实现 应用层依赖领域层处理业务逻辑 应用层可以使用部分基础设施层工具、类型 领域层不反向依赖应用层和接口层。可以依赖部分基础设施层工具和类型 2. 禁止大面积拷贝 2.1 禁止拷贝反编译生成的代码 说明 Java源代码编译成class文件时会保留一些公共部分如类名公共方法名等。但是JVM出于一些优化考虑会调整一些细节部分如将内部常量变量方法内联省略形参变量名仅保留类型包装异常块等。因此根据class文件反向编译出来的源代码与生成class的原始源代码大相径庭。在代码中直接使用反向编译生成的勉强能工作的源代码严重影响可读性后续也极难维护应该杜绝。 错误示例 try { try { Object[] result BusinessDataWriter.save(dataEntities[0].getDataEntityType(), dataEntities, option); if (Configuration.isEnable()) { DTXServiceHelper.confirmXid(dbkey, result ! null ? DynamicObjectSerializeUtil.serialize(result, dataEntities[0].getDynamicObjectType()) : null); } RecordSaveFormServiceHelper.recordSaveFormToCache( dataEntities[0].getDataEntityType().getName()); var7 result; } catch (Throwable var17) { throw var17; } } catch (Throwable var18) { throw var18; } return var7; #### 2.2 禁止拷贝第三方代码需要引用/修改时应显式声明依赖后扩展 说明直接拷贝第三方/开源代码有版权问题且直接拷贝源码失去了后续迭代的一切可能性在出现漏洞/升级时补救成本巨大。按照Open-Close原则应该将依赖显式声明在需要修改依赖包API行为时使用装饰器转换器等模式进行扩展。直接拷贝其他工程的代码也及容易留下无用代码和产生重复代码应该禁止。### 3. 命名和分包约束 #### 3.1 类型、变量和方法使用合适的命名 说明类型变量方法签名必须具备一定的自解释性也是代码可读性的重要基础。在《阿里巴巴编码规范》基础上禁止使用 mapobject, json, data, list 等非常泛化的命名#### 3.2 数据库映射对象实体命名以Entity/Pojo结尾如 CalcPersonEntity/CalcPersonPojo 对于数据库映射对象统一使用 *Entity/Pojo 的命名风格放在 entity/pojo 包下#### 3.3 API结构定义对象 命名以Dto结尾如 CalcPersonDto 对于API结构定义类对象统一使用 *Dto 的命名风格数据传输对象#### 3.4 领域层一般模型直接使用语义命名放在 model 包下 领域层实体模型按照3.2放在entity包下其他非实体领域层模型放在model包下#### 3.5 领域层一般模型不建议保留古老的 VO/BO 等包名和命名后缀 VO原意至Value Object 或 View Object。值对象的含义已由Dto概括View Object 在前后端分离架构中通常已经不复存在。BO 原意为 Business Object名称太泛不建议使用。#### 3.6 数据库查询类非持久化结构使用 Query 结尾如 CalPersonQuery对于事务类结构建议使用Command结尾或直接语义化命名 例如根据业务需要定制的查询参数结构建议使用 *Query 的命名风格。对于事务类操作可以使用*Command的命名风格也可以直接按照上下文语义进行命名。#### 3.7 贯穿接口/领域层的枚举类型放在 infrastructure 层定义领域层内部的枚举可以直接定义在 domain 层 model 包中 对于枚举类型通常不适合在接口层和领域层重复定义为保持层次依赖关系清晰共用的枚举结构建议定义在基础设施层中作为公共结构。领域层专用枚举可以直接放在domain层model包下。### 4 代码结构约定 #### 4.1 禁止使用动态类型描述固定结构 说明JAVA是面向对象的语言也是JAVA代码保持良好延展性的重要基石。在描述格式固定的结构时使用类型和对象非常合适可以有效的进行语义化表达和类型约束让更多的错误在编译阶段即可识别和解决。而不至于留到运行时。JsonMap等动态类型仅在描述真正不确定的动态结构时是合理的但是如果结构较为固定如获取/设置固定字符串描述的Key使用动态类型表达会绕过一些编译期检查同时往往伴随着诸多类型转换降低了代码可读性重用性和健壮性。错误示例Map param new HashMap(); param.put(appId, ConfigPropertiesUtil.getContextProperty(application.appId)); param.put(subAppId, ConfigPropertiesUtil.getContextProperty(application.subAppId)); param.put(jobWorkerDuId, ConfigPropertiesUtil.getContextProperty(lite.job.client.jobworkerduid)); param.put(jobName, ConfigPropertiesUtil.getContextProperty(lite.job.client.jobname)); param.put(taskName, ConfigPropertiesUtil.getContextProperty(lite.job.client.taskname)); JSONObject obj new JSONObject(param); // 此处Map中的结构是固定的使用一个固定结构更为合适。对比示例 Getter Setter public class JobConfig { private String appId; private String subAppId; private String jobWorkerDuId; private String jobName; private String taskName; } #### 4.2 代码块合理分段确保结构清晰避免出现过多代码块缩进嵌套 箭头函数是一个临时定义的方法缺省了方法签名在内容较少时比较适用。箭头函数的代码块中不宜存放过多代码内容会导致更多复杂的缩进和嵌套不利于理解。如果代码块中需要执行的指令较多应该提取为单独的方法进行合适的方法署名。错误示例list.stream().forEach(beforeVO - {try {LogRecordVo logRecordVo LogRecordVo.builder().tableName(PayElementAttributeDomain.LOG_TABLE_NAME).entities(Arrays.asList(PayElementAttributeDomain.LOG_TABLE_NAME)).moduleName(PayElementAttributeDomain.LOG_MODULE_NAME_DELETE).businessNo(String.valueOf(beforeVO.getAttributeId())).operationEnum(LogOperationEnum.DELETE).beforeObject(beforeVO).afterObject(null).build();AsyncMessage asyncMessage new AsyncMessage(LogRecordConstant.MSG_LOG_RECORD_SEND);asyncMessage.setContent(logRecordVo);messageSender.send(asyncMessage);} catch (Exception e) {log.error(log error: {}, e.getMessage());} });等价示例 list.forEach(beforeVO - sendMessage(beforeVO)); private void sendMessage(PayElementAttributeBusinessViewDto vo) { try { // … 原始发送消息相关代码 } catch (Exception exception) { log.error(“log error: {}”, e.getMessage()); } } #### 4.3 基于SOLID原则使用组合优于继承 SOLID原则包括的内容很多其基本含义是职责单一Single Responsibility,对扩展开放对修改关闭Open Close, 里氏替换Interface Segregation接口隔离Interface Segregation和依赖反转Dependency Inversion五部分过多的使用继承关系来获取已有的父类功能和属性不利于代码的可读性和可维护性应该优先使用接口抽象和组合关系表达功能的组合。错误示例public class PayrollCalcTaskRunVO extends HRBaseVO {//.... attributes } 等价示例 public class PayrollCalcTaskRunVO { JsonUnwrapped private HRBaseVO baseInfo; //.... attributes} **说明在Mybatis等ORM框架中可以使用合适的配置写法将结果映射成复杂对象如Mybatis中的accociation配置。在API中可以通过 JsonUnwrapped 等注解将属性对象的内容展开到父级json块达到与继承相同的JSON格式。**#### 4.4 减少switch语句的使用 switch是早期JVM提供的一个关键字《Clean Code》中这样描述switch语句写出只做一件事的switch语句也很难switch天生就要做N件事。switch语句本身很复杂也不容易理解一般时候应该避免/减少使用switch-case关键字的使用。错误示例switch (operationType) {case R : // 授权addPermissions(rolePlanEntity, personInfoEntity.getGlobalUserId(), billDispatchRolePlanEntity);break;case D : // 延期break;case C : // 取消deleteRolePerson(personInfoEntity.getGlobalUserId(), billDispatchRolePlanEntity);break;default :log.error(IAuthServiceImpl operationType is null);break; }等价示例 MapString, Runnable actionMap newHashMap(); actionMap.put(“R”, () - addPermissions(rolePlanEntity, personInfoEntity.getGlobalUserId(), billDispatchRolePlanEntity)); actionMap.put(“D”, () - {}); actionMap.put(“C”, () - deleteRolePerson(personInfoEntity.getGlobalUserId(), billDispatchRolePlanEntity)); Runnable defaultAction () - log.error(“IAuthServiceImpl operationType is null”); actionMap.getOrDefault(operationType, defaultAction).run(); 4.5 避免过多的if-else嵌套switch式的if-else使用map进行简化 if-else嵌套时会让代码的分指数显著增加一般需要对一些代码块进行分割并尽量共用重复逻辑部分。某些连续的 if-else 分支写法其实是类似于switch的表达同样可以使用Map进行简化。 错误示例 // 此处明显为固定结构应该使用相应的类型进行描述而不是使用Map。且变量名mp也明显缺乏含义 MapString, Object mp new HashMapString, Object(); if(“1”.equals(search_type)){ mp.put(“rehiredatebegin”, search_param); mp.put(“rehiredateend”, search_param1); mp.put(“search_type”, search_type); } else if (“2”.equals(search_type)){ mp.put(“oldnumber”, search_param); mp.put(“search_type”, search_type); } else if(“all”.equals(search_type)){ mp.put(“search_type”, search_type); } else { return null; } mp.put(“pageInfo”,“true”); mp.put(“pageSize”,“3000”);//分页数 mp.put(“curPage”,“1”);//当前页 等价示例 // 将searchType、pageInfo、pageSize、curPage等固定内容放在构造函数中统一初始化 RequestParam requestParam new RequestParam(search_type); MapString, Runnable typeActionMap newHashMap(); typeActionMap.put(“1”, () - injectParamAsDate(requestParam, search_param, search_param1)); typeActionMap.put(“2”, () - injectParamAsNumber(requestParam, search_param)); typeActionMap.put(“all”, () - {}); // 为重构需要将退出语句更换为运行时异常结束 Runnable defaultAction () - { throw new InvalidSearchTypeException(“search type is not valid”); }; typeActionMap.getOrDefault(search_type, defaultAction).run(); 4.6 逻辑关系简明化避免过多 return true/ false的指令 返回 boolean类型的断言方法一般只用专注与断言条件极其组合而不需要太多分支控制分支控制中的条件可以直接作为boolean的结果返回让代码看起来更加简洁内聚 错误示例 public boolean isContainsSpecilValue(String currentDeptCode, String path) { String configValues getRegistryValuesByPath(path); if (!StringUtils.isEmpty(configValues)) { String[] values configValues.split(“,”); if (values ! null values.length 0) { List list deptQueryDao.findChildrensDeptsByCodes(Arrays.asList(values)); if (!CollectionUtils.isEmpty(list) list.contains(currentDeptCode)) { // 当前部门在此部门体系中则允许异地纳税 return true; } else { // 不允许异地纳税 return false; } } } else { log.info(“指定的paht” path “的值未配置值!”); return false; } return true; } 等价示例 public boolean isContainsSpecilValue(String currentDeptCode, String path) { String configValues getRegistryValuesByPath(path); return StringUtils.isNotEmpty(configValues) deptQueryDao.findChildrensDeptsByCodes(newArrayList(configValues.split(“,”))).contains(currentDeptCode); } 4.7 使用泛型时需要显式指定类型避免代码含糊不清 错误示例 final Map subMap parserToMap(array[i]); // 由于没有指定泛型类型代码可读性变差后续使用时通常需要一些强制转换 对比示例 final MapString, String subMap parserToMap(array[i]); // 实在不知道类型可以使用T或者代替 MapString, T subMap parserToMap(array[i]); 4.8 抛出业务异常时异常信息必须考虑多语言禁止中文硬编码 错误示例 if (!save) { throw new SystemException(“保存业务属性配置失败”); } 对比示例 if(newlyResult0) { // 该异常中获取message时会根据code查询 i18n 配置获取 throw new BusinessI18nException(AccumulatorCalcExceptionDesc.ACC_EXISTS_NEWLY_RESULT); } 4.9 按照正确的格式打印日志 错误示例 logger.info(success: dto); //不符合使用习惯 logger.error(“failed: {}”, exception); // 不会打印异常栈 logger.error(“failed: {}”, exception.getMessage()) // 仅打印异常信息 对比示例logger.info(success : {} , dto); log.error(failed: , exception); //该接口会打印异常栈### 5. 减少重复 #### 5.1 禁止脱离业务实际需要堆砌CRUD禁止开发预留、测试、无用的API 说明开发人员开始编写代码时需要有清晰具象化的业务需求和边界而不能基于模棱两可的诉求进行开发。开发阶段对功能进行测试验证时应优先使用单元测试通过编写符合业务诉求的单元测试开发者测试来验证和确保功能实现的正确性而不是在产品代码中留下一些测试、无用的代码。虽然大部分模型最终都会需要CRUD等接口但是按Story开发功能需求时也应该首先聚焦Story包含的实际功能和边界而不是站在开发的角度无脑添加CRUD四个接口如此做容易留下一些实际上不会用到的功能和接口。#### 5.2 减少重复代码出现重复时及时重构 代码中明显存在重复的部分应该及时重构提取公共部分进行共用。框架性的公共代码考虑使用AOP等方式通过切面和注解统一处理。错误示例在每个请求之前需要初始化苍穹平台的请求上下文public SwitchPolicy listPolicies(RequestParam requestParam) {initHcmRequestContext();//... listLogic }public SwitchPolicy createOrUpdate(SwitchPolicy switchPolicy) {initHcmRequestContext();//... createOrUpdateLogic }private void initHcmRequestContext() {RequestContext ctx RequestContext.getOrCreate();if (Objects.isNull(ctx.getAccountId())) {ctx.setAccountId(System.getProperty(requestContext.accountId));}if (Objects.isNull(ctx.getTenantId())) {ctx.setTenantId(System.getProperty(requestContext.tenantId));} }等价示例// 定义为切面通过HcmContext注解进行标注 Slf4j Component Aspect public class HcmContextAspect {Around(annotation(HcmContext))public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {initHcmRequestContext();log.info(Initialized HCM context ... );return joinPoint.proceed();}private void initHcmRequestContext() {// init logic} }#### 5.3 不同分支中存在较多相同逻辑时分支只负责差异部分相同的部分不重复书写。 避免在不同分支中出现太多重复逻辑分支专注于差异的部分公共部分抽取方法。错误示例if (privateBusiness.get(elementTypeCode) null) {SetString privateBusinessSet new HashSet();for (String string : strings) {if (string ! null !string.trim().equals()) {privateBusinessSet.add(string);}}privateBusiness.put(elementTypeCode, privateBusinessSet); } else {SetString privateBusinessSet privateBusiness.get(elementTypeCode);for (String string : strings) {if (string ! null !string.trim().equals()) {privateBusinessSet.add(string);}}privateBusiness.put(elementTypeCode, privateBusinessSet); }等价示例SetString privateBusinessSet Optional.ofNullable(privateBusiness.get(elementTypeCode)).orElse(new HashSet()); for (String string : strings) {if (string ! null !string.trim().equals()) {privateBusinessSet.add(string);} } privateBusiness.put(elementTypeCode, privateBusinessSet);### 6. 推荐工具和表现力较强的API #### 6.1 使用stream接口替换常用的循环操作错误示范boolean isAllow false; if (StringUtil.isNotNull(cities)) {String[] cityArr cities.split(,);for (String city : cityArr) {city city.trim();if (city.equals(tlasApplicationVO.getToResidentLocation())) {isAllow true;break;}} }等价示例boolean isAllow StringUtil.isNotNull(cities) Stream.of(cities.split(,)) .anyMatch(city - city.trim().equals(tlasApplicationVO.getToResidentLocation() ));Stream常用操作附录 | API | 作用| 使用场景| 案例代码| |--|--|--|:--| | map | 映射操作将集合中每个元素转换为其他格式的元素 | 按照用户列表获取每个用户的常驻地 | ListLocation userLocations userList.stream().map(User::getLocation).collect(toList()) | | filter | 按照条件筛选集合中满足条件的元素 |筛选有效账号 |ListUser enabledUsers userList.stream().filter(user - Objects.equals(Y, user.getEnableFlag())).collect(toList()); | | peek |在循环中做额外动作如打日志不改变输入输出 | 打印stream中的处理日志 | userList.stream().peek(user - logUserName(user)).filter(user - isValid(user)).collect(toList()) | | reduce |聚合集合元素/特征如求和 |计算用户列表的工资总额 | Integer totalSalary userList.stream().map(user - user.getSalary()).reduce(0, Integer::sum) | | allMatch | 判断集合中是否每个元素都满足某条件 | 判断是否都是有效用户 | Boolean isAllValid userList.stream().allMatch(user - isValid(user)); | | anyMatch |判断集合中是否有至少一个元素满足条件 |判断是否包含异常用户 | Boolean existAbnormalUser userList.stream().anyMatch(user - isAbnormal(user)); | | Collectors.groupBy|按元素特征分类 |按用户类型进行分类 | MapString, ListUser groupedUser userList.stream().collect(groupingBy(User::getType)); |#### 6.2 guava 和各种 Utils 工具包 guava是google提供的开发工具包在Java8提供Lambda写法之前就已经存在其提供的多种函数式编程接口非常流行。在Java8发布之后许多原有的功能逐渐内置到了JVM中但仍然存在一些方便的工具可供使用。以其集合包还有数学等其他辅助工具包中的一些常用接口举例如下| 接口名 | 功能说明 | 举例 | |--|--| --| | Lists.newArrayList |构造一个List对象可以接受数组其他List或者可变长的Item列表 | ListPerson personList newArrayList(personOne, personTwo); | |Lists.partition | 将List按照指定最大长度拆分为一些小的List | ListListPerson subLists partition(personList, 100); | |Sets.intersection / union |取两个集合的交集 / 并集 |SetInteger answer Sets.intersection(set1, set2); |除guava外还有一些Apache提供的Utils工具包对于一些常见模式的问题提供了接口封装如StringUtilJsonXML等相关的常用工具等。### 7 使用框架能力解决通用问题 #### 7.1 对象转换工具 Mapstruct spring BeanUtils 在不同的层次之间经常需要进行类型转换与其手写转换关系不如使用一些常用的工具如MapStructspring BeanUtils等。MapStruct会根据对象结构的字段名称在编译阶段生成转换代码类型安全且自动生成空保护等语句通过声明式配置指定转换关系。spring BeanUtils基于反射机制进行对象属性映射也可以省略一部分手工编写的类型转换代码但是需要注意copyProperties自身的特性如需要类型匹配以及不会忽略null属性等。错误示例UserInfoBean userInfoBean new UserInfoBean(null); userInfoBean.setUid(user.getUid()); userInfoBean.setEmployeeNumber(user.getEmployeeNumber()); userInfoBean.setEmail(user.getEmail()); userInfoBean.setEmployeeType(user.getEmployeeType()); userInfoBean.setCn(user.getCn()); 等价示例Mapper(componentModel spring) public interface UserMapper {UserInfoBean toBean(User user) }#### 7.2 使用框架Validator进行参数校验减少手动实现 请求参数的非空性有效性长度范围取值范围校验等属于常用的框架级校验一般应该借助框架工具来控制而不需要手动编写代码逐个字段进行手动校验错误示例public Boolean submitVisaToDo(SubmitVisaAndSalaryTaxDto submitVisaAndSalaryTaxDto) {VisaInfoDto visaInfoDto submitVisaAndSalaryTaxDto.getVisaInfoDto();// 签证数据基础非空校验if (visaInfoDto.getCategoryCode() null) {throw new ResultException(I18nConstant.VISA_CATEGORY_NULL);}if (StringUtil.isNullOrEmpty(visaInfoDto.getTypeCode())) {throw new ResultException(I18nConstant.VISA_TYPE_NULL);}if (StringUtil.isNullOrEmpty(visaInfoDto.getComplianceApproval())) {throw new ResultException(I18nConstant.SALARY_TAX_COMPLANCE_APPROVAL_NULL);}if (!StringUtil.isNullOrEmpty(visaInfoDto.getDescription()) visaInfoDto.getDescription().length() ContractPlanEnum.ONE_THOUSAND.getCode()) {throw new ResultException(I18nConstant.SALARY_TAX_REMIND_BEYOND_ONE_THOUSAND);}//... business logic }等价示例public class VisaInfoDto {/*** 签证大类*/ApiModelProperty(签证大类id)NotBlank(message I18nConstant.VISA_CATEGORY_NULL)private Long categoryCode;/*** 签证类型编码*/ApiModelProperty(签证类型编码)NotBlank(message I18nConstant.VISA_TYPE_NULL)private String typeCode;/*** 是否涉及合格审批*/ApiModelProperty(是否涉及合格审批)NotBlank(message I18nConstant.SALARY_TAX_COMPLANCE_APPROVAL_NULL)private String complianceApproval;/*** 重要提示*/ApiModelProperty(重要提示)Size(max 1000, message I18nConstant.SALARY_TAX_REMIND_BEYOND_ONE_THOUSAND)private String description; }#### 7.3 使用統一异常处理器取代每个API的单独手工处理 后台服务在发生异常时通常需要对异常信息进行一定的处理和包装结构上可与正常相应存在差异。在Spring框架中提供了统一的异常处理机制RestControllerAdvice按照异常类型和code进行统一修饰。无需每个API单独处理一遍。错误示例:Override public BasicResponseString export(PayElementLabelPageDto queryDTO) {try {localExcelExportAssistant.submitExportTask(payrollCalcService.PayElementLabel, queryDTO);return BasicResponse.ok();} catch (ApplicationException e) {log.error(export payElementLabel error:, e);return BasicResponse.error();} }等价示例Slf4j Provider Named(applicationExceptionHandler) public class ApplicationExceptionHandler implements ExceptionMapperApplicationException {Overridepublic Response toResponse(ApplicationException exception) {log.error(A ApplicationException occurred during the request process:, exception);return Response.status(Response.Status.BAD_REQUEST).type(application/json;charsetUTF-8).entity(BasicResponse.error()).build();} }#### 7.4 使用Builder模式构造对象 builder模式提供了一种可联连续设置属性的构造对象方式可以较方便的将属性值构造成对象且避免了临时变量的多次出现。错误示例PageDTO pageDTO new PageDTO(); pageDTO.setPageNo(curPage); pageDTO.setPageSize(pageSize);等价示例 PageDTO pageDto PageDTO.builder.pageNo(curPage).pageSize(pageSize).build(); 注意使用Lombok注解Builder时会生成全参构造器覆盖默认的无参构造器如果需要保留无参构造器应叠加NoArgsConstructor注解一起使用 7.5 使用Lombok注解生成模板代码 Lombok相关的注解可以在编译期自动生成一下常用的模板代码如构造函数getter/setter等能有效减少模板代码。 错误示例 public class PageDTO implements Serializable { private static final long serialVersionUID 1211673654467855785L; private Integer pageNo 1; private Integer pageSize 15; public PageDTO() { }public Integer getPageNo() {return this.pageNo; }public void setPageNo(Integer pageNoTemp) {this.pageNo pageNoTemp; }public Integer getPageSize() {return this.pageSize; }public void setPageSize(Integer pageSizeTemp) {this.pageSize pageSizeTemp; }} 等价示例 Getter Setter public class PageDTO implements Serializable { private static final long serialVersionUID 1211673654467855785L; private Integer pageNo 1; private Integer pageSize 15; } 说明添加Data注解时除了生成getter/setter外还会生成包含所有属性的equals和hashCode方法在对象属性较多接近1000个左右时会无法编译。一般而言仅需要Getter/Setter而不需要进行对象比较时可以只添加Getter/Setter注解而不是直接使用 Data。 7.6 使用和参考IDE提示进行必要的简化和重构 说明Intellij是一个非常智能的IDE在源代码中会给出诸多优化建议和提示如使用灰色文字表示没有被用到的变量/参数使用黄色背景给出一些优化建议等。鼠标停留在提示的部分IDE会给出相应的说明使用AltEnter会给出对应的修改建议等价于鼠标点击浮出的灯泡按钮。IDE提示的范围非常广不一一展开称述编写代码时务必参考IDE进行一些必要的优化举例如下 错误示例 // 集合类已经自己扩充了forEach接口无需转换为stream便可遍历 resultDtos.stream().forEach // IDE 提示可以使用Lambda写法省略临时形参 batchPersonList.forEach(batchList - save(batchList)); // IDE 提示可以使用anyMatch写法 public static boolean isValidState(int flag) { for (PaymentMethodEnum value : PaymentMethodEnum.values()) { if (flag value.getFlag()) { return true; } } return false; } 说明Intellij中还包含许多功能强大的插件代码检查、统计、生成等插件等不展开具体说明。 8 注释的使用 8.1 废弃的代码直接删除不要通过注释标记废弃 说明用于测试的代码直接放到测试类中写成单元测试用例不要遗留在产品代码中弃用的代码直接删除不要以注释/标注的方式遗留在代码中 错误示例 //本地测试放开 // public void doGet(HttpServletRequest req, HttpServletResponse resp) { // logger.info(“----------local—test—start------------”); // AutoRetentionDataService autoRetentionDataService SpringContextUtil.getBean(AutoRetentionDataService.class); // autoRetentionDataService.asyncExecute(); // logger.info(“----------local—test—end--------------”); // } 8.2 减少过多不必要的注释使用单元测试用例描述复杂代码的行为 存在于代码中的注释初衷是对代码进行说明但是一般的开发习惯中对于编译错误运行错误更为关注而对于说明性的文档通常难以时时确保其正确和及时更新注释极易腐化。因此应该将精力花在编写可执行可校验的单元测试代码上而非撰写过多说明性注释。 错误示例 //1、法人实体为发薪公司 // 1.1、查看法人实体Legal Entity Code(companyCode)在配置列表里 // 1.2、满足1 则查看COA对应的组织属于国内 // 1.3、则Legal Entity Code(companyCode)作为发薪公司 if(isHasLegalEntity isHasCoa){ result companyCode; //2、coa为发薪公司 // 2.1、查看法人实体Legal Entity Code不在配置列表里 // 2.2、则查看COACOA作为发薪公司 }else if(!isHasLegalEntity){ result orgCoa; //3、不识别发薪公司 // 3.1、查看法人实体Legal Entity Code(companyCode)在配置列表里 // 3.2、COA对应的组织不属于国内 }else{ } 等价示例 Test public void should_use_company_code_as_payment_company_when_coa_is_chinese_org() { // 场景先关的上下文准备 assertEquals(“test_company_code”, extractedMethod(someCondition)); } Test public void should_use_coa_as_payment_company_when_legal_entity_is_not_configured() { // 场景先关的上下文准备 assertEquals(“test_coa”, extractedMethod(someCondition)); } Test public void should_use_empty_payment_company_when_legal_entity_is_not_configured_and_coa_is_not_chinese() { // 场景先关的上下文准备 assertNull(extractedMethod(someCondition)); } 8.3 禁止在产品代码中添加仅用于测试的main方法 测试代码应该和产品代码严格区分禁止在产品代码中添加静态main方法用于测试。使用产品代码中的main方法测试不容易自动化也存在污染产品代码的风险需要单元测试时应该将测试用例代码放在test目录下 错误示例 public static void main() { LocalDateTime start LocalDateTime.of(2022,7,01,12,20,21); LocalDateTime end LocalDateTime.of(2022,8,29,12,20,21); Date date1 LocalDateTimeToDate(start); Date date2 LocalDateTimeToDate(end); System.out.println(“工作日:” getTotalWorkdaysNum(date1, date2)); }
http://www.hkea.cn/news/14563355/

相关文章:

  • 网站建设得花多少钱住房城乡建设部网站主页
  • 做pc端网站市场装修公司十大排名北京哪家好
  • 采购网站建设wordpress制作主题
  • 白山做网站注册公司需要啥资料
  • 网站建设大型沈阳哪个公司可以做网站
  • 网站做百度口碑什么是网络营销型网站
  • 网站快速优化排名推荐关键词优化一般收费价格
  • 怎么做网站推广电话如何设计一个高端网站简洁大方大气
  • 网站设计与制作说明网站广告位一般多少钱
  • 如何搭建平台运营体系重庆seo薪酬水平
  • 需要做网站建设和推广注册网站显示lp或设备超限怎么办
  • 建设个人网站ip农产品电子商务网站建设
  • 网站售后维护十大it教育培训机构排名
  • 个人工商注册查询网站专业微信网站
  • 大气的网站首页做网站界面的软件
  • 写资料的网站有哪些内容标签云小工具 wordpress nofollow
  • wordpress客户端APP企业seo解决方案
  • 长春网站建设翻译深圳做电子工厂的网站
  • 网站推广 方法js网页制作代码大全
  • 吕梁建设机械网站网站建设责任分工
  • 网站开发亿玛酷1专注电子商务师证报考官网
  • 哪个网站可以做问卷调查网站怎么弄实名制认证
  • 哪能建设网站网站备案去哪备案
  • 兰州新站点seo代理在哪里买域名
  • 坪山网站建设多少钱网站版块模板
  • 网站备案号是什么50款软件app免费下载大全
  • 网站php源码长沙网站建设价格
  • 岳阳网站建设制作drupal与wordpress
  • 我们做网站 老公弟弟也跟着做网站建设 万网 域名
  • 西安网站推广wordpress黄页