1. 技术诞生的背景
在我们开始深入讨论贫血模型和充血模型之前,让我们先回顾一下它们的诞生背景。在软件开发的早期阶段,我们通常使用过程式编程语言来编写代码,这种方式的主要问题是它们很难处理复杂的业务逻辑。随着面向对象编程的出现,我们开始将现实世界的实体抽象为对象,这使得我们能够更好地管理和处理复杂的业务逻辑。然而,随着业务逻辑的增长,我们发现传统的面向对象设计模式可能无法满足我们的需求,这就是贫血模型和充血模型诞生的背景。
2. 技术使用注意事项
在使用贫血模型和充血模型时,有一些重要的注意事项需要我们牢记。
首先,贫血模型和充血模型并不是互斥的。在某些情况下,使用贫血模型可能更为合适,而在其他情况下,充血模型可能更为合适。关键在于理解你的业务需求,并选择最适合的模型。
其次,无论你选择哪种模型,都需要确保你的代码是清晰的、可读的、可维护的。这意味着你需要遵循良好的编程实践,例如使用有意义的变量名,编写清晰的注释,以及保持代码的整洁。
最后,记住,模型只是工具,而不是目标。你的目标应该是创建出能够满足业务需求的软件,而不是坚持使用某一种模型。
3. 使用场景
贫血模型和充血模型都有各自的使用场景。
贫血模型通常用于简单的、数据驱动的应用程序,其中的业务逻辑相对较少。在这种情况下,贫血模型可以提供一个简单、直接的方式来处理数据。
相比之下,充血模型则更适合于复杂的、业务逻辑丰富的应用程序。在这种情况下,充血模型可以提供一个强大的框架,用于处理复杂的业务逻辑。
4. 案例
让我们来看一个具体的案例,以更好地理解贫血模型和充血模型。
假设我们正在开发一个电商应用程序。在这个应用程序中,我们有一个Order
类,代表一个订单。
在贫血模型中,Order
类可能只包含数据,如订单号、客户ID、订单日期等,而所有的业务逻辑,如计算订单总价、检查库存等,都在服务层完成。
相比之下,在充血模型中,Order
类不仅包含数据,还包含业务逻辑。例如,Order
类可能有一个calculateTotalPrice
方法,用于计算订单总价,以及一个checkStock
方法,用于检查库存。
通过这个案例,我们可以看到,贫血模型和充血模型在处理业务逻辑方面有着根本的区别。
你可能会有一些疑问,这两种开发模式,落实到代码层面,区别不就是一个将业务逻辑放到 Service 类中,一个将业务逻辑放到 Domain 领域模型中吗?为什么基于贫血模型的传统开发模式,就不能应对复杂业务系统的开发?而基于充血模型的 DDD 开发模式就可以呢?
实际上,除了我们能看到的代码层面的区别之外(一个业务逻辑放到 Service 层,一个放到领域模型中),还有一个非常重要的区别,那就是两种不同的开发模式会导致不同的开发流程。基于充血模型的 DDD 开发模式的开发流程,在应对复杂业务系统的开发的时候更加有优势。为什么这么说呢?我们先来回忆一下,我们平时基于贫血模型的传统的开发模式,都是怎么实现一个功能需求的。
不夸张地讲,我们平时的开发,大部分都是 SQL 驱动(SQL-Driven)的开发模式。我们接到一个后端接口的开发需求的时候,就去看接口需要的数据对应到数据库中,需要哪张表或者哪几张表,然后思考如何编写 SQL 语句来获取数据。之后就是定义 Entity、BO、VO,然后模板式地往对应的 Repository、Service、Controller 类中添加代码。
业务逻辑包裹在一个大的 SQL 语句中,而 Service 层可以做的事情很少。SQL 都是针对特定的业务功能编写的,复用性差。当我要开发另一个业务功能的时候,只能重新写个满足新需求的 SQL 语句,这就可能导致各种长得差不多、区别很小的 SQL 语句满天飞。
所以,在这个过程中,很少有人会应用领域模型、OOP 的概念,也很少有代码复用意识。对于简单业务系统来说,这种开发方式问题不大。但对于复杂业务系统的开发来说,这样的开发方式会让代码越来越混乱,最终导致无法维护。
如果我们在项目中,应用基于充血模型的 DDD 的开发模式,那对应的开发流程就完全不一样了。在这种开发模式下,我们需要事先理清楚所有的业务,定义领域模型所包含的属性和方法。领域模型相当于可复用的业务中间层。新功能需求的开发,都基于之前定义好的这些领域模型来完成。