当前位置: 首页 > 科技观察

领域驱动设计解释:什么,为什么,如何?

时间:2023-03-21 17:41:31 科技观察

什么是领域驱动设计?传统的分层架构在实际开发中存在哪些问题?业务开发人员如何设计和构建自己的领域模型?阿里文娱技术专家战獒将一一解答,并分享文娱领域的经验。领域驱动设计实践。1.什么是领域驱动设计?领域驱动设计的概念于2004年由EvicEvans在其著作《Domain-Driven Design : Tackling Complexity in the Heart of Software》(中文译名:Domain-DrivenDesign:TheWaytoCopewiththeComplexityofSoftwareCore)中提出。15年了,为什么最近火遍了中国互联网圈?似乎大家一夜之间都在议论纷纷,那么领域驱动设计帮我们解决了哪些问题呢?带着这些问题,我们来看看阿里巴巴文娱是如何实践领域驱动设计的。2、领域驱动设计流行的必然原因软件系统从来都不是凭空产生的,而是以软件的形式解决具体问题。当我们在现实世界中面临复杂的问题时,我们如何以软件的形式来实现呢?领域驱动设计是一套指导我们拆分复杂问题的方法论,拆分出各个子系统之间的关系和工作方式,帮助我们解决大型复杂系统实现中遇到的问题。EvicEvans在他的著作中将软件系统的设计分为两部分:战略设计和战术设计。在战略设计层面,提出领域、子领域、限界上下文等重要概念;在战术设计层面,提出实体、值对象、领域服务、领域事件、聚合、工厂、资源库等重要概念。如图1所示:图1StrategicDesignandTacticalDesign战略设计部分指导我们如何拆分一个复杂的系统,战术部分指导我们如何实现拆分后的单个子系统,在落地过程中应该遵循哪些原则.以大家熟知的电子商务系统为例。因为早期电商系统的业务比较简单,用户数量和团队规模都比较小,单个应用就可以搞定。随着容量的增加,单体应用可以横向扩展,比如淘宝早期就是这么做的。在拆分过程中,我们可以将电商系统单体应用拆分为订单子系统、库存子系统、物流子系统、搜索推荐子系统等,如图2所示:图2电商系统微服务划分领域驱动设计在战略层面对领域、子领域、限界上下文的划分与微服务的划分不谋而合。域对应一个问题空间,即上例中的电子商务系统;子领域是将领域的大问题空间拆分成几个更容易解决的较小问题空间,即从单体应用到微服务的演进过程中划分的各个子系统;有界上下文是解空间,每个子域对应一个或多个解空间。微服务的划分也是将一个大问题分成若干个小问题,每个小问题由一个或多个微服务来解决。对于大部分开发同学来说,是没有机会接触到系统的划分的。这些任务通常由公司的技术领导和架构师完成。普通开发同学只是在日常工作中接触到一个具体的微服务或者微服务。是不是说领域驱动设计对普通开发同学没用?当然不是,领域驱动设计的战术设计部分就是指导我们如何去实现一个系统,让系统具有高Scalability,高可读性。所有的系统最终都要以代码的形式实现,而实现工作则由普通的开发同学完成。系统是否具有高扩展性和高可读性,直接影响到整个团队的效率。传统分层架构存在的三大问题对于大部分开发同学来说,大部分时间都花在了一个一个地实现微服务上。看看阿里文娱是如何结合领域驱动设计的思想来战术性地实现微服务的。.目前,我接触到的微服务大多是分层架构,在Service层和Manager层实现特定的业务逻辑。DO、DTO、BO、VO等用于数据传输,数据和行为基本完全隔离。这种层级结构图3就是《Java开发手册》中的标准层级结构。规范定义了各层的职责,其中最重要的两个层,Service层和Manager层,是这样规定的(以下两层的解释摘自《Java 开发手册》):Service层是一个相对具体的业务逻辑服务层。Manager层是一个普通的业务处理层,具有以下特点:对第三方平台进行封装,对返回结果进行预处理,异常信息转换的层。Service层通用能力的下沉,比如缓存方案和中间件的通用处理。与DAO层交互,复用多个DAO的组合。图3传统层级结构阿里文娱早期的项目层级基本采用了这种架构形式。上面的分层是没有问题的,但是这种分层架构采用了包形式的层的隔离,这就需要每一位开发同学理解并自觉遵守上面的规范,但是在实际工作中,我们发现很多同学的Service层和Manager层的区别不是特别清楚,即使大部分清楚的同学也没有完全遵守手册中的规范,这种现象导致Manager层与Service没有本质层除了一些通用功能。区别。在实际业务代码中,无论是Service层还是Manager层都充斥着大量的第三方依赖,对系统的稳定性影响很大。每个对第三方服务的依赖都需要各种例外。这些异常处理代码往往与业务代码混在一起。当这样的代码过多时,代码的可读性会很差。阿里巴巴娱乐业务的复杂度在快速增加,业务迭代速度也非常快。Service层和Manager层的代码量在快速膨胀,业务逻辑也越来越复杂。在这个业务场景中,大文娱乐引入了领域驱动设计,设计了一套完整的领域驱动模型评估和演化解决方案,协助开发者落地领域驱动设计的思想。4、在文化娱乐领域实践领域驱动设计,关键是要找准商业模式,商业模式会随着业务的发展而演进。针对新业务,能效平台提供商业模式分析功能。开发人员可以在EnergyEfficiencyPlatform上设计和构建自己的领域模型。搭建完成后,EnergyEfficiencyPlatform可以评估领域模型设计是否合理。如果模型设计合理,可以基于上述设计的符合领域模型规范规范的模型。针对已有的应用,能效平台设计了一套领域注解,并以SDK的形式提供:第一步:开发者根据领域设计的原则,对业务代码进行分析和注解。第二步:能效平台可以自动扫描项目,收集项目中的领域模型。第三步:模型采集完成后,开发者可以在能效平台上完善业务模型,根据领域模型的规范生成代码。完整的流程如下图所示:图4领域模型的生命周期1模型获取对于已有的准备重构的应用,我们设计了一套领域模型注解,开发者可以在相应的类、属性上添加注解,方法。当系统按照数据模型而不是领域模型来实现时,可以先找到系统的数据模型,然后在能效平台上组织数据模型生成领域模型。图5领域模型注2模型构建对于新的应用或已经完成模型收集的应用,开发者可以在能效平台上构建和修改模型,如图6所示。图6领域模型3健康评估对于模型能效平台构建完成后,根据领域驱动设计规范创建一套完整的验证规则。模型搭建完成后,会根据验证规则进行评分,再生成脚手架。评分时模型可以在通过时搭建脚手架。图7模型验证4脚手架生成当模型搭建完成,验证通过后,就可以生成模型作为脚手架了。代码结构按照六边形架构的标准生成。六边形架构也成为端口和适配器架构。这个想法是将内部核心领域逻辑与外部依赖隔离开来。这里的依赖是指所有对其他微服务的依赖,http依赖,数据库依赖,缓存依赖,消息中间件依赖等等,所有这些依赖都是通过适配器,转化为应用能够理解和识别的最小信息。在实际项目中,每个依赖都要考虑各种异常并进行处理,但这些处理实际上并不是数据域逻辑,而是耦合到业务代码上。当依赖较多时,会影响系统的稳定性。它有很大的影响。虽然传统的分层架构会让我们把自己的领域逻辑和依赖分离,但是阿里巴巴规范手册中提到所有的依赖都应该放在Manager层,但是这个规范很容易被破坏。六边形的架构让我们从应用分层的角度更容易遵守这样的规范。图8六边形架构根据六边形架构的指导思想,实际应用分层一般分为四层,分别是:用户界面层:负责用户显示相关逻辑。应用层:负责一个用例的流程安排(将接口用例分成几个步骤,但不负责每个步骤的具体实现)。领域层:负责实现核心领域逻辑,即业务逻辑(负责实现具体的业务逻辑)。基础设施层:所有依赖的具体实现。但是,从应用程序架构的角度来看,分层组织形式可以分为两种类型:图9左侧的传统分层架构,这种分层架构是由EvicEvans在《Domain-Driven Design : Tackling Complexity in the Heart of Software》中提出的,其中用户界面层,应用层1.领域层可以直接依赖于基础设施层,这与图3中的传统架构没有本质区别,因为所有层都直接依赖于基础设施层。这种方式需要强制开发者下沉所有的依赖,随着时间的推移,这种规范很容易被打破。图9LayerDependencyDependencyInversionLayeredArchitecture如图9右侧所示,该分层架构是一种依赖倒置分层架构,具有以下特点:基础设计层可以直接依赖其他三层,反之则不能。如果用户界面层、应用层和领域层想要使用基础设施层的能力,只能通过IOC进行依赖注入,这也符合面向对象编程中的依赖倒置原则。当开发者想直接引用上述三层的第三方依赖时,找不到具体的类信息,也就是无法导入。同时,这种方法在单元测试的规范中也能起到很大的作用。我们在编写单元测试的时候,可以为领域层注入一个测试运行时依赖,这样应用就可以在不依赖下游服务的情况下运行单元测试。在代码层面也更加规范。五、总结虽然经典的三层或多层架构是目前最常见的架构,但在隔离方面做得不够好。在选择业务架构时,需要结合自身的业务特点,而不是千篇一律地选择某一种业务架构。合适的业务架构可以延长项目的生命周期,减少项目重构的频率,最终达到降低人力成本的目的。