前言

战术设计

战略设计为我们提供一种高层视野来审视我们的软件系统,主要包括领域/子域、通用语言、限界上下文和架构风格等概念,

而战术设计则将战略设计进行具体化和细节化,它主要关注的是技术层面的实施,也是对程序员来得最实在的地方。

战术设计的目的是保证战略的实现。在DDD中,代码就是设计本身,你不再需要那些繁文缛节的并且永远也无法得到实时更新的设计文档。

警惕贫血对象,要创建行为饱满的领域对象并不难,我们需要转变一下思维,将领域对象当做是服务的提供方,而不是数据容器,多思考一个领域对象能够提供哪些行为,而不是数据。

实体

一个实体模型就是一个独立的事物,采用充血模型,具有业务属性和业务行为。每个实体都拥有一个唯一的标识符,可以将它的个性化和所有其他类型相同或者不同的实体区分开。许多时候,实体是可变的,它的状态会随着时间发生变化。

对一个实体进行多次修改,修改后的数据和原来可能会不大相同,但它们依然是同一个实体,因为唯一标识没变。

值对象

一个值对象,是对一个不变的概念整体所建立的模型,没有一个唯一的标识符。在这个模型中,值就真的只有一个值。和实体不一样,它没有唯一标识符,而是由值类型封装的属性对比来决定相等性。此外,一个值对象不是实物,而是常常用来描述、量化或者测量一个实体。

一个典型的值对象是地址值对象,比如下单中,有下单人、商品信息、优惠信息、还有收货地址信息,如果地址信息用省、市、区等属性表示,会有些零碎,拿出来构成一个“地址”属性,会更合适一些,这个多个值的集合就是值对象了。

聚合

在DDD中,实体和值对象是很基础的领域对象,实体跟值对象都只是个体化的对象,它们的行为表现出来的是个体能力。聚合用来确保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性。

聚合是由业务和逻辑紧密关联的实体和值对象组合而成的。聚合是数据修改和持久化的基本单元。

聚合设计的四条基本规则

  • 在聚合边界内保护业务规则不变性
  • 聚合要设计得小巧
  • 只能通过标识符引用其他聚合
  • 使用最终一致性更新其他聚合

聚合根

每个聚合都有一个根实体,叫做聚合根,外界只能通过聚合根跟聚合通信。聚合根的主要目的是为了避免由于复杂数据模型缺少统一的业务规则控制,而导致聚合、实体之间数据不一致的问题。

如果把聚合比作一个团队,那么聚合根就是团队的leader,其他团队的需求都需要跟该团队的leader商量后才能开始动工。

领域服务

当某个操作不适合放在聚合和值对象上时,最好的方式便是使用领域服务了。

可以使用领域服务的地方,过度使用领域服务将导致贫血领域模型。

  • 执行一个显著的业务操作过程
  • 对领域对象进行转换
  • 已多个领域对象作为输入进行计算,结果产生一个值对象

领域服务不需要定义接口,直接定义实现即可

  • 如果接口有不同的实现,那么需要考虑领域中是否存在特定的功能行为
  • 如果我们采用了依赖注入或者工厂,即便接口和实现类是合并在一起的,我们依然能达到这样的目的。依赖倒置容器(例如 Spring)将完成服务实例的注入工作,由于客户端并不负责服务的实例化,它并不知道接口和实现类是分开的还是合并在一起的。

领域服务与实体方法的区别

  • 实体方法完成单一实体自身的业务逻辑,相对简单的原子业务逻辑
  • 领域服务则是多个实体组合出的相对服务的业务逻辑

仓储

仓储用于保存和获取聚合对象,应该将仓储看作一个对象的集合,而不是数据库的CRUD,更不是一张表一个仓储。

需要做到让用户无感知的,以为就在内存中使用一个集合一样。

仓储的出现就是为了让大家聚焦领域模型,不要聚焦表结构。

领域事件

领域事件是一条记录,记录着在限界上下文中发生的对业务产生重要影响的事情,经常用于保证两个聚合之间的一致性。

对于领域事件的命名,必须体现出模型的通用语言,这些名词是连接模型之间的桥梁,对发生的事情进行充分的沟通至关重要。

领域事件类型名称应该是对过去发生事情的陈述,即动词的过去式,如OrderCreated。

参考资料

  • 《领域驱动设计——软件核心复杂性应对之道》
  • 《实现领域驱动设计》
  • 《领域驱动设计精粹》

DDD(领域驱动设计)--战术设计的更多相关文章

  1. DDD 领域驱动设计-商品建模之路

    最近在做电商业务中,有关商品业务改版的一些东西,后端的架构设计采用现在很流行的微服务,有关微服务的简单概念: 微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独 ...

  2. DDD领域驱动设计落地实践(十分钟看完,半小时落地)

    一.引子 不知今年吹了什么风,忽然DDD领域驱动设计进入大家视野.该思想源于2003年 Eric Evans编写的"Domain-Driven Design领域驱动设计"简称DDD ...

  3. 浅谈我对DDD领域驱动设计的理解

    从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...

  4. DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)

    上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...

  5. DDD 领域驱动设计-两个实体的碰撞火花

    上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...

  6. DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(2)

    上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(1)> 阅读目录: 抽离 IRepository 并改造 Reposi ...

  7. DDD 领域驱动设计-领域模型中的用户设计

    上一篇:<DDD 领域驱动设计-如何控制业务流程?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新,并增加了 ...

  8. DDD 领域驱动设计-如何控制业务流程?

    上一篇:<DDD 领域驱动设计-如何完善 Domain Model(领域模型)?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sa ...

  9. DDD 领域驱动设计-如何完善 Domain Model(领域模型)?

    上一篇:<DDD 领域驱动设计-如何 DDD?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 阅读目录: ...

  10. DDD领域驱动设计之领域服务

    1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 3.DDD领域驱动设计之领域基础设施层 什么是领域服务,DDD书中是说,有些类或者方法,放实体A也不好,放实体B ...

随机推荐

  1. 力扣 - 768. 最多能完成排序的块II

    目录 题目 思路 代码实现 复杂度分析 题目 这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一 ...

  2. visual c++6.0使用VA注意事项

    visual c++6.0使用VA时配置: (1)因为VA安装时会自动检索MSDEV.exe:如果V6安装在XP或者win7系统上,直接安装,添加addin即可: (2)但是如果安装在win8上,V6 ...

  3. SQL存储过程返回值

    1 SQL存储过程返回值有3种 1.1 直接return返回(例如 return 1): 1.2 通过参数output返回(例如字符串类型): 1.3 直接返回程序集(Dataset程序集). 2 用 ...

  4. create event[]

    一.前言自 MySQL5.1.6起,增加了一个非常有特色的功能–事件调度器(Event Scheduler),可以用做定时执行某些特定任务(例如:删除记录.对数据进行汇总等等),来取代原先只能由操作系 ...

  5. 预训练模型——开创NLP新纪元

    预训练模型--开创NLP新纪元 论文地址 BERT相关论文列表 清华整理-预训练语言模型 awesome-bert-nlp BERT Lang Street huggingface models 论文 ...

  6. .Net核心依赖项注入:生命周期和最佳实践

    在讨论.Net的依赖注入(DI)之前,我们需要知道我们为什么需要使用依赖注入 依赖反转原理(DIP): DIP允许您将两个类解耦,否则它们会紧密耦合,这有助于提高可重用性和更好的可维护性 DIP介绍: ...

  7. Ceph部署的时候修改默认权重

    前言 部署集群的时候权重是默认生成的,这个是根据磁盘大小分配的,我们有的时候需要去修改一下这个默认权重 修改 如果统一的初始值,那么直接添加参数即可 osd_crush_initial_weight ...

  8. 使用进程池模拟多进程爬取url获取数据,使用进程绑定的回调函数去处理数据

    1 # 使用requests请求网页,爬取网页的内容 2 3 # 模拟使用进程池模拟多进程爬取网页获取数据,使用进程绑定的回调函数去处理数据 4 5 import requests 6 from mu ...

  9. phpmyadmin 4.8.1任意文件包含(CVE-2018-12613)

    简介 环境复现:https://gitee.com/xiaohua1998/hctf_2018_warmup 考察知识点:文件包含漏洞(phpmyadmin 4.8.1任意文件包含) 线上平台:榆林学 ...

  10. [web安全原理分析]-XEE漏洞入门

    前言 1 前言 XXE漏洞 XXE漏洞全称(XML External Entity Injection)即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致 ...