接触领域驱动设计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. Couldn't open CUDA library cublas64_80.dll etc. tensorflow-gpu on windows

    I c:\tf_jenkins\home\workspace\release-win\device\gpu\os\windows\tensorflow\stream_executor\dso_load ...

  2. UML大战需求分析--阅读笔记02

    这次阅读了第三章--类图.本章主要讲解了类图的基本使用规则和一些使用的例子.类图是UML中非常重要的一部分,作用很大. 类图之间有五种关系:关联关系,聚合关系,组合关系,泛化关系,依赖关系.关联关系有 ...

  3. wifi万能钥pc版提示手机未连接

     关于PC版万能钥匙的用法 大部分人都是在“未连接到手机”再不知道怎么搞了 怎么连接到手机呢? 首先要把你的手机变成路由器 让电脑连上 这个都知道怎么搞吧 手机版万能钥匙有个一键让手机变成热点 再用电 ...

  4. java 多线程 4 线程池

    系统启动一个新线程的成本是比较高的,因为它涉及到与操作系统的交互.在这种情况下,使用线程池可以很好的提供性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池. 与数据库连接池类似 ...

  5. CSS解决未知高度垂直居中

    尽管有CSS的vertical-align特性,但是并不能有效解决未知高度的垂直居中问题(在一个DIV标签里有未知高度的文本或图片的情况下). 标准浏览器如Mozilla, Opera, Safari ...

  6. php.h: No such file or directory

    建立一个php的include路径到/usr/include的软连接就好了 ln -s /usr/include/php-zts/* /usr/include/

  7. Javascript面向对象特性实现封装、继承、接口详细案例——进级高手篇

    Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript ...

  8. 前端构建工具的用法—grunt、gulp、browserify、webpack

    随着前端项目的飞速发展,项目越来越大.文件越来越多,前端工程化的工具也越来越多.下面介绍目前最流行的四种构建工具——grunt.gulp.browserify.webpack 所有的构建工具都是基于N ...

  9. java基础杂烩

    1. int ... arg: 可变参数   2. 数组拷贝放在JDK中的System类中,arraycopy(原数组,从原数组那一个索引开始拷贝,目标数组,在目标数组哪一个位置开始粘贴,拷贝元素的个 ...

  10. bash学习

    if 的使用 declare -i x=10 if [ $x -lt 14 ];then echo $x'小于14'; elif [ $x -gt 9 ];then echo $x'大于9'; els ...