·设为首页收藏本站📧邮箱修改🎁免费下载专区📒收藏夹👽聊天室📱AI智能体
DZ插件网 门户 网站安全 查看内容

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!

2025-1-18 04:31| 发布者: 𝕷𝖎𝖑𝖏𝖆𝖈𝖐| 查看: 65032| 评论: 0

摘要: mall学习教程官网:macrozheng.com1. 背景DDD 向来以高门槛而文明,他内部提出了非常多且抽象晦涩难懂的概念,比如实体、值对象、领域服务、领域事件、聚合根、工厂、仓库、应用服务等,第一批涌入人员很多被这些概 ...

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!9088 作者: 来源: 发布时间:2025-1-18 04:31

mall学习教程官网:macrozheng.com

1. 背景


DDD 向来以高门槛而文明,他内部提出了非常多且抽象晦涩难懂的概念,比如实体、值对象、领域服务、领域事件、聚合根、工厂、仓库、应用服务等,第一批涌入人员很多被这些概念击退,少数坚持下来爱好学习的人继续往深处走,迎接他们的是更多的概念,比如 CQRS、六边形架构的内六边形&外六边形、输入适配器、输出适配器、防腐层、开放主机……

少数异常坚韧者熬了无数次通宵,终于将这些概念搞明白。一边感慨设计的精妙,可以形成科学且高度结构化的解决方案。一边又在摇头,叹息落地实现的难度,自己融会贯通已经这么艰难,还怎么奢求整个团队能步调一致。

追求到手真的是一场空吗?

这个问题在很长一段时间内一直困扰着我,按高度结构化进行开发,成本太高,很多关键的类和扩展点自己都没有办法记牢。不按结构化进行开发,代码就会失控,各种逻辑耦合在一起,几千甚至上万行代码的方法慢慢涌现,项目逐渐走向失控。

直到我将 结构化、标准化、模版化 这三个概念放在一起考虑,才真正豁然开朗。
  1. 结构化:DDD、CQRS 给出的解决方案都是高度结构化的方案,每个组件的边界和职责清晰明了,组件间的交互关系都有明确的规则。
  2. 标准化:在结构化的基础上,每个组件都具备高度的标准化。尽管承载的业务流程不同,但每个组件的设计都遵循同样的规则。
  3. 模版化:标准化意味着会有大量重复逻辑(不是重复代码),这些重复逻辑在开发手里就是 复制-粘帖-稍作修改。

既然是重复工作那就应该由机器完成!

2. 目的


目的非常明确:
  1. 降低概念的记忆成本,让初级开发不在惧怕 DDD。
  2. 统一规范,业务流程、组件设计在团队内保存高度一致。
  3. 提升开发效率,逻辑重复部分交由机器完成,提升开发效率。

这或许是一个对你有用的开源项目,mall项目是一套基于 SpringBoot + Vue + uni-app 实现的电商系统(Github标星60K),采用Docker容器化部署,后端支持多模块和微服务架构。包括前台商城项目和后台管理系统,能支持完整的订单流程!涵盖商品、订单、购物车、权限、优惠券、会员、支付等功能!
  • Boot项目:https://github.com/macrozheng/mall
  • Cloud项目:https://github.com/macrozheng/mall-swarm
  • 视频教程:https://www.macrozheng.com/video/

项目演示:
新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!7880 作者: 来源: 发布时间:2025-1-18 04:31

3. 功能介绍

3.1. Maven 脚手架


Maven 脚手架主要实现整个项目的结构高度统一,降低新项目构建成本。

使用以下命令,可快速创建符合公司规范的项目:
mvn archetype:generate  -DarchetypeGroupId=com.geekhalo.lego -DarchetypeArtifactId=services-archetype -DarchetypeVersion=0.1.39-plugin_demo-SNAPSHOT  -DgroupId=com.geekhalo -DartifactId=user -Dversion=0.1.39-plugin_demo-SNAPSHOT

该命令行是基于 Maven 的构建工具,用于生成项目骨架。具体来说,这个命令执行的是 archetype 插件的 generate 目标,用于创建一个预定义项目结构的模板实例。

参数解释如下:
  • -DarchetypeGroupId=com.geekhalo.lego: 指定要使用的原型(archetype)所在的组ID,这是一个自定义的 Maven 组织标识符,对应于提供项目的骨架模板的组织或团体。
  • -DarchetypeArtifactId=services-archetype: 指定要使用的原型的工件ID,这是特定于该组织下用于生成新项目的模板名称。
  • -DarchetypeVersion=0.1.39-plugin_demo-SNAPSHOT: 设置所用原型版本,这里是一个快照版本号,表明它可能在开发过程中频繁更新。
  • -DgroupId=com.geekhalo: 为将要生成的新项目设置组ID,这是新项目所属的Maven组织标识符。
  • -DartifactId=user: 设置新项目的工件ID,即新项目的名字。
  • -Dversion=0.1.39-plugin_demo-SNAPSHOT: 设置新项目的初始版本号,与原型版本保持一致,同样使用了一个快照版本。

综上所述,这条命令的作用是在本地通过Maven生成一个新的项目结构,该项目是基于 com.geekhalo.lego 组下的 services-archetype 模板,并且初始化时设置的项目信息是 groupId=com.geekhaloartifactId=user,以及 version=0.1.39-plugin_demo-SNAPSHOT

命令执行完成后,你便可以看到新增符合公司规范的 user 模块:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!2447 作者: 来源: 发布时间:2025-1-18 04:31

这个项目是一个用户服务,它被划分为多个模块:
  • user-domain:包含了用户服务的核心领域模型和领域逻辑。它是六边形架构中的核心层,不直接依赖于外部系统或技术栈。
  • user-infrastructure:包含了用户服务的具体实现细节和技术栈相关的代码。例如,数据库访问层、消息队列客户端等。
  • user-app:实现了用户服务的应用逻辑。它依赖于其他模块(如 user-domainuser-infrastructure)来完成业务功能。
  • user-api:定义了用户服务对外提供的接口,也就是服务契约,包括 基于Feign的RPC契约 和 基于RocketMQ的消息契约。
  • user-feign-service:如果用户服务需要提供给其他微服务调用,那么这里会定义 Feign 服务接口。
  • user-feign-client:是用户服务对外提供的 SDK,它提供了对用户服务的简单易用的 API 接口,使得其他服务能够快速地集成和调用用户服务的功能。
  • user-bootstrap:启动用户服务的引导程序。它通常包含 Spring Boot 的启动类和一些配置文件。

在根目录下,有两个重要的文件:
  • pom.xml:Maven 项目的配置文件,用于管理所有子模块的依赖关系和构建过程。
  • README.md:项目的说明文档,通常包括项目简介、如何运行、如何开发等内容。

结构没有对错,不同的公司存在不同规范,这块不是关注的重点。

3.2. 自定义 Idea 插件


有了项目骨架后,接下来的重点就是业务开发。通过自定义 idea 插件,可以将规范融合到插件内,保障规范落地的同时,大幅降低开发成本。

3.2.1. 创建聚合根和视图模型


聚合根是DDD中最为重要的一个概念,也是承接业务逻辑的最小单元。

日常开发基本都是围绕聚合根进行的,对此 idea 很多功能都是围绕聚合根进行构建。

让我们使用插件新建一个聚合根 “BasicUser” 用于存储用户的基本信息。在 domain 模块下的 basic 包上点击右键,选择 lego 菜单下的 “创建 聚合根” 功能,具体如下:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!4239 作者: 来源: 发布时间:2025-1-18 04:31

在弹出的对话框中填入 聚合根类名为“BasicUser”,其他保存默认,详见:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!8129 作者: 来源: 发布时间:2025-1-18 04:31

点击左上角的 View,切换到视图模型配置:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!1862 作者: 来源: 发布时间:2025-1-18 04:31

点击 “OK” 按钮,观察项目变化:Domain 模块:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!2251 作者: 来源: 发布时间:2025-1-18 04:31

Infrastructure 模块:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!6646 作者: 来源: 发布时间:2025-1-18 04:31

App 模块:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!6348 作者: 来源: 发布时间:2025-1-18 04:31

创建一个简单的 BasicUser 聚合根,插件为我们生成一系列文件。这些文件之前都需手工完成,浪费了大量时间。

从设计上,项目采用 CQRS 进行设计,需要同时应对简单和复杂两个场景。换个说法就是:
  1. 业务通常从一个简单场景开始,需要满足快速开发的要求。
  2. 随着迭代的增加复杂性也随之增加,此时可以在不影响架构设计的前提下快速升级架构。

对于简单场景,推荐使用共享存储的 CQRS 架构,具体如下:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!4295 作者: 来源: 发布时间:2025-1-18 04:31

如果写操作和读操作两者差距巨大,推荐使用标准的 CQRS 架构,具体如下:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!2997 作者: 来源: 发布时间:2025-1-18 04:31

简单介绍完背景后,看框架帮我们生成了什么:
  1. 基于 DDD 的写流程
    1. BasicUser:这是用户服务的核心领域对象,它包含了用户的属性信息以及与之相关的业务逻辑。作为领域聚合根,它可以确保数据的一致性和完整性,并且控制了对用户状态的修改操作。
    2. AbstractBasicUserEvent:一个抽象事件,表示用户服务中发生的一些重要事件。这些事件可能会触发用户服务的状态变化或者引发其他行为。具体的事件类型可以通过继承该抽象类来实现。
    3. BasicUserCommandRepository:这是用户服务的命令存储库,负责处理对用户对象的创建、更新和删除等操作。它通常会将这些操作持久化到数据库或其他存储介质中。
    4. JpaBasedBasicUserCommandRepository:是用户服务的命令侧存储库的一个具体实现,它使用 JPA(Java Persistence API)来操作数据库。这种实现方式可以让开发者更专注于业务逻辑,而无需关心底层的数据访问细节。
    5. BasicUserCommandApplication:这是用户服务的命令侧应用服务,它封装了用户服务的业务逻辑,并协调各个组件(如领域对象、存储库等)的工作。它接收来自客户端的请求,执行相应的业务逻辑,并返回结果。
  2. 基于 View 的读流程
    1. BasicUserView:是用户服务的查询侧视图模型,它包含了用户的基本信息,但不会包含任何业务逻辑。它的主要作用是在查询时提供快速响应的服务,以满足高并发读取的需求。
    2. BasicUserQueryRepository:这是用户服务的查询侧存储库,负责处理对用户视图模型的查询操作。它可以从数据库、缓存或者其他快速的数据源中获取数据。
    3. JpaBasedBasicUserQueryRepository:这是用户服务的查询侧存储库的一个具体实现,它使用 JPA(Java Persistence API)来操作数据库。这种实现方式可以让开发者更专注于业务逻辑,而无需关心底层的数据访问细节。
    4. BasicUserQueryApplication:这是用户服务的查询应用服务,它封装了用户服务的查询逻辑,并协调各个组件(如视图模型、存储库等)的工作。它接收来自客户端的查询请求,执行相应的查询逻辑,并返回结果。

idea 插件帮我们完成了大部分工作,快速生成共享存储的 CQRS 业务代码骨架。

3.2.2. 创建聚合根方法


有了聚合根后,我们需要在聚合根上添加业务方法。在 BasicUser 类上右键选择 lego 下的 创建聚合根方法,如图所示:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!7748 作者: 来源: 发布时间:2025-1-18 04:31

在弹窗中填入方法名为:create,如图所示:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!699 作者: 来源: 发布时间:2025-1-18 04:31

点击“OK”按钮,会有如下变化:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!8000 作者: 来源: 发布时间:2025-1-18 04:31

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!239 作者: 来源: 发布时间:2025-1-18 04:31

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!9958 作者: 来源: 发布时间:2025-1-18 04:31

自动生成信息如下:
  1. 新创建的 create 目录,包含流程中的核心组件
    1. CreateBasicUserCommand:这是一个创建用户的命令对象,它包含了创建用户所需的所有参数和信息。当客户端想要创建一个新的用户时,它会发送这个命令对象到用户服务。
    2. CreateBasicUserContext:这是一个上下文对象,它包含了创建用户所需的环境信息和其他辅助信息,可以帮助操作流程更好地维护和共享数据。
    3. BasicUserCreatedEvent:这是一个事件对象,表示用户已经被成功创建。当用户服务接收到 CreateBasicUserCommand 命令并成功创建了一个新的用户后,它会发布这个事件对象。
  2. BasicUser 新增 create 业务方法
    1. 静态的 create 方法,用于使用 Context 对象创建 BasicUser
    2. 实例的 init 方法,用于对 BasicUser 进行核心状态设置、创建并发布领域事件
  3. BasicUserCommandApplication 新增 create 方法
    1. 输入  CreateBasicUserCommand 对象,协调内部组件,完成创建流程

无需编写应用服务的代码,框架会自动生成 Proxy 类来完成全部流程。开发人员只需将精力放在 create 目录下的各种组件即可,组件的协作集成全部由 lego 框架完成。

此时,你就已经具备了一个不含任何业务逻辑的 创建用户 流程。

3.2.3. 创建查询方法


在 BasicUserQueryApplication 右键选择创建 “创建查询方法”,弹出如下对话框:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!4033 作者: 来源: 发布时间:2025-1-18 04:31

我们选择分页查询,确定后,自动生成:
@QueryServiceDefinition(
        repositoryClass = BasicUserQueryRepository.class,
        domainClass = BasicUserView.class
)
@Validated
public interface BasicUserQueryApplication {
    // 分页查询方法
    Page<BasicUserView> pageOf(@Valid PageByStatus query);
}

打开 PageByStatus 类,完善信息如下:
@NoArgsConstructor
@Data
public class PageByStatus{
    // 使用 status 字段进行过滤
    @FieldEqualTo("status")
    private UserStatus status;
    // 分页信息
    private Pageable pageable;
    // 排序信息
    private Sort sort;
}

此时什么都不需要做,你便拥有了一个检索接口。

其中 PageByStatus 为 QueryObject,通过 注解 和 特定类型的字段声明查询能力:
  1. @FieldEqualTo("status") 标明该字段将用于与 status 进行过滤
  2. Pageable 类型的字段为分页信息,可以指定页码和每页大小,完成快速分页
  3. Sort 类型的字段提供排序信息,用于对数据进行排序

3.2.4. 其他支持


除了生成骨架代码外,框架对核心组件也提供了支持。
3.2.4.1. 通用枚举

选择创建枚举,弹出如下对话框:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!6353 作者: 来源: 发布时间:2025-1-18 04:31

点击确定,自动生成枚举和Jpa 转化器,如果使用 MyBatis 也可以选择生成 TypeHandler。

UserStatus 代码如下:
public enum UserStatus implements CommonEnum {
    ;
    // code 为枚举的唯一标识
    private final int code;
    // 枚举描述信息
    private final String descr;

    UserStatus(int code, String descr){
        this.code = code;
        this.descr = descr;
    }
    @Override
    public int getCode() {
        return this.code;
    }

    @Override
    public String getDescription() {
        return this.descr;
    }
}

UserStatusConverter 代码如下:
// 基于枚举的 Code 完成持久化处理
@Converter(autoApply = true)
public class UserStatusConverter
       extends CommonEnumAttributeConverter<UserStatus> {
   public UserStatusConverter(){
       super(UserStatus.values());
   }
}
3.2.4.2. 上下文工厂

选择创建上下文工厂,弹出以下弹窗:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!990 作者: 来源: 发布时间:2025-1-18 04:31

点击“OK” 自动生成 CreateBasicUserContextFactory 如下:
@Component
@Slf4j
public class CreateBasicUserContextFactory
        extends AbstractSmartContextFactory<CreateBasicUserCommand, CreateBasicUserContext> {

    public CreateBasicUserContextFactory(){
        super(CreateBasicUserCommand.class, CreateBasicUserContext.class);
    }

    @Override
    public CreateBasicUserContext create(CreateBasicUserCommand cmd) {
        CreateBasicUserContext context = CreateBasicUserContext.apply(cmd);
        return context;
    }
}
3.2.4.3. 聚合根工厂

选择创建聚合根工厂,弹出以下弹窗:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!4307 作者: 来源: 发布时间:2025-1-18 04:31

点击“确定”自动生成 BasicUserFactory 如下:
@Component
@Slf4j
public class BasicUserFactory
        extends AbstractSmartAggFactory<CreateBasicUserContext, BasicUser> {

    public BasicUserFactory(){
        super(CreateBasicUserContext.class, BasicUser.class);
    }

    @Override
    public BasicUser create(CreateBasicUserContext context) {
        return BasicUser.create(context);
    }
}
3.2.4.4. 业务验证器

右键选择“创建业务验证器”,输入类名为:CreateBasicUserPhoneValidator,自动生成代码如下:
@Component
@Slf4j
public class CreateBasicUserPhoneValidator
    extends AbstractBusinessValidator<CreateBasicUserContext> {
    public CreateBasicUserPhoneValidator(){
        super(CreateBasicUserContext.class);
    }
    @Override
    public void validate(CreateBasicUserContext context, ValidateErrorHandler validateErrorHandler) {
        log.info("validate(context) {}", context);
    }
}
3.2.4.5. 结果转换器

右键选择“创建结果转换器”,弹出如下对话框:

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!3014 作者: 来源: 发布时间:2025-1-18 04:31

自动生成代码如下:
@Component
@Slf4j
public class BasicUserKeyConverter
        extends AbstractSmartResultConverter<BasicUser, CreateBasicUserContext, BasicUserKey> {

    public BasicUserKeyConverter(){
        super(BasicUser.class, CreateBasicUserContext.class, BasicUserKey.class);
    }

    @Override
    public BasicUserKey convert(BasicUser agg, CreateBasicUserContext context) {
        // 添加转换代码
        return null;
    }
}


Github上标星60K的电商实战项目mall,全套 视频教程(2023最新版) 已更新完毕!全套教程约40小时,共113期,通过这套教程你可以拥有一个涵盖主流Java技术栈的完整项目经验,同时提高自己独立开发一个项目的能力,下面是项目的整体架构图,感兴趣的小伙伴可以点击链接 mall视频教程 加入学习。

新来个技术总监,为推行DDD熬夜撸了一套IDEA插件,佩服!3905 作者: 来源: 发布时间:2025-1-18 04:31

整套 视频教程 的内容还是非常完善的,涵盖了mall项目最佳学习路线、整体框架搭建、业务与技术实现全方位解析、线上Docker环境部署、微服务项目学习等内容,你也可以点击链接 mall视频教程 了解更多内容。

推荐阅读

  • 69K Star!这是我见过最强的开源电商系统 !!
  • Github标星60K!一套完整的项目实战教程来了,主流Java技术一网打尽!
  • 看了我项目中购物车、订单、支付一整套设计,同事也开始悄悄模仿了...
  • 订单系统就该这么设计,稳的一批!
  • 支付系统就该这么设计,稳的一批!
  • 权限系统就该这么设计,稳的一批!






上一篇:投行Jefferies迎来强援!前华兴资本高管开启新征程
下一篇:小红书引流方式,每天询单1000加

鲜花

握手

雷人

路过

鸡蛋

评论

您需要登录后才可以发表言论 登录立即注册
关闭

站长推荐上一条 /1 下一条

AI智能体
投诉/建议联系

discuzaddons@vip.qq.com

未经授权禁止转载,复制和建立镜像,
如有违反,按照公告处理!!!
  • 联系QQ客服
  • 添加微信客服

联系DZ插件网微信客服|最近更新|Archiver|手机版|小黑屋|DZ插件网! ( 鄂ICP备20010621号-1 )|网站地图 知道创宇云防御

您的IP:3.141.24.158,GMT+8, 2025-4-19 05:52 , Processed in 0.131450 second(s), 43 queries , Gzip On, Redis On.

Powered by Discuz! X5.0 Licensed

© 2001-2025 Discuz! Team.

关灯
扫一扫添加微信客服
QQ客服返回顶部
返回顶部