DDD落地:从携程订单系统重构,看DDD的巨大价值

news2024/11/16 1:34:31

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:

谈谈你的DDD落地经验?

谈谈你对DDD的理解?

如何保证RPC代码不会腐烂,升级能力强?

微服务如何拆分?

微服务爆炸,如何解决?

你们的项目,DDD是怎么落地实操的?

所以,这里尼恩给大家做一下系统化、体系化的梳理,使得大家可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”

也一并把这个题目以及参考答案,收入咱们的 《尼恩Java面试宝典PDF》V135版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,后台回复:领电子书

除了本文,尼恩输出了一个 《从0到1,带大家精通DDD》系列,帮助大家彻底掌握DDD,链接地址是:

《阿里DDD大佬:从0到1,带大家精通DDD》

《阿里大佬:DDD 落地两大步骤,以及Repository核心模式》

《阿里大佬:DDD 领域层,该如何设计?》

《极兔面试:微服务爆炸,如何解决?Uber 是怎么解决2200个微服务爆炸的?》

《阿里大佬:DDD中Interface层、Application层的设计规范》

《字节面试:请说一下DDD的流程,用电商系统为场景》

《DDD如何落地:去哪儿的DDD架构实操之路》

《DDD落地:从腾讯视频DDD重构之路,看DDD极大价值》

《DDD落地:从美团抽奖平台,看DDD在大厂如何落地?》

《美团面试:微服务如何拆分?原则是什么?》

《DDD神药:去哪儿结合DDD,实现架构大调优》

《DDD落地:从网易新闻APP重构,看DDD的巨大价值》

《DDD落地:从阿里单据系统,看DDD在大厂如何落地?》

《DDD落地:有赞的生产项目,DDD如何落地?》

大家可以先看前面的文章,再来看本篇,效果更佳。

另外,尼恩会结合一个工业级的DDD实操项目,在第34章视频《DDD的学习圣经》中,给大家彻底介绍一下DDD的实操、COLA 框架、DDD的面试题。

DDD现在非常火爆,是有其巨大生产价值,经济价值的, 绝不仅仅是一套概念那么简单。

DDD的绝大价值,具体请参见以下视频:

从腾讯视频DDD重构案例,看看DDD极大价值

文章目录

    • 尼恩说在前面
    • DDD在携程用车/租车订单系统重构中的实践
    • 一、案例介绍
    • 二、问题分析
      • 2.1 沟通困难
      • 2.2 业务边界不清晰
      • 2.3 面对业务变化修改困难
    • 三、解决方案
      • 3.1 回归业务本质——挖掘愿景
      • 3.2 高效沟通——利用事件风暴统一语言
      • 3.3 自上而下细化边界——子域划分
      • 3.4 自下而上抽象概念——限界上下文
      • 3.5 挖掘业务变化的瓶颈——上下文依赖关系
    • 四、收益总结
      • 4.1 业务逻辑耦合降低
      • 4.2 团队效率提高
      • 4.3 性能和稳定性提高
      • 4.4 数据一致性
      • 4.5 人力成本大幅下降
    • 五、遇到的问题和方案探索
      • 5.1 领域专家难寻
      • 5.2 业务需求多且急
      • 5.3 团队对DDD理解不深
    • 说在最后
    • 尼恩技术圣经系列PDF

DDD在携程用车/租车订单系统重构中的实践

作者:小白龙,携程资深后端开发工程师,关注架构落地、研发效能领域。

随着历史业务的不断演进和业务场景的日益复杂,携程用车和租车(简称两车)在面对历史技术债务和系统复杂度不断上升带来的理解、维护、迭代难题时,开始寻求更有效的方法来降低复杂度和提升效率。

本文描述了两车如何利用DDD(Domain-driven Design,领域驱动设计)方法论来减轻系统复杂度,以及在重构历史系统过程中所作出的取舍和思考。此案例对于复杂业务场景下的领域驱动设计具有借鉴意义。

一、案例介绍

携程用车订单业务包括接送机、包车、打车等产线,涉及订单状态管理、支付状态管理、供应商订单状态管理、履约状态管理等功能。履约状态关乎司机相关状态,完成订单需结清额外费用。

携程租车订单业务涵盖订单状态管理、支付状态管理、押金扣除记录、供应商订单状态管理、履约状态管理等功能。履约状态主要涉及取还车相关状态。

订单和相关实体如下图所示:

二、问题分析

由于两车业务存在一些差异,为了读者更容易理解,因此将抽取共性问题来说明。

2.1 沟通困难

关于沟通困难,在整个开发过程中,沟通是一个耗时且复杂的过程。需求方需与产品沟通,产品再与研发沟通。研发在开发过程中发现问题需与产品确认,产品则需寻找需求方核实。跨团队沟通更加复杂。以下是一些常见场景:

  • 产品不关心研发的实现,但是觉得需求很简单或者很复杂。
  • 研发开发过程中发现一些忽略的细节需要产品确认,产品要找需求方确认。
  • 历史逻辑没人知道,需求评审的时候无法发现问题,做到最后发现有问题。
  • 跨团队之间不了解对方的业务,需要反复沟通确认。
  • 遇到同一个名词不同的理解导致无效沟通。
  • 一个需求到底该哪个域来实现是我们在实践中经常反复探讨的问题。

例如订单和供应商订单在不同的团队内都叫订单,在沟通中针对“订单”的讨论就会产生歧义。

2.2 业务边界不清晰

设计之初,订单被各调用方当作了对外输出的数据源头,数据需求方只要调订单详情即可获取全量数据,这为以后订单的迭代带来了相当大的隐患。订单在自己的业务模型中加入大量不涉及自身业务的冗余字段,在系统的演进过程中,由于无脑插入他方业务字段使得订单自己也要维护相关的逻辑(解释和修改),导致各方对订单的耦合日益加深,导致订单服务的发布变成高风险行为,甚至一个无关订单业务的相关字段修改也可能导致系统故障。

例如订单上关于供应商的相关数据,用户订单有一份,采购订单也有一份,当采购要修改供应商的相关逻辑时要用户订单也一起修改,而用户订单必须排查和推动相关使用到这个字段的业务方切换替代方案。

2.3 面对业务变化修改困难

随着历史业务迭代,订单中集成了许多非订单关注的核心业务逻辑。例如,历史上发送用户通知是根据订单状态变化触发的。订单需提供所有相关参数,导致核心业务依赖非核心业务。在这种情况下,若需求变更,如重发发送失败的通知,逻辑似乎只能放在订单上,不够优雅。

三、解决方案

3.1 回归业务本质——挖掘愿景

为了解决业务归属问题和明确系统发展方向,避免将资源浪费在非核心功能上,我们需要了解当前项目的本质和目标。因此,我们需要为系统设定一个愿景,这将引导我们在未来的迭代中保持正确的方向。愿景就像是我们的产品定位,它区别于其他系统,也确定了当前系统的边界。

愿景就像是手电筒发出的光,黑暗中的边界就是我们的系统,而光的延伸方向则代表着系统的未来。

有许多方法可以阐述一个愿景,为了降低实施的难度,我们选择采用麦肯锡的“电梯演讲”形式,围绕机遇、挑战、优势和劣势来展开。这个过程中,领域专家和开发团队需要共同进行头脑风暴,这实际上也是领域驱动设计(DDD)统一语言的起点,我们必须在愿景的层面达成一致。

产品名称用户订单管理系统
产品品类一个查看和管理订单平台
描述目标客户或利益相关人的需求或机会1、定后履约的查看和管理
2、流畅: 每个用户有操作需求的节点高度自动化,无需人工处理
3、贴心:想用户所想,在合适的时间告诉用户合适的事情
4、无忧: 减少用户的焦虑,让用户放心的使用我们的服务
阐释产品能够带来的关键价值(或者说购买的理由)为用户提供订单流程管理。
与竞争产品的不同之处

友情提醒

Eric Evans 在他的书中曾提到过一种模式:领域愿景描述(Domain Vision Statement)

“由于一开始项目的模型通常不存在,但是需求是早已定下的重点,为了我们在后续阶段清楚了解系统的价值,以价值作为我们的导向。”

在研究领域愿景声明时,我们发现编写一份合格的文档并非易事。因为它没有明确的规范和套路,Eric 也只是提供了几个案例供我们参考。虽然撰写愿景声明并不复杂,但要达到合格标准仍有一定的门槛。因此,我们选择回归 Eric 的观点:“很多项目团队都会编写‘愿景说明’以便管理。最好的愿景说明会展示出应用程序为组织带来的具体价值。”

3.2 高效沟通——利用事件风暴统一语言

关于统一语言,一个经典的例子便是传话游戏。一句话经过多人的转述,最后可能完全变了一个意思。

为了迅速实现统一语言,我们在订单重构过程中投入了大量时间进行事件风暴。事件风暴有以下几个优点:

  • 事件风暴以业务流程为核心进行讨论,使在场的每一个人都能通过多条流程深入了解业务实体的变化。

  • 事件风暴汇集了“领域专家”,包括产品、开发、测试等团队成员,本质上是一场集合集体智慧的头脑风暴。在事件风暴中,所有人都能达成业务共识。

  • 事件风暴整合了各人的领域知识,是一场领域知识的分享会。

过去,事件风暴主要以线下工作坊的形式开展,以增强参与感。然而,由于成本和线上办公的兴起,我们现在更多地采用在线工作坊。在此推荐两个工具:行知蜂(BeeArt)和可画(Canva),它们都支持多人在线协作。

事件风暴实际上非常简单,就是业务流程+业务用例。将业务流程横向展开,通过用例将业务中的名词状态变化一一列举。色块的大小和颜色可以参考www.eventstorming.com,但只要能统一大家的认知,颜色并非关键。

在实践过程中,我们发现先列举业务中单据的状态变化,再补全触发状态变化的动作和角色,效率会更高。关键是要识别出大家认知中的不同事物相同名词、不同名词相同事物,以便后续建模。

通过事件风暴,我们主要关注以下几种情况:

  • 沟通中那些脱离当前领域就难以理解的词汇;
  • 相同名词,含义不同的;
  • 名词不同,含义相同的。

将以上三种情况涉及的名词动词总结成统一语言表,特别是第三种情况,是我们划分限界上下文的关键依据。例如,在讨论支付单时,我们发现存在两种支付单:一个是包含我们业务的支付单,它需要记录当前支付场景并包含一定的业务规则;另一个是支付平台的支付单,每次支付都会生成一个支付单,它可以认为是与更抽象的订单相关(如会员订单、优惠券订单)。

于是我们提取了费项记录这个概念,表示一笔订单可以有多个支付事件,用于区分我们的支付单与支付中台的支付单之间的差异。通过这种方式,我们逐步实现了统一语言,为后续的建模和协作奠定了基础。

3.3 自上而下细化边界——子域划分

传统的面向过程开发方法在面对复杂系统时,通常采用 DFD(数据流图)进行拆分。在 DDD(领域驱动设计)中,子域概念应运而生。我们经常听到领域和子域这两个词,无论是 Eric 的 DDD 还是 IDDD,都大量使用了这两个概念。但有时候,我们并未真正理解子域是如何划分而来的。

对于一个已有的系统而言,我们可以根据康威定律得出:团队边界=系统边界,因此,我们可以认为每个团队负责的部分就是天然的子域。以订单团队为例,我们可以初步划分为用户订单组和采购派发组。基于此,我们可以得出一个领域划分:

此时我们根据愿景,可以明确两个子域各自的职责:

  • 用户订单子域: 负责用户订单流程的查看和管理,并在需要时主动通知用户。

  • 采购订单子域: 负责采购订单流程的流转,包括供应商和行前行中行后的状态更新。

最后支付使用的是携程金融的能力,由于支付平台的能力在携程内部是统一的,因此我们认为支付平台属于通用域。

3.4 自下而上抽象概念——限界上下文

领域的概念相对而言还是模糊的,因此Eric提出了DDD中最重要的概念:限界上下文。而限界上下文并非凭空而来,而是需要对我们在事件风暴中得到的名词进行归纳而来。

首先,我们列举了用户订单域的各种用例,包括下订单、支付订单、修改订单、取消订单等。

通过建模法归纳模型,我们发现订单流程中存在多种支付场景,同时依赖支付平台的支付单。因此,我们得到了维护支付单状态的支付费项记录,它既维护了支付单相关的信息,也维护了订单系统内关于支付的业务逻辑。

最后我们根据业务相关性对得出的实体进行归纳,结合我们的愿景得出三个上下文,分别是:

  • 用户订单状态上下文:负责管理用户订单状态管理;
  • 支付费项上下文:负责订单支付相关状态管理;
  • 用户通知上下文:负责对用户进行多种方式的通知。

3.5 挖掘业务变化的瓶颈——上下文依赖关系

实际上,限界上下文可以拆分为更细的粒度,但应遵循奥康姆剃刀原则,尽量设置合理的数量,有理有据地进行拆分。我们先来看看原系统的上下文依赖关系:

  • 消息中心: 作为携程的消息中台,不会为某个业务线做特殊逻辑,因此是遵奉者(Conformist)。此时,订单内部耦合了消息处理,如果发送消息没有业务逻辑,采用防腐层(ACL)方式较为常见。

  • 用户通知: 由于用户通知存在业务逻辑,订单直接与消息中心交互显得不合理。订单作为核心域,应尽量不依赖其他域。为此,我们进行了如下设计:

  • 用户订单状态上下文: 更加内聚,关注订单状态管理。

  • 用户通知上下文: 独立于订单,便于迭代。

根据Eric对上下文关系的总结,我们可以得出消息中心作为携程的消息中台,不会为了某个业务线做特殊逻辑,因此是很明显的遵奉者(Conformist)。此时消息相关的处理耦合在订单内部,如果发送消息没有业务逻辑那么采取防腐层(ACL)的方式是比较常见的。

由于我们已经识别到用户通知存在业务逻辑,因此订单直接和消息中心交互显得奇怪,而且订单作为核心域,本来就应该尽量不依赖其它域,对此我们进行了如下设计:

这样用户订单上下文更加内聚,而用户通知也更加易于迭代。

四、收益总结

4.1 业务逻辑耦合降低

通过划分上下文和明确职责,各个领域负责自己的数据和领域知识。这样一来,订单不再涉及这些字段,而是由数据写入的业务方负责维护。因此,在后续与订单无关的业务逻辑发生变化时,订单无需进行修改。这有助于降低业务逻辑耦合,提高系统的灵活性和可维护性。

4.2 团队效率提高

在上下文划分和康威定律应用的过程中,各个团队的职责与各自领域形成映射。这使得过去在功能分工上存在的争议得以解决,团队之间能够更加高效地协作。此外,通过优化资源分配和任务协调,进一步提高了团队协作的效率。

4.3 性能和稳定性提高

经过上下文划分,订单实体从原来的780多个字段简化为200多个字段,大大降低了订单的维护成本。同时,存储数据量减少,各个业务逻辑也由各自的写入方负责维护。接口性能得到优化,p95写入速度从68ms提升至12ms,读取速度从63ms降低至5ms。这些改进提高了系统性能和稳定性,为业务发展奠定了基础。

4.4 数据一致性

过去,业务方在将数据写入订单时,可能因网络抖动等原因导致写入失败或数据错误。如今,业务方将数据存储在自己的领域内,不再写入订单。这样一来,数据一致性得到增强,避免了因耦合导致的数据不一致和字段写错等问题。

4.5 人力成本大幅下降

产研沟通涉及的相关方数量减少,链路缩短。去除因业务逻辑耦合导致订单修改的人力成本,整体人力成本在小项目中下降70%,大项目甚至下降80%。通过降低人力成本,提高了项目效益和投资回报率。

五、遇到的问题和方案探索

实际应用领域驱动设计(DDD)的过程中,我们遇到诸如领域专家难寻、业务需求多变且紧急、团队对DDD理解不足等问题。针对这些问题,我们总结出以下几点经验:

5.1 领域专家难寻

在实际工作中,找到一位严格的领域专家往往是困难且成本高昂的。为了解决这个问题,我们可以借助资深研发人员、资深QA人员等,同时通过互相借鉴的方式,尽管业务不完全相同,但领域上仍有相通之处。此外,培养内部领域专家和建立知识体系也是非常重要的。

5.2 业务需求多且急

实际工作中,我们常常陷入各种业务项目的忙碌之中,很多项目都十分紧急。这种情况很容易导致我们无法专注于DDD改造。为应对这一问题,我们采取在有时间时确定方向、提前进行设计,然后在业务项目中逐步实现的策略。同时,通过敏捷开发方法和良好的需求管理,确保在紧急业务需求中仍能保持DDD改造的进度。

5.3 团队对DDD理解不深

为提高团队对DDD的认识,我们成立了专门的DDD培训小组,将实际落地经验整理成规范和最佳实践。在落地过程中,培训小组负责把关,确保大家不走弯路。此外,通过内部交流、分享和实践,提高团队成员对DDD的认知和实践能力。

说在最后

DDD架构如何落地,是是非常常见的面试题。

以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,并且在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

当然,关于DDD,尼恩即将给大家发布一波视频 《第34章:DDD的学习圣经》, 帮助大家彻底穿透DDD。

尼恩技术圣经系列PDF

  • 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
  • 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
  • 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
  • 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
  • 《大数据HBase学习圣经:一本书实现HBase学习自由》
  • 《大数据Flink学习圣经:一本书实现大数据Flink自由》
  • 《响应式圣经:10W字,实现Spring响应式编程自由》
  • 《Go学习圣经:Go语言实现高并发CRUD业务开发》

……完整版尼恩技术圣经PDF集群,请找尼恩领取

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1272238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玄学调参实践篇 | 深度学习模型 + 预训练模型 + 大模型LLM

😍 这篇主要简单记录一些调参实践,无聊时会不定期更新~ 文章目录 0、学习率与batch_size判断1、Epoch数判断2、判断模型架构是否有问题3、大模型 - 计算量、模型、和数据大小的关系4、大模型调参相关论文经验总结5、训练时模型的保存 0、学习率与batch_s…

抑制过拟合——Dropout原理

抑制过拟合——Dropout原理 Dropout的工作原理 实验观察 在机器学习领域,尤其是当我们处理复杂的模型和有限的训练样本时,一个常见的问题是过拟合。简而言之,过拟合发生在模型对训练数据学得太好,以至于它捕捉到了数据中的噪声和…

热烈欢迎省工信厅毛郑建处长莅临公司调研指导工作

2023年11月28日,河南省工信厅信息化和软件服务业处毛郑建处长莅临郑州埃文计算机科技有限公司(以下简称“埃文科技”)调研考察工作。河南省工业信息安全产业发展联盟理事长任传军陪同调研。 首先,埃文科技董事长王永向毛处长介绍埃…

开源运维监控系统-Nightingale(夜莺)应用实践(未完)

一、前言 某业务系统因OS改造,原先的Zabbix监控系统推倒后未重建,本来计划用外部企业内其他监控系统接入,后又通知需要自建才能对接,考虑之前zabbix的一些不便,本次计划采用一个类Prometheus的监控系统,镜调研后发现Nightingale兼容Prometheus,又有一些其他功能增强,又…

JDK 动态代理从入门到掌握

快速入门 本文介绍 JDK 实现的动态代理及其原理,通过 ProxyGenerator 生成的动态代理类字节码文件 环境要求 要求原因JDK 8 及以下在 JDK 9 之后无法使用直接调用 ProxyGenerator 中的方法,不便于将动态代理类对应的字节码文件输出lombok为了使用 Sne…

孩子都能学会的FPGA:第十七课——用FPGA实现定点数的乘法

(原创声明:该文是作者的原创,面向对象是FPGA入门者,后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门,作者不光让大家知其然,还要让大家知其所以然!每个工程作者都搭建了全自动化的仿…

SpringBoot-监听Nacos动态修改日志级别

目录 一、pom文件 二、项目配置文件 三、日志配置文件 四、日志监听类 五、日志动态修改服务类 线上系统的日志级别一般都是 INFO 级别,有时候需要查看 WARN 级别的日志,所以需要动态修改日志级别。微服务项目中使用 Nacos 作为注册中心&#xff0c…

什么是网络攻击?阿里云服务器可以避免被攻击吗?

网络攻击是指:损害网络系统安全属性的任何类型的进攻动作。进攻行为导致网络系统的机密性、完整性、可控性、真实性、抗抵赖性等受到不同程度的破坏。 网络攻击有很多种,网络上常见的攻击有DDOS攻击、CC攻击、SYN攻击、ARP攻击以及木马、病毒等等,所以再…

CTO对生活和工作一点感悟

陌生人,你好啊。 感谢CSDN平台让我们有了隔空认识,交流的机会。 我是谁? 我呢,毕业快11年,在网易做了几年云计算,后来追风赶上了大数据的浪潮,再到后来混迹在AI、智能推荐等领域。 因为有一颗…

SS8847T 双通道 H 桥驱动芯片 替代DRV8847

SS8847E是一款双桥电机驱动器,具有两个H桥驱动器,可以驱动两个直流有刷电机,一个双极步进电机,螺线管或其他感性负载。该器件的工作电压范围为 2.7V 至 15V,每通道可提供高达 1.0A 的负载电流。每个H桥的输出驱动器模块…

2023年安全员-A证证模拟考试题库及安全员-A证理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2023年安全员-A证证模拟考试题库及安全员-A证理论考试试题是由安全生产模拟考试一点通提供,安全员-A证证模拟考试题库是根据安全员-A证最新版教材,安全员-A证大纲整理而成(含2023年…

navigator.clipboard is undefined in JavaScript issue [Fixed]

navigator.clipboard 在不安全的网站是无法访问的。 在本地开发使用localhost或127.0.0.1没有这个问题。因为它不是不安全网站。 在现实开发中,可能遇到测试环境为不安全网站。 遇到这个问题,就需要将不安全网站标记为非不安全网站即可。 外网提供了3…

python动态加载内容抓取问题的解决实例

问题背景 在网页抓取过程中,动态加载的内容通常无法通过传统的爬虫工具直接获取,这给爬虫程序的编写带来了一定的技术挑战。腾讯新闻(https://news.qq.com/)作为一个典型的动态网页,展现了这一挑战。 问题分析 动态…

【开源视频联动物联网平台】视频接入网关的用法

视频接入网关是一种功能强大的视频网关设备,能够解决各种视频接入、视频输出、视频转码和视频融合等问题。它可以在应急指挥、智慧融合等项目中发挥重要作用,与各种系统进行对接,解决视频能力跨系统集成的难题。 很多视频接入网关在接入协议…

Go 语言输出文本函数详解

Go语言拥有三个用于输出文本的函数: Print()Println()Printf() Print() 函数以其默认格式打印其参数。 示例 打印 i 和 j 的值: package mainimport "fmt"func main() {var i, j string "Hello", "World"fmt.Print(…

【力扣:526】优美的排列

状态压缩动态规划 原理如下: 遍历位图可以得到所有组合序列,将这些序列的每一位看作一个数,取序列中1总量的值作为每轮遍历的位,此时对每个这样的位都能和所有数进行匹配,因为一开始就取的是全排列,并且我们…

MySQL表的查询、更新、删除

查询 全列查询 指定列查询 查询字段并添加自定义表达式 自定义表达式重命名 查询指定列并去重 select distinct 列名 from 表名 where条件 查询列数据为null的 null与 (空串)是不同的! 附:一般null不参与查询。 查询列数据不为null的 查询某列数据指定…

陈嘉庚慈善践行与卓顺发的大爱传承

陈嘉庚慈善践行,了解陈嘉庚后人与卓顺发的大爱传承。 2023年11月25日,卓顺发太平绅士以及陈家后人在分享他们对慈善领域见解的过程中,特别强调了慈善在促进社会和谐以及推动社会进步方面的关键作用。同时,他们深入探讨了如何在当今社会中继续传扬和实践家国情怀以及…

C++ CryptoPP使用AES加解密

Crypto (CryptoPP) 是一个用于密码学和加密的 C 库。它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密、非对称加密、哈希函数、消息认证码 (MAC)、数字签名等。Crypto 的目标是提供高性能和可靠的密码学工具,以满足软件开发中对…

什么是木马

木马 1. 定义2. 木马的特征3. 木马攻击流程4. 常见木马类型5. 如何防御木马 1. 定义 木马一名来源于古希腊特洛伊战争中著名的“木马计”,指可以非法控制计算机,或在他人计算机中从事秘密活动的恶意软件。 木马通过伪装成正常软件被下载到用户主机&…