首页 > 其他分享 >DDD项目落地之充血模型实践

DDD项目落地之充血模型实践

时间:2023-08-07 10:45:39浏览次数:53  
标签:聚合 落地 模型 实体 充血 save 行为 DDD

背景:

充血模型是DDD分层架构中实体设计的一种方案,可以使关注点聚焦于业务实现,可有效提升开发效率、提升可维护性;

1、DDD项目落地整体调用关系

调用关系图中的Entity为实体,从进入领域服务(Domin)时开始使用,直到最后返回。

2、实体设计

充血模型是实体设计的一种方法,简单来说,就是一种带有具体行为方法和聚合关联关系的特殊实体;

关于实体设计,需要明白的关键词为:领域服务->聚合->聚合根->实体->贫血模型->充血模型

聚合与聚合根:

聚合是一种关联关系,而聚合根就是这个关系成立的基础,没有聚合根,这个聚合关系就无法成立;

举个例子,存在3个实体:用户、用户组、用户组关联关系,这3个实体形成的关联关系就是聚合,而用户实体就是这个聚合中的聚合根;

实体:

定义在领域层,是领域层的重要元素,从领域划分到工程实践落地,都应该围绕实体进行,DDD中的实体和数据库表不只是1对1关系,可能是1对多或者仅为内存中的对象;

贫血模型:

实体不带有任何行为方法,也不带有聚合关联关系,作用基本相当于值对象(ValueObject),仅作为值传递的对象,和传统三层项目架构中的实体具有相同作用,不建议使用。补充说明:一般我们使用的DTO就可以被当做是值对象

充血模型:

实体中带有具有行为方法和聚合关联关系,行为方法是说create、save、delete等封装了一类可以指代行为的方法,比如在用户实体对象中具有用户组实体的引用,这样当我们需要操作用户组时,只通过用户实体进行操作就可以。

工程实践中,建议采用充血模型,好处是隐藏胶水代码,提升代码可读性,使关注点聚焦于业务实现。

充血模型在实践中的问题:

行为代码量过多,导致实体内部臃肿膨胀,难以阅读,难以维护,对于这种问题,我们需要根据实体行为的代码量多少来采取不同的解决方案。

解决方案:

场景1:行为不会导致实体臃肿的情况下,在实体中完成行为定义

public CooperateServicePackageConfig save() {    
    // 直接调用基础设施层进行保存
    cooperateServicePackageConfigRepository.save(this);    
    return this;
}

场景2:行为导致实体臃肿的情况下,采用外部定义行为的方式,核心思想是借助其他类实现行为代码定义,将臃肿代码外移,保留干净的实体行为:

1)创建工具类,将某个实体中的行为定义其中,实体负责调用该工具类

public CooperateServicePackageConfig save() {    
    // 将处理过程放在工具类中
    ServicePackageSaveUtils.save(this);   
    return this;
 }

2)创建新实体,将该实体的使用场景明确至某个细分行为,比如一个聚合根(ExampleEntity)的保存可能涉及到5个实体的保存,那么我们定义一个ExampleSaveEntity实体,专门用来处理该聚合下的保存行为

实践经验:

1、关于spring bean注入:充血模型在实体中使用静态注入方法实现。例:

private LabelInfoRepository labelInfoRepository = ApplicationContextUtils.getBean(LabelInfoRepository.class);

2、充血模型的实体序列化,排除非必要属性,在一些redis对象缓存时可能会用到。例:

// 使用注解排除序列化属性
@Getter(AccessLevel.NONE)
private LabelInfoRepository labelInfoRepository = ApplicationContextUtils.getBean(LabelInfoRepository.class);



// 使用注解排除序列化属性
@JSONField(serialize = false)
private ServicePackageConfig servicePackageConfig;
// 使用注解排除序列化 get 方法
@Transient
@JSONField(serialize = false)
public static CooperateServicePackageRepositoryQuery getAllCodeQuery(Long contractId) {    
    CooperateServicePackageRepositoryQuery repositoryQuery = new CooperateServicePackageRepositoryQuery();    
    repositoryQuery.setContractIds(com.google.common.collect.Lists.newArrayList(contractId));    
    repositoryQuery.setCode(RightsPlatformConstants.CODE_ALL);   
     return repositoryQuery;
}

3、利用Set方法建立聚合绑定关系。例:

public void setServiceSkuInfos(List<ServiceSkuInfo> serviceSkuInfos) {    
    if (CollectionUtils.isEmpty(serviceSkuInfos)) 
    {        
        return;    
    }    
    this.serviceSkuInfos = serviceSkuInfos;    
    List<String> allSkuNoSet = serviceSkuInfos
                                .stream()
                                .map(one -> one.getSkuNo())
                                .collect(Collectors.toList());   
     String skuJoinStr = Joiner.on(GlobalConstant.SPLIT_CHAR).join(allSkuNoSet);    
     this.setSkuNoSet(skuJoinStr);}

作者:京东健康 张君毅

来源:京东云开发者社区

标签:聚合,落地,模型,实体,充血,save,行为,DDD
From: https://www.cnblogs.com/jingdongkeji/p/17610817.html

相关文章

  • 以物联网数据中台实现智慧城市系统集成落地
    近年来,随着工业物联网技术的发展与经济政策的引导,工业物联网逐渐形成集成落地的经营模式,单一的物联网产品供应逐渐减少,越来越多厂家通过自身开发或强强联合实现物联网系统的集成,提供硬件与软件一体化的解决方案。在智慧城市领域,关系到智慧园区、智慧交通、智慧能源、智慧水务等多个......
  • automate-dv 基于dbt 的data vault 2.0 落地工具
    automate-dv基于dbt的datavault2.0落地工具,包装了不少方便的宏,可以方便我们呢进行datavault2.0数据仓库建模理论的实际落地功能企业级保障支持datavault的hub,links,satelintes以及一些扩展(方便使用)元数据驱动的代码生成dbt包配置支持多平台支持,支持多种数据库平......
  • 云原生在工业互联网的落地及好处!
    什么是工业互联网?工业互联网(IndustrialInternet)是新一代信息通信技术与工业经济深度融合的新型基础设施、应用模式和工业生态,通过对人、机、物、系统等的全面连接,构建起覆盖全产业链、全价值链的全新制造和服务体系,为工业乃至产业数字化、网络化、智能化发展提供了实现途径,是第四......
  • 【快应用】adbutton如何直接下载广告而不跳落地页再下载
    ​ 【关键词】原生广告、adbutton、下载 【问题背景】快应用中的原生广告推出了adbutton组件来直接下载广告app,在使用的时候,点击adbutton按钮的安装文案,不是直接下载广告app,而是跳转到落地页后直接下载,这种情形该如何解决?相关代码:<template><!--Onlyonerootnode......
  • SaaS销售打法:常规有效的四种SaaS营销策略,落地执行增长突破
    在外面常规的认知中:SaaS营销与常规的营销其实没有什么不同,都在遵循着传统的推广和销售策略,简单来说就是将自己的产品卖给更多的用户,从而换取利润。SaaS营销策略但是SaaS产品与其他产品不同的地方在于它本身是没有实体的,并不能实实在在的把握在手里,正是因为这样的产品性质使得它对......
  • python coding style guide 的快速落地实践——业内python 编码风格就pep8和谷歌可以
    pythoncodingstyleguide的快速落地实践机器和人各有所长,如codingstyle检查这种可自动化的工作理应交给机器去完成,故发此文帮助你在几分钟内实现codingstyle的自动检查。1.有哪些著名的PythonCodingStyleGuidePEP8https://www.python.org/dev/peps/pep-0008/发明Python语言......
  • 抖音引流微信的广告推广投放方案梳理(自制落地页)
    主要功能说明:需要在抖音直播下投放自己的广告落地页面,用户在抖音视频或者直播间,进入我们的落地页,引导用户添加公司的企业微信,并需要记录用户的相关信息(如unionid,昵称,头像,直播间名称,广告点击id),按照要求进行广告上报。主要有两种链路模式:一种模式是:抖音——落地页——企微自动客......
  • 领域设计的贫血模型和充血模型
    在领域实体Dao中,实体可以设计为贫血模型和充血模型。贫血模型只包含见到的get和set方法,不包含业务逻辑,是简单的POJO,所有的业务逻辑都放在service层。这种模型并不是面向对象的,和对象相关以来的逻辑被解耦到了业务层,优点是模型很简单,缺点是service层的逻辑负责繁重。充血模型包......
  • 【完结15章】React18+TS 通用后台管理系统解决方案落地实战
    课程下载——【完结15章】React18+TS通用后台管理系统解决方案落地实战 提取码:qwu4 给大家分享一套课程——React18+TS通用后台管理系统解决方案落地实战,已完结15章,附源码+笔记。TypeScript是微软开发的一个开源的编程语言,通过在JavaScript的基础上添加静态类型定义构建而成......
  • 记一次公司内部技术分享—DDD
    前言笔者于2021年入职了杭州一家做水务系统的公司,按照部门经理要求,新人需要做一次个人分享(主题随意)。当时笔者对DDD充满了浓厚的兴趣,之前也牛刀小试过,于是就决定班门弄斧Show一下。后来在公司的新项目中,笔者也是大胆启用了DDD,带领团队和DDD来了一场亲密拥抱。尽管该项目最后被......