写点什么

面试官问:能聊聊你对充血模型和贫血模型的理解吗?

用户头像
面试官问
关注
发布于: 2021 年 04 月 09 日

面试官问:随着微服务架构的普及,领域驱动设计也焕发了新春,得到了大范围的推广,在代码实现层面,领域驱动设计相比数据表驱动设计的主要区别就是充血模型和贫血模型,你能聊聊对这两个模型的理解吗?


候选人甲:额,这个没有听说过...


面试官:好的,没关系,那我们继续其他问题...


旁白:确实有很多候选人没有了解过充血模型和贫血模型,虽然平时开发中可能一直在使用贫血模型而不自知。此外,领域驱动设计已经在很多公司或多或少实践着,例如:



所以,作为一名现代的后端开发,掌握领域驱动设计的基本概念和思想能够让你无论是在平时项目开发中还是跳槽面试中受益匪浅。


候选人乙:说到充血模型和贫血模型区别,不得不先聊一聊领域驱动设计和数据表驱动设计:


  • 领域驱动设计:系统的设计以面向对象的方式进行,当拿到需求后,首先进行用例模型设计,分析整个系统要实现哪些功能;然后进行领域模型的设计,识别出系统中的实体、属性和关系,可以采用类图的形式,每个类通过它的属性来描述数据结构,通过类方法来描述对数据结构的操作。领域模型设计好之后,最后才是进行数据库的设计,此时,数据库设计就弱化成领域对象的一种持久化方式而已,实际的业务逻辑都封装在领域对象中,如果需要的话,可以将持久化实现为插件式方案,既可以使用 MySQL 来存储,也可以使用 MongoDB 来存储,但无论采用何种存储,领域对象都是不变的。这种既包含数据,也包含数据对应的业务逻辑的类设计方式就被称为充血模型(Rich Domain Model),它满足面向对象的封装特性,是典型的面向对象编程风格。

  • 数据表驱动设计:系统的设计以数据库表设计为核心,当拿到需求并进行分析后,首先把数据库表设计好之后,再通过工具自动生成数据库表对应的 Mapper、DO、BO、Service、VO、Controller 等对象。在这种模式下,Service 层的数据和业务逻辑被分割到 BO 和 Service 两个类中。其中,像 BO 这种只包含属性以及属性对应的 setter、getter 方法的类,本质上就是一个纯粹的数据结构类,不包含业务逻辑,因此被称为贫血模型(Anemic Domain Model)。同理,DO 和 VO 也都是基于贫血模型的设计。贫血模型将数据和操作分离,破坏了面向对象的封装特性,是一种典型的面向过程的编程风格。


面试官:好的,那充血模型相比贫血模型的优点是什么?


候选人乙:首先从代码可读性方面看,充血模型的实体类由于包含业务逻辑,符合人类的思维模式,因此易于阅读与理解;而贫血模型的实体类不包含业务逻辑,相关操作都封装在 Service 甚至 SQL 语句中,因此,代码可读性可理解性较差。此外,从可测试性方面看,充血模型的设计将业务操作与数据库操作解耦了,因此,在测试业务功能时,可以仅通过对实体类进行单元测试来验证业务逻辑的正确性,效率高;而贫血模型中,实体类是纯粹的数据结构,不需要测试,但需要对 Mapper 类写数据库集成测试,而核心业务逻辑封装在 Service 中,因此单元测试重点是对 Service 的测试,但 Service 中的方法逻辑是面向过程的封装,可测试性并不好,说白了就是单元测试可能没那么好写。


面试官:好的,那既然充血模型有这么多优点,那为何基于贫血模型的传统开发模式还是如此受欢迎呢?


候选人乙:主要有几个原因,首先数据库表驱动设计这种传统方式已经深入人心,大家用起来很顺手,在没有外因或者内因驱动的情况下,大家更倾向待在舒适区;其次充血模型的设计相比贫血模型而已,有一定的学习门槛,设计起来也会更花费时间和精力;最后,对大多数系统来说,可能没有太复杂的业务逻辑,因此基于贫血模型的表驱动设计就能够满足需求,也不会给后续系统的维护升级带来太多影响,因此也体现不出使用充血模型的价值。


面试官:好的,那什么项目适合使用基于充血模型的 DDD 开发模式呢?


候选人乙:从领域驱动设计的经典之作《领域驱动设计:软件核心复杂性应对之道》书名中我们可以看出,DDD 适用于复杂度较高的软件设计,例如企业级软件设计。其次,从系统的分类来看,可以分为 OLTP 系统和 OLAP 系统,前者是在线事务系统,也就是平时大家接触较多的业务系统,而后者是在线分析系统,也就是统计分析类系统,大部分是从大数据平台中获取数据进行报表、大屏等的展示。基于充血模型的 DDD 开发模式显然更适合 OLTP 系统,而 OLAP 系统还是老老实实采用传统的表驱动设计就行了,别瞎折腾。

拓展阅读


关于我

微信公众号:面试官问,原创高质量面试题,始于面试题,但不止于面试题。


发布于: 2021 年 04 月 09 日阅读数: 68
用户头像

面试官问

关注

还未添加个人签名 2017.10.20 加入

还未添加个人简介

评论

发布
暂无评论
面试官问:能聊聊你对充血模型和贫血模型的理解吗?