前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DDD初探

DDD初探

原创
作者头像
小爽只会CRUD
发布2023-05-10 15:50:16
2380
发布2023-05-10 15:50:16
举报
文章被收录于专栏:一头猪的学习一头猪的学习

前言:架构设计是为了解决系统复杂度

架构的误区1:每个系统都要做架构设计/公司流程要求有架构设计

知其然更要知其所以然,不能仅仅因为其他公司都在做架构设计而盲目跟从,而应该深入理解架构设计的目的和必要性,根据实际需求进行合理的设计。如果架构师或设计师只是为了找点事做而进行架构设计,不仅会浪费时间和人力,还会拖慢整体开发进度。此外,其他公司的架构设计并不一定适用于当前项目,如果强行引入,很可能会导致架构水土不服、运行不流畅等问题,最终需要不断重构或者推倒重来。因此,架构师或设计师应该深刻理解为何要进行架构设计,避免生搬硬套,针对具体需求进行合理的设计,才能保证项目的顺利进行。

架构的误区2:架构设计是为了追求高性能、高可用、可扩展性等单一目标

持有这类观点的人看似具备一定架构经验或基础,但实际上他们无论面对什么系统或业务,都会不顾一切地追求这些目标,导致架构设计变得复杂、项目实施时间拖延、团队内部不和等问题的出现。这些问题使得整个项目进展缓慢,系统稳定性差,出现问题难以解决,甚至加入新功能也需要花费大量时间。这些情况不是危言耸听,而是广泛出现的现象。因此,架构师或设计师必须深入了解系统和业务需求,根据实际需要合理设计,不可盲目追求“高XX”目标,才能确保项目开发进度和系统的稳定性。

架构设计的目的

整个软件技术发展的历史,其实就是一部与“复杂度”斗争的历史。架构也是为了应对软件系统复杂度而提出的一个解决方案,其主要目的是为了解决软件系统复杂度带来的问题。

那到底什么是复杂度呢?John Ousterhout教授在 A Philosophy of Software Design 书中提到,复杂度就是任何使得软件难于理解和修改的因素

复杂的系统有一些非常明显的特征,John教授将它抽象为变更放大(Change amplification)、认知负荷(Cognitive load)与未知的未知(Unknown unknowns)这3类。

变更放大(Change amplification)指得是看似简单的变更需要在许多不同地方进行代码修改。系统开发者之前没有及时重构代码,提取公共逻辑,而是省时间Ctrl-C,Ctrl-V式代码开发(这样做不会影响已有的稳定模块,不需要做比较多的回归测试,上线风险小)。当需求变化时,需要改动多处代码。

认知负荷(Cognitive load)是指系统的学习与理解成本高,开发人员的研发效率大大降低。

未知的未知(Unknown unknowns)是指不知道修改哪些代码才能使系统功能正确的运行,也不知道这行代码的改动是否会引发线上问题。这一项是复杂性中最糟糕的一个表现形式。

系统复杂度的六个来源及通用解法

1.高性能 2.高可用 3.可扩展性 4.低成本 5.安全 6.规模

简单的复杂度分析案例

分析一个简单的案例,一起来看看如何将“架构设计的真正目的是为了解决软件系统复杂度带来的问题”这个指导思想应用到实践中。

当我们设计一个大学的学生管理系统时,我们需要考虑该系统的复杂度以及如何解决这些复杂度带来的问题。首先,我们可以将该系统的复杂度分为以下几个方面:

性能 该系统的访问频率并不高,因此性能并不是一个很大的问题。我们可以使用MySQL作为存储,Nginx作为Web服务器,无需考虑缓存。

可扩展性 该系统的功能比较稳定,可扩展的空间并不大,因此可扩展性方面也不是一个很大的问题。

高可用 数据丢失是不可接受的,故该系统的高可用性方面需要考虑多种异常情况,如机器故障、机房故障等。为此,我们需要设计MySQL同机房主备方案和MySQL跨机房同步方案。

安全性 该系统存储的信息涉及到学生的隐私,因此需要考虑安全性。我们可以使用Nginx提供的ACL控制、用户账号密码管理和数据库访问权限控制来保证系统的安全性。

成本 由于该系统比较简单,基本上几台服务器就可以搞定,因此成本方面并不需要太多关注。

规模 同上,规模复杂度无需过度关注。

总体来说,我们需要在架构设计中充分考虑系统的复杂度,同时根据不同问题选择合适的解决方案,以提高系统的可靠性和安全性。

微服务架构解决了高可用、可扩展问题,但性能下降、成本以及规模复杂度暴增

软件架构模式大体来说经历了从单机、集中式到分布式微服务架构三个阶段的演进 。随着分布式技术的快速兴起,我们已经进入到了微服务架构时代。

微服务架构的优点

高可用

当架构中的某一组件发生故障时,在单一进程的传统架构下,故障很有可能在进程内扩散,导致整个应用不可用。在微服务架构下,故障会被隔离在单个服务中。若设计良好,其他服务可通过重试、平稳退化等机制实现应用层面的容错。

可扩展

单个服务应用也可以实现横向扩展,这种扩展可以通过将整个应用完整的复制到不同的节点中实现。当应用的不同组件在扩展需求上存在差异时,微服务架构便体现出其灵活性,因为每个服务可以根据实际需求独立进行扩展。

微服务架构的缺点

复杂度高

与单体式架构相比,微服务会导致复杂性上升,因为多个团队会在更多地方创建更多服务。若管理不当,则会导致开发速度和效率降低。

性能下降

微服务之间通过REST、RPC等形式进行交互,通信的时延会受到较大的影响

DDD帮助微服务控制复杂度

控制成本&规模复杂度需要明晰微服务的边界

随着微服务数量上升,规模复杂度呈指数级上升,那么我们理应控制微服务的数量,这就带来了争论和疑惑:微服务的粒度应该多大呀?微服务到底应该如何拆分和设计呢?

长期以来,微服务架构缺乏一套系统的理论和方法来指导其拆分,这导致了一些人对微服务架构的理解出现了一些曲解。有人简单地认为微服务只是将原来的单体应用程序拆分为多个部署包或更换为支持微服务架构的技术框架,便可成为微服务。还有人认为,微服务越小越好。

然而,在过去的几年中,一些项目由于在前期过度拆分微服务,导致项目复杂度过高,无法进行上线和运维的情况已经出现。综合来看,我认为微服务拆分困境的根本原因在于不清楚业务或微服务的边界在哪里。换句话说,只有确定了业务边界和应用边界,这个困境才能迎刃而解。

DDD能够帮我们设计出清晰的领域和应用边界

DDD 包括战略设计和战术设计两部分。战略设计主要从业务视角出发,建立业务领域模型,划分领域边界,建立通用语言的限界上下文,这些限界上下文可以作为微服务设计的参考边界。而战术设计则从技术视角出发,着重于领域模型的技术实现,包括聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。

在战略设计过程中,领域模型的建立是重中之重。为此,DDD 提出了事件风暴这一建立领域模型的方法。事件风暴是一个从发散到收敛的过程,通常采用用例分析、场景分析和用户旅程分析,全面分解业务领域,梳理领域对象之间的关系,这是一个发散的过程。在事件风暴过程中,会产生很多实体、命令、事件等领域对象,我们将这些领域对象从不同的维度进行聚类,形成如聚合、限界上下文等边界,建立领域模型,这就是一个收敛的过程。

因此,DDD 可以帮助软件工程师建立清晰的领域模型,划分业务和应用边界,以指导微服务的设计和拆分。事件风暴是建立领域模型的主要方法,通过其发散的过程和聚合的过程,建立起合理的领域模型,从而实现高效的软件开发和落地。

可以用三步来划定领域模型和微服务的边界

  1. 在领域驱动设计的战略设计中,我们采用事件风暴方法梳理业务过程中的用户操作、事件以及外部依赖关系等,从而梳理出领域实体等领域对象。
  2. 然后,我们根据领域实体之间的业务关联性,形成聚合,并确定聚合中的聚合根、值对象和实体。
  3. 接着,根据业务及语义边界等因素,将一个或多个聚合划定在一个限界上下文内,形成领域模型。这个过程中,我们建立了领域模型,划定了业务领域的边界,建立了通用语言和限界上下文,确定了领域模型中各个领域对象的关系。这些限界上下文可以作为微服务设计的参考边界,从而确定了应用端的微服务边界

在领域驱动设计的战略设计中,我们采用事件风暴方法梳理业务过程中的用户操作、事件以及外部依赖关系等,从而梳理出领域实体等领域对象。

然后,我们根据领域实体之间的业务关联性,形成聚合,并确定聚合中的聚合根、值对象和实体。

接着,根据业务及语义边界等因素,将一个或多个聚合划定在一个限界上下文内,形成领域模型。这个过程中,我们建立了领域模型,划定了业务领域的边界,建立了通用语言和限界上下文,确定了领域模型中各个领域对象的关系。这些限界上下文可以作为微服务设计的参考边界,从而确定了应用端的微服务边界

微服务与DDD的异同

DDD 是一种面向复杂业务领域的设计方法论,而微服务是一种面向分布式系统的架构风格。它们的共同目标都是通过将系统分解为更小,更易于管理的组件来提高系统的可维护性和可扩展性。

  1. 在 DDD 中,我们关注的是业务领域的划分和领域模型的设计,以便更好地理解业务需求,并将其转化为可执行的代码。
  2. 在微服务中,我们主要关注的是运行时的通信,容错和故障隔离,以及服务治理等问题,以确保各个微服务可以独立开发、测试、构建和部署。
  3. 通过结合 DDD 和微服务,我们可以更好地实现高效的业务逻辑,同时也可以充分利用微服务的优点,提高应用程序的可扩展性和可维护性。因此,DDD 和微服务是互补的,可以共同用于构建可靠且高效的应用程序。

DDD业务建模

学习链接:https://blog.csdn.net/Chang_Yafei/article/details/129783414

失血模型

数据对象中只有只有属性和set和get方法,业务逻辑层里包含了几乎所有的逻辑,不重要几乎不用

优点:领域对象结构简单

缺点:业务逻辑臃肿,难以维护,无法应对频繁修改的需求

贫血模型

数据对象在失血模型中的数据对象的基础上添加固有行为

固有行为:我们的本能行为,如吃饭走路

非固有行为:一些后天行为

优点:层次结构清晰,各层级单向依赖

缺点:法良好的应对非常复杂的逻辑和场景

这种模型是Spring一致引领的方向,所以非常的流行用途极广

充血模型

更加符合面相对象的设计

优点:符合面向对象的原则,业务逻辑层薄接近符合单一职责原则

缺点:没有专门的持久层(实际上图的持久层放在对象里面),要求开发者水平高,模型包含操作多,实例化增加了资源消耗

胀血模型

取消了业务逻辑层,直接在domain Object(领域对象)上封装事务以及授权,授权很多原本不属于这个领域对象的逻辑,模型不稳定,代码缺乏可维护的稳定性

以上内容仅为学习记录所用,如有侵权行为请联系!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言:架构设计是为了解决系统复杂度
  • 微服务架构解决了高可用、可扩展问题,但性能下降、成本以及规模复杂度暴增
    • 微服务架构的优点
      • 高可用
      • 可扩展
    • 微服务架构的缺点
      • 复杂度高
      • 性能下降
  • DDD帮助微服务控制复杂度
  • DDD业务建模
    • 失血模型
      • 贫血模型
        • 充血模型
          • 胀血模型
          相关产品与服务
          云数据库 MySQL
          腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档