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

DDD学习笔记五

模型引力场:聚合

  • 强作用力体现:
    某个领域模型是另一些模型存在的前提,没有前者,后者就失去了生存的意义。
    一组领域模型之间存在关联的领域逻辑,任何时候都不能违反。
    一组领域模型必须以一个完整的、一致的状态呈现给外部,而不能是某个中间彼此不和谐的状态。

  • 当模型之间的相互作用力强到一定程度的时候,将产生质变,必须把它们当作一个整体,我们称之为聚合

  • 聚合是一组相关对象的集合,可以称其为数据修改单元或者事务一致性组合单元。
    每个聚合都有一个根(root)和一个边界(boundary)。
    边界定义了聚合内部包含的内容,
    根则是聚合所包含的一个特定的实体(entity)。

  • 聚合概念的必要性:
    1)保证模型存在的意义。聚合内的成员脱离聚合根的存在是没有意义的,比如支付之于订单。这不是一个技术问题,而是一个领域逻辑问题,领域专家和用户不会在意一个没有订单的支付对象。
    2)时刻保持领域内在逻辑不被违反。这里的关键字是“时刻”,即不允许在任何时候把不和谐的状态暴露给用户。相关逻辑一般体现在聚合根内。
    3)划定事务的合理边界。在某种程度上,划定聚合就是划定事务边界。如果事务范围过大,锁定机制会导致多个用户之间毫无意义的互相干扰,而如果事务范围过小,会产生实时一致性问题,有把不完整的模型状态呈现给客户的风险。并不是强求时刻一致性就好,因为有性能代价,但无视客户体验也并非良策。聚合代表着两者的平衡。
    4)聚合根提供了业务操作入口和界面。前三点偏技术,这一点对领域专家来说可能是最重要的。
    聚合对于使用者来说是一个“整体”,不能把其中的成员当作独立的成员来看待。

  • 聚合内的约束一般归纳为以下6条:
    1)只有聚合根具有全局标识,它最终负责领域内在规则的检查。有标识意味着聚合根必须是一个实体,而不是值对象。聚合根负责校验聚合中的规则而不是其他成员或在聚合外部。
    2)聚合范围内的实体具有本地标识,这些标识不需要全局范围内唯一,保证在聚合范围内唯一即可。为何不需要全局标识呢?这是由第三条约束决定的。
    3)只能通过聚合根才能访问聚合内的其他元素,聚合根是其所在聚合所有模型的唯一操作界面。不要略过订单去操控支付对象,不要忽略车辆而去保养轮胎,不要省掉棋盘去访问棋子,不要不看新闻就去看评论。聚合保证了对象存在的意义,避免产生不符合逻辑的操作。这些例子中,脱离聚合根去访问对象是没有实际意义的。
    聚合根可以把对内部实体的引用传递给外部,但只是临时使用这些引用,而不能一直保持引用。这意味着外部获得的是内部对象的一个副本,对这个副本的修改丝毫不影响聚合内真实的对象。
    4)只有聚合根才能直接通过数据库查询获取,其他对象必须通过遍历关联发现。当然,聚合的获取一般通过工厂和存储库
    5)删除根元素,必须一次删除聚合内所有对象。这个问题在有垃圾回收机制的语言中不用过分操心,因为缺少外部引用,当聚合根被删除之后,其他对象会被自动回收。
    6)当聚合内部任何对象被修改时,整个聚合内的所有规则都必须被满足。这里不是指有延迟的最终一致性,而是任何时间点都不存在中间状态。

  • 7条聚合设计法则
    (1)与生命周期保持一致
    如果一个部分脱离整体后不再有业务意义,那么该部分应当属于一个聚合;如果一个模型脱离了聚合根仍有其业务价值,那么它就不属于该聚合。比如,发动机与汽车虽然存在明显的从属关系,但因为发动机有自己的编号且脱离汽车还会被单独跟踪,所以它不属于汽车这个聚合。当然,是不是一个聚合不会影响汽车和发动机正常的关联关系
    (2)围绕领域内在逻辑
    在定义聚合时,需要识别出满足一个用例共同工作的对象组合,并且这些对象彼此必须时刻保持一致以满足业务用例
    (3)与事务的粒度保持一致
    (4)不滥用聚合
    (5)作用范围宜小不宜大
    大的聚合会影响性能。成员数据在聚合被创建时都需要从数据库中加载,当集合成员快速增长时,对内存的占用也不可忽视
    小的聚合不仅有利于性能,还有助于事务的成功执行,可以减少事务提交的冲突,系统的可用性也获得了提升(不再锁定资源)
    (6)通过标识符引用其他聚合
    聚合是小巧的,但关联是丰富的。一个聚合可以引用另一个聚合的聚合根来完成自己的任务。但被引用的聚合根不应该放在引用聚合的内部,这不符合聚合的规则。另外,在引用聚合根时,应该优先考虑全局唯一标识(ID)而不是通过直接的对象引用
    (7)利用最终一致性更新其他聚合
    聚合内的规则是时刻不能被违反的,但聚合间的规则要弱一些,所以跨越多个聚合的规则不立刻保持一致是可以接受的(容忍时长取决于业务),我们可以应用最终一致性规则来更新其他聚合
    最终一致性意味着不同聚合间的数据在一段时间内会存在一定的不一致状态,但它们最终会保持一致,否则就不符合规则了

  • 实现方法

  • (1)如何限定访问
    尽量不要开放聚合内部成员的可见性为public。如果确实需要引用,也不要开放该属性的设置(set)功能,可以设为私有可见性,从而保护其不被修改。

  • (2)如何验证规则
    验证规则是在聚合根完成的,保证规则的方法就是封装聚合的责任和行为,在对应的业务操作和方法中验证领域内在规则,而不是暴露成员

  • (3)如何同生共消亡
    往往采用工厂方法来实现同生。工厂一次性创建聚合的所有成员,并且按照一定规则组装。工厂可以放置在聚合根内,也可以是一个单独的领域服务。
    不要为聚合成员提供单独的构造函数,理论上也不应将聚合组装的权力交给用户,因为组装体现的是领域逻辑而不是给用户的自由。聚合成员最好只依赖于工厂而被创建,避免被越级使用而产生副作用。
    共消亡机制要用到存储库模式,存储库将只为客户端提供对聚合根的访问,我们无法通过存储库去访问不是聚合根的对象,也就不会越过聚合根获得其成员的引用。
    在有垃圾回收机制的语言中,没有引用的对象会被定时回收,比如Java、C#。当然,也可以在聚合根使用析构函数或实现IDispose接口,来显式释放其他成员占用的资源。

  • (4)实现事务一致性
    第一,不要在一个事务中更新一个以上的聚合。
    第二,聚合作为一个整体,持久化时必须在一个事务中以保证内在的一致性。聚合是存储在一个表或多个表中并不重要,重要的是当聚合被持久化时,需要在单个事务中提交,以确保在持文化失败时,聚合不会以不一致的状态被存储。
    实现事务一致性很大程度上依赖于所采用的持久化技术。ORM(Object Relational Mapping,对象关系映射)框架如Hibernate和NHibernate提供了对几乎一切数据库命令的显式事务的支持。

  • (5)实现最终一致性
    实现最终一致性保证的是聚合间的一致性,而不是聚合内的一致性。常见策略是采用异步方法来处理数据不一致问题,这与本地事务有所区别。虽然异步方法会导致聚合间数据不一致的时间较长,但其实现更为可靠且不会对并发性能产生影响。之所以说更为可靠,是因为当操作失败时通常可以重试,但必须采用kafka、MQ等消息传递技术。
    聚合间的最终一致性可以通过异步领域事件来实现,使用EventBus等事件发布和订阅框架可以很方便地发布和订阅领域事件。

** 模型装配线:工厂**

  • 在DDD中,工厂是生产领域模型的地方,特别是聚合

  • 工厂模式的主要目的是生产对象的实例并提供给调用者

  • 为什么需要工厂
    (1)解耦:分离领域职责与创建工序
    工厂的主要目的是分离模型的领域职责及其复杂的创建工序
    (2)通用语言:让创建过程体现业务含义
    工厂是领域层中承载领域逻辑的对象
    (3)验证:确保所创建的聚合处于正确状态
    在工厂中创建新对象时,可以添加逻辑验证以确保创建出的聚合符合领域内在规则。
    例如,在聚合根账户上创建订单,要满足账户必须有足够的信用额度
    (4)多态:为一种接口生产多个组件
    (5)重建:重建已存储的对象
    基于持久化机制的对象重建一定要封装在工厂之内。
    重建工厂与创建新对象的工厂有以下两个不同点:
    1)创建实体对象时,新对象是生成新的标识符,而重建工厂则是获取已有的标识符ID。
    2)模型或聚合的内在领域逻辑不满足时,新对象工厂可以直接拒绝生成对象,而重建工厂生成的对象违背规则时,需要设计师采用一种纠错机制,比如默认值等策略来处理冲突。

  • 厂址选择
    (1)聚合根上的工厂
    如果往一个聚合内添加元素,可以在聚合根上添加一个工厂方法,这样聚合内部的元素的生成细节,外部就无须关心了。同时,因为聚合的内在原则检查都在聚合根内,所以可以保证添加的元素都符合领域内在规则
    (2)“信息专家”工厂
    信息专家模式是把职责分配给具有完成该职责所需信息的那个模型
    (3)领域服务类工厂
    将工厂单独地构建为领域服务是一种不错的方法,也是最常用的工厂形式
    (4)只需使用构造函数的场合
    是否任何模型的创建都要经过工厂呢?恰恰相反,我们应该优先使用构造函数而不是工厂,因为领域模型并不一定都是复杂对象或聚合。如果在不需要解耦、不需要创建聚合、不需要表达通用语言、没有内在规则或不需要多态的场合,应该直接使用构造函数new,因为构造函数更简单、方便
    若满足以下条件,则可直接选择简单的、公共构造函数。
    对象是值对象,且不是任何相关层次结构的一部分,而且不需要创建对象多态性。
    客户关心的是具体类,而不是只关心接口。
    客户可以访问对象的所有属性,且模型没有嵌套对象的创建。
    构造环节并不复杂,客户端创建代价不高。
    构造函数必须满足工厂的相同规则:创建过程必须是一个原子操作,且能满足领域内在规则。
    (5)厂名选择
    1)选择与领域含义相关的命名,如BookTicket(预订车票)、ScheduleMeeting(安排会议)。
    2)将Create与要创建的类型名连在一起,以此来命名工厂方法,如CreateWhite-Board。
    3)将创建的类型名与Factory连接在一起,以此来命名工厂类型。例如,可以将创建Role对象的工厂类型命名为RoleFactory。
    模型货架:存储库

  • 领域模型要想保持自己的独立性,离不开存储库将其与持久化机制解耦

  • 存储库承担了4个角色:隔离墙、冰箱和菜单、体现通用语言和管理员

  • (1)隔离墙:隔离领域模型与持久化技术,保证领域模型独立性
    存储库模式的第一个意义在于保持领域模型与技术持久化机制的分离。这保证了领域模型的独立性,使模型能够在不受底层技术影响的情况下进行演化,让我们可以独立开发领域模型,无须关注架构的技术细节
    在这里插入图片描述

  • 存储库分为两部分
    1)存储库接口:位于领域层内,既有标准化的方法,如增加和删除,又有体现通用语言的、业务上、特殊的检索需求。
    2)存储库实现:位于基础设施层,实现存储库接口。图6-7是一个典型的依赖倒置架构,领域模型无须关心存储库的实现部分,而只需要和存储库接口打交道即可。

  • 2)冰箱和菜单:保鲜且提供菜肴而不是食材
    存储库要负责所有对象的持久化工作,同时提供这些对象的访问接口。如果把模型比作一道道菜,存储库就是存放这些菜的冰箱,当你下次使用它们时,依然保持着上次放入冰箱的状态。存储库要保证只保存和提供成品菜肴,也就是聚合
    一个聚合提供一个存储库,即一个聚合对应一个存储库,代码实现上也是一对一存在的

  • (3)体现通用语言:让检索请求体现业务含义
    除了通用的接口方法,每个聚合的存储库必须支持通用语言的特定查询。存储库不仅是CRUD接口,还是领域模型的扩展,应当以领域专家的术语来编写,应当基于用例实现来构建查询接口,而不是类似于CRUD数据访问的角度来构建。

  • (4)管理员:集合的统计与汇总
    作为模型仓库,存储库的另一个实用的功能是扮演仓库管理员,给我们提供关于集合的统计信息,比如对象的数量、集合中所有匹配对象的某个数值属性的总和等。此时,存储库提供的方法不再返回一个聚合根,而是一个值对象。对于“最好贴近原始数据进行计算”的计算原则来说,存储库的这个功能非常强大

  • 实现存储库接口时,我们要注意以下几点:
    要把Add()方法实现为幂等,即使向集合重复添加相同聚合(一般由ID判断),实际效果仅为一个聚合实例。
    如果持久化机制支持对对象变化的跟踪,那么它会自动将内存中的更改保存到数据库中,比如Hibernate框架,在存储库接口定义中不需要添加Save()方法。但如果持久化机制不支持对变化的跟踪,则上述接口中需要添加Save()方法,并在领域对象被改变后,显式调用该方法,以使更改在数据库中生效。
    不要在领域模型上维护已更改的标识符,也不要让持久化逻辑干扰领域模型的纯洁性。将跟踪变化的工作交由存储库来处理。

  • 存储库与工厂的设计出发点有些相似,但有区别。:
    1)负责模型生命周期的不同阶段。工厂负责模型生命周期的开始,而存储库管理模型生命周期的中间和结束。工厂的作用之一是重建已存储的对象,这与存储库有些类似,但此时对象还不存在或未成型,因此具有“新建”的含义。而在存储库中的对象,则让用户感觉是一直存在于内存集合中的既有对象。
    2)存储库专注于封装持久化机制,而工厂专注于创建新对象。工厂用数据和领域逻辑来初始化和装配一个复杂的对象(聚合)。新对象创建好之后,需要调用存储库的Add()方法将其添加到存储库中,由存储库负责其在数据库中的存储。
    3)工厂更注重于对象创建的多态机制,而存储库分为两个部分,接口部分更注重符合业务需求和通用语言的支持,实现部分的重点则是对持久化技术的封装。

  • 存储库与数据访问对象的区别
    存储库面向的是内存中的集合方式,而DAO面向数据库表提供CRUD操作。
    存储库的设计更加贴近领域,而DAO中方法的业务意图并不明显。
    存储库接口必须位于领域层内,且只提供聚合根的访问,DAO没有这种约束。

  • 存储库实现的注意事项
    (1)不要提供无条件随机查询接口
    (2)可以像工厂一样在存储库中使用多态,返回子类或实现类
    (3)充分利用存储库接口与实现解耦的特点
    (4)存储库中不要涉及事务

相关文章:

DDD学习笔记五

模型引力场:聚合 强作用力体现: 某个领域模型是另一些模型存在的前提,没有前者,后者就失去了生存的意义。 一组领域模型之间存在关联的领域逻辑,任何时候都不能违反。 一组领域模型必须以一个完整的、一致的状态呈现给…...

CAN报文的发送类型-OnChange、OnWrite、IfActive、Repetition

CAN报文的发送类型分为基本发送类型和混合发送类型两大类 CAN基本发送类型包括Cyclic周期发送、OnChange变化时发送、OnWrite写入时发送和IfActive有效时发送。基本发送类型中的Cyclic称为周期型,而其他3个类型称为事件型(Event)。发送次数是通过定义Repetition重复次数来实…...

神经网络在机器学习中的应用:手写数字识别

机器学习是人工智能的一个分支,它使计算机能够从数据中学习并做出决策或预测。神经网络作为机器学习的核心算法之一,因其强大的非线性拟合能力而广泛应用于各种领域,包括图像识别、自然语言处理和游戏等。本文将介绍如何使用神经网络对MNIST数…...

QT拖放事件之四:自定义拖放操作-利用QDrag来拖动完成数据的传输-案例demo

1、核心代码 #include "Widget.h" #include "ui_Widget.h" #include "MyButton.h"Widget::Widget(QWidget *parent): QWidget...

Spring Boot应用的部署与扩展

Spring Boot应用的部署与扩展 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 引言 Spring Boot作为现代化Java应用的首选框架之一,以其简化的配置…...

Spring底层原理之bean的加载方式八 BeanDefinitionRegistryPostProcessor注解

BeanDefinitionRegistryPostProcessor注解 这种方式和第七种比较像 要实现两个方法 第一个方法是实现工厂 第二个方法叫后处理bean注册 package com.bigdata1421.bean;import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.…...

大数据面试题之Spark(5)

Spark SQL与DataFrame的使用? Sparksql自定义函数?怎么创建DataFrame? HashPartitioner和RangePartitioner的实现 Spark的水塘抽样 DAGScheduler、TaskScheduler、SchedulerBackend实现原理 介绍下Sparkclient提交application后,接下来的流程? Spark的几种…...

springboot笔记示例六:fastjson2集成

springboot笔记示例六:fastjson2集成 本文md下载 https://download.csdn.net/download/a254939392/89491102本文md文档下载地址 #springboot json官方说明 https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-json.htmlsprin…...

VLOOKUP函数在表格的简单运用-两个表匹配

1.什么是VLOOKUP? VLOOKUP是Excel中的一个内置函数,主要用于在区域或表格的首列查找指定的值,并返回该行中其他列的值。它特别适用于跨表格数据匹配 2.函数运用 2.1.这边两个表取名a表和b表,做为我们的实例表。 表格a包含&…...

http.cookiejar.LoadError: Cookies file must be Netscape formatted,not JSON.解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

逻辑操作符

目录 && --- 逻辑与操作符 || --- 逻辑或操作符 && --- 逻辑与操作符 逻辑与操作符有并且的意思,一般用于判断语句中 逻辑与操作符运行规则是都要为真,才会继续执行或计算 360笔试题: 有关前置(--),后置(-…...

Java调用第三方接口的秘籍:技巧、案例与最佳实践

Java调用第三方接口的秘籍:技巧、案例与最佳实践 在Java开发中,调用第三方接口是一项常见的任务。无论是与外部系统交互、集成其他服务,还是调用远程API获取数据,掌握有效的第三方接口调用技巧都是至关重要的。本文将深入剖析Jav…...

【机器学习】机器学习重要方法——深度学习:理论、算法与实践

文章目录 引言第一章 深度学习的基本概念1.1 什么是深度学习1.2 深度学习的历史发展1.3 深度学习的关键组成部分 第二章 深度学习的核心算法2.1 反向传播算法2.2 卷积神经网络(CNN)2.3 循环神经网络(RNN) 第三章 深度学习的应用实…...

计网之IP

IP IP基本认识 不使用NAT时,源IP地址和目的IP地址不变,只要源MAC和目的MAC地址在变化 IP地址 D类是组播地址,E类是保留地址 无分类地址CIDR 解决直接分类的B类65536太多,C类256太少a.b.c.d/x的前x位属于网路号,剩…...

mybatis延迟加载

mybatis延迟加载 1、延迟加载概述 应用场景 ​ 如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。 延迟加载的好处 ​ 先从单表查询、需要时再从关联表去关联查…...

危险!属性拷贝工具的坑!

1. 背景​ 之前在专栏中讲过“不推荐使用属性拷贝工具”,推荐直接定义转换类和方法使用 IDEA 插件自动填充 get / set 函数。 不推荐的主要理由是: 有些属性拷贝工具性能有点差有些属性拷贝工具有“BUG”使用属性拷贝工具容易存在一些隐患&#xff08…...

qt实现打开pdf(阅读器)功能用什么库比较合适

关于这个问题,网上搜一下,可以看到非常多的相关博客和例子,可以先看看这个总结性的博客(https://zhuanlan.zhihu.com/p/480973072) 该博客讲得比较清楚了,这里我再补充一下吧(qt官方也给出了一些…...

在node.js环境中使用web服务器http-server运行html静态文件

http-server http-server是一个超轻量级web服务器,它可以将任何一个文件夹当作服务器的目录供自己使用。 当我们想要在服务器运行一些代码,但是又不会配置服务器的时候,就可以使用http-server就可以搞定了。 使用方法 因为http-server需要…...

前端学习篇一(HTML)

Introduction ##文章内容:使用HBuilder制作一个简单的HTML5网页以此达到学习HTML5 的目的 ##编写内容:1.HTML实现平台 2.HTML简介 3.HTML语言解析 ##编写人:贾雯爽 ##最后更新时间:2024/07/01 Overview Details 一、HTML简介…...

VUE笔记

框架: 框架结构,把很多基础功能已经实现(封装了)。 框架:在基础语言之上,对各种基础功能进行封装,方便开发者,提高开发效率。 举例:操作页面 现在:点击按…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

从实验室到产业:IndexTTS 在六大核心场景的落地实践

一、内容创作&#xff1a;重构数字内容生产范式 在短视频创作领域&#xff0c;IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色&#xff0c;生成的 “各位吴彦祖们大家好” 语音相似度达 97%&#xff0c;单条视频播放量突破百万…...

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot&#xff0c;它能根据上下文补全代码&#xff0c;快速生成常用…...

CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14

什么是 Pattern Matching&#xff08;模式匹配&#xff09; ❝ 模式匹配就是一种“描述式”的写法&#xff0c;不需要你手动判断、提取数据&#xff0c;而是直接描述你希望的数据结构是什么样子&#xff0c;系统自动判断并提取。❞ 你给的定义拆解&#xff1a; ✴ Instead of …...