随笔

【注】本文译自: https://www.geeksforgeeks.org/domain-driven-design-ddd/   领域驱动设计(Domain-Driven Design)是程序员 Eric Evans 于 2004 在他的《 领域驱动设计:解决软件核心中的复杂性》一书中提出的一个概念。   这是一种自顶向下的软件设计方法。首先,让我们尝试重点介绍一下在这种情况下领域的含义。

什么是领域?

  在软件开发的上下文中,“域”指的是业务。在应用程序开发过程中,通常使用术语域逻辑或业务逻辑。基本上,业务逻辑是应用程序逻辑所围绕的知识领域。 应用程序的业务逻辑是一组规则和指导原则,用于解释业务对象应如何相互交互以处理建模数据。 注意:   软件工程领域的领域是要在其上构建应用程序的业务。

领域驱动设计:

  假设我们的软件已经使用了所有最新技术堆栈和基础设施,这样的软件设计架构非常棒,但是当我们在市场上发布这个软件时,最终还是要由最终用户来决定我们的系统是否优秀。另外,如果系统不能解决业务需求,对任何人都没有用处;不管它看起来有多漂亮,或者它的基础设施有多好。根据 Eric Evans 的说法,当我们在开发软件时,我们的重点不应该主要放在技术上,而应该主要放在业务上。记住:

“客户的工作不是知道他们想要什么“—史蒂夫·乔布斯

  领域驱动设计涉及两种设计工具,一种是战略设计工具,另一种是战术设计工具。程序员或开发人员通常处理战术设计工具,但如果我们有战略设计工具的知识和良好的理解,它将帮助我们构建好的软件。   Spring 数据家族下的大多数框架都是根据领域驱动的设计方法构建的。

战略设计:

  战略设计工具帮助我们解决所有与软件建模相关的问题。它是一种类似于面向对象设计的设计方法,在面向对象设计中,我们被迫从对象的角度思考问题。在战略设计方面,我们被迫从环境的角度来思考。

上下文(Context):

  我们可以把这个词看作是一个英语单词,它指的是某一事件、事件、陈述或想法的情况,它的意思可以根据这些情况来确定。   除了上下文之外,战略设计还讨论了模型、泛在语言和边界语境。这些是领域驱动设计的战略设计中常用的术语。让我们逐一理解。

  • 模型:   充当核心逻辑并描述领域的选定方面。它用于解决与该业务有关的问题。
  • 通用语言:   所有团队成员使用的一种公共语言,用于连接团队围绕领域模型的所有活动。与领域专家和团队成员交谈时,可以将其视为对类、方法、服务和对象使用通用动词和名词。
  • 边界上下文:   指的是上下文的边界条件。它是对边界的描述,并充当一个阈值,在这个阈值中定义并适用于特定的域模型。

    战术设计:

      战术设计讨论实现细节,即建模领域。它通常会处理有界上下文中的组件。我们可能听说过或使用过诸如服务、实体、存储库和工厂之类的东西。它们都是通过域驱动设计创造并流行的。战术设计过程发生在产品开发阶段。   让我们讨论一些重要的战术设计工具。 这些工具是高级概念,可用于创建和修改域模型。

    1. 实体:   基于面向对象原则工作的程序员可能知道类和对象的概念。在这里,实体是具有某些属性的类。这些类的实例具有全局标识,并且在整个生命周期中都保持相同的标识。请记住,属性状态可能会发生变化,但身份永远不会改变。简而言之,实体可以实现一些业务逻辑,并且可以使用 ID 进行唯一标识。在编程的上下文中,它通常在 DB 中作为行持久保存,并且由值对象组成。
    2. 值对象:   它是不可变的轻量级对象,没有任何标识。值对象通过执行复杂的计算,将繁重的计算逻辑与实体隔离开来,从而降低了复杂性。   在上图中,User 是一个实体,Address 是一个值对象,地址可以更改很多次,但用户的身份证号永远不会更改。每当地址更改时,都会实例化一个新地址并将其分配给用户。
    3. 服务:   服务是无状态的类,可以适合实体或值对象以外的其他地方。简而言之,服务是一种功能,存在于实体和值对象之间的某个位置,但它既不与实体相关,也不与值对象相关。
    4. 聚合:   当我们有更大的项目时,对象图也变得更大,更大的对象图更难维护。聚合是位于单个事务边界下的实体和值的集合。基本上是聚合,控制变化,有一个根实体叫做聚合根。根实体以聚合的方式管理其他实体的生命周期。   在上面的示例中,如果根实体 UserOrder 被删除,则与该根实体关联的其他实体将毫无用处,并且该关联的信息也将被删除。这意味着聚合在本质上总是一致的,这是在域事件的帮助下完成的。生成域事件是为了确保最终的一致性。   在上面的例子中,如果用户的地址已经改变,那么它必须同样反映在订单上。为此,我们可以触发一个从 User 到 Order 的域事件,以便 Order 更新地址,这样我们就有了最终的一致性,Order 也将最终一致。   聚合和聚合根的其他例子可以是对帖子的评论、问答细节、银行事务细节等。ORM 工具如 hibernate 在创建一对多或多对一关系时使用了大量聚合。
    5. 工厂和存储库:   工厂和存储库用于处理聚合。工厂帮助管理聚合生命周期的开始,而存储库帮助管理聚合生命周期的中间和末端。工厂帮助创建聚合,而存储库帮助持久化聚合。我们应该总是为每个聚合根创建存储库,而不是为所有实体创建存储库。   工厂是 GoF 的设计模式,工厂是有用的,但在聚合规则的上下文中不是强制性的。

      领域驱动设计的优点:

  • 提高了我们的技艺
  • 提供了灵活性
  • 更倾向于域而不是接口
  • 通过通用语言减少了团队之间的沟通差距

    领域驱动设计的缺点:

  • 需要一个具有很强领域专业知识的专业人员
  • 鼓励团队遵循迭代实践

  DevOps 在商业界的一些解决方案,主要包括:

  1. 微软公司的 Azure DevOps
  2. 亚马逊公司的 Aws DevOps
  3. 阿里云的 云效 DevOps

Azure DevOps


  Azure DevOps 也称为 Microsoft Visual Studio 团队服务(VSTS)。它是为云构建的一组协作开发工具。 VSTS 通常被用作独立术语,Azure DevOps 是一个由几种不同产品组成的平台,例如:

  • Azure 测试计划
  • Azure 看板
  • Azure 存储库
  • Azure 流水线
  • Azure 制品

  Azure DevOps是将创意转化为工作软件所需的一切。您可以使用 Azure 工具计划项目。

  Azure 流水线是 Azure DevOps 的 CI 组件。Azure 流水线是微软的云原生连续集成服务器,它使团队可以从云中连续构建、测试和部署所有组件。Azure 流水线可以连接到任意数量的源代码存储库,例如 Azure Repos、GitHub、Tests,以获取代码和制品以进行应用交付。

Azure DevOps 服务器

  Azure DevOps Server 是微软的一个产品,提供版本控制、需求管理、报告、软件库管理、项目管理、测试、自动生成和发布管理功能。它涵盖了应用的整个生命周期,并启用了 DevOps 功能。
  Azure DevOps 可以用作众多集成开发环境的后端,但针对 Microsoft Visual Studio 和 Eclipse 的所有平台上进行了定制。

Azure DevOps 服务

  微软宣布在 Microsoft Azure 平台上发布该软件即 Visual Studio 的服务产品,当时微软将其称为在线Visual Studio。

  微软为 Azure DevOps 服务提供了 Visual Studio,基本和利益干系人访问级别。基本计划是免费的,最多可容纳五个用户。订阅了 Visual Studio 的用户可以免费添加到项目中。

AWS DevOps

  AWS 是最好的云服务提供商,DevOps 是软件开发生命周期的实现。

  以下是使 AWS DevOps 成为非常受欢迎的组合的一些原因,例如:

  • AWS CloudFormation
  • AWS EC2
  • AWS CloudWatch
  • AWS CodePipeline

  让我们简要地看一下这些,例如:

AWS CloudFormation


  与开发团队相比,DevOps 团队需要更频繁地创建和发布云实例和服务。诸如 EC2 实例,ECS 容器和 S3 存储桶之类的 AWS 资源模板使您可以设置整个堆栈,而不必将所有内容放在一起。

AWS EC2

  您可以在 EC2 实例中运行容器。因此,您可以利用 AWS 安全和管理功能。

  Amazon EC2 提供最广泛、最深入的实例选择,这些实例构建于最新的计算、存储和网络技术,进行了高性能和安全设计。

AWS CloudWatch


  该监控工具可跟踪 AWS 必须提供的所有资源。轻松使用第三方工具进行监视,例如sumo logic 等。

AWS CodePipeline


  代码流水线是 AWS 的一项重要功能,它极大地简化了你管理 CI / CD 工具集的方式。它与 Jenkins、GitHub 和 CodeDeploy等工具集成,使你可以直观地控制从构建到生产的应用更新流程。

云效 DevOps


  阿里云云效,云原生时代新 DevOps 平台,支持公共云、专有云和混合云多种部署形态,通过云原生新技术和研发新模式,助力创新创业和数字化转型企业快速实现研发敏捷和组织敏捷,打造“双敏”组织,实现 10 倍效能提升。

项目

一站式项目管理

  以项目为维度,管理需求、任务、缺陷、迭代、里程碑、风险和文档。大型项目管理
  支持父子项目以分级管理战略专题项目,支持项目集合以联合管理双十一等大型协作项目。

快速迭代项目管理

  支持Scrum、看板等多种敏捷实践。

应用

应用全生命周期管理

  以应用为单位,申请、创建和配置软件运行所需资源、环境和中间件服务,提供变更、发布、监控和运维等应用全生命周期管理服务。

多种部署运行方式

  支持Docker等多种部署运行方式

交付

持续交付流

  多人协作开发集成、多种编程语言构建打包和分布式集群部署发布等服务。

质量与安全保障

  轻松搭建从代码提交、集成、构建到测试环境、预发环境、线上环境部署发布验证的持续交付流水线,质量和安全层层把关。

运营

用户反馈跟踪

  用户反馈秒级必答,产品知识智能回复。

产品动态监测

  问卷调查和舆情监测,把握产品动态。

数据驱动优化

  分析研发和运营数据,数据驱动效能提升和产品优化创新。

      这个话题要从最近工作中接触到的一些问题说起:大概情况是这样的,公司年前收购了一家公司(以下简称Y公司),虽然行业领域相同,但从业务模式到技术框架都是截然不同的。我们原有采用的是C#、.Net架构,Y公司全栈采用Java,Dubbo微服务架构,本人刚好在公司主导了几个Java项目实践,被分配到接手Y公司的部分项目。几个月下来,感触颇多,简记如下:

  1. 项目模块缺乏整体规划,同一功能出现在项目的多个模块中,重复代码比比皆是;
  2. 与第三方平台接口不规范,比如与X团的API接口中需要获取Token及加密,这样的接口本可以在一个地方统一实现,但却散落在各个地方,且用法不一;最奇葩的是明明对方的结果有返回代码(returnCode)和响应消息(message),却偏偏要自己定义一个枚举类来解释返回代码,最要命的是这个枚举是不完整的,结果就是有些代码找不到就抛出了一个异常”找不到对应的代码“云云,在调试过程中一头雾水……为什么不直接用第三方平台定义的错误代码和消息呢?
  3. 对于底层协议调用没有统一封装,最典型的比如HTTP协议,几乎所有的十几个项目中都有HttpUtil,从Header到PUT/GET/POST都要层层处理,不知道有OkHttp,更有上层封装Retrofit可以直接用吗?还有Json处理,甚至String处理都要写一堆,还各个项目各自为政,结果是出现了一堆无用的代码,臃肿还不能保证效率和正确性。

    上面的问题都可以归结为代码的规范性,如果大家是一个团队,就应该互通有无,有所分工,不要重复造轮子,首先要利用已经有的开源框架,其次要有统一的底层框架;这样既能提高整体效率,也保障了代码的稳定性和可维护性。试想,如果一个地方出了问题,比如第三方接口做了变化,那么上述的编码方式岂不是要改几十个地方?       其实规范性的重要性不言而喻,大家都懂,特别是对于团队开发而言,更是如此。那为什么实际执行下来就这么难呢?其实是一个团队领导力的问题,当今互联网行业,许多是赚快钱,只求快速上线,不出bug就行,至于怎么实现的,什么规范性、复用性,不值一提。但是仔细想想,日积月累,这些东西就变成了“负”能量,时刻在影响着你的产品质量,当然也包括成本。到最后,大家都改不动了,习惯了差,没有了改的动力,到这时候就是整个团队的悲哀了。说到底是一种文化和精神,如果一个公司只求眼前利益,没有对细节和质量的追求,那么永远也成为不了一家伟大的公司,为之工作的员工也只能浑浑噩噩,打更混日子了!