TypeScript中的六边形架构:构建灵活应用的纯净架构

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么六边形架构不只是流行术语,而是您代码的救星?

想象一下,您正在建造一栋房子。您不会把插座直接砌进混凝土墙里吧?您会先铺设线路、做好标记,然后小心地连接插座。在软件开发中,情况完全一样——您的业务逻辑(应用核心)不应依赖于与之交互的方式:REST API、数据库或消息队列。

六边形架构(也称为“端口与适配器”,或Alistair Cockburn诠释的“纯净架构”)正是为了解决这个问题。在本文中,我们将通过真实的代码示例,讲解如何在TypeScript中实现这种架构。您将学会如何将业务逻辑与基础设施分离,使代码可测试且灵活。



用简单的话说,什么是六边形架构?

想象一个六边形。中心是您的应用程序及其业务逻辑。每条边都是一个“端口”(接口),外部世界通过它与核心通信。适配器是具体的实现:控制器、存储库、外部服务客户端。它们像插头插入插座一样连接到端口。

主要原则是:依赖关系指向内部。外部代码(数据库、框架)依赖于核心,而不是相反。这使得您可以将数据库从PostgreSQL更换为MongoDB,而无需改动业务逻辑中的任何一行代码。



基本概念

  • 核心(Domain) — 业务逻辑、实体、值对象、用例。没有外部依赖。
  • 端口(Port) — 接口(在TypeScript中是抽象类或interface),定义了与外部世界的契约。
  • 适配器(Adapter) — 端口的具体实现。例如,通过TypeORM与PostgreSQL交互的存储库。
  • 应用层(Application) — 协调用例执行的层。


实践示例:订单管理系统

让我们设计一个简单的订单系统。我们将有Order和Product实体、CreateOrder用例、存储库端口以及PostgreSQL适配器。



步骤1. 定义核心(Domain层)

创建domain/文件夹。这里存放实体和端口接口。没有任何框架依赖!



// domain/order.entity.tsexport class Order {    constructor(        public readonly id: string,        public items: OrderItem[],        public status: 'pending' | 'confirmed' | 'shipped',        public total: number    ) {}

public addItem(productId: string, quantity: number, price: number): void { this.items.push({ productId, quantity, price }); this.total = this.calculateTotal(); }

private calculateTotal(): number { return this.items.reduce((sum, item) => sum + item.price * item.quantity, 0); }}

export interface OrderItem { productId: string; quantity: number; price: number;}


现在定义存储库的端口:



// domain/ports/order.repository.interface.tsimport { Order } from '../order.entity';

export interface IOrderRepository { save(order: Order): Promise<void>; findById(id: string): Promise<Order | null>; findAll(): Promise<Order[]>;}


步骤2. 用例——应用的核心

用例是一个使用场景。它包含业务逻辑并使用端口,但不知道谁实现了它们。



// application/use-cases/create-order.use-case.tsimport { Order } from '../../domain/order.entity';import { IOrderRepository } from '../../domain/ports/order.repository.interface';

export class CreateOrderUseCase { constructor(private readonly orderRepository: IOrderRepository) {}

async execute(use

博客

书籍推荐