张建飞 frank

读完需要

21

分钟

速读仅需 7 分钟

阿里巴巴高级技术专家,著有图书《代码精进之路 从码农到工匠》,维护公众号《从码农到工匠》 ID:craftsman_frank

阿里妹导读:什么是领域模型?什么又是数据模型?两者可以等同吗?在实际应用中,怎么样才能用好它们?本文介绍领域模型和数据模型的概念定义,并举例说明两者相互混淆的错误用法,分享如何正确地应用它们。

依稀记得我第一次设计一个系统的时候,画了一堆UML(Unified Modeling Language,统一建模语言)图,面对Class Diagram(其实就是领域模型),纠结了好久,不知道如何落地。因为,如果按照这个类图去落数据库的话,看起来很奇怪,有点繁琐。可是不按照这个类图落库的话,又不知道这个类图画了有什么用。

现在回想起来,我当时的纠结源自于我对领域模型和数据模型这两个重要概念的不清楚。最近,我发现对这两个概念的混淆不是个例,而是非常普遍的现象。其结果就是,小到会影响一些模块设计的不合理性,大到会影响像业务中台这样重大技术决策,因为如果底层的逻辑、概念、理论基础没搞清楚的话,其构建在其上的系统也会出现问题,非常严重的问题。

鉴于很少看到有人对这个话题进行比较深入的研究和探讨,我觉得有必要花时间认真明晰这两个概念,帮助大家在工作中,更好的做设计决策。

一  领域模型和数据模型的概念定义

领域模型关注的是领域知识,是业务领域的核心实体,体现了问题域里面的关键概念,以及概念之间的联系。领域模型建模的关键是看模型能否显性化、清晰的表达业务语义,扩展性是其次。

数据模型关注的是数据存储,所有的业务都离不开数据,都离不开对数据的CRUD,数据模型建模的决策因素主要是扩展性、性能等非功能属性,无需过分考虑业务语义的表征能力。

按照Robert在《整洁架构》里面的观点,领域模型是核心,数据模型是技术细节。然而现实情况是,二者都很重要。

这两个模型之所以容易被混淆,是因为两者都强调实体(Entity),都强调关系(Relationship),这可不,我们传统的数据库的数据模型建模就是用的ER图啊。

是的,二者的确有一些共同点,有时候领域模型和数据模型会长的很像,甚至会趋同,这很正常。但更多的时候,二者是有区别的。正确的做法应该是有意识地把这两个模型区别开来,分别设计,因为他们建模的目标会有所不同。如下图所示,数据模型负责的是数据存储,其要义是扩展性、灵活性、性能。而领域模型负责业务逻辑的实现,其要义是业务语义显性化的表达,以及充分利用OO的特性增加代码的业务表征能力。

然而,现实情况是,我们很多的业务系统设计,并没有很好的区分二者的关系。经常会犯两个错误,一个是把领域模型当数据模型,另一个是把数据模型当领域模型。

二  错把领域模型当数据模型

这几天我在做一个报价优化的项目,里面涉及到报价规则的问题,这块的业务逻辑大意是说,对于不同的商品(通过类目、品牌、供应商类型等维度区分),我们会给出不同的价格区间,然后来判断商家的报价是否应该被自动审核(autoApprove)通过,还是应该被自动拦截(autoBlock)。

对于这个规则,领域模型很简单,就是提供了价格管控需要的配置数据,如下图所示:

如果按照这个领域模型去设计我们的存储的话,自然是需要两张表:price_rule和price_range,一张用来存价格规则,一张是用来存价格区间。

如果这样去设计数据模型,我们就犯了把领域模型当数据模型的错误。这里,更合适的做法是一张表就够了,把price_range作为一个字段在price_rule中用一个字段存储,如下图所示,里面的多个价格区间信息用一个JSON字段去存取就好了。

这样做的好处很明显:

  • 首先,维护一张数据库表肯定比两张的成本要小。

  • 其次,其数据的扩展性更好。比如,新需求来了,需要增加一个建议价格(suggest price)区间,如果是两张表的话,我需要在price_range中加两个新字段,而如果是JSON存储的话,数据模型可以保持不变。

可是,在业务代码里面,如果是基于JSON在做事情可不那么美好。我们需要把JSON的数据对象,转换成有业务语义的领域对象,这样,我们既可以享受数据模型扩展性带来的便捷性,又不失领域模型对业务语义显性化带来的代码可读性。

三  错把数据模型当领域模型

的确,数据模型最好尽量可扩展,毕竟,改动数据库可是个大工程,不管是加字段、减字段,还是加表、删表,都涉及到不少的工作量。

说到数据模型的扩展设计经典之作,非阿里的业务中台莫属,核心的商品、订单、支付、物流4张表,得益于良好的扩展性设计,就支撑了阿里几十个业务的成千上万的业务场景。

拿商品中台来说,它用一张auction_extend垂直表,就解决了所有业务商品数据存储扩展性的需求。理论上来说,这种数据模型可以满足无限的业务扩展。

JSON字段也好,垂直表也好,虽然可以很好的解决数据存储扩展的问题,但是,我们最好不要把这些扩展(features)当成领域对象来处理,否则,你的代码根本就不是在面向对象编程,而是在面向扩展字段(features)编程,从而犯了把数据模型当领域模型的错误。更好的做法,应该是把数据对象(Data Object)转换成领域对象来处理。

如下所示,这种代码里面到处是getFeature、addFeature的写法,是一种典型的把数据模型当领域模型的错误示范。

四  领域模型和数据模型各司其职

上面展示了因为混淆领域模型和数据模型,带来的问题。正确的做法应该是把领域模型、数据模型区别开来,让他们各司其职,从而更合理的架构我们的应用系统。

其中,领域模型是面向领域对象的,要尽量具体,尽量语义明确,显性化的表达业务语义是其首要任务,扩展性是其次。而数据模型是面向数据存储的,要尽量可扩展。

在具体落地的时候,我们可以采用COLA[1]的架构思想,使用gateway作为数据对象(Data Object)和领域对象(Entity)之间的转义网关,其中,gateway除了转义的作用,还起到了防腐解耦的作用,解除了业务代码对底层数据(DO、DTO等)的直接依赖,从而提升系统的可维护性。

此外,教科书上教导我们在做关系数据库设计的时候,要满足3NF(三范式),然而,在实际工作中,我们经常会因为性能、扩展性的原因故意打破这个原则,比如我们会通过数据冗余提升访问性能,我们会通过元数据、垂直表、扩展字段提升表的扩展性。

业务场景不一样,对数据扩展的诉求也不一样,像price_rule这种简单的配置数据扩展,JSON就能胜任。复杂一点的,像auction_extend这种垂直表也是不错的选择。

wait,有同学说,你这样做,数据是可扩展了,可数据查询怎么解决呢?总不能用join表,或者用like吧。实际上,对一些配置类的数据,或者数据量不大的数据,完全可以like。然而,对于像阿里商品、交易这样的海量数据,当然不能like,不过这个问题,很容易通过读写分离,构建search的办法解决。

五  关于扩展的更多思考

最后,再给一个思考题吧。

前面提到的数据扩展,还都是领域内的有限扩展。如果我连业务领域是什么还不知道,能不能做数据扩展呢?可以的,Salesforce的force.com就是这么做的,其底层数据存储完全是元数据驱动的(metadata-driven[2]),他用一张有500个匿名字段的表,去支撑所有的SaaS业务,每个字段的实际表意是通过元数据去描述的。如下图所示,value0到value500都是预留的业务字段,具体代表什么意思,由metadata去定义。

说实话,这种实现方式的确是一个很有想法,很大胆的设计,也的确支撑了上面数以千计的SaaS应用和Salesforce千亿美金的市值。

只是,我不清楚从元数据到领域对象的映射,Salesforce具体是怎么做的,是通过他们的语法糖Apex?如果没有领域对象,他们的业务代码要怎么写呢?反正据在Salesforce里面做vendor的同学说,他们所谓的Low-Code,里面还是有很多用Apex写的代码,而且可维护性一般。

anyway,我们绝大部分的应用都是面向确定问题域的,不需要像Salesforce那样提供“无边际”的扩展能力。在这种情况下,我认为,领域对象是最好的连接数据模型和业务逻辑的桥梁。

相关链接

[1]https://github.com/alibaba/COLA

[2]https://developer.salesforce.com/wiki/multi_tenant_architecture

- EOF -

想要加入中生代架构群的小伙伴,请添加群合伙人大白的微信

申请备注(姓名+公司+技术方向)才能通过哦!

阿里技术精彩文章推荐

往期推荐

深度:揭秘阿里巴巴的客群画像

多隆:从工程师到阿里巴巴合伙人

阿里技术专家楚衡:架构制图的工具与方法论

蚂蚁集团技术专家山丘:性能优化常见压测模型及优缺点

阿里文娱技术专家战獒: 领域驱动设计详解之What, Why, How?

阿里专家马飞翔:一文读懂架构整洁之道

阿里专家常昊:新人如何上手项目管理?

蚂蚁集团沈凋墨:Kubernetes-微内核的分布式操作系统

阿里合伙人范禹:常挂在阿里技术人嘴边的四句土话

阿里技术专家都铎:一文搞懂技术债

支付宝研究员兼OceanBase总架构师杨传辉:我在数据库梦之队的十年成长路

阿里技术专家麒烨:修炼测试基本功

阿里计算平台掌门人贾扬清:我对人工智能方向的一点浅见

蚂蚁资深算法专家周俊:从原理到落地,支付宝如何打造保护隐私的共享智能?

阿里高级技术专家箫逸:如何画好一张架构图?

阿里高级技术专家张建飞:应用架构分离业务逻辑和技术细节之道

蚂蚁科技 Service Mesh 落地实践与挑战 | GIAC 实录

阿里6年,我的技术蜕变之路!

蚂蚁集团涵畅:再启程,Service Mesh 前路虽长,尤可期许

阿里P9专家右军:大话软件质量稳定性

阿里合伙人程立:阿里15年,我撕掉了身上两个标签

阿里高工流生 | 云原生时代的 DevOps 之道

阿里高级技术专家邱小侠:微服务架构的理论基础 - 康威定律

阿里P9专家右军:以终为始的架构设计

阿里P8架构师:淘宝技术架构从1.0到4.0的架构变迁!12页PPT详解

阿里技术:如何画出一张合格的技术架构图?

蚂蚁资深技术专家王旭:开源项目是如何让这个世界更安全的?

阿里资深技术专家崮德:8 个影响我职业生涯的重要技能

儒枭:我看技术人的成长路径

阿里高级技术专家宋意:平凡人在阿里十年的成长之旅

阿里技术专家甘盘:浅谈双十一背后的支付宝LDC架构和其CAP分析

阿里技术专家光锥:亿级长连网关的云原生演进之路

阿里云原生张羽辰:服务发现技术选型那点事儿

蚂蚁研究员玉伯:做一个简单自由有爱的技术人

阿里高级技术专家至简: Service Mesh 在超大规模场景下的落地挑战

阿里巴巴山猎:手把手教你玩转全链路监控

阿里涉江:你真的会学习吗?从结构化思维说起

蚂蚁金服资深技术专家经国:云原生时代微服务的高可用架构设计

深入分布式缓存之EVCache探秘开局篇

   END
#架构师必备#

阿里高级技术专家张建飞:深度剖析领域模型vs数据模型的用法相关推荐

  1. 阿里高级技术专家张建飞:面对复杂业务,if-else coder 如何升级?

    阿里高级技术专家 张建飞 Frank <从码农到工匠>作者 读完需要 7 分钟 速读仅需 3 分钟 阿里妹导读:针对业务在不同场景下的差异,我们常常会习惯性地使用 if-else 来实现不 ...

  2. 阿里高级技术专家张建飞:应用架构分离业务逻辑和技术细节之道

    中生代技术 链接技术大咖,分享技术干货 全文:4449字14图 张建飞 <从码农到工匠> 读完需要 9 分钟 速读仅需 3 分钟 架构 什么是架构? 关于架构这个概念很难给出一个明确的定义 ...

  3. 阿里高级技术专家箫逸:如何画好一张架构图?

    中生代技术 链接技术大咖,分享技术干货 全文:10000字 阿里妹导读:架构图是什么?为什么要画架构图?如何画?有哪些方法?本文从架构的定义说起,分享阿里文娱高级技术专家箫逸关于画架构图多年的经验总结 ...

  4. 阿里高级技术专家宋意:平凡人在阿里十年的成长之旅

    宋意 读完需要 14 分钟 速读仅需 5 分钟 阿里妹导读:不管是什么角色,成长是我们每个人都必须经历的过程.作为一个技术人,成长不仅是技术上的不断精进,也包括日常工作中的方方面面. 本文分享阿里巴巴 ...

  5. 应用架构的核心使命是什么?阿里高级技术专家这样说

    阿里妹导读:什么是架构?关于架构这个概念很难给出一个明确的定义,也没有一个标准的定义.如果,硬是要给一个概述,阿里巴巴高级技术专家张建飞认为架构就是对系统中的实体以及实体之间的关系所进行的抽象描述.今 ...

  6. 应用架构的核心使命是什么?阿里高级技术专家如是说

    导读:什么是架构?关于架构这个概念很难给出一个明确的定义,也没有一个标准的定义.如果,硬是要给一个概述,阿里巴巴高级技术专家张建飞认为架构就是对系统中的实体以及实体之间的关系所进行的抽象描述.今天,张 ...

  7. 阿里高级技术专家:整洁的应用架构“长”什么样?

    简介: 作者张建飞是阿里巴巴高级技术专家,入司6年,他创建了COLA.希望可以探索一套切实可行的应用架构规范,这个规范不是高高在上的纸上谈兵,而是可以复制.可以理解.可以落地.可以控制复杂性的指导和约 ...

  8. 阿里高级技术专家方法论:如何写复杂业务代码?

    阿里妹导读:张建飞是阿里巴巴高级技术专家,一直在致力于应用架构和代码复杂度的治理.最近,他在看零售通商品域的代码.面对零售通如此复杂的业务场景,如何在架构和代码层面进行应对,是一个新课题.结合实际的业 ...

  9. 阿里高级技术专家邱小侠:微服务架构的理论基础 - 康威定律

    邱小侠 阿里高级技术专家 读完需要 10 分钟 速读仅需 4 分钟 邱小侠,阿里巴巴集团客户体验事业群高级技术专家,阿里花名肥侠.2014年加入阿里巴巴,现在负责客户体验驱动及创新中心有关商家业务的开 ...

最新文章

  1. Oracle10g 回收站及彻底删除table : drop table xx purge
  2. MySQL:基础—数据分组
  3. LAMP源码编译安装配置+wordpress
  4. Linux多线程之线程同步(条件变量)
  5. sharepoint简单说明
  6. 【registry】registry合并带spring boot项目第一弹
  7. linux下安装 Sublime Text 3
  8. DeFi 保险协议InsurAce将于3月15日在Balancer开启代币首发
  9. 中国超级计算机扩大领先优势:TOP500总量首次超越美国
  10. Test from Windows Live Writer
  11. 好友管理系统 Python
  12. console application
  13. SQL Server 数据库之数据约束
  14. 《太极张三丰》原声音乐 320/mp3打包下载
  15. 广告联盟的实现过程(一)
  16. 亿发定制ERP企业管理系统,适用中小型企业的经济实惠的解决方案
  17. 任务提交SparkSubmit源码解析
  18. [iOS]URL编码和解码
  19. 手淘移动端适配的方案学习和相关思考
  20. 基于c51单片机的毕业设计——智能温度控制

热门文章

  1. php mysql mvc_超简洁PHPMVC
  2. go修改服务器时间,Windows 配置时间同步服务器以及配置时间同步间隔
  3. 简述运行PHP文件的步骤,简述PHP运行机制
  4. 船舶定位实时查询系统_港口人员精准定位系统,实时安全管控与智能预警
  5. (王道408考研数据结构)第五章树-第一节:树的定义、基本用语和常考性质
  6. windbg-!address、!vadump、!vprot(读取内存状态)
  7. poj2109 Power of Cryptography
  8. 渗透测试web未设置http头 Strict Transport Security
  9. MySQL给新建用户并赋予权限
  10. C# string转double,double转string