领域建模刍议(一):
(资料图)
分清问题域和问题解决域
领域与领域模型
俗话说,人人心中有一个Hamlet,人人心中也都有一个领域模型的定义。
常见的有:
说法1:我理解的领域是对业务工作进行归类划分,归类的方式是业务工作具有相关的知识,这些所需要的知识构成一个领域,这些知识是业务工作的背景,通过对领域的分析,可以帮助我们挖掘、分析、理解业务工作的本质。 也就是说,领域是为需求分析工作服务的,它的目的是挖掘、分析、理解业务工作的本质。
说法2:领域模型就是对领域内的概念类和现实世界中对象的可视化表示。
说法3:企业应用架构模式中明确提出了三种领域逻辑组织模式:事务脚本、领域模型和表模块。领域模型同时将行为和数据作为领域逻辑的核心。
从上面可以3种说法,可以看到不同上下文不同的观点,甚至未必是同一个表达对象。企业应用架构模式中的领域模型是设计到实现层的一个概念,而说法1,说法2种的领域是业务层面及分析阶段的一个概念。因此,本文特指[领域模式]为业务视角的模型,引用定义如下:
• 领域: 是相对于系统而言的,是系统要解决的现实问题。
• 领域模型是对领域内的概念类或现实世界中对象的可视化表示(百度)
• 领域模型是针对某个特定问题的所有相关方面的抽象模型(Wikipedia)
思考,如何对上图的元素建模?
领域建模的好处
领域建模的好处,有哪些呢?
不同角色统一语言、统一认知
如上图所示,客户需求历经演变之后已经面目全非,每一个加工制造环节都以为在[正确的做事]。君不见这样的生动局面一再上演:
产品经理宣讲prd,产品经理需要分别把名词翻译给业务方和开发人员,一则业务语言,一则技术语言。
几个架构师在小黑屋吵了半天,为了争论一个名词定义。比如什么是支付?百度百科的解释:社会经济活动所引起的货币债权转移的过程。包括:交易、清算、结算。
那么对于下列情况是否属于支付范畴就是可以根据其内涵来比照了。
用户A转账给B。用户通过某某网站还信用卡。用户在天猫购买了一个东西,使用花呗付款。由此可见,显性的统一语言很重要,让干系人明白讨论的是一件事情。
对业务本质描述,抓到主旨
比如在支付宝渊源的发展过程中,我们先后使用有红包、实时优惠、商户优惠券等产品。这是烟囱式架构发展下的产物。
行业也有其它类似券的东东,如下图所示:
这3个产物我们锊一下:
1、 对于商户或者机构而言,这些是否可称之产品,可以面向商户售卖包括收费。
2、 对于用户而言,是否需要理解这3个东西不同的?这些认知对于营销,对于交易促成,对于品牌的好处是什么?
3、 对于支付宝平台而言,他们的管理模式有何区别?
4、 对于技术团队而言,他们是否可以抽象?
后来,我们在产品上形成了如下定义:
券定义:
是一种票据,作为券发行方和拥有方之间凭证,具有一定的价值和法律效应。
相关干系方:
券的发放方[提供权益]
券的拥有方[享受权益]
劵的发放工具[是券发行方向拥有方发放券凭证的工具]
券形式:
以介质分类:纸质券,电子券
以使用方式分类:入场券,礼品券,提货券,代金券、红包,打折卡,满减卡等
可以把券作为基础产品,在业务形态上可以包装为打折卡,满减卡等用户感知的[产品]或者是[营销工具]。
领域模型=ER?
领域模型是否就是ER模型呢?答案是否定的,领域模型是特定业务域业务实体关系的自然浮现,而ER是设计阶段数据库实现关系的产物。
如下图所示,自然人Person在特定业务领域有2类,一类是客户(Customer),一类是雇员(Employee).
但究其实现而言,数据库设计有多种形态。
领域建模=DDD?
一说领域建模就提及DDD, 是大家的自然反应。因为DDD(2004年著名建模专家EricEvans发表了他最具影响力的著名书籍:Domain-Driven Design –TacklingComplexity in the Heart of Software)的知名度颇高。我的观点是领域模型的产生是分析阶段的产品,分析是对需求及需求背后相关内容的挖掘,不用创造内容。DDD顾名思义是模型驱动设计,是从需求打通到设计阶段的方法。
领域建模涉及到哪些概念呢?
域(domain):需要讨论的问题范围,称为域或者问题域。
子域(subdomain):对于域进行不同纬度切分相对内聚的单元。比如电商业务涉及订单、库存、营销子域等。
语境(context):是一个特定人群在讨论的问题域是所形成的上下文。 这里要强调一个概念,特定人群不是以团队或者是项目为边界划分的人群, 而是以知识为边界来划分的人群。 也就是说上下文不是普遍存在的, 而是存在于一个人群内部的,并且这些上下文大多是以隐形知识(Tacit Knowledge)的方式而存在的。
域语言(Ubiquitous Language): 领域模型可以成为大家沟通公共语言的核心,同时将团队沟通与软件实现紧密联系到一起。这种公共语言是整个团队工作中的UBIQUITOUS LANGUAGE(通用语言)。
实体(Entity):实体就是领域中需要唯一标识的领域概念。因为我们有时需要区分是哪个实体。有两个实体,如果唯一标识不一样,那么即便实体的其他所有属性都一样,我们也认为他们两个不同的实体;因为实体有生命周期,实体从被创建后可能会被持久化到数据库,然后某个时候又会被取出来。所以,如果我们不为实体定义一种可以唯一区分的标识,那我们就无法区分到底是这个实体还是哪个实体。
数值对象(Value Object): 值对象没有唯一标识,这是它和实体的最大不同。有一部电影中说联邦调查局通过隐私查询,查询到男主和女二曾在大学期间拥有相同的收货地址而判断他们曾住在一起。这里的Address可以作为值对象,它的所有属性决定它是谁,而不必通过ID来区别。
触发事件(Event):企业级应用程序事件大致可以分为三类:系统事件、应用事件和领域事件。领域事件的触发点在领域模型(Domain Model)中,故以此得名。通过使用领域事件,我们可以实现领域模型对象状态的异步更新、外部系统接口的委托调用,以及通过事件派发机制实现系统集成。在系统分析阶段,我的观点是不区分事件类型。
思考 Event与彩色建模中的MI有无区别和联系?
在电信信息架构中有大量的事件,如下图所示。
观点:不建议在分析阶段区别Entity和Value Object
不建议在分析阶段区别Entity和Value Object。比如Customer和Adress的关系和区别一样,在后续精细化过程中,认识自然就清楚了,比如Adress是可以复用的,非唯一的。
观点:在域模型中可以增加业务规则作为补充
在域模型中可以增加业务规则作为补充。比如下图在送货单和订单项的关系上有一行约束说明:只有当所有订单项都已经送到,才能成功关闭订单。
我们来看看 DDD的内容那些是领域建模(分析阶段应该识别的)。
如上图所示,在分析阶段可以用的至多有entity、value object。再次论证了DDD是一个重在Design的工具。
基于上面域,域语言等概念,不难理解不同域同一名词的含义不同,即使是同一介质它的内涵和外延也不同,我们可以把域表述为问题域。
比如电子商务网站有优惠券,包括天猫购物券、店铺券、商品优惠券等,下图为淘宝券截图。
还有一个专门做券导航的网站:券妈妈。
这2个网站管理的券是同类的东西,它们的模型是否就一样了呢?这2个网站管理的都是券,但是业务实体[券]是有差异的,因为它们要解决的问题域不同。券妈妈是一个流量入口,关注领用和跳转;而淘宝券关注使用情况[下单时订单金额扣减],包括使用券的用户对店铺的黏性,二次消费等。业务实体的业务行为,状态也有有所差异。
问题域vs问题解决域
最后总结一下,问题域和问题解决域是2个范畴,分属分析、设计及实现阶段,在不同阶段使用的工具和目标也有所差异,如下图所示:
在分析阶段的领域模型中,我觉得主要描述领域实体及关系,可以辅助领域名词解释(可以是业务字典形式)、以及约束(业务规则),而业务实体(域实体)仅描述主特征即可。
未完待续,领域建模刍议(二)将介绍建模的方法体系。
ps: 系统化思考是最好的总结和学习,我在编写本章的过程中发现了一些模糊的内容,包括写完也有不少未知。
ps:长期使用java语言,近几个月发现.net领域不乏对于领域的深入思考者。
特别推荐:
汤雪华,网名netfocus,2006年毕业于浙江大学,目前住在杭州。对DDD,以及CQRS架构比较感兴趣。开源软件ENode负责人,现就职阿里巴巴。
文章中关于entity的描述参考了汤老师的下文
陈晴阳(Sunny Chen),2003年毕业于中南大学铁道校区。高级程序员,系统分析员,微软MVP(Visual C#)。cnblogs网名daxnet,并打算以该名闯荡IT江湖。MicrosoftDynamics AX、Microsoft .NET/C#以及领域驱动设计(DDD)的狂热爱好者。
文中关于Domain Events的描述引用自
ps:集团内阿白对于界限上下文(Bounded context)、语境映射(Context Mapping)以及域语言(Ubiquitous Language)均有非常精彩的论述。
关键词: