首页 > 基础资料 博客日记

还在被框架绑架?一文看懂“六边形架构”,让你的核心业务稳如泰山!

2026-06-14 07:30:02基础资料围观2

极客资料网推荐还在被框架绑架?一文看懂“六边形架构”,让你的核心业务稳如泰山!这篇文章给大家,欢迎收藏极客资料网享受知识的乐趣

引言:那些年我们写过的“面条代码”

痛点场景: 你一定经历过这样的噩梦:系统最初用 MySQL 存储数据,后来为了性能要迁移到 MongoDB。结果你发现,业务代码里密密麻麻全是对 MySQL 驱动的直接调用。或者,老板突发奇想,要求把原本的 Web 页面功能,原封不动地搬到一个新的命令行工具(CLI)里,你却发现业务逻辑和 HTTP 的 Request / Response 对象死死绑定在一起。

“牵一发而动全身”,修改一行代码,整个系统崩溃。这是因为我们的核心业务逻辑被外部框架、数据库和 UI 强行“绑架”了。

解决方案: 这时候,六边形架构(Hexagonal Architecture) 闪亮登场。它的核心理念极其简单:将核心业务逻辑与外部依赖彻底隔离。它能让你的业务代码变得像插座一样通用,无论外接的是哪种数据库或哪个前端框架,核心系统都能从容应对。

概念拆解:餐厅后厨的生存哲学 (The "What" & "Why")

生活化类比:米其林餐厅的运作

别被“六边形”这个高大上的名字吓到,它其实也被称为端口与适配器模式(Ports and Adapters)。我们用“去餐厅点餐”来理解它:

想象一家顶级的米其林餐厅,它的核心竞争力是“后厨大厨的烹饪手艺”(核心业务逻辑)。

  1. 输入端(Driving):大厨根本不在乎客人是通过服务员点餐、通过美团外卖下单,还是打电话预定。大厨只认一样东西:标准化的点餐单(输入端口 Input Port)。服务员和外卖App在这里就是输入适配器(Input Adapter),负责把各种乱七八糟的请求翻译成大厨能看懂的点餐单。

  2. 输出端(Driven):大厨做菜需要土豆。他不会自己跑去菜市场买,他只会对采购员下达指令:“给我拿两个土豆”(输出端口 Output Port)。至于采购员是从门口超市买的,还是从远洋货轮上空运的(输出适配器 Output Adapter,如 MySQL、Redis、第三方 API),大厨毫不关心。

工作流图解:洋葱般的结构

如果画个图,六边形架构就像一个洋葱,分为内、中、外三层:

  • 最内层(Domain):纯粹的业务实体和规则(大厨的手艺)。这里没有任何外部框架的代码。

  • 中间层(Ports):接口定义层(点餐单和采购单)。它规定了外部如何与核心交互,以及核心如何向外部要数据。

  • 最外层(Adapters):具体的实现(服务员、外卖App、采购员)。比如 Spring Boot 控制器、REST API、MyBatis Mapper。

核心原则:依赖只能从外向内! 外层可以调用内层的接口,但内层绝对不能知道外层的任何细节。

动手实战:用 TypeScript 烤一个“六边形”MVP (The "How")

让我们用 TypeScript 写一个极简的“创建用户”功能,感受一下六边形架构的魅力。

1. 核心领域与端口(Domain & Ports)

首先,我们定义核心逻辑和它需要的“契约”。这部分代码绝对不能引入任何外部库(比如 expressmongoose)。

TypeScript
 
// 1. 领域模型 (Domain Model) - 纯纯的业务对象
export class User {
  constructor(public readonly id: string, public name: string, public email: string) {}
}

// 2. 输出端口 (Output Port) - 核心业务向外要数据的“采购单”
export interface UserRepositoryPort {
  save(user: User): Promise<void>;
  findByEmail(email: string): Promise<User | null>;
}

// 3. 输入端口 (Input Port) - 外部调用核心业务的“点餐单”
export interface CreateUserUseCase {
  execute(name: string, email: string): Promise<User>;
}

2. 应用服务(Application Service)

接下来,实现核心业务逻辑。它实现了输入端口,并调用输出端口。

TypeScript
 
// 4. 核心业务逻辑实现
export class UserService implements CreateUserUseCase {
  // 依赖注入:我不在乎你传给我的是 MySQL 还是 MongoDB,只要实现了接口就行!
  constructor(private readonly userRepository: UserRepositoryPort) {}

  async execute(name: string, email: string): Promise<User> {
    const existingUser = await this.userRepository.findByEmail(email);
    if (existingUser) {
      throw new Error("邮箱已被注册!"); // 纯粹的业务异常
    }
    
    const newUser = new User(Date.now().toString(), name, email);
    await this.userRepository.save(newUser); // 调用输出端口
    
    return newUser;
  }
}

3. 适配器层(Adapters)

最后,我们编写外围代码,连接真实的世界。

TypeScript
 
// 5. 输出适配器 (Output Adapter) - 真正连接数据库的地方
// 假设这里用的是内存数据库,随时可以换成 MongoUserRepository
export class InMemoryUserRepository implements UserRepositoryPort {
  private users: User[] = [];

  async save(user: User): Promise<void> {
    this.users.push(user);
    console.log(`[Database] 用户 ${user.name} 已保存到内存数据库。`);
  }

  async findByEmail(email: string): Promise<User | null> {
    return this.users.find(u => u.email === email) || null;
  }
}

// 6. 组装运行 (类似框架的 Controller / CLI 入口)
async function main() {
  // 装配阶段:将适配器插入端口
  const repository = new InMemoryUserRepository();
  const userService = new UserService(repository);

  // 模拟一个 HTTP 请求进来
  console.log("--> 收到前端请求:创建用户张三");
  try {
    const user = await userService.execute("张三", "zhangsan@example.com");
    console.log("<-- 响应前端:创建成功", user);
  } catch (error) {
    console.error("<-- 响应前端:创建失败", error.message);
  }
}

main();

代码解析: 为什么这么写?你会发现 UserService 里没有任何数据库的影子。如果明天老板说要把用户数据存到 Redis,你只需要新建一个 RedisUserRepository 实现 UserRepositoryPort 接口,然后在组装阶段替换掉 InMemoryUserRepository 即可。核心业务代码一行都不用改!

进阶深潜:新手防坑指南 (Deep Dive)

常见陷阱

⚠️ 在领域实体里写 ORM 注解 很多新手会在 User 类上加上 @Entity@Table(name="users")。千万别这么干!这就等于让大厨在菜谱上写满了采购员的进货路线。领域对象必须是纯洁的,数据库持久化对象(Entity/Model)应该在 Adapter 层单独定义,并在 Adapter 里进行转换映射(Mapper)。

最佳实践

  1. 测试驱动开发(TDD)的绝佳搭档:由于核心逻辑(Domain & Application)只依赖接口(Ports),你可以非常轻松地 Mock 掉数据库,实现秒级的单元测试。

  2. 切忌过度设计:六边形架构会增加类的数量(多了一堆接口和转换代码)。如果你的项目只是一个简单的、生命周期很短的 CRUD 脚本,传统的 MVC 三层架构可能更高效。好钢要用在刀刃(复杂核心业务)上。

总结与延伸 (Conclusion)

核心总结:六边形架构通过“端口与适配器”的机制,建立了一堵防火墙,让你的核心业务逻辑摆脱了底层技术选型的束缚,实现了真正的可插拔、可测试、可维护。


文章来源:https://www.cnblogs.com/swizard/p/20511552
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云