接触领域驱动设计DDD有一年多的时间了,中间看过不少书,参与过一些讨论(ENode QQ群)。目前对DDD的认知还停留在理论阶段,所以对领域建模非常感兴趣,这里说的建模是指以DDD的思想为指导再加上DDD的工具,比如聚合、实体、值对象等等。

  昨天有群友分享了一个建模的案例,我想在这儿记录下来,有两个目的:1、为自己学习DDD储存素材  2、锻炼自己写文章的能力

  关于DDD中的一些概念,请见如下文章链接:

  http://www.cnblogs.com/ivanzheng/p/5533162.html(Ivan翻译)

  http://www.cqrs.nu/Faq(这是原文链接,英文好的可以直接读这个)

场景


  大家肯定都听说过视频课程网站吧,比如慕课网。这儿要说的场景跟这个网站的后台管理比较相关。比如,课程的作者可以上传一些课程视频(Video)到该网站,然后再创建一个课程(Course),把之前上传的视频放到该课程下,等所有的课程视频都审核通过了,则就可以发布这个课程了,学习者就可以在网上看到该课程。

  上面那段话只是对“视频课程”场景做了大致的描述,下面我将逐条以用例(Use Case)的方式做一个列表:

  1. 用户可以把一个或多个视频上传到网站,并等待审核
  2. 用户创建了一个课程,比如叫《Lisp从入门到放弃》
  3. 用户把一个或多个视频关联到该课程下(关联的时候不要求视频是已审核状态)
  4. 用户发布创建的课程时,要求其下至少关联3个以上的视频,且这些视频必须是已审核通过。只有满足了这两个要求才能发布课程
  5. 一个视频可以放到多个课程下

  从Use Case中可以很容易的得到这几个概念(名词):视频、课程。(因为本次建模只关注课程与视频的关系,不考虑用户);业务的行为概念也很容易得到:审核、发布。

  业务模型很简单,课程和视频是典型的多对多关系。

分析


  通过场景可以分析出如下两个实体:视频、课程

  必须满足的业务规则:

      1、发布课程时,要求该课程下的关联的视频个数≥3

      2、发布课程时,其下的所有视频必须都是已经审核通过的状态

  很显然,在场景描述时,我们隐含的表达了以下这些概念:

      1、视频可以单独上传,管理,审核等,从业务规则上来看,它不依赖于任何课程的状态

      2、课程可以单独创建,在发布时需要依赖视频的个数和状态

  所以,视频显然是一个聚合根。在现有的业务场景中,课程也是一个聚合根,这个应该没有歧义。业务规则1和2也是在课程这个聚合下体现,并保证业务规则被满足。

设计


  有一个最容易想到的非DDD的设计,代码可能如下:

class Course
    {
        public string Id { get; }
        public ICollection<Video> Videos { get; }
        public void Publish()
        {
            )
                throw Exception("One course must associate 3 videos.");
            if (Videos.Any(v => !v.Approved))
                throw Exception("All videos need to be approved.");
            ...
        }
    }

    class Video
    {
        public string Id { get; }
        public bool Approved { get; set; }
        public ICollection<Course> Courses { get; }
    }

  先不说这个设计的好坏,我们直接来看从DDD的角度如何设计这两个聚合根。

  首先一点,聚合之间不可直接引用(内存引用),必须以Id的方式引用,因为根据定义聚合是不允许接触到他们外部的. (如果允许了那意味着聚合不再是一个事务边界, 我们也不再能充分的推导出聚合有能力确保他的不变性;这也将妨碍到聚合的分片处理)

  因为课程发布时,需要验证其下所关联视频个数和是否全部审核,所以需要一个视频信息的实体聚合在课程下。

class Course
    {
        public string Id { get; }
        public ICollection<VideoInfo> VideoInfos { get; } //视频信息的实体集合
        public void Publish()
        {
            )
                throw Exception("One course must associate 3 videos.");
            if (VideoInfos.Any(v => !v.Approved))
                throw Exception("All videos need to be approved.");
            ...
        }
    }

    //视频信息,至少包含视频Id和是否已审核的状态
    class VideoInfo
    {
        public string VideoId { get; }
        public bool VideoApproved { get; set; }
    }

    class Video
    {
        public string Id { get; }
        public bool Approved { get; set; }
        public ICollection<string> Courses { get; } //Course Id的集合
    }

  为了保证高并发及性能,聚合之间采用最终一致性,且聚合之间的交互通过Saga来完成。当视频审核通过后,视频聚合根发消息通知所有关联它的课程,以便更新课程中的VideoInfo的状态,所以Video聚合根下要有课程Id集合的原因。

  

总结


  在DDD中,有个例子经常被用来讲解聚合、实体、值对象的概念,那就是电商领域的订单(Order)、订单项(OrderLine)、商品(Product)。其实上面的场景很类似于Order、OrderLine、Product之间的关系,课程相当于Order,视频相当于Product,视频信息相当于OrderLine。这也许就是举一反三的体现吧。

  注:此图来源于汤雪华的博客 

  欢迎大家加入ENode群讨论DDD和牛逼的ENode框架,QQ群号:185916873。群主(汤雪华,netfocus)博客:http://www.cnblogs.com/netfocus/

DDD建模案例----“视频课程”场景的更多相关文章

  1. 《Python从菜鸟到高手》已经出版,开始连载了,购买送视频课程

    好消息,<Python从菜鸟到高手>已经出版!!!   JetBrains官方推荐图书!JetBrains官大中华区市场部经理赵磊作序!送2400分钟同步视频课程!500个案例,400道P ...

  2. Spring Boot 实战与原理分析视频课程

    Spring Boot 实战与原理分析视频课程 链接:https://pan.baidu.com/share/init?surl=PeykcoeqZtd1d9lN9V_F-A 提取码: 关注公众号[G ...

  3. IT视频课程集

    马哥Linux培训视频课程:http://pan.baidu.com/s/1pJwk7dp Oracle.大数据系列课程:http://pan.baidu.com/s/1bnng3yZ 天善智能BI培 ...

  4. IT视频课程集(包含各类Oracle、DB2、Linux、Mysql、Nosql、Hadoop、BI、云计算、编程开发、网络、大数据、虚拟化

    马哥Linux培训视频课程:http://pan.baidu.com/s/1pJwk7dp Oracle.大数据系列课程:http://pan.baidu.com/s/1bnng3yZ 天善智能BI培 ...

  5. 传智 Python基础班+就业班+课件 【最新完整无加密视频课程】

    点击了解更多Python课程>>> 传智 Python基础班+就业班+课件 [最新完整无加密视频课程] 直接课程目录 python基础 linux操作系统基础) 1-Linux以及命 ...

  6. 《Python爬虫技术:深入理解原理、技术与开发》已经出版,送Python基础视频课程

    好消息,<Python爬虫技术:深入理解原理.技术与开发>已经出版!!!   JetBrains官方推荐图书!JetBrains官大中华区市场部经理赵磊作序!送Python基础视频课程!J ...

  7. 视频课程 | Kubernetes的兴起

    视频课程 | Kubernetes的兴起 原创: 京小云 京东云开发者社区  4月3日 京东云开发者社区在3月底于北京举行了以"Cloud Native时代的应用之路与开源创新"为 ...

  8. 花了半年时间,我把Pink老师的HTMLCSS视频课程,整理成了10万字的Markdown笔记!

    说明:本文内容真实!!!不是推广!!! 学习前端的同学应该都或多或少听说过 Pink 老师,我个人觉得 Pink 老师的前端视频教程应该说是目前B站上最好的了,没有之一! Pink老师 HTML CS ...

  9. QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL

    QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL 课程1   C语言程序设计高级实用速成课程 基础+进阶+自学 课程2   C语言程序设计Windows GDI图形绘 ...

随机推荐

  1. 【先定一个小目标】Windows下安装MongoDB 3.2

    1.MongoDB 安装 官网提供了三个版本下载: - MongoDB for Windows 64-bit 适合 64 位的 Windows Server 2008 R2, Windows 7 , ...

  2. Python之路3【知识点】白话Python编码和文件操作

    Python文件头部模板 先说个小知识点:如何在创建文件的时候自动添加文件的头部信息! 通过:file--settings 每次都通过file--setings打开设置页面太麻烦了!可以通过:View ...

  3. hub,桥,交换机,路由器的区别

    1.四种设备在网络中的物理位置 如下图 2.这四种设备的本质 这四种设备,不管怎样,他们都是进行包的转发,只不过转发的行为有些不一样而已 3.逐一介绍 对于hub,一个包过来后,直接将包转发到其他口. ...

  4. 常用function() 收集

    1.随机数生成函数(来源-微信支付demo案例) /** * * 产生随机字符串,不长于32位 * @param int $length * @return 产生的随机字符串 */ public st ...

  5. 室内定位系列(二)——仿真获取RSS数据

    很多情况下大家都采用实际测量的数据进行定位算法的性能分析和验证,但是实际测量的工作量太大.数据不全面.灵活性较小,采用仿真的方法获取RSS数据是另一种可供选择的方式.本文介绍射线跟踪技术的基本原理,以 ...

  6. ES6 语法笔记

    //如果使用let,声明的变量仅在块级作用域内有效 { var a = 1; let b = 2; } console.log(a); // 1 console.log(b); // Uncaught ...

  7. Mysql基础(二)

    学习路线:数据约束-> 数据库的设计过程-> 存储过程的相关知识-> 触发器-> 权限管理 (一)数据约束 1.1.默认值的设置 创建员工表emp 将默认地址设置为'中国'my ...

  8. JAVA之线程同步的三种方法

    最近接触到一个图片加载的项目,其中有声明到的线程池等资源需要在系统中线程共享,所以就去研究了一下线程同步的知识,总结了三种常用的线程同步的方法,特来与大家分享一下.这三种方法分别是:synchroni ...

  9. JavaScript原型

    prototype与_proto_ 对象的 prototype 属性的方法.属性为对象所属的那一"类"所共有.对象原型链通过 proto 属性向上寻找. 为 proto 指定 nu ...

  10. 思考JavaScript异常如何转为知识库?

    线上 js 报错会变成一个邮件,发给前端开发 team,每个人自己认领.解决.其实这是一个不错的选择,也解决了最基本的问题:立即响应,修掉.不过也存在着一个问题,如何避免同样的错误?我的初步想法是这样 ...