接触领域驱动设计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. Linux学习之CentOS(二十)--CentOS6.4下修改MySQL编码方法

    但是当我们在试图对数据库中的数据进行备份或者将sql文件导入到我们的数据库时可能就会碰到编码的问题,在windows下安装mysql时我们可以在安装的时候就选择好整个数据库的编码方式(通常设置成utf ...

  2. UP Board 人若有大胆,板子就很惨:首次上电开机失败

    前言 原创文章,转载引用务必注明链接. 注意:拍照自带抖动功能,画质大家凑合着看.冬日天气干燥,手触摸板子前建议流水洗手或者握持大体积导电体将静电放走. 本文使用Markdown写成,为获得更好的阅读 ...

  3. 【CVE-2016-10009】OpenSSH < 7.4 - agent Protocol Arbitrary Library Loading

    粗看了一下,发现这个漏洞还是比较鸡肋的.如果前提条件满足,该漏洞可以在ssh server执行任意指令.不过前提是:1.攻击者可以往受害者磁盘上写文件.

  4. webapi-创建项目

  5. java创建文件和目录

    java创建文件和目录 2013-09-04 12:56 99933人阅读 评论(7) 收藏 举报  分类: JAVA基础(10)  版权声明:本文为博主原创文章,未经博主允许不得转载. 创建文件和目 ...

  6. throttle和debounce简单实现

    function debounce(delay,fn){ var timer; return function(){ var ctx = this,args = arguments; clearTim ...

  7. 解决Maven工程中报 Missing artifact jdk.tools:jdk.tools:

    jdk.tools:jdk.tools是与JDK一起分发的一个JAR文件,可以如下方式加入到Maven项目中:<dependency>    <groupId>jdk.tool ...

  8. permission denied to create extension "hstore"解决方案

    首先 sudo -u postgres psql postgres 进入数据库后输入命令 ALTER USER mydb_user WITH SUPERUSER;        (把某个用户设置为超级 ...

  9. Delphi XE7中各种字符串与字符类型的内存结构

    1. ShortString 类型 定义:type ShortString = string[255]; 内存结构与大小:ShortString 是每个字符为单字节的字符串.ShortString 的 ...

  10. 修改Centos 6.5的yum源

    1.进入目录 cd /etc/yum.repos.d/ 2.保持副本 mv CentOS-Base.repo CentOS-Base.repo.backup 3.下载新的CentOS-Base.rep ...