首页 > 其他分享 >袋鼠云代码检查服务,揭秘高质量代码背后的秘密

袋鼠云代码检查服务,揭秘高质量代码背后的秘密

时间:2023-11-14 10:08:14浏览次数:29  
标签:袋鼠 检查 代码 规则 public searchParam SQL 揭秘


质量是产品的生命线,代码检查是软件开发过程中至关重要的一环,它可以帮助我们发现并纠正潜在的错误,提高软件质量,降低维护成本。

袋鼠云产品中也存在这个问题,由于离线数据开发人员 SQL 水平不一,导致代码书写混乱、SQL 代码运行问题较多。本文将介绍在离线产品中如何利用 SQL 检查规则规范化 SQL 代码,对代码书写问题进行拦截,便于统一管理,用于预防引入需要治理的问题。

通过本文的介绍,我们希望您能够认识到代码检查的重要性,并了解如何通过最佳实践来提高代码质量和开发效率。

何时进行代码规则检查?

SQL 任务在离线产品界面开发完成之后,点击运行的按钮,会先经过代码规则检查,如果代码规则不满足则会提示到用户具体的原因。

数据资产模块内置了 5 种代码检查规则,用户可以根据需要选择性开启。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_SQL

开启后在离线项目管理中可以选择使用的代码规则检查项、生效范围和 SQL 任务类型。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_sql_02

在离线 SQL 任务中去运行一条 SQL 前会根据选择的规则先进行代码检查,如果代码检查不通过则会反馈给用户,用户可以根据实际需要判断要不要执行该 SQL。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_代码检查_03

在数据资产的代码检查时间中可以看到已经触发的检查历史以及相应的统计数据。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_sql_04

如何实现代码检查规则?

在 CodeCheck 包下定义了通用的代码规则检查的接口。

public interface ICheck {
 Result codeCheck(String checkContent, String defaultDb, Integer dataSourceType, Long tenantId, SqlParseInfo sqlParseInfo);
 CodeCheckType getCheckType();
}

分区表查询必须带分区规则为例,会先调用 SQLParser 组件进行 SQL 解析,SQLParseInfo 即为 SQL 解析结果,检查时会先判断 SQL 语句是不是查询语句,如果是则判断查询的表是不是分区表,再判断是否有查询条件,最后判断查询条件中是否包含分区字段来判断是否检查通过。

public class CodeCheckImplType01 extends AbstractCheck {
 private static final Logger LOGGER = LoggerFactory.getLogger(CodeCheckImplType01.class);
 @Autowired
 private DataTableColumnThirdService dataTableColumnThirdService;
 @Autowired
 private DataTableThirdService dataTableThirdService;
 @Override
 public Result codeCheck(String checkContent, String defaultDb, Integer dataSourceType, Long tenantId, SqlParseInfo sqlParseInfo) {
 if (!isQuery(sqlParseInfo.getSqlType())) {
 return Result.buildSuccessResult();
 }
 try {
 MetadataSearchParam searchParam = new MetadataSearchParam();
 searchParam.setDbName(sqlParseInfo.getMainTable().getDb());
 searchParam.setTableName(sqlParseInfo.getMainTable().getName());
 searchParam.setDataSourceType(dataSourceType);
 searchParam.setTenantId(tenantId);
 List<TableDTO> tableDTOS = dataTableThirdService.tableList(searchParam);
 // 获取表信息
 for (TableDTO tableDTO : tableDTOS) {
 List<DataTableColumn> tableColumns = dataTableColumnThirdService.listColumnByTableIds(Lists.newArrayList(tableDTO.getTableId()));
 if (CollectionUtils.isEmpty(tableColumns)) {
 continue;
 }
 List<String> partitionColumnNameList = tableColumns.stream()
 .filter(Objects::nonNull)
 .filter(t -> HavePartitionEnum.have_partition.getPartitionValue().equals(t.getIsPartition()))
 .map(DataTableColumn::getColumnName)
 .collect(Collectors.toList());
 // 非分区表直接返回
 if (CollectionUtils.isEmpty(partitionColumnNameList)) {
 continue;
 }
 if (CollectionUtils.isEmpty(sqlParseInfo.getColumnIdentifierList())) {
 // 没有查询条件则校验失败
 return Result.buildFailedResult(String.format(getCheckType().getCheckResultFormat(), searchParam.getTableName()));
 }
 List<String> columnList = sqlParseInfo.getColumnIdentifierList().stream()
 .filter(c -> StringUtils.equals(c.getDb(), searchParam.getSchemaName()) && StringUtils.equals(c.getTable(), searchParam.getTableName()))
 .map(ColumnIdentifier::getColumn).collect(Collectors.toList());
 boolean disjoint = Collections.disjoint(partitionColumnNameList, columnList);
 if (disjoint) {
 return Result.buildFailedResult(String.format(getCheckType().getCheckResultFormat(), searchParam.getTableName()));
 }
 }
 } catch (Exception e) {
 // 异常情况先通过
 LOGGER.error("code check error, check content: {}, defaultDb: {}, checkType: {}", checkContent, defaultDb, getCheckType().name());
 }
 return Result.buildSuccessResult();
 }
 @Override
 public CodeCheckType getCheckType() {
 return CodeCheckType.TYPE_01;
 }
}

如何自定义代码检查规则?

如果内置的代码检查规则不满足客户的使用场景,客户可以通过上传 jar 的方式自定义代码检查规则。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_SQL_05

自定义代码检查规则使用 SPI 机制加载用户上传的自定义 jar,并在代码检测时调用 CodeCheck 方法,在资源关闭时调用 close 方法,用户需要将配置文件说明中的 jar 依赖自己的项目中。具体如下:

● 创建一个类实现接口

创建一个类实现接口 com.dtstack.assets.spi.codecheck.ICodeCheckClient 并实现 CodeCheck 和 close 方法,书写相关逻辑代码,如果校验通过需要将 CheckResult 对象中 success 设置为 true,失败时设置 success 字段为 false 并设置校验不通过的理由。

package com.dtstack.assets.spi.codecheck;
import java.util.Map;
public interface ICodeCheckClient {
 /**
 * 代码检查
 *
 * @param checkContent 检查内容
 * @param extMap 扩展配置
 * @return 检查结果
 */
 CheckResult codeCheck(String checkContent, Map<String, Object> extMap);
 /**
 * 释放资源, 调用时需要关闭所使用的资源
 */
 void close();
}

· 入参字段解释

– checkContent 为单条 SQL 信息

– extMap 会设置一些平台的属性,包含任务名称、任务类型等

· 出参字段解释

– success 为是否校验通过,必须设置

– checkResult 为校验结果,校验不通过时不能为空

package com.dtstack.demo;
import com.dtstack.assets.spi.codecheck.CheckResult;
import java.util.Map;
public class CodeCheckImpl implements com.dtstack.assets.spi.codecheck.ICodeCheckClient{
 @Override
 public CheckResult codeCheck(String checkContent, Map<String, Object> extMap) {
 // 代码检查相关逻辑
 CheckResult checkResult = new CheckResult();
 checkResult.setSuccess(false);
 checkResult.setCheckResult("校验不通过的理由");
 return checkResult;
 }
 @Override
 public void close() {
 // 关闭相关资源
 }
}

● 在 resource 目录下创建 META-INF/services 目录

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_代码检查_06

● 在 META-INF/services 目录下创建文件

文件名称为 com.dtstack.assets.spi.codecheck.ICodeCheckClient ,文件内容为实现 ICodeCheckClient 接口类的权限定类名。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_SQL_07

文件名称和内容示例:

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_代码检查_08

● 打包当前工程并在数据资产页面注册代码校验规则

不符合条件的 jar 会给出提示。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_sql_09

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_SQL_10

如何加载自定义代码规则对应的 jar ?

我们会为上传的每个规则对应的 jar 初始化一个唯一的自定义 classloader,该 classloader 继承 URLClassLoader 并保证子类加载器优先加载。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_SQL_11

在第一次调用时进行加载并缓存对应的 client。

在用户重新上传或者编辑规则后清除旧的 classloader 和加载的 client 并释放资源。

袋鼠云代码检查服务,揭秘高质量代码背后的秘密_sql_12


标签:袋鼠,检查,代码,规则,public,searchParam,SQL,揭秘
From: https://blog.51cto.com/u_15137832/8361028

相关文章

  • Java复制文件的4种方式及拷贝文件到另一个目录下的实例代码
    尽管Java提供了一个可以处理文件的IO操作类。但是没有一个复制文件的方法。复制文件是一个重要的操作,当你的程序必须处理很多文件相关的时候。然而有几种方法可以进行Java文件复制操作,下面列举出4中最受欢迎的方式。1.使用FileStreams复制这是最经典的方式将一个文件的内容复......
  • VCR库代码示例
    首先,我们需要在代码中添加对VCR库的引用:require'vcr'require'rest-client'然后,我们需要创建一个VCR录制器,以便我们可以记录实际的HTTP请求和响应:VCR.use_cassette('download_video',record::new_episodes)do#下载代码将在这里end接下来,我们需要设置:proxy={然后,我们可......
  • TypeScript 和 needle 库代码示例
    TypeScript和needle库编写的爬虫程序。import*asneedlefrom'needle';import{Request}from'http';constproxyHost='www.duoip.cn';constproxyPort=8000;//创建一个HTTP请求对象constreq=newRequest(',{headers:{&......
  • httrOAuth库代码示例
    #导入httr和httrOAuth库library(httr)library(httrOAuth)#设置服务器,主机为proxy_host<-proxy_port<-proxy_url<-"#设置httrOAuth的客户端ID和客户端密钥consumer_key<-"your_consumer_key"consumer_secret<-"your_consumer_secret"......
  • isomorphic-fetch库代码示例
    isomorphic-fetch库的爬虫程序。//引入isomorphic-fetch库importfetchfrom'isomorphic-fetch';//设置constproxy=;//定义视频URLconsturl=';//使用fetch获取视频数据fetch(url,{method:'GET',headers:{'Accept':'appl......
  • Fetch库代码示例
    importFetch._importFetch.{FetchException,FetchProxyException,FetchTimeoutException}//创建对象valproxy=newFetchProxy)//创建Fetch对象,并传入对象valfetch=newFetch(proxy)//创建请求对象,并传入视频的URLvalrequest=newFetchRequest("")//进......
  • APK代码被混淆,这个混淆怎么理解,会造成什么结果
    APK代码被混淆,通常是指在安卓应用的发布过程中,为了保护代码不被轻易理解或篡改,开发者会使用特定的工具或技术来改变代码的外观,但不改变其功能。这个过程称为“代码混淆”。混淆的结果通常包括:标识符重命名:将变量、方法和类名等标识符改为无意义的字符组合,如将变量名username改为......
  • APK代码被混淆,搜不到字符串,怎么解决?
    当您遇到一个APK文件中的代码被混淆,导致无法搜索到特定的字符串时,可以采取以下几种方法来解决这个问题。这些方法包括使用反编译工具、理解和应对混淆技术,以及可能的自动化脚本处理。以下是详细步骤:1.反编译APK文件首先,需要将APK文件反编译成可读的代码形式。可以使用以下......
  • 阅读以下代码,请选择可以正确打印h1标签宽度的选项( )
    阅读以下代码,请选择可以正确打印h1标签宽度的选项()<template><div><h1ref='h1'v-if="show">nowcoder</h1></div></template><script>exportdefault{data(){return{show:false}},......
  • 博客园cnblogs的代码折叠
    实现折叠的代码如下:<details><summary>查看代码</summary><pre><code>这里写需要被折叠的代码</code></pre></details>效果如下:查看代码这里写需要被折叠的代码参考链接:https://www.cnblogs.c......