领域驱动设计(DDD)【3】之事件风暴
文章目录
- 说明
- 一 事件风暴理论知识
- 1.1 事件风暴的核心目标
- 1.2事件风暴的关键步骤
- 1.2.1 准备工作
- 1.2.2 核心流程
- 1.2.3 事件风暴的输出
- 1.3 事件风暴的优势
- 1.4 常见问题
- Q1:事件风暴适合所有项目吗?
- Q2:事件风暴后如何落地?
- Q3:在事件风暴里是否要列出所有的领域事件和命令?
- Q4:各个领域事件需要体现严格的时间顺序吗?
- Q5:每个步骤的颗粒度应该有多大?
- Q6:怎么保存和维护事件风暴的结果?
- Q7:怎么保存领域规则?
- 二 事件风暴实践
- 2.1 事件风暴的第一步:识别领域事件
- 2.2 识别“项目管理”流程的领域事件
- 2.3 识别其他流程的领域事件
- 2.4 关于领域事件的补充说明
- 2.5 事件风暴第二步:识别命令
- 2.6 事件风暴第三步:识别领域名词
- 三 深入理解事件风暴的作用
说明
- 本文学习自极客时间的《手把手教你落地DDD》,仅供学习和交流使用。
一 事件风暴理论知识
- 事件风暴(Event Storming)是DDD中一种高效的协作式建模方法,由 Alberto Brandolini 提出。它通过**领域事件(Domain Events)**作为核心,快速探索业务逻辑,识别聚合、限界上下文等关键元素。
1.1 事件风暴的核心目标
- 快速理解业务:通过事件流梳理业务流程。
- 发现领域模型:识别聚合、实体、值对象等。
- 划分限界上下文:明确系统边界和交互方式。
- 促进团队协作:业务专家、开发人员、架构师共同参与。
1.2事件风暴的关键步骤
1.2.1 准备工作
- 参与者:业务专家、开发人员、架构师等(建议 4-8 人)。
- 工具:白板、便利贴(不同颜色)、马克笔。
- 时间:通常需要 1-3 天的工作坊。
1.2.2 核心流程
- 识别领域事件(Domain Events):表示业务中已发生的事实(过去时态)。示例:订单已创建(OrderCreated)、支付已受理(PaymentReceived)。
- 排序事件流:按时间顺序排列事件,形成业务流程的完整链路。
订单已创建 → 支付已受理 → 库存已扣减 → 物流已安排
。 - 识别命令(Commands):触发领域事件的动作(通常由用户或外部系统发起)。示例:
创建订单(CreateOrder) → 触发 订单已创建(OrderCreated)
- 识别聚合(Aggregates):管理一组相关对象的一致性边界(如
Order
聚合根)。
- 规则:
- 每个命令必须由一个聚合处理。
- 每个事件必须由一个聚合发布。
- 示例:
Order
聚合处理创建订单
命令,发布OrderCreated
事件。
- 识别角色(Actors)与外部系统
- 角色:谁发起了命令?(如用户、管理员、第三方服务)。
- 外部系统:哪些系统参与流程?(如支付网关、物流系统)。
- 划分限界上下文(Bounded Context):将相关事件、聚合划分到独立的上下文中。
- 示例:
订单上下文
:处理订单创建、支付。库存上下文
:处理库存扣减。
- 识别策略(Policies)与规则
- 业务规则:如“支付超时自动取消订单”。
- 策略:通过领域事件触发后续动作(如
PaymentTimeout
触发CancelOrder
)。
1.2.3 事件风暴的输出
- 领域模型:明确的聚合、实体、值对象。
- 限界上下文:系统模块划分。
- 业务流程:事件流与命令的完整映射。
- 协作共识:团队对业务逻辑的统一理解。
1.3 事件风暴的优势
- 高效:快速梳理复杂业务,避免冗长文档。
- 可视化:通过便利贴直观展示逻辑。
- 协作友好:业务与技术人员共同参与。
- 适应变化:易于调整和迭代模型。
1.4 常见问题
Q1:事件风暴适合所有项目吗?
- 适合:业务复杂、需深度领域建模的系统(如金融、电商)。
- 不适合:简单 CRUD 或技术驱动型项目。
Q2:事件风暴后如何落地?
- 转换为 DDD 战术设计(实体、聚合、仓储等)。
- 结合 CQRS、事件溯源(Event Sourcing) 等模式实现。
Q3:在事件风暴里是否要列出所有的领域事件和命令?
- 列出所有领域事件和命令并没有原则上的错误,但这样做会让结果变得繁琐,反而让人抓不住重点。
- 建议:在事件风暴里只列出主要的、足以用于表达和交流领域知识的步骤,如签订合同、生效合同等等。而像修改合同和删除合同这样的步骤是显而易见的,在讨论过程中可以提一下,但不必列出。
Q4:各个领域事件需要体现严格的时间顺序吗?
- 只需要按照大致的顺序,贴出领域事件即可。如果要体现严格的时间顺序,需要用到更复杂的符号,例如条件判断,还有要画更多的连线,会使事件风暴变得非常繁琐。
Q5:每个步骤的颗粒度应该有多大?
-
事务完整性准则
- 当一组操作需要作为原子单元成功/失败时,应合并为单一领域事件
- 示例:合同签订包含「基本信息录入→明细填写→附件上传」三个步骤,若业务要求三者全部完成才算有效合同,则应聚合为「合同已签订」单个事件
-
业务价值导向
- 领域事件应反映对业务状态产生实质影响的关键节点
- 反例:合同草稿自动保存(无业务价值) vs 合同最终提交(触发法务审核)
-
事件消费意义检验
- 每个事件至少应有1个明确的下游消费者(如报表生成、风控系统等)
- 决策树:
- 合同签订案例
步骤 | 独立事件必要性 | 决策依据 | 最终方案 |
---|---|---|---|
1. 录入基础信息 | ❌ | 中间状态无业务价值 | 合并到「合同已签订」 |
2. 填写付款条款 | ✔️ | 触发财务系统预审计 | 「合同条款已确定」 |
3. 上传签字扫描件 | ❌ | 仅作为合同完成的附属条件 | 合并到主事件 |
Q6:怎么保存和维护事件风暴的结果?
- 如果事件风暴的内容最终会反映到用户故事、用例、功能列表等产出物中,而这些产出物会进行维护,那我们就不必专门更新事件风暴的产出物了,只在需要的时候作为一种沟通工具,将电子化的结果作为一种中间产物保存就可以了。但是,如果你的团队并没有用户故事和用例等保存行为需求的方式,那么我建议你对事件风暴进行维护和更新。
- 除了绘图之外,事件风暴也可以用表格的形式来保存
业务流程 | 命令 | 领域事件 | 执行者 | 查询数据 | 领域对象 |
---|---|---|---|---|---|
租户管理 | 添加租户 | 租户已添加 | 管理者 | – | – |
组织管理 | 添加开发中心 | 开发中心已添加 | 人事人员 | 企业 | – |
组织管理 | 添加开发组 | 开发组已添加 | 人事人员 | 开发中心 | – |
组织管理 | 添加直属部门 | 直属部门已添加 | 人事人员 | 企业 | – |
员工管理 | 添加员工 | 员工已添加 | 人事人员 | 所属部门 | – |
员工管理 | 转移员工 | 员工已转移部门 | 人事人员 | 目标部门 | – |
Q7:怎么保存领域规则?
- 领域规则是重要的领域知识,必须妥善保存。在事件风暴的过程里我们已经识别出了一些领域规则,在后续的领域建模阶段,可能还会识别出更多。
- 编辑一个领域规则表,把所有的领域规则都汇总在里面,然后再把领域规则表和领域模型放在一起,作为领域知识的重要组成部分。
规则编号 | 模块 | 规则描述 | 举例 | 影响的主要功能 |
---|---|---|---|---|
R001 | 项目管理 | 任一时刻,一个员工在各个项目上累计的预计投入工作量不能超过 100% | 小王在项目 A 上预计投入 60%,如果现在要把他同时分配到项目 B 上,那么项目 B 上的预计投入工作量不能超过 40% | 为项目分配员工 |
R002 | 工时管理 | 员工只能在被分配的项目上报工时 | 小王被分配到项目 A 上,但没有分配到项目 B,则小王周一可以在项目 A 上报 4 小时,但不能在项目 B 上报工时 | 报工时 |
R003 | 工时管理 | 一个员工一天累计工时不能超过 24 小时 | 小王被分配到项目 A 和 B 上,在周一,在 A 上报了 12 小时,在 B 上报了 13 小时,由于超过 24 小时所以不能通过 | 报工时 |
R004 | 工时管理 | 员工只有在项目有效期内才能报工时 | 小王被分配到项目 A,项目 A 在 8 月 1 日结束,小王想在 8 月 5 日为项目 A 报工时则不能通过 | 报工时 |
R005 | 工时管理 | 工时单位为小时,最小颗粒度为 0.5 小时 | 小王为项目 A 报 4.5 小时,可以通过,但报 4.6 小时,则不能通过 | 报工时 |
二 事件风暴实践
- 准备工作:准备场地、人员、工具,场地可以是较大的会议室或者有一面足够长的墙,人员包括技术人员(架构师、技术经理、测试人员)和业务人员(产品经理)。工具可以使用便利贴或其他电子形式的绘图工具。
2.1 事件风暴的第一步:识别领域事件
- 假设我是产品经理(具有较丰富的DDD经验),你是架构师。我开头和你讲了一遍需求,然后我们开始识别事件风暴的第一步:识别领域事件。
- 领域事件表示的是,业务流程中每个步骤引发的结果。事件风暴的作者认为,从结果入手来梳理需求,比从操作入手,更容易把业务想清楚。事件风暴中的“事件”两个字就来源于领域事件。
- 领域事件的命名,一般是完成时 + 被动语态。比如说,订单已提交。
2.2 识别“项目管理”流程的领域事件
- 首先进行项目管理流程的领域事件。我们各自按照自己的理解,把项目管理中发生的各个领域事件,分别梳理绘制,然后进行讨论,得出最终一致的结果。绘制结果如下:
- 首先,第一个区别,你写的是“客户已创建”,我写的是“客户已添加”。
- 你问我:“业务人员一般会说客户已创建还是客户已添加呢?”
- 我回答你:“一般是说客户已添加,因为从业务的角度,客户本来就是存在的 ,不需要创建,只是把客户资料添加到我们的系统而已”。
- 你表示同意。
- 然后,第二个区别,你写的是“签订合同”,我写的是“合同已签订”。
- “签订合同”是个动作,不是事件。所以达成一致后。
- 接着,第三个区别,你写的是“项目已创建”,我写的是“合同已生效”。我后面还有一步“立项”,应该和你的“项目已创建”是一回事,所以说明我比你多了一步“合同已生效”。
- 你又问:“合同签订以后不是马上就生效了吗,还要有一个额外的生效步骤吗?”
- 我解释说:“合同签订的时候未必马上生效,比如 1 月 1 日签了合同,但合同中可以约定,真正生效是在 2 月 1 日,所以需要一个单独的步骤让合同生效。”
- 然后你又问:“我写了项目已创建,但是你写的是已立项,你这种写法好像和其他的不太一致呀。”
- 我解释说:“虽然我们为领域事件命名的时候,常常用‘什么什么已什么什么’的形式,不过如果业务上已经有约定俗成的术语,我们就直接使用术语,这样更容易和业务沟通。现在业务觉得已立项是一个通用的术语,写成项目已创建反而显得生硬。”
- 在 DDD 中的各种命名,一般都优先使用约定俗成的业务术语。
- 目前讨论统一后的内容:
- 其次,第四个区别,我发现自己漏写了“项目已启动”。然后我们再比较了一下“项目已终止”和“项目已结束”两个说法,觉得“项目已结束”更符合业务术语。而“合同已结束”这一步,咱们俩是一样的。不过我在“项目已结束”前面还多了一个“员工已分配”。
- 于是你又问我:“刚才你讲需求的时候,好像是把员工分配作为一块单独的需求来讲的,不属于项目管理这个流程吧?”
- 我想了想,说:“员工分配背后的业务逻辑有点复杂,所以之前单独拿出来讲,其实员工分配是项目运作中的一个重要环节,放在项目管理中也没毛病。”
- 你对此表示认可。
- 我又补充了一点:“员工分配到项目的时候,要填入预计的投入工作量的百分比,一个人可以同时上多个项目,但预计的投入百分比总和不能超过 100%。这种逻辑一般叫业务规则,为了避免忘记,咱们也写上吧。”
-
再下一步,你多了一个“客户已终止”。
-
我解释说:“客户可以在系统中长期存在,以便不断挖掘商机,一般不必专门进行终止。理论上说,万一客户破产了,是应该终止,不过目前业务上还没有这个需求,这一点可以以后再考虑。”。 于是,我们把“客户已终止”拿掉了。
-
然后你又发现,我的流程中最后还多了一个“客户经理已更换”。
-
你有点惊讶地问:“可以更换客户经理吗?你刚才好像没说呀。”
-
我说:“可以更换,我刚才忘记说了。”
-
你紧跟着追问:“那么负责合同的销售人员,还有项目经理是不是也可以换呢?”
-
我说:“也可以。”
- 最后,我们把整个流程又仔细检查了一遍。又发现了一个遗漏的领域事件。员工分配到项目上以后,还可以下项目,所以应该有一个“员工已退出”事件。
2.3 识别其他流程的领域事件
- 用上述同样的方法,识别其他流程的领域事件。
2.4 关于领域事件的补充说明
- 不要把技术事件当成领域事件。领域事件一定要是领域专家所关注的,用的是业务术语。像数据库事务已回滚、缓存已命中之类的技术术语,不是领域事件,不在这个阶段讨论。
- 查询功能不算领域事件。领域事件应该是对某样事物产生了影响,并被记录的事情。一般是某个事物的创建、修改和删除。还有一种情况是向其他人或者系统发消息,例如“通知邮件已发送”也算领域事件,因为接收方可能会通过进一步处理来影响某些事物。而像“客户信息已查询”这些就不算领域事件,因为还没有对事物产生实际影响。不过,这并不代表查询功能不重要,查询功能也要以某种方式体现。
2.5 事件风暴第二步:识别命令
- 命令(command)是引发领域事件的操作,可以通过分析领域事件获得。除了识别出命令本身以外,我们通常还要识别出执行命令的角色,以及执行命令要查询的数据。比如说,对于“合同已签订”这个事件,对应的命令就是“签订合同”。这里,在水蓝色的便利贴上写出命令,然后贴在对应的领域事件上方。“签订合同”的操作者是“销售人员”。售人员术语上叫做“执行者”,英文是 actor。把执行者写在小一点的粉色便利贴上,贴在命令上方,如下图:
- 在执行“签订合同”操作时,执行者要先从系统里查出客户信息,才能和这个客户签订合同。这里,“客户”是一种“查询数据”。我们把查询数据写在小一点的绿色便利贴上,也贴在命令上方。
- 按照前面的方法一边讨论,一边识别出所有的命令。
2.6 事件风暴第三步:识别领域名词
- 领域名词是从命令、领域事件、执行者、查询数据里找到的名词性概念。例如,对于签订合同这个命令而言,受到影响的名词性概念是“合同”;类似地,对于合同已签订这个领域事件,是由于“合同”这个名词性概念的状态变化所导致的。
- 识别领域名词的操作步骤可以分成两小步。
- 第一步,挪动上一步的便利贴,把围绕同一个名词的命令、事件、执行者、查询数据摆在一起,分成好几“堆”,贴在墙上。
- 第二步,把领域名词写在大一点的黄色便利贴上,贴在每堆便利贴的中间。
- 所有领域名词识别结果
- 为项目分配员工”和“员工已分配”出现了两次,一次是关于“员工”的,另一次是关于“项目”的。因为这对命令和事件是关于两个名词的,所以抄写了两遍。关于项目的那次,在命令和事件后面加了一个 “2” ,就是同一个概念在图中出现了第二次的意思,这是我们画图时的一个常用技巧,其他有 “2” 的命令和事件也是同理。
三 深入理解事件风暴的作用
- 从整机视角来看,事件风暴是业务人员和技术人员一起协作,捕获行为需求、消化领域知识、形成统一语言的一种方法。
- 领域事件的作用:从代码实现的角度来看,领域事件一般会对应一段代码逻辑,这段逻辑可能会最终改变数据库中的数据。另外,在事件驱动的架构中,一个领域事件可能会表现为一个向外部发送的异步消息。
- 命令的作用:领域建模时,可以通过对命令的走查(walkthrough),细化和验证领域模型。在实现层面,一个命令可能对应前端的一个操作,例如按下按钮;对于后端而言,一个命令可能对应一个 API。
- 命令的执行者:在领域建模时,执行者可能本身就是一个领域对象,也可能是领域对象充当的角色,或者是权限管理中的一个角色。
查询功能不产生领域事件,因此也不会有相应的命令。那么如何保证查询功能不被遗漏呢?
- 实际上,每个查询数据对应着一个查询功能。查询数据是为某个命令服务。系统中可能还有一些单纯的查询功能,并不与某个特定的命令绑定。这些查询功能不会通过事件风暴识别出来,需要单独进行分析。
相关文章:
领域驱动设计(DDD)【3】之事件风暴
文章目录 说明一 事件风暴理论知识1.1 事件风暴的核心目标1.2事件风暴的关键步骤1.2.1 准备工作1.2.2 核心流程1.2.3 事件风暴的输出 1.3 事件风暴的优势1.4 常见问题Q1:事件风暴适合所有项目吗?Q2:事件风暴后如何落地?Q3…...
3.10 坐标导航
1.编写代码 新建文件nav_clienr.cpp编写代码 #include<ros/ros.h> #include<move_base_msgs/MoveBaseAction.h> #include<actionlib/client/simple_action_client.h>typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBas…...
TensorFlow 安装与 GPU 驱动兼容(h800)
环境说明TensorFlow 安装与 GPU 驱动兼容CUDA/H800 特殊注意事项PyCharm 和终端环境变量设置方法测试 GPU 是否可用的 Python 脚本 # 使用 TensorFlow 2.13 在 NVIDIA H800 上启用 GPU 加速完整指南在使用 TensorFlow 进行深度学习训练时,充分利用 GPU 能力至关重要…...
WPF调试三种工具介绍:Live Visual Tree、Live Property Explorer与Snoop
WPF调试工具详解:Live Visual Tree、Live Property Explorer与Snoop 1. Live Visual Tree (实时可视化树) 简介 Live Visual Tree是Visual Studio内置的WPF调试工具,允许开发者在应用程序运行时检查可视化树结构,查看控件的层次关系及其状态。…...
用OBS Studio录制WAV音频,玩转语音克隆和文本转语音!
言简意赅的讲解OBS Studio解决的痛点 随着AI技术的快速发展,语音克隆与文本生成语音技术越来越受欢迎。无论你想要制作个人虚拟主播,还是给自媒体视频配音,拥有高质量的原始音频都是关键。本文详细教你使用免费且功能强大的软件——OBS Stud…...
5.3 VSCode使用FFmpeg库
一、VSCMake 1.1 使用ffmpeg动态库 项目目录结构: ./ ├── 3rdparty # 第三方依赖库 │ └── ffmpeg_4.4.1 │ ├── include # 头文件 │ ├── lib # 静态库库 │ └── share ├── build # 编译目…...
【Datawhale组队学习202506】零基础学爬虫 02 数据解析与提取
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言2.1 概述2.2 re 解析2.3 bs4 解析2.4 xpath 解析总结 前言 Datawhale是一个专注于…...
[muduo] ThreadPool | TcpClient | 异步任务 | 通信测试
第九章:线程池(ThreadPool) 在第八章《TcpServer》中,我们了解到muduo::net::TcpServer通过EventLoop线程池处理入站连接。 这些EventLoop线程主要负责网络I/O:套接字读写和定时器处理,由Poller和Channel…...
探索 Vue 替代方案
Vue vs React vs Angular 在快速迭代的前端世界,Vue、React和Angular三大框架的竞争从未停止。2025年的今天,它们各自进化出了怎样的面貌?让我们深入剖析它们的核心差异,助你做出明智的技术选型。 Vue.js 完整的基于组件的UI框…...
大模型的开发应用(十二):RAG 与 LlamaIndex基础
这里写目录标题 1 LlamaIndex 简要介绍1.1 核心价值1.2 核心组件1.3 核心流程1.4 为什么要用 LlamaIndex?1.5 典型应用场景1.6 与类似工具对比1.7 安装1.8 学习资源 2 文档解析与 Document 对象2.1 示例文件与代码2.2 Document 对象的核心特性2.3 在 RAG 工作流程中…...
Java面试题025:一文深入了解数据库Redis(1)
欢迎大家关注我的JAVA面试题专栏,该专栏会持续更新,从原理角度覆盖Java知识体系的方方面面。 一文吃透JAVA知识体系(面试题)https://blog.csdn.net/wuxinyan123/category_7521898.html?fromshareblogcolumn&sharetypeblogco…...
Web攻防-XSS跨站Cookie盗取数据包提交网络钓鱼BEEF项目XSS平台危害利用
知识点: 1、Web攻防-XSS跨站-手工代码&框架工具&在线平台 2、Web攻防-XSS跨站-Cookie盗取&数据提交&网络钓鱼 演示案例-WEB攻防-XSS跨站-Cookie盗取&数据提交&网络钓鱼&Beef工具 1、XSS跨站-攻击利用-凭据盗取 条件:无防…...
(LeetCode 面试经典 150 题) 169. 多数元素(哈希表 || 二分查找)
题目:169. 多数元素 方法一:二分法,最坏的时间复杂度0(nlogn),但平均0(n)即可。空间复杂度为0(1)。 C版本: int nnums.size();int l0,rn-1;while(l<r){int mid(lr)/2;int ans0;for(auto x:nums){if(xnums[mid]) a…...
71、单元测试-Junit5简介
71、单元测试-Junit5简介 # JUnit 5 简介 JUnit 5 是 Java 平台上最流行的单元测试框架之一,是 JUnit 的重大升级版本,引入了许多新特性和改进,旨在提供更现代化、灵活和强大的测试体验。 ## 主要组成部分 JUnit 5 由三个模块组成:…...
IEC61850 一致性测试中的 UCA 测试
一、IEC61850 与 UCA 的关系背景 标准演进:IEC61850 是电力系统自动化领域的国际通信标准,其发展与美国 UCA(User Communications Architecture)标准密切相关。2001 年,UCA 国际用户组织与 IEC 合作,将 UC…...
ProtoBuf:proto3 语法详解
🌈 个人主页:Zfox_ 🔥 系列专栏:ProtoBuf 在语法详解部分,依旧使⽤项⽬推进的⽅式完成讲解。这个部分会对通讯录进⾏多次升级,使⽤2.x表⽰升级的版本,最终将会升级如下内容: 不再打…...
博图SCL语言GOTO语句深度解析:精准跳转
在SCL编程中,**GOTO语句**是控制流程的底层工具,它允许程序无条件跳转到指定的**标签位置**。虽然现代编程中较少使用,但在特定工业场景下仍能发挥独特价值。 GOTO语句核心机制 基本语法结构 // 定义标签 <标签名>: // 跳转指令 GOTO…...
面试题-在ts中有两个类型,一个是a,一个是b,这两个联合起来就是c,如何实现联合
在 TypeScript 中,若要将两个类型 a 和 b 联合成一个新类型 c,可以使用 联合类型(Union Type) 或 交叉类型(Intersection Type),具体取决于你的需求: 一、联合类型(Unio…...
Mac电脑-触摸板增强工具-BetterTouchTool
BetterTouchTool mac 触摸板增强工具,允许用户使用各种手势来控制其计算机。 Bettertouchtool mac是一个小而高效的macOS应用程序,旨在帮助您为手势定义快捷方式。 此外,Bettertouchtool可用于使用常规鼠标和键盘快捷键,并提供伴…...
MySQL误删数据急救指南:基于Binlog日志的实战恢复详解
背景 数据误删是一个比较严重的场景 1.典型误操作场景 场景1:DELETE FROM orders WHERE status0 → 漏写AND create_time>‘2025-06-20’ 场景2:DROP TABLE customer → 误执行于生产环境 认识 binlog 1.binlog 的核心作用 记录所有 DDL/DML 操…...
API网关Apisix管理接口速查
🧭 管理接口总体分类(基于 REST API) 资源类别接口路径前缀功能说明路由(Routes)/apisix/admin/routes/{id}定义 HTTP 请求的匹配规则及转发目标服务(Services)/apisix/admin/services/{id}封装…...
React 组件通信
父传子 函数式组件 function Footer(props){const [count,setCount] useState(0)const {name,age} propsconst onClick ()>{setCount(count1)}return (<div><button onClick{()>{onClick()}}>点此1</button><div>{count}</div><di…...
Zephyr 电源管理机制深度解析:从 Tickless Idle 到平台 Suspend 实践
本文系统解析 Zephyr 的电源管理机制,包括 Tickless Idle 模式、系统 suspend/resume 生命周期管理、平台级功耗优化 Hook、自定义设备电源域,以及如何结合低功耗 SoC 实现最小化功耗设计。全文超过 5000 字,适合构建对功耗敏感的 IoT、BLE、…...
clickhouse-server连不上clickhouse-keeper的问题记录
背景 想简单部署一个1 shard 2 replica,1keeper的集群。 有两个虚拟机:192.168.1.3,192.168.1.6。 192.168.1.3:部署1个ck,1个keeper 192.168.1.6:部署1个ck 192.168.1.3和192.168.1.6的ck组成1个shar…...
Python 数据分析与可视化 Day 3 - Pandas 数据筛选与排序操作
🎯 今日目标 掌握 DataFrame 的条件筛选(布尔索引)学会多条件筛选、逻辑运算熟练使用排序(sort_values)提升数据组织力结合列选择进行数据提取分析 🧪 一、列选择与基本筛选 ✅ 选择单列 / 多列 df[&quo…...
Android NDK下载链接及配置版本
Android NDK下载链接及配置版本 https://github.com/android/ndk/releases 在build.gralde里面这样配置ndk具体版本号: android {ndkVersion "27.0.12077973" } Android Studio报错:Could not move temporary workspace () to immutable locat…...
Mac Parallels Desktop Kali 2025 代理设置
Mac Parallels Desktop Kali 2025 代理设置 核心步骤: kali设置桥接wifi 查看kali和主机ip 运行命令ifconfig查看kali ip: mac主机ip: kali设置proxy ip填写主机ip,port为主机proxy端口 enjoy...
Python 的内置函数 hash
Python 内建函数列表 > Python 的内置函数 hash Python 的内置函数 hash() 是一个非常有用的工具函数,主要用于获取对象的哈希值。哈希值是一个固定长度的整数,代表该对象的唯一标识。在 Python 中,hash() 函数常用于字典键值、集合元素等…...
文生视频(Text-to-Video)
🕒 生成时间:每张图大概 10–60 秒(取决于设备) ✅ 二、文生视频(Text-to-Video) 以下项目中,很多都基于 SD 模型扩展,但视频生成复杂度高,生成时间一般 超过 30 秒&am…...
(LeetCode 面试经典 150 题) 80. 删除有序数组中的重复项 II (双指针、栈)
题目:80. 删除有序数组中的重复项 II 思路:左指针 left 类似于指向栈顶的下一个待填的元素,每次遍历只需看当前元素nums[i]和栈顶的下一个元素nums[left-2]是否相等,不等就可以插入栈当中。时间复杂度0(n)。 C版本: …...
【舞蹈】编排:如何对齐拍子并让小节倍数随BPM递减
音的强弱关系 当前划分编排最小单位的代码的分析 📊 代码逻辑分析 ✅ 完整性方面 代码逻辑相对完整,包含了: 结构段落分析(intro, verse, chorus等)强拍时间点提取歌词时间轴处理AI增强的编舞建议生成⚠️ 主要问题 1. 强拍对齐逻辑不够精确 # 当前代码只是简单提取…...
LangGraph--基础学习(工具调用)
本节将详细学习大模型是怎么调用工具的,为什么可以调用工具等等,手写一个工具调用,后续可以通过mcp自己调用即可,没必要自己写,但是学习过程中需要手写,通常怎么使用第三方工具调用呢? import o…...
华为云 Flexus+DeepSeek 实战:华为云单机部署 Dify-LLM 开发平台全流程指南【服务部署、模型配置、知识库构建全流程】
华为云 FlexusDeepSeek 实战:华为云单机部署 Dify-LLM 开发平台全流程指南【服务部署、模型配置、知识库构建全流程】 文章目录 华为云 FlexusDeepSeek 实战:华为云单机部署 Dify-LLM 开发平台全流程指南【服务部署、模型配置、知识库构建全流程】前言1、…...
【appium】2.初始连接脚本配置
连接配置 from appium import webdriver desired_caps {platformName: Android,automationName: UIAutomator2,deviceName: ZTEB880,appPackage: com.taobao.taobao,appActivity: com.taobao.tao.welcome.Welcome,noReset: True }driver webdriver.Remote(http://localhost:…...
磁性传感器在电机控制闭环系统中的反馈作用
磁性传感器的基本原理和类型 基本原理 :磁性传感器是基于磁学原理来检测磁场强度、方向或其他与磁场相关的物理量。常见的磁性传感器有霍尔传感器、磁阻传感器等。霍尔传感器是利用霍尔效应工作的,当电流通过置于磁场中的半导体材料时,在垂直…...
Python:.py文件如何变成双击可执行的windows程序?(版本1)
1、如下.py文件,右键重命名文件后缀名:py改为:pyw 2、修改时,提示如下:不用管点击:是即可 3、之后双击,即可执行python代码文件。 好的,我们来详细介绍一下 Python 的 .pyw 文件。 简…...
Spring Boot + MyBatis + Vue:全栈开发的深度剖析与实践指南
一、技术栈深度剖析 (一)Spring Boot:后端开发的加速器 Spring Boot 是基于 Spring 框架的一个开源 Java 项目,旨在简化基于 Spring 的应用开发。它通过自动配置机制,能够根据项目中添加的依赖自动配置 Spring 和相关…...
学习C++、QT---03(C++的输入输出、C++的基本数据类型介绍)
每日一言 你比想象中更强大,那些咬牙坚持的瞬间,都在雕刻更好的你。 案例:C的输入输出 但是我也会用c语言的方式来回顾c语言的写法,因为两种语言都是密不可分的,所以不能忘记,所以两个一起写 注意点&#…...
八、Redis的主从原理、哨兵
简介: 想要了解Redis的主从原理,首先得认识一个基本的分布式理论-CAP理论。要理解这个理论,其实也非常简单。 CAP理论 C:Consistency、A:Available、P:Partition tolerance 。这是CAP三个字母的全称。C&…...
springboot通过独立事务管理器实现资源隔离与精准控制
安心流转站核心业务模块,为什么!我们考虑这样设计,下面讲讲专用事务管理器的设计与必要性! 一、为什么需要专属事务管理器? 在安心流转站模块中,存在 「多资源混合操作」 和 「业务高敏…...
59-Oracle 10046事件-知识准备
上一篇说到了autotrace,SQL调试时候的获取性能和参数数据,直接用上trace,还有个更全能的工具10046。是不是很多小伙伴会对这么个数字,觉得起名很奇怪,数字起名任性。“10046”本质是Oracle内核事件的随机性技术编号&am…...
2025年渗透测试面试题总结-2025年HW(护网面试) 03(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 2025年HW(护网面试) 03 1. 同源策略(Same-Origin Policy) 2. XSS攻击用途 3. XSS类…...
嵌入式开发之嵌入式系统硬件架构设计时,如何选择合适的微处理器/微控制器?
在嵌入式系统硬件架构设计中,选择合适的微处理器 / 微控制器(MCU/MPU)是关键环节,需从多维度综合评估。以下是系统化的选择策略及核心考量因素: 一、明确应用需求与核心指标 1. 性能需求 处理能力:根据任…...
C++(面向对象编程——继承)
继承基础概念 1.什么是继承? 继承是C三大特性之一;继承是一个已经存在的类的基础上新建一个类,新建的类拥有已经存在的类的特性。主要提现的是代码复用的思想。新的类继承了基类的所有成员变量和成员函数,包括不显示的函数&…...
Unity Shader开发-着色器变体(2)-定义着色器变体
一.定义着色器变体 定义一个着色器变体(Shader Variant)从概念和实现上讲,主要包括以下几个核心部分 1.使用预编译指令来声明变体关键字 关键字是驱动变体生成的“开关”。它们是简单的字符串标识符,用于在 Shader 代码中标记不…...
Cookie和Session的作用和区别
Cookie 客户端持久化保存服务器数据的一种机制(持久化存储就是存硬盘里)。Cookie文件数据为键值对形式,客户端根据服务器域名的不同分别存储Cookie,不同域名的Cookie不同,不会产生冲突。 典型应用场景: 保…...
Redis集群部署终极指南:架构选型、生产部署与深度优化
第一部分:Redis集群技术全景解析 1.1 Redis集群演进史 单机时代(2009-2012):Redis 2.8之前,纯单机模式复制时代(2012-2015):Redis 2.8引入PSYNC改进复制哨兵时代(2015-…...
腾讯云IM即时通讯:开启实时通信新时代
一、引言 在当今数字化浪潮席卷全球的时代,即时通讯已然成为互联网世界中不可或缺的关键元素。无论是个人日常生活中的社交互动,还是企业运营里的高效协作,即时通讯都发挥着举足轻重的作用,已然渗透到人们生活与工作的每一个角落…...
基于Qt的UDP主从服务器设计与实现
概述 一个基于Qt框架实现的UDP主从服务器系统,该系统具备自动主机选举、故障转移和状态同步等关键功能,适用于分布式能源管理系统中的设备通信与协调。 系统核心功能 1. 自动主机选举与故障转移 系统通过优先级机制实现自动主机选举,当主机…...
JVM(8)——详解分代收集算法
JVM 的分代收集算法不是一种具体的垃圾收集算法实现,而是一种指导思想和设计原则,是现代 JVM 垃圾收集器的基石。其核心思想源于对程序运行过程中对象生命周期分布的观察(即弱分代假说)。 核心思想与理论基础:分代假说…...