云巧组件如何实现代码架构设计可视化

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 在项目搭建完成进行了N个迭代之后,往往因为需求的变化以及设计的缺陷导致领域模型、接口、数据库设计等和最开始的时候大为不同,架构设计需要保鲜会花去大量的时间。有没有一种办法可以实时反应项目的各种技术设计呢?就像Swagger一样,代码自动生成文档。我们采用了静态代码扫描的方案,通过代码来反应真实的技术设计,这就是《云巧工坊-应用素描》的功能。

在项目搭建完成进行了N个迭代之后,往往因为需求的变化以及设计的缺陷导致领域模型、接口、数据库设计等和最开始的时候大为不同,架构设计需要保鲜会花去大量的时间。有没有一种办法可以实时反应项目的各种技术设计呢?就像Swagger一样,代码自动生成文档。我们采用了静态代码扫描的方案,通过代码来反应真实的技术设计,这就是《云巧工坊-应用素描》的功能。

《应用素描》提供了领域模型、数据模型、接口信息的详细信息查看功能,还提供了模型与模型之间的关系,表与表之间的关系图,是一个快速了解现有项目设计的好帮手。

使用方式

一、项目引入

<dependencies>    ...
<dependency><groupId>com.aliyun.gts.yunqiao</groupId><artifactId>yunqiao-boot-starter-arch-annotation</artifactId><version>${yunqiao-boot.version}</version></dependency>    ...
</dependencies>x



二、注解使用

2.1 领域模型注解

根据 领域驱动开发的理论(DDD),领域模型分为3中类型:

  1. ValueObject(值对象):没有唯一标识只是代表一些列属性的对象,比如
importcom.aliyun.gts.yunqiao.arch.annotation.domain.ValueObject;
/*** 表示一个点*/@ValueObjectpublicclassPoint {
/*** x 坐标*/privatedoublex;
/*** y 坐标*/privatedoubley;
}
  1. Entity(实体):有唯一标识,可以根据唯一标识获取到的唯一的对象,比如
importcom.aliyun.gts.yunqiao.arch.annotation.domain.Entity;
/*** 地址*/@Entity(identity="addressCode")
publicclassAddress {
/*** 地址编码*/privateStringaddressCode;
/*** 省*/privateStringprovince;
/*** 市*/privateStringcity;
/*** 区*/privateStringarea;
}
  1. Aggregate(聚合根):聚合根是一种特殊的实体,它除了有唯一标识,还聚合了很多其他实体和值对象,相当于数据库表中的主表,比如
importcom.aliyun.gts.yunqiao.arch.annotation.domain.Aggregate;
/*** 用户*/@Aggregate(identity="userId")
publicclassUser {
/*** 用户ID*/privateStringuserId;
/*** 用户名*/privateStringname;
/*** 年龄*/privateintage;
/*** 用户住址*/privateAddressaddress;
}
  1. Context(限界上下文):把高内聚相关的一些聚合根、实体、值对象划分到一起的一种分类,一般在java里就是一个package(包)。
// package-info.java@Context(code="user", name="用户域")
packagecom.aliyun.gts.x.user;
importcom.aliyun.gts.yunqiao.arch.annotation.domain.Context;
  1. DomainService(领域服务):把不太适合在领域模型中编写的,但又和领域模型相关的一些方法放到独立的对象中,称之为领域服务,在贫血模型中,所有方法都是在领域服务中的,比如:
importcom.aliyun.gts.yunqiao.arch.annotation.domain.DomainService;
/*** 用户领域服务*/@DomainService(User.class)
publicclassUserDomainService {
/*** 创建用户*/publicUsercreateUser(...) {...}
}
6.DomainRepository(领域仓储):持久化领域模型的对象,一般为数据库操作对象,称之为领域仓储,比如importcom.aliyun.gts.yunqiao.arch.annotation.domain.DomainRepository;
/*** 用户领域仓储*/@DomainRepository(User.class)
publicinterfaceIUserDomainRepository {
/*** 保存用户*/voidsave(Useruser);
}



把 yunqiao-boot-starter-arch-annotation 引入项目后,就可以使用它提供的注解对领域模型进行标记,上面示例中的

  • @ValueObject 对值对象进行标记
  • @Entity(identity="") 对实体进行标记,其中 identity 标识该实体的唯一标识的属性名称
  • @Aggregate(identity="") 对聚合根进行标记,其中 identity 标识该实体的唯一标识的属性名称
  • @Context(code="", name="") 在package-info.java文件中对package进行标记,其中code为该限界上下文的唯一标识,name为该限界上下文的名称。
  • @DomainService(value=Class) 对领域服务进行标记,其中value为聚合根的类,表示该服务为哪一个聚合根服务。
  • @DomainRepository(value=Class) 对领域仓储进行标记,其中value为聚合根的类,表示该仓储为哪一个聚合根进行持久化操作。

2.2 数据模型注解

复用 Mybatis-Plus 的 @TableField、@TableId、@TableName 用来标记 Data Object。除此之外,添加了以下注解,以更全面的描述数据模型的结构。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited@Documentedpublic@interfaceTableExt {
Index[] indexes() default {};
PrimaryKeyprimaryKey() default@PrimaryKey(columns= {});
Stringcharset() default"utf8";
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited@Documentedpublic@interfaceTableFieldExt {
booleanunique() defaultfalse;
booleannotNull() defaultfalse;
booleanautoIncrement() defaultfalse;
StringdefaultValue() default"";
intlength() default-1;
}
@Target({})
@Retention(RetentionPolicy.RUNTIME)
public@interfaceIndex {
IndexColumn[] columns();
Stringname();
booleanunique() defaultfalse;
}
@Target({})
@Retention(RetentionPolicy.RUNTIME)
public@interfacePrimaryKey {
IndexColumn[] columns();
}
@Target({})
@Retention(RetentionPolicy.RUNTIME)
public@interfaceIndexColumn {
enumIndexColumnOrder {
UNDEFINED,
ASC,
DESC,
    }
Stringname();
IndexColumnOrderorder() defaultIndexColumnOrder.UNDEFINED;
intlength() default-1;
}

Example

@TableExt(charset="gb2312", primaryKey=@PrimaryKey(
columns=@IndexColumn("id")
),
indexes= {
@Index(name="idx_1", columns=@IndexColumn("field1")),
@Index(name="uk_1", columns= {@IndexColumn(value="field2", length=100),
@IndexColumn(value="field1", order=IndexColumn.IndexColumnOrder.DESC)})
    })
@TableName(value="tableName", schema="schemaName")
publicclassMybatisPlusDataObject {
privatestaticfinalStringDUMMY="DUMMY";
@TableId(value="ID", type=IdType.AUTO)
privateLongid;
@TableField(exist=false)
privateStringnotExistField;
@TableField@TableFieldExt(unique=true, notNull=true, autoIncrement=true, defaultValue="1234", length=1024)
privateStringfield1;
@TableField("the_second_field")
privateStringfield2;
}


2.3 其他支持的注解

控制器(Rest API)标记

兼容 Spring MVC。通过 @Controller 或 @RestController 标记类是一个控制器类;通过 @RequestMapping、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping,标记方法是一个对外的 API。

AppService 标记

通过 @AppService 标记类是一个应用服务类(此注解继承了 Spring 的 @Service 注解,故无需再重复使用 Spring 的注解);应用服务类下所有的 public 方法为应用服务的行为。

Mapper 标记

复用 Mybatis-Plus 的 Mapper<T> 接口(BaseMapper 扩展了 Mapper),用以标记 mapper 以及其服务的数据模型;mapper 接口的所有方法为 mapper 的行为。


实现原理

Java语法解析使用的是开源库 javaparser,javaparser 可以把Java源代码解析成一颗语法树,然后提供各种回调接口来有序遍历这棵树。例如遍历一个文件里所有定义的类和获取类里面的方法定义:

voiditerateClassOrInterface(CompilationUnitcompilationUnit) {
compilationUnit.accept(newVoidVisitorAdapter<Void>() {
@Overridepublicvoidvisit(ClassOrInterfaceDeclarationn, Voidarg) {
super.visit(n, arg);
List<MethodDeclaration>methods=c.getMethods();
            }
    }, null);
}

javaparser 解析一个文件成为语法树是非常消耗性能的,所以不能频繁的去调用 parse 方法去解析文件,但是也不能把所有的语法分析逻辑写在一个回调里,那么就非常适合使用责任链模式来对不同业务的分析逻辑进行解耦

最后把解析后的结构化数据交给前端页面进行可视化渲染展示,就可以实现代码即文档了。

目录
相关文章
|
3月前
|
数据采集 机器学习/深度学习 大数据
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
这篇文章详细介绍了C3D架构在行为检测领域的应用,包括训练和测试步骤,使用UCF101数据集进行演示。
94 1
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
|
3月前
|
消息中间件 存储 Java
RocketMQ(一):消息中间件缘起,一览整体架构及核心组件
【10月更文挑战第15天】本文介绍了消息中间件的基本概念和特点,重点解析了RocketMQ的整体架构和核心组件。消息中间件如RocketMQ、RabbitMQ、Kafka等,具备异步通信、持久化、削峰填谷、系统解耦等特点,适用于分布式系统。RocketMQ的架构包括NameServer、Broker、Producer、Consumer等组件,通过这些组件实现消息的生产、存储和消费。文章还提供了Spring Boot快速上手RocketMQ的示例代码,帮助读者快速入门。
|
4月前
|
负载均衡 5G 网络性能优化
深入解析LTE(长期演进技术)的基本架构及其关键组件
深入解析LTE(长期演进技术)的基本架构及其关键组件
612 2
|
3月前
|
存储 分布式计算 API
大数据-107 Flink 基本概述 适用场景 框架特点 核心组成 生态发展 处理模型 组件架构
大数据-107 Flink 基本概述 适用场景 框架特点 核心组成 生态发展 处理模型 组件架构
135 0
|
2月前
|
监控 前端开发 数据可视化
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
@icraft/player-react 是 iCraft Editor 推出的 React 组件库,旨在简化3D数字孪生场景的前端集成。它支持零配置快速接入、自定义插件、丰富的事件和方法、动画控制及实时数据接入,帮助开发者轻松实现3D场景与React项目的无缝融合。
200 8
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
|
2月前
|
SQL 数据采集 分布式计算
【赵渝强老师】基于大数据组件的平台架构
本文介绍了大数据平台的总体架构及各层的功能。大数据平台架构分为五层:数据源层、数据采集层、大数据平台层、数据仓库层和应用层。其中,大数据平台层为核心,负责数据的存储和计算,支持离线和实时数据处理。数据仓库层则基于大数据平台构建数据模型,应用层则利用这些模型实现具体的应用场景。文中还提供了Lambda和Kappa架构的视频讲解。
263 3
【赵渝强老师】基于大数据组件的平台架构
|
2月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
43 3
|
3月前
|
机器学习/深度学习 网络架构 计算机视觉
目标检测笔记(一):不同模型的网络架构介绍和代码
这篇文章介绍了ShuffleNetV2网络架构及其代码实现,包括模型结构、代码细节和不同版本的模型。ShuffleNetV2是一个高效的卷积神经网络,适用于深度学习中的目标检测任务。
121 1
目标检测笔记(一):不同模型的网络架构介绍和代码
|
2月前
|
存储 安全 Java
系统安全架构的深度解析与实践:Java代码实现
【11月更文挑战第1天】系统安全架构是保护信息系统免受各种威胁和攻击的关键。作为系统架构师,设计一套完善的系统安全架构不仅需要对各种安全威胁有深入理解,还需要熟练掌握各种安全技术和工具。
172 10
|
3月前
|
SQL 存储 分布式计算
大数据-157 Apache Kylin 背景 历程 特点 场景 架构 组件 详解
大数据-157 Apache Kylin 背景 历程 特点 场景 架构 组件 详解
51 9
下一篇
开通oss服务