贫血模型:简化设计还是过度简化(架构篇)?

贫血模型是一种软件设计模式,其中业务逻辑被放置在服务层或管理类中,而领域模型仅包含数据和访问这些数据的方法。这种模式有时被认为是反模式,因为它可能导致领域模型过于简单,缺乏业务逻辑。

2. 贫血模型设计图:

贫血模型的设计哲学是将业务逻辑从领域模型中移除,使得领域模型只包含属性和基本的getter/setter方法,而业务逻辑则在应用服务层中实现。

  • DomainModel 是一个领域模型,它包含数据和基本的getter/setter方法。
  • Service 是一个服务类,它处理业务逻辑。在这个例子中,我们展示了 OrderService 处理 Order 对象的逻辑。
  • Order 是一个具体的领域模型,包含订单数据和基本的getter/setter方法。
  • User 是另一个领域模型,包含用户数据和基本的getter/setter方法。
  • OrderService 是一个服务类,它依赖于 Order 模型,并处理订单相关的业务逻辑。

3.贫血模型解决什么:

贫血模型试图通过简化领域模型来降低系统的复杂性,使得领域模型更容易理解和维护。

4. 贫血模型特点:

  • 简单性:领域模型简单,只包含数据和基本的数据访问方法。
  • 业务逻辑集中:所有的业务逻辑都集中在服务层,易于管理和测试。

5. 贫血模型缺点:

  • 领域模型贫血:领域模型失去了表达业务逻辑的能力,变得过于简单。
  • 服务层臃肿:随着业务逻辑的增加,服务层可能会变得过于复杂和难以维护。

6. 模型使用场景:

当面临需要快速开发和部署的简单应用程序时,或者当领域逻辑非常简单时,可以考虑使用贫血模型。

7. 贫血模型案例

7.1 电商平台的订单处理系统案例

考虑一个电商平台的订单处理系统,该系统需要处理订单和用户信息。

重构前:

 

java

代码解读

复制代码

public class Order { private String orderId; private double totalAmount; private User user; // 仅包含基本的getter和setter方法 public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public double getTotalAmount() { return totalAmount; } public void setTotalAmount(double totalAmount) { this.totalAmount = totalAmount; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } public class UserService { public void processOrder(Order order) { // 订单处理逻辑 } }

分析问题:

  1. 业务逻辑分布不均
    • 所有业务逻辑集中在服务层,领域模型只包含数据和访问器,没有业务逻辑。
  2. 领域模型功能不足
    • 领域模型变得简单但无用,不能表达业务规则或行为。
  3. 服务层臃肿
    • 随着业务逻辑的增加,服务层变得越来越复杂,难以维护。
  4. 测试困难
    • 由于业务逻辑分散在服务层,单元测试变得更加困难,需要大量模拟。
  5. 缺乏封装
    • 领域模型没有封装业务逻辑,导致数据和行为分离。
  6. 违反DRY原则
    • 服务层可能重复实现相同的业务逻辑,违反了“不要重复自己”(DRY)原则。

重构后:

 

java

代码解读

复制代码

public class Order { private String orderId; private double totalAmount; private User user; // 仅包含基本的getter和setter方法 public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public double getTotalAmount() { return totalAmount; } public void setTotalAmount(double totalAmount) { this.totalAmount = totalAmount; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public void applyDiscounts() { // 应用折扣逻辑 } } public class OrderService { public void processOrder(Order order) { order.applyDiscounts(); // 其他订单处理逻辑 } }

解决的问题:

  1. 业务逻辑合理分布
    • 将业务逻辑移至领域模型,使得领域模型能够表达业务规则。
  2. 增强领域模型的实用性
    • 领域模型不再只是数据容器,而是具有实际业务逻辑的实体。
  3. 服务层简化
    • 服务层不再负责所有业务逻辑,而是协调领域模型之间的交互。
  4. 易于测试
    • 领域模型具有明确的业务逻辑,便于编写单元测试。
  5. 封装性增强
    • 业务逻辑封装在领域模型中,提高了数据和行为的封装性。
  6. 遵循DRY原则
    • 通过将业务逻辑集中到领域模型,避免了在服务层的重复代码。
  7. 提高代码可读性和可维护性
    • 领域模型的业务逻辑清晰,提高了代码的可读性和可维护性。
  8. 更好的扩展性
    • 当业务需求变化时,可以更容易地在领域模型中添加或修改逻辑。

8.贫血模型与充血模型区别

  • 业务逻辑的位置
    • 贫血模型将业务逻辑放在服务层,而充血模型将业务逻辑封装在领域对象内部。
  • 领域对象的复杂性
    • 贫血模型的领域对象通常更简单,而充血模型的领域对象可能更复杂,因为它们包含业务逻辑。
  • 测试的难易程度
    • 贫血模型可能使单元测试更容易编写,因为测试可以集中在服务层。
    • 充血模型可能使单元测试更复杂,因为需要模拟领域对象的内部行为。
  • 系统的可维护性
    • 贫血模型可能导致服务层随着业务逻辑的增加而变得难以维护。
    • 充血模型通过分散业务逻辑,可能提高系统的可维护性,但也可能增加单个对象的复杂性。
  • 设计哲学
    • 贫血模型倾向于简化领域对象,专注于数据。
    • 充血模型强调领域对象的完整性,认为对象应该完全表达其业务意图。

9. 参考开源框架:

许多现代Web框架,如Spring Boot,鼓励使用服务层来处理业务逻辑,这有时会导致贫血模型的使用。

10. 总结:

贫血模型通过将业务逻辑从领域模型中移除,试图简化设计。然而,这种方法可能会导致领域模型过于简单,而服务层变得过于复杂。在设计系统时,需要权衡领域模型的复杂性和服务层的职责,以确保系统的可维护性和可扩展性。虽然贫血模型在某些情况下可能有用,但过度简化可能会导致其他问题。

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值