领域驱动实践总结二:架构分析与代码设计

  领域驱动实践总结二:架构分析与代码设计。金老师在网易云课堂精心设计了三个系列的MOOC课程——《面向对象软件开发实践》全开放全免费能有效地帮助初学者成长为一名职业软件开发者。

  完成“认识--理解--模仿--应用”这样一个流程最终得到一个真正有用的软件作品或示例系统在这个过程中培养出真实的软件开发职业技能。

  教学内容围绕着“一个真正有用的软件是怎样开发出来的”这样一个主题而展开介绍人们在实际软件开发过程中 “真正”使用的开发技术、系统设计原则、软件开发流程等。

  常常看到一些程序员对某些软件开发技术和理论的执著也常常听到一些程序员谈论某某项目的技术含量的话题。软件专业开发技术作为程序员的立身之本受到 这样的厚爱是无可厚非的。但是软件作为一种多种知识集成的载体我们不能只把眼光盯在专业的开发技术上还应该看到其中包含的丰富软件应用领域的业务知 识、开发过程中的控制管理知识以及与客户同事之间的交流方式和手段这些都应该成为我们在日常的开发过程积累的素材。

  从项目实践中学习软件专业开发技术是很容易被开发人员接受并在项目开发过程中加以关注和积累的但是项目中的业务知识往往被大家所忽略因为这些东西似 乎与开发人员无关其实大错特错了。笔者就曾经历过这样的一个项目项目中应用的开发技术大家都很熟悉但是应用的业务领域都很陌生在项目开始的初期对 项目中的业务知识和术语进行了一些了解但是由于业务流程和数据关系复杂着实让我们吃了很多苦头不说首次提交的成果物根本就满足不了客户的要求。现在 回想起来还心有余悸。如果当时我们对业务都很熟悉的线c;我们就可以更多的从客户应用的角度去思考问题设计程序结构解决客户问题了。少走很多弯路不说 开发过程也不回异常艰苦。

  在开发实践中我们在提高专业技能的同时一定要注意软件中所包含的业务知识的积累久而久之我们很自然的就会把软件专业知识和行业业务知识结合到一 起在项目开发过程中不但能够游刃有余而且还可以减少跟客户的沟通障碍想客户之所想为客户提供更好的软件解决多方案。

  挑选编程实践题目的过程中有些普遍被关注的问题今天在这里集中聊一聊包括我这些年指导学生的一点经验供各位参考。

  可以说所有编程学习者都离不开实践的过程。除非你只是心血来潮仅仅想看下编程是怎样一回事不打算去用它。否则不管你是准备成为一名专业的开发人员还是想在其他领域使用编程提升效率只要你打算“线c;那就离不开练习。

  少数技能是知道/不知道的性质比如某种工具软件的使用、某种机器的操作只要经过培训就能上岗大多数的技能是熟练/不熟练的性质比如演奏乐器、驾驶汽车。编程亦是如此。你了解基础的语法、类型、常用的函数、模块就好像你知道如何在吉他上弹出单音、和弦这离演奏出一首曲子来还差了大量的练习时间。

  编程虽不用像乐器一样需要肌肉记忆但你同样需要对常用“套路”的熟悉才能在使用时信手拈来。另一方面只有去面对实际的问题才会倒逼你思考解决问题的“大局观”如何流程化模块化地实现你需要的功能。

  尽管项目实践很重要但也不宜过早所谓“欲速则不达”。如果你还没有掌握编程的基础就急于做出一个可展示的作品往往事倍功半说不定还带来挫败感丧失继续学习的动力。我建议至少你对基本的语法、类型常用的数据结构如 list、dict 的使用函数及参数的原理字符串、文件、网络操作如何使用模块提供的功能等方面都有所了解之后再动手做项目。在此之前把教程上的例程自己写一遍会更有效果。

  当然也不宜太晚。学会编程但迟迟不动手过一阵子这个技能就荒废了等到下次想起来要用的时候发现又得从头学。很多人表示我上学时候学过 C 语言但依然写不出代码就是这个原因。

  尽可能选择难度在自己能力上界左右的项目。太简单了对能力提升不大太难了步子太大通常都是半途而废。偶尔会遇到有人问类似问题我刚学 Python我想做个自动驾驶程序应该怎么做这问题我回答不了答案也没有意义在你能力还不够的时候即便答案放在你面前也是理解不了的。高出自己能力一点点在过程中通过搜索、查阅、询问等方式解决问题你的经验值才会得到增长。

  除了合适的难度外尽量从身边入手寻找可用程序解决的问题。做一个你平常用得上的批量文件处理小程序会比千篇一律的抓图片爬虫更有意思。这样的项目目标明确最终更可能完成。

  从模仿做起从核心功能做起。比如你要做网站项目那就可以模仿一个知乎。开发时不建议用瀑布式的开发模式一步到位而是迭代式的开发例如1.先完成最基本的问答功能2.之后增加点赞、排序3.再增加评论功能4.实现关注用户功能……迭代式开发可以让你更快获得阶段成就感。永远记住完成比完美更重要

  当你慢慢已经可以模仿得像那么回事之后不妨尝试下1.深入细节把一两个具体功能做到“像素级”复刻原版的程度2.增加你自己的功能甚至完全原创一个项目3.把你的作品发给别人使用。当做到这几点的时候你已经离一个程序员不远了。

  以上是我对于通过项目实践提升编程能力的一些经验和建议。欢迎留言讨论也欢迎分享你在学习中的心得。

  领域驱动设计DDD是一种设计思想它可以同时指导中台业务建模和微服务设计(中台本质是业务模型微服务是业务模型的系统落地)领域驱动设计强调领域模型和微服务设计的一体性先有领域模型然后才有微服务而不是脱离领域模型来谈微服务设计。

  微服务拆分困境产生的根本原因:不知道业务或者微服务的边界到底在什么地方。

  DDD核心思想:通过领域驱动设计方法定义领域模型从而确定业务和应用边界保证业务模型与代码模型的一致性。

  对于领域驱动设计的学习做的总结主要写三篇博客主要包括三部分:基本理论总结与分析、架构分析与代码设计、具体应用设计分析主要参考的资料为极客时间的欧创新架构师的《DDD》实战其他参考书籍在文章下方的参考书籍中。

  微服务架构模型现有的选择模型包括整洁架构、CQRS 和六边形架构、DDD 分层架构等。

  每种架构模式虽然提出的时代和背景不同但其核心理念都是为了设计出“高内聚低耦合”的架构轻松实现架构演进。

  DDD 分层架构的思想使架构边界变得越来越清晰它在微服务架构模型中占有非常重要的位置。建议选择DDD 分层架构。

  在整洁架构里同心圆代表应用软件的不同部分从里到外依次是领域模型、领域服务、应用服务和最外围的容易变化的内容比如用户界面和基础设施。

  整洁架构最主要的原则是依赖原则它定义了各层的依赖关系越往里依赖越低代码级别越高越是核心能力。外圆代码依赖只能指向内圆内圆不需要知道外圆的任何情况。

  也就是说在下图的六边形架构中红圈内的核心业务逻辑应用程序和领域模型与外部资源包括 APP、Web 应用以及数据库资源等完全隔离仅通过适配器进行交互。它解决了业务逻辑与用户界面的代码交错问题很好地实现了前后端分离。

  六边形架构各层的依赖关系与整洁架构一样都是由外向内依赖。

  六边形架构的一个端口可能对应多个外部系统不同的外部系统也可能会使用不同的适配器由适配器负责协议转换。这就使得应用程序能够以一致的方式被用户、程序、自动化测试和批处理脚本使用。

  这里的用户可能是用户、程序、自动化测试和批处理脚本等等。

  应用层是很薄的一层理论上不应该有业务规则或逻辑主要面向用例和流程相关的操作。

  位于领域层之上领域层包含多个聚合所以它可以协调多个聚合的服务和领域对象完成服务编排和组合协作完成业务操作。

  应用层也是微服务之间交互的通道它可以调用其它微服务的应用服务完成微服务之间的服务组合和编排。

  在设计和开发时不要将本该放在领域层的业务逻辑放到应用层中实现。因为庞大的应用层会使领域模型失焦时间一长你的微服务就会演化为传统的三层架构业务逻辑会变得混乱。

  应用服务是在应用层的它负责服务的组合、编排和转发负责处理业务用例的执行顺序以及结果的拼装以粗粒度的服务通过 API 网关向前端发布。

  应用服务还可以进行安全认证、权限校验、事务控制、发送或订阅领域事件等。

  领域层的作用是实现企业核心业务逻辑通过各种校验手段保证业务的正确性。

  领域层主要体现领域模型的业务能力它用来表达业务概念、业务状态和业务规则。

  领域模型的业务逻辑主要是由实体和领域服务来实现的其中实体会采用充血模型来实现所有与之相关的业务功能。

  实体和领域服务在实现业务逻辑上不是同级的当领域中的某些功能单一实体或者值对象不能实现时领域服务就会出马它可以组合聚合内的多个实体或者值对象实现复杂的业务逻辑。

  基础层是贯穿所有层的它的作用就是为其它各层提供通用的技术和基础服务包括第三方工具、驱动、消息中间件、网关、文件、缓存以及数据库等。比较常见的功能还是提供数据库持久化。

  基础层包含基础服务它采用依赖倒置设计封装基础资源服务实现应用层、领域层与基础层的解耦降低外部资源变化对应用的影响。

  DDD 分层架构中的要素其实和三层架构类似只是在 DDD 分层架构中这些要素被重新归类重新划分了层确定了层与层之间的交互规则和职责边界。

  重点关注图中的红色线c;它们是非常重要的分界线c;这三种架构里面都有它的作用就是将核心业务逻辑与外部应用、基础资源进行隔离。

  领域层实现面向领域模型实现领域模型的核心业务逻辑属于原子模型

  它需要保持领域模型和业务逻辑的稳定对外提供稳定的细粒度的领域服务所以它处于架构的核心位置。

  应用层实现面向用户操作相关的用例和流程对外提供粗粒度的 API 服务

  。它就像一个齿轮一样进行前台应用和领域层的适配接收前台需求随时做出响应和调整尽量避免将前台需求传导到领域层。

  DDD 并没有给出标准的代码模型不同的人可能会有不同理解。这里我们在使用的时候还是建议按照欧创新架构师总结的来进行适用具体如下

  根据 DDD 分层架构模型建立了标准的微服务代码模型在代码模型里面各代码对象各据其位、各司其职共同协作完成微服务的业务逻辑。它包括用户接口层、应用层、领域层和基础层分层架构各层的职责边界非常清晰又能有条不紊地分层协作。

  用户接口层面向前端提供服务适配面向资源层提供资源适配。这一层聚集了接口适配相关的功能。

  应用层职责实现服务组合和编排适应业务流程快速变化的需求。这一层聚集了应用服务和事件相关的功能。

  领域层实现领域的核心业务逻辑。这一层聚集了领域模型的聚合、聚合根、实体、值对象、领域服务和事件等领域对象以及它们组合所形成的业务能力。

  基础层贯穿所有层为各层提供基础资源服务。这一层聚集了各种底层资源相关的服务和能力。

  业务逻辑从领域层、应用层到用户接口层逐层封装和协作对外提供灵活的服务既实现了各层的分工又实现了各层的协作。

  主要存放用户接口层与前端交互、展现数据相关的代码。前端应用通过这一层的接口向应用服务获取展现所需的数据。这一层主要用来处理用户发送的 Restful 请求解析用户输入的配置文件并将数据传递给 Application 层。数据的组装、数据传输格式以及 Facade 接口等代码都会放在这一层目录里。

  主要存放应用层服务组合和编排相关的代码。应用服务向下基于微服务内的领域服务或外部微服务的应用服务完成服务的编排和组合向上为用户接口层提供各种应用数据展现支持服务。应用服务和事件等代码会放在这一层目录里。

  Event事件这层目录主要

  。前者主要存放事件发布相关代码后者主要存放事件订阅相关代码事件处理相关的核心业务逻辑在领域层实现。

  为了实现事件的统一管理建议你将微服务内所有事件的发布和订阅的处理都统一放到应用层事件相关的核心业务逻辑实现放在领域层

  。通过应用层调用领域层服务来实现完整的事件发布和订阅处理流程。

  Service应用服务这层的服务是

  会对多个领域服务或外部应用服务进行封装、编排和组合对外提供粗粒度的服务

  。应用服务主要实现服务组合和编排是一段独立的业务逻辑。你可以将所有应用服务放在一个应用服务类里也可以把一个应用服务设计为一个应用服务类以防应用服务类代码量过大。

  存放领域层核心业务逻辑相关的代码。领域层可以包含多个聚合代码包它们共同实现领域模型的核心业务逻辑。聚合以及聚合内的实体、方法、领域服务和事件等代码会放在这一层目录里。

  Aggregate聚合它是

  。在聚合内定义聚合根、实体和值对象以及领域服务之间的关系和边界。聚合内实现高内聚的业务逻辑它的代码可以独立拆分为微服务。

  以聚合为单位的代码放在一个包里的主要目的是为了业务内聚而更大的目的是为了以后微服务之间聚合的重组

  。聚合之间清晰的代码边界可以让你轻松地实现以聚合为单位的微服务重组在微服务架构演进中有着很重要的作用。

  存放聚合根、实体、值对象以及工厂模式Factory相关代码

  Service领域服务它

  中你也可以把每一个领域服务设计为一个类。如果领域服务内的业务逻辑相对复杂建议将一个领域服务设计为一个领域服务类避免由于所有领域服务代码都放在一个领域服务类中而出现代码臃肿的问题。

  Repository仓储它

  存放所在聚合的查询或持久化领域对象的代码通常包括仓储接口和仓储实现方法

  。为了方便聚合的拆分和组合我们设定了一个原则

  。特别说明按照 DDD 分层架构仓储实现本应该属于基础层代码但为了在微服务架构演进时

  保证代码拆分和重组的便利性把聚合仓储实现的代码放到了聚合包内

  存放基础资源服务相关的代码为其它各层提供的通用技术能力、三方软件包、数据库服务、配置和基础资源服务的代码都会放在这一层目录里。

  这些方法和服务的分层以及领域类型比如实体方法、领域服务和应用服务等它们之间的调用和组合的依赖关系。

  在严格分层架构模式下不允许服务的跨层调用每个服务只能调用它的下一层服务。服务从下到上依次为实体方法、领域服务和应用服务。建议采用服务逐层封装的方式服务的封装和调用主要有以下几种方式

  领域服务会对多个实体和实体方法进行组合和编排供应用服务调用。

  应用服务会对多个领域服务进行组合和编排暴露给用户接口层供前端应用调用。

  多个应用服务可能会对多个同样的领域服务重复进行同样业务逻辑的组合和编排。当出现这种情况时就需要分析是不是领域服务可以整合了。可以将这几个不断重复组合的领域服务合并到一个领域服务中实现这样领域模型将会越来越精炼更能适应业务的要求。

  事件风暴结束时领域模型聚合内一般会有聚合、实体、命令和领域事件等领域对象。

  故事分析和微服务设计后微服务的聚合内一般会有聚合、聚合根、实体、值对象、领域事件、领域服务和仓储等领域对象。

  大多数情况下领域模型的业务实体与微服务的数据库实体是一一对应的。

  但某些领域模型的实体在微服务设计时可能会被设计为多个数据实体或者实体的某些属性被设计为值对象。

  实体采用充血模型在实体类内实现实体的全部业务逻辑。这些不同的实体都有自己的方法和业务行为比如地址实体有新增和修改地址的方法银行账号实体有新增和修改银行账号的方法。

  聚合根来源于领域模型聚合根是一种特殊的实体它有自己的属性和方法。聚合根可以实现聚合之间的对象引用还可以引用聚合内的所有实体。

  在个人客户聚合里个人客户这个实体是聚合根它负责管理地址、电话以及银行账号的生命周期。

  个人客户聚合根通过工厂和仓储模式实现聚合内地址、银行账号等实体和值对象数据的初始化和持久化。

  聚合根类放在代码模型的 Entity 目录结构下。聚合根有自己的实现方法比如生成客户编码新增和修改客户信息等方法。

  根据需要将某些实体的某些属性或属性集设计为值对象。值对象类放在代码模型的 Entity 目录结构下。

  有些领域对象可以设计为值对象也可以设计为实体我们需要根据具体情况来分析

  如果领域模型中领域事件会触发下一步的业务操作我们就需要设计领域事件。

  如果一个业务动作或行为跨多个实体我们就需要设计领域服务。

  通过对多个实体和实体方法进行组合完成核心业务逻辑。可以认为领域服务是位于实体方法之上和应用服务之下的一层业务逻辑。

  根据实体对象之间的业务关联性将业务紧密相关的多个实体进行组合形成聚合聚合之间是第一层边界。

  根据业务及语义边界等因素将一个或者多个聚合划定在一个限界上下文内形成领域模型限界上下文之间的边界是第二层边界。

  为了方便理解我们将这些边界细分为逻辑边界、物理边界和代码边界。

  逻辑边界主要定义同一业务领域或应用内紧密关联的对象所组成的不同聚类的组合之间的边界。

  微服务内聚合之间的边界就是逻辑边界。一般来说微服务会有一个以上的聚合在开发过程中不同聚合的代码隔离在不同的聚合代码目录中。它是一个虚拟的边界强调业务的内聚可根据需要变成物理边界也就是说聚合也可以独立为微服务。

  微服务的架构演进并不是随心所欲的需要遵循一定的规则这个规则就是逻辑边界。微服务架构演进时在业务端以聚合为单位进行业务能力的重组在微服务端以聚合的代码目录为单位进行微服务代码的重组。

  微服务之间的边界是物理边界。它强调微服务部署和运行的隔离关注微服务的服务调用、容错和运行等。

  物理边界主要从部署和运行的视角来定义微服务之间的边界。不同微服务部署位置和运行环境是相互物理隔离的分别运行在不同的进程中。这种边界就是微服务之间的物理边界。

  有些项目团队在将集中式单体应用拆分为微服务时首先进行的往往不是建立领域模型而只是按照业务功能将原来单体应用的一个软件包拆分成多个所谓的“微服务”软件包而这些“微服务”内的代码仍然是集中式三层架构的模式“微服务”内的代码高度耦合逻辑边界不清晰这里我们暂且称它为

  而随着新需求的提出和业务的发展这些小单体微服务会慢慢膨胀起来。当有一天你发现这些膨胀了的微服务有一部分业务功能需要拆分出去或者部分功能需要与其它微服务进行重组时你会发现原来这些看似清晰的微服务不知不觉已经摇身一变变成了臃肿油腻的大单体了而这个大单体内的代码依然是高度耦合且边界不清的。

  这种单体式微服务只定义了一个维度的边界也就是微服务之间的物理边界本质上还是单体架构模式。微服务设计时要考虑的不仅仅只有这一个边界别忘了还要定义好微服务内的逻辑边界和代码边界这样才能得到你想要的结果。

  不同层或者聚合之间代码目录的边界是代码边界。它强调的是代码之间的隔离方便架构演进时代码的重组。

  前端应用调用发布在 API 网关上的 Facade 服务Facade 定向到应用服务。应用服务作为服务组织和编排者它的服务调用有这样两种路径

  。此时领域服务会组装实体和实体方法实现核心领域逻辑。领域服务通过仓储服务获取持久化数据对象完成实体数据初始化。

  。这种方式主要针对像缓存、文件等类型的基础层数据访问。这类数据主要是查询操作没有太多的领域逻辑不经过领域层不涉及数据库持久化对象。

  微服务内通过事件总线;EventBus完成聚合之间的异步处理。

  微服务之间通过消息中间件完成。异步化的领域事件驱动机制是一种间接的服务访问方式。

  当应用服务业务逻辑处理完成后如果发生领域事件可调用事件发布服务完成事件发布。

  DO 是实体和值对象的数据和业务行为载体承载着基础的核心业务逻辑。

  如果需要调用其它微服务的应用服务DO 会转换为 DTO完成跨微服务的数据组装和传输。

  如果 DTO 与 DO 是一对多的关系这时就需要进行 DO 数据重组。

  用户接口层会完成 DO 和 DTO 的互转完成微服务与前端应用数据交互及转换。

  、跨界学习、实操应用相结合的课程体系,重点培养具有大数据思维和应用创新的“π”型人才。2017年7

  总结三:具体应用设计分析 领域驱动设计DDD是一种设计思想,它可以同时指导中台业务建模和微服务设计(中台本质是业务模型,微服务是业务模型的系统落地),领域驱动设计强调领域模型和微服务设计的一体性...

  因为在大厂里,能提供架构师所需的分布式组件开发调试以及上线的经验,上进点的程序员只要跟着大流,多通过排查问题观察底层,多通过压测或部署组件多

  课程介绍 从 2009 年第一届 DevOpsDays 算起...本课程从 DevOps 历史源头出发,追踪 DevOpsDays 全球发展动态,并结合作者过去 4 年在国内外进行 DevOps 咨询和

  中面对真正的挑战,综合实力才以最脚踏实地的方式发挥影响和接受检验,我们也会发现思考,编程,创造

  总是不够的,“stay hungary stay foolish”绝对不是一...

  Go 转自:简介 近一两年来,微服务架构已经成为热门话题( microservices.io ),与传统的一体化应用架构相比,微服务架构在开发、...

  新的物质诞生,而随着数字化转型对传统行业的冲击,为应对快速的市场需求和业务创新发展,提升客户服务意识及服务

  成为各企业的主要关注点,通过积极引入DevOps,将开发、测试和 ...

  一:SharedResponsibility–职责共享 Theme Level State Description Reference Implementations 3+ 组织级结对...

  审计代码 传入参数a,进入parserIfLabel函数 ...发现参数a的模板,a的格式要匹配pattern,如{if:payload}{end if} ...可知ifstr是a中匹配的第一组的值,即payload中的值 ...Ifstr经过很多过滤替换,最终里面不包含大...

  很大的帮助。 本文从Raft成员变更理论出发,介绍了Raft成员变更和单步成员变更的问题,其中包括Raft著名的Bug。 对于Raft成员变更...

  一段时间,从零开始构建推荐系统的过程中,在总结了业界一些成功的经验的同时,也摸索了一些有效的

  方法。愿在此沉淀,通过交流扩展眼界。推荐系统重在算法,这也是各大公司...

  在Android M中权限系统被重新设计,发生了颠覆性的变化,很多人把握...这里

  一切关于Android运行时权限你需要知道的,包括如何在代码中实现,如果你以前不知道这些东西,现在我将在详解之后给你一个最佳的

  在DevOps知识地图 中介绍了DevOps方法论的来源和知识体系。 下面是根据《DevOps

  。 作者:鲁严波 前言 配置管理作为软件开发中重要的一环,肩负着连接代码和环境的职责,能很好的分离开发人员和维护人员的关注点。 Nacos的配置管理功能就很好地满足了云原生应用...

  2017年11月29日,清华-青岛数据科学研究院(以下简称:数据院)...此次讲座属于清华大数据

  模块”环节,通过组织学界和业界的专家、学者,以及具有丰富比赛经验的学生进行学术分享,让大数据

  国内关于领域驱动设计(Domain Driven Design,DDD)的原创书籍少之又少,甚至可以说没有,作者结合十余年

  领域驱动设计的经验与心得,并糅合了 DDD 社区最新发展的理论知识与最佳

  本期我们采访的讲师是来自搜狗架构师刘建——负责商业平台基础架构,对分布式计算、服务化、流式计算、数据库架构、高可用高可靠等方面都

  (一)小试牛刀》从最简单的Spring Security入门案例开始展开,分析了HTTP Basic在Spring Security中的应用原理以及部分源码。本篇文章将从最常用的认证方式——表单...

  活动已经结束,蓦然回首,虽然没有很长时间的锻炼,但却给我带来的影响远没结束。它使我们走出校园,走出课堂,走向社会,走上了与

  情况 人口老龄化已经成为世界各国广泛关注的社会性问题之一,经查阅资料显示,截止2013年底,我国60周...

延伸阅读:

标签:实践技能

上一篇:湖南中公教育

下一篇:返回列表

留言与评论(共有 0 条评论)
   
验证码: