领域驱动设计(Thoughtworks洞见)
上QQ阅读APP看书,第一时间看更新

什么是端口和适配器架构

套用流行的提问方式:当我们在说架构时,我们在说什么?在本文中我们不是在讨论微服务架构,也不是讨论基础设施架构,这里的架构指:

1.在单个应用(进程)中。

2.代码是如何组织起来实现一个端到端的用户请求的。

3.它与框架无关,不管你是使用ORM框架或是JDBC,这不是架构的关键差异点。

一个例子是三层架构,展现层负责接收用户指令、渲染视图;业务逻辑层负责处理”业务逻辑”;数据层负责和数据库打交道,保存和读取数据。

“经典”的三层架构

三层(或多层)架构仍然是目前最普遍的架构,但它也有缺点:

1.架构被过分简化,如果解决方案中包含发送邮件通知,代码应该放置在哪些层里?

2.它虽然提出了业务逻辑隔离,但没有明确的架构元素指导我们如何隔离。

因此,在实际落地时,业务逻辑容易泄漏到展示层中,导致当应用需要一种新的使用方式时(例如开放API),原有的业务逻辑层可能不能快速重用,同样的问题也发生在数据层和业务逻辑层之间。

那么有没有替代的方案?Alistair Cockburn是敏捷运动的早期推动者之一,他于2005年在其博客中提出了端口和适配器架构,他对该架构的一句话定义是:

“应用应能平等地被用户、其他程序、自动化测试或脚本驱动,也可以独立于其最终的运行时设备和数据库进行开发和测试”。

原文为“Allow an application toequally be driven by users, programs, automated test or batch scripts, and to be developed and tested inisolation from its eventual run-time devices and databases.”

该架构由端口和适配器组成,所谓端口是应用的入口和出口,在许多语言中,它以接口的形式存在。例如以取消订单为例,“发送订单取消通知”可以被认为是一个出口端口,订单取消的业务逻辑决定了何时调用该端口,订单信息决定了端口的输入,而端口为预订流程屏蔽了通知发送方式的实现细节。

而适配器分为两种,主适配器(别名Driving Adapter)代表用户如何使用应用,从技术上来说,它们接收用户输入,调用端口并返回输出。Rest API是目前最常见的应用使用方式,以取消订单为例,该适配器实现Rest API的Endpoint,并调用入口端口CancelOrderService。同一个端口可能被多种适配器调用,例如CancelOrderService也可能会被实现消息协议的Driving Adapter调用以便异步取消订单。

次适配器(别名Driven Adapter)实现应用的出口端口,向外部工具执行操作,例如

• 向MySQL执行SQL,存储订单

• 使用Elasticsearch的API搜索产品

• 使用邮件/短信发送订单取消通知

若将其可视化,Driving Adapter和Driven Adapter基于端口围绕着应用形成左右结构,有别于传统的分层形象,形成一个六边形,因此也会称作六边形架构。

可视化端口和适配器架构

如果到此我已经成功地把你讲晕了,请不要担心,我们接下来通过一个案例体验一下这个架构。