Kotlin中的六边形架构:代码的纯净与灵活性

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

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

开始课程

Kotlin中的六边形架构:当代码自由呼吸

\n\n

想象一下,你在建造一栋房子。你可以直接浇筑地基、砌起墙壁、安装窗户。但也可以先设计框架、铺设管线,最后再进行装修。在编程世界中,第二种方法被称为六边形架构(也称为端口与适配器)。而Kotlin凭借其简洁性和强大的类型系统,是实现这一概念的理想语言。

\n\n

本文并非枯燥的教科书,而是一份实用指南,将展示Kotlin中的六边形架构如何将你的代码转变为灵活、可测试且独立于外部服务的系统。我们将从零开始分析一个示例,编写真实代码,并观察其实际运行效果。

\n\n

什么是六边形架构,为何需要它?

\n\n

提出这一术语的Alistair Cockburn将应用程序比作一个六边形。中心是你的业务逻辑。边缘是端口(接口),通过它们与外部世界通信。适配器则是这些接口针对特定技术(如数据库、Web框架、消息队列)的具体实现。

\n\n

核心理念:业务逻辑对数据存储方式或使用的框架一无所知。它只是调用端口的方法。想将PostgreSQL替换为MongoDB?只需编写一个新的适配器。业务逻辑甚至不会察觉到替换。

\n\n

在Kotlin中,这尤其方便,得益于带有默认实现的接口、密封类和函数式风格。让我们开始实践吧。

\n\n

系统设计:以在线商店为例

\n\n

假设我们正在编写一个用于管理订单的微服务。核心是OrderService,它负责创建订单并检查商品库存。外部世界包括HTTP控制器和数据库。

\n\n

项目结构如下:

\n\n
src/\n├── domain/          # 核心(业务逻辑)\n│   ├── model/\n│   ├── port/\n│   └── service/\n├── adapter/\n│   ├── input/       # 输入适配器(控制器)\n│   └── output/      # 输出适配器(仓库)\n└── Application.kt   # 入口点\n
\n\n

步骤1. 核心:模型与端口

\n\n

从订单模型开始。在Kotlin中,这将是一个data class:

\n\n
// domain/model/Order.kt\ndata class Order(\n    val id: String,\n    val customerId: String,\n    val items: List<OrderItem>,\n    val status: OrderStatus\n)\n\nenum class OrderStatus {\n    PENDING, CONFIRMED, SHIPPED, CANCELLED\n}\n\ndata class OrderItem(\n    val productId: String,\n    val quantity: Int\n)\n
\n\n

现在定义端口——核心与外部世界通信的接口。我们将有两个端口:一个用于获取商品数据,另一个用于保存订单。

\n\n
// domain/port/ProductRepository.kt\ninterface ProductRepository {\n    fun checkAvailability(productId: String, quantity: Int): Boolean\n}\n\n// domain/port/OrderRepository.kt\ninterface OrderRepository {\n    fun save(order: Order): Order\n    fun findById(id: String): Order?\n}\n
\n\n

请注意:任何地方都没有提及数据库、HTTP或框架。纯粹的业务逻辑。

\n\n

步骤2. 业务服务

\n\n

现在编写OrderService,它使用这些端口。在Kotlin中,我们通过构造函数传递依赖关系——这称为依赖注入(DI)。

\n\n
// domain/service/OrderService.kt\nclass OrderService(\n    private val productRepository: ProductRepository,\n    private val orderRepository: OrderRepository\n) {\n    fun createOrder(customerId: String, items: List<OrderItem>): Order {\n        // 检查每个商品的库存\n        for (item in items) {\n            if (!productRepository.checkA                

博客

书籍推荐