什么是端口和适配器架构
套用流行的提问方式:当我们在说架构时,我们在说什么?在本文中我们不是在讨论微服务架构,也不是讨论基础设施架构,这里的架构指:
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基于端口围绕着应用形成左右结构,有别于传统的分层形象,形成一个六边形,因此也会称作六边形架构。
可视化端口和适配器架构
如果到此我已经成功地把你讲晕了,请不要担心,我们接下来通过一个案例体验一下这个架构。