在开篇词中我们说过,为了让你更好地掌握 DDD,咱们这门课设置了一个贯穿始终的案例。我们会模仿真实的敏捷开发过程,把案例分成三个迭代,每个迭代的需求规模逐渐扩大,复杂性也逐渐增加。为了满足变化的需求,就会出现新的问题,为了解决这些问题,咱们就会引入新的 DDD 模式和实践,或者深化之前学过的知识。
今天开始,咱们通过迭代一,实现一个“麻雀虽小、五脏俱全”的项目。打通从需求分析,到领域建模,再到架构设计,最后到数据库和代码实现的完整闭环。
学完迭代一,你就可以理解 DDD 实践中那些最基本的套路了,甚至还可以在自己实际工作的项目里,选择一个小的“切片”,开始尝试落地 DDD。
当然了,在实践过程中,你可能也会遇到这样那样的问题,别急,这些问题的答案,很可能就在迭代二和迭代三的内容里。当然,你也可以把问题写在评论区,咱们一起讨论。
现在我们就来看一下这个迭代的具体需求。
这次迭代的需求
假设咱们俩要一起创业,经过了一轮市场调研,我们发现很多中小企业,都有诸如考勤管理、工时管理、项目管理、请假管理等通用的需求。我们姑且把这些应用统称为“企业管理系统”。
现在咱们顺便回顾一下领域驱动设计里“领域”这个词的含义。领域指的是软件要解决的那些业务问题,所以也可以叫业务领域,英文叫 Business Domain。在这个例子里,“企业管理”就是咱们要处理的领域。
过去,这些企业只能自建或购买软件系统,安装到公司内部的服务器上,甚至还要有自己的机房,软硬件以及运维成本都比较高。如果咱们能够把这些应用放在云上,那么企业就只需要有选择地购买我们提供的服务,按需付费就好了,不再需要自建机房,也不需要自己运维,可以有效降低企业的成本。
咱们这种系统,其实是基于 SaaS 的应用。所谓 SaaS,英文全称是 Software-as-a-Service,中文译作“软件即服务”。也就是说,软件不再像传统上那样交付并安装在客户本地,而是安装到云上,成为客户可以直接使用的服务。
SaaS 应用往往有个特点,用户五花八门,需求也是复杂多变。有些应用,如果只针对一个企业开发,本来挺简单,一旦放到云上,需求复杂性就会急剧上升。所以这次迭代,我们先做最简单的需求,后面两个迭代中我们再逐渐增加更多的灵活性。
由于云原生是这两年的热点,所以咱们凭这个点子幸运地拉到了投资,成立了一个叫做“卷卷通”的公司,开始着手研发系统的第一个版本。
由于不同行业的需求可能有较大差别,我们决定先聚焦于一个细分市场,之后再扩大范围。这个细分市场是我们比较熟悉的软件服务企业。这些企业会向自己的客户提供软件咨询、软件开发等等服务。
我们发现,这些企业的员工一般都工作在各个项目上。企业为了满足管理诉求,希望员工每周在系统中填报自己在哪些项目上花了多少时间,也就是所谓的报工时。所以我们第一步先来满足这个功能。但是,为了完成报工时的功能,我们还要首先对组织、人员、项目等等进行管理。
这里还要说一下,在领域驱动设计中有一个重要的角色叫做“领域专家”,叫业务专家也可以。领域专家需要对业务有总体性和本质性的把握,同时对业务发展也要有一定前瞻性,也就是说,心里要有一盘棋。
所以领域专家往往不是一线业务操作人员,在很多企业中,是那些干了很多年业务,逐渐成长起来的中级管理干部。还有一些企业,由产品经理担任领域专家。
那么,下面就由我暂时充当一下领域专家,详细说一下需求。
需求一:租户管理
这个系统可以给多家企业使用,每家企业的数据是隔离的。这些作为客户的企业,在云原生应用里,习惯上叫做“租户(tenant)”。咱们的系统就是要对这些租户进行增删改查等管理。这样的系统叫多租户系统。
假设我们做市场调研时,研究了一家叫“零零后科技有限公司”的企业,我们这个迭代,就先来满足这家企业的需求。
需求二:人员与组织管理
除了对租户进行增删改查等管理,我们还必须还有人员和组织管理。
零零后公司有多个开发中心,每个开发中心下有多个开发组。此外,还有公司直属的人事部、财务部等部门,系统要能够管理这些部门。
而且,我们对员工也要进行增删改查,并且把员工分配到部门。每个员工只能属于一个部门,比如王小牛属于开发一组。
下面这个图说明了需求中的人员和组织结构:
需求三:项目管理
接下来的需求是项目管理。
首先,租户要向它的客户提供服务,就要和客户签订合同,然后完成合同下的项目。比如说,租户零零后公司的客户可能包括安安保险公司、开心电信等等。那么,租户零零后公司就得为安安保险公司,安排一堆程序员帮他们开发核心保险系统项目,也得为开心电信,安排几个咨询师帮他们的敏捷转型做咨询。
这里具体的需求是这样的:
一个租户企业可以有多个客户,可以在系统里对客户信息进行增删改查,每个客户都有一个客户经理来跟进;
租户可以和它的客户签订多份合同,在系统中对合同信息进行增删改查,每个合同都有一个销售人员负责,可以开始和结束合同;
一个合同下可以有多个项目,系统可以对项目进行增删改查,每个项目有一个项目经理;
可以在系统中开始和结束项目,需要记录开始和结束时间等信息。项目结束以后,很多事情就不能随便做了。
下图说明了客户、合同、项目等概念的关系:
需求四:人员分配
有了项目,我们就可以把员工分配到项目上,也可以让一个人退出项目。而且,一个项目可以有多个人参与,一个人又可以同时参与多个项目。
除了这些,我们在把人分配到项目上的时候,还要记录每个人预计的投入百分比。比如说,王小牛在 A 项目上准备投入自己 30% 的时间,同时在 B 项目准备投入 40% 的时间等等。
之所以要记录预计的投入时间,是为了让企业能够在总体上调配人力资源。比如说管理人员看到王小牛还有 30% 的空余时间,就可以把它同时再安排到另一个项目上,以便实现“内卷最大化”。
下图说明了人员和项目投入的关系:
需求五:工时登记
把人员分配到项目上以后,我们就可以登记工时了。
我们这里规定只有当一个员工分配到一个项目上以后,才能通过这个项目报工时。这样的规定,一来是为了符合公司的管理要求,一个员工不能随意参加一个项目;二来也可以防止员工不小心把工时填到错误的项目上。
而且每个员工每周都需要在系统中填报工时,登记自己哪一天在哪个项目上投入了多少时间。当然,员工可对工时进行查询和修改,还可以为每天的投入的时间填写备注。你可以看一看工时登记的界面原型,进一步理解需求。
工时登记界面原型图
另外,尽管咱们尽量采用接近真实的案例,但也无法面面俱到。为了突出重点,我们这个课程还是省略了一些需求,比如说人员登录和权限控制等等。
现在,第一个迭代的需求基本上就说完了。这些需求看起来简单,其实关键点还是挺多的。而且更重要的是,在实际项目里,这些需求未必会这么清清楚楚、白纸黑字地列出来给你,更多是隐藏在领域专家的脑子里,需要我们去挖掘。
还有一些需求,我故意没有说得很详细,而是要在后续的开发过程中逐步揭示。这也是为了模拟实际项目的场景。
DDD 的基本开发过程
那么,我们怎么用一套系统化的方法,抽丝剥茧、一步一步地把需求落实到代码呢?咱们看看下面这张图,它表示了领域驱动设计中的主要流程。
领域驱动设计主要的开发流程
你可以看到,在整个开发流程中,首先是要捕获行为需求,也就是传统软件工程里的“获取需求”。这一步,我们要识别需求里有哪些流程、哪些功能,每个功能由什么人操作,会产生什么结果。
在传统软件工程中,这一步常用的方式是用例建模,也就是用 Use Case 来建模。在这套课程里面,我们会用 DDD 中比较流行的一种方法,叫做“事件风暴”。
接下来,我们就可以进行领域建模了,也就是通过建立领域模型,把需求里的主要业务知识描述清楚。DDD 的领域模型,大体上相当于传统软件工程中的分析模型。
基于领域模型,我们就可以做架构设计,包括进程间和进程内的架构。比如说微服务设计、中台设计都属于进程间架构。而 DDD 分层架构,通常说的是进程内架构。
然后就可以根据领域模型进行数据库设计,最后是代码实现。
这样,就形成了一个基于 DDD 的开发闭环。其实,在实践中,尤其是对敏捷软件开发来说,这些步骤不是线性的,而是反复迭代、互相穿插的。
DDD 是以领域模型为核心的。所以,我们可以把上面说的步骤分成模型的建立和模型的实现两部分。
模型的建立阶段,使用的都是业务术语,归根结底来自业务人员,业务人员不仅能听懂,而且负责评价建模的正确性。而模型的实现,则是业务人员不需要理解也不关注的,会包含技术实现方面的内容。这两者的边界很重要,我们在后面还会反复提到。
总结
好,今天就讲到这里,我们来总结一下。
这节课,我们概述了迭代一的目的和需求,并且介绍了 DDD 的基本开发过程。
咱们要开发的是一个基于 SaaS 的企业管理系统,它的需求主要包括租户管理、人员与组织管理、项目管理、人员分配和工时登记这几部分。
在介绍需求的同时,我们也穿插着介绍了领域和领域专家的概念。领域就是软件要解决的业务问题。领域专家则是十分了解业务知识本质的人。
DDD 开发的基本流程是以领域模型为核心的。整个流程可以分为模型的建立和模型的实现两部分。其中模型的建立一定要使用业务语言,而模型的实现则增加了技术语言。模型的建立,是通过领域专家和开发人员的协作共同完成的。
最后,今天讲的所有需求我都汇总到了下面这张表里,你可以看一下,方便后面的实战。
思考题
- 如果这是一个真实的项目,你觉得还缺少哪些需求?
- 希望在你自己的项目里,选择一个不太复杂的部分,然后跟着后续的课程,按照 DDD 的方法尝试实践。
好,今天的课程结束了,有什么问题欢迎在评论区留言,下一节课我们将通过事件风暴的方式,理清系统的行为需求,并为进一步的领域建模打下基础。