DEV Community

架构师小白
架构师小白

Posted on

洋葱架构深度指南:构建可测试可维护软件的精髓之道

洋葱架构深度指南:构建可测试可维护软件的精髓之道

洋葱架构(Onion Architecture)是一种将系统组织为同心层结构的架构模式,核心原则是"依赖指向中心"——外层依赖内层,内层完全独立于外层。

为什么需要洋葱架构?

传统的三层架构(表现层、业务逻辑层、数据访问层)存在一个根本性问题:业务逻辑层依赖数据访问层,这导致:

  • 更换数据库需要修改业务代码
  • 单元测试难以进行(难以mock数据层)
  • 业务逻辑与基础设施紧耦合

洋葱架构通过依赖倒置原则解决这些问题。


洋葱架构的核心层次

┌─────────────────────────────────────┐
│         基础设施层 (Infrastructure)   │ ← 数据库、API客户端、文件系统
├─────────────────────────────────────┤
│         应用层 (Application)        │ ← 用例、编排、事务管理
├─────────────────────────────────────┤
│         领域层 (Domain)              │ ← 实体、值对象、领域服务
├─────────────────────────────────────┤
│         核心层 (Core)                 │ ← 业务规则、接口抽象
└─────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

1. 核心层(Domain Core)

最内层,完全独立,不依赖任何外部:

# 领域实体
class Order:
    def __init__(self, order_id, items):
        self.id = order_id
        self.items = items
        self.status = "pending"

    def total(self):
        return sum(item.price * item.quantity for item in self.items)

    def can_cancel(self):
        return self.status == "pending"
Enter fullscreen mode Exit fullscreen mode

2. 领域层(Domain)

定义业务接口,不实现:

# 领域接口(抽象)
class IOrderRepository:
    def save(self, order: Order): pass
    def find_by_id(self, order_id): pass

class IPaymentService:
    def process_payment(self, order: Order): pass
Enter fullscreen mode Exit fullscreen mode

3. 应用层(Application)

用例(Use Cases)所在,协调领域对象:

class CreateOrderUseCase:
    def __init__(self, order_repo: IOrderRepository):
        self.order_repo = order_repo

    def execute(self, order_data):
        # 创建订单
        order = Order(order_data["id"], order_data["items"])
        self.order_repo.save(order)
        return order
Enter fullscreen mode Exit fullscreen mode

4. 基础设施层(Infrastructure)

实现领域层定义的接口:

class PostgresOrderRepository(IOrderRepository):
    def __init__(self, db_connection):
        self.db = db_connection

    def save(self, order):
        # 实际的数据库操作
        self.db.insert("orders", order.__dict__)
Enter fullscreen mode Exit fullscreen mode

依赖流向:关键原则

所有依赖都指向内层,通过依赖注入实现:

表现层 → 应用层 → 领域层 → 基础设施层
   ↑         ↑         ↑         ↓
   └─────────┴─────────┴─────────┘
              依赖注入
Enter fullscreen mode Exit fullscreen mode

依赖注入示例

# 运行时注入实现
order_repo = PostgresOrderRepository(db_connection)
create_order = CreateOrderUseCase(order_repo)
Enter fullscreen mode Exit fullscreen mode

实战:用DI容器管理依赖

from injector import Injector

# 注册绑定
injector = Injector()
injector.bind(IOrderRepository, to=PostgresOrderRepository)
injector.bind(IPaymentService, to=StripePaymentService)

# 注入使用
order = injector.get(CreateOrderUseCase).execute(data)
Enter fullscreen mode Exit fullscreen mode

洋葱架构 vs 传统分层

维度 三层架构 洋葱架构
依赖方向 上层→下层 外层→内层
业务逻辑 在Service层 在Domain层
可测试性 困难 容易
替换数据库 修改业务代码 仅替换Infrastructure
依赖注入 可选 必需

何时使用洋葱架构?

适合场景

  • 中大型复杂业务系统
  • 需要频繁更换数据存储
  • 高度可测试性要求
  • 微服务内部架构

不适合场景

  • 简单CRUD应用
  • 快速原型验证
  • 小型脚本工具

总结

洋葱架构的核心理念:

让核心业务逻辑完全独立于基础设施

通过依赖指向中心的组织方式,我们实现了:

  • 🎯 高度可测试
  • 🔄 易于替换组件
  • 📦 清晰的责任边界
  • 🛠 长期可维护

这是构建企业级应用的坚实基础。


下期预告:六边形架构(Hexagonal Architecture)与洋葱架构的对比与融合。


如果你觉得这篇文章有帮助,欢迎关注、点赞、转发!我是@甜心,上午好!🍬

Top comments (0)