整洁架构or整洁代码?或许需要一个整洁的API!

整洁架构or整洁代码?或许需要一个整洁的API!

【引】你可能读过《clean architecture》一书, 也读过《clean code》,如果缺了些什么? 那可能就是 Clean API 了。本文译自“https://medium.com/perry-street-software-engineering/clean-api-architecture”。

在软件架构领域,网上讨论最广泛的架构之一是整洁架构(Clean Architecture)。它通过将项目划分为多个层级,实现关注点分离,从而提升代码的可维护性和可扩展性。

img

每一层都遵循单一职责原则,确保每个类只负责一部分逻辑,不仅使系统结构更清晰,也极大地方便了单元测试的编写与执行。

整洁架构的核心理念可以概括为:

依赖关系向内指向“业务核心”,外层可以依赖内层,但内层绝不可以反向依赖外层。

换句话说,没有哪一层可以看到比它更高层的细节。它们可以引用自己的子层,但从不允许跨层依赖或反向耦合。

这种设计思想不仅适用于整体系统架构,在具体场景如 API 开发中同样具有重要价值。那么,如何将 Clean Architecture 的理念应用到 API 端点的设计中?这就引出了“Clean API 架构”这一实践模式:

img

它将接口层、应用服务、领域逻辑和数据访问等模块清晰隔离,使 API 结构更加清晰、易于测试和长期演进。

1. 框架:从请求入口到架构分层

在现代 Web 系统中,任何一个 API 请求通常都需要经过多个层级的处理——从负载均衡器、Web 服务器,到应用服务器,最终由具体的 API 或 Web 框架将请求路由到正确的代码路径。目前主流的开发框架如 Rails、Django 和 Spring Boot 等都提供了丰富的文档支持和成熟的生态体系,是大多数开发者首选的技术栈。

然而,当请求真正进入框架并开始业务逻辑处理后,不同系统的设计路径往往开始显著分化。

以 Rails 为例,其采用经典的 MVC(Model-View-Controller)架构,在小型项目中表现优异,结构清晰且上手成本低。但对于大型、高可用性的 API 系统而言,这种模式逐渐显露出局限性——控制器和模型容易膨胀为臃肿的“上帝类”,违背了单一职责原则,导致维护困难、测试复杂。

正因如此,在框架层级之下,我们所构建的整个系统设计更加注重解耦与可扩展性,并深受 Clean Architecture 的启发。这套设计理念强调业务逻辑应独立于外部依赖(如数据库、UI、框架等),从而提升系统的可测试性和长期可维护性。

在本系列后续内容中,我们将深入剖析我们是如何按照这一思想来组织各层级代码的。

在每一层中,我们会定义一个或多个单一职责的支持类,它们只服务于当前层级,不引用上下层的具体实现。这种严格隔离不仅有助于代码复用,也有效避免了层级混乱和过度耦合的问题。

此外,虽然我们在架构中使用了诸如 AWS EC2、SQS、RDS 和 ElastiCache 等云服务,但这些服务在我们的设计中被作为框架层的辅助工具类存在,而非核心业务逻辑的一部分。正如 Clean Architecture 所强调的那样:业务规则不应依赖于基础设施或数据存储方式,而应保持完全的独立。这也确保了我们的系统具备更强的可移植性与灵活性。

2. 接口适配器层:连接外部世界与核心逻辑的桥梁

当一个请求穿越框架层,进入系统内部时,接口适配器层便开始发挥作用。这一层的核心职责是将外部输入转化为内部可理解的数据结构,并将应用逻辑的执行结果以合适的格式返回给调用者。

在这一过程中,**控制器(Controller)**扮演着协调者的角色。它首先通过 Request 对象提取请求参数,验证其语法格式,并完成用户身份认证等前置操作。随后,控制器实例化相应的业务类,驱动数据在不同层级之间的流转,从而启动真正的应用逻辑处理流程。

值得注意的是,控制器并不是接口适配器层中唯一负责业务流程的对象。我们还引入了 Jobs(任务),用于处理异步队列相关的操作——这部分内容将在后续章节中详细展开。

为了确保系统的清晰分层与职责分离,控制器依赖于多个辅助类:

  • Validators(验证器)

    负责检查输入数据的合法性,确保进入系统的信息符合预期格式;

  • Presenters(展示器)

    专注于输出数据的格式化处理,为上层逻辑提供统一的数据视图;

  • Response(响应)对象

    则承担最终输出的封装工作,能够将数据转换为 JSON、HAML 或其他客户端可识别的格式返回。

此外,系统中还包含一种特殊的适配器——套接字中继类(Socket Relay),它通过 WebSocket 等通信通道,实时将状态变更推送给客户端,实现双向通信能力。

Request 类则是一个类型化的数据结构,聚合了当前请求所需的所有信息。与传统 HTTP 请求(通常是以键值对形式存在的 CGI 风格请求)不同,这种设计提供了更强的类型安全性和结构清晰性。

Response 类的功能类似于 Rails 中的渲染器,但它更加灵活,支持多种输出格式,如 HAML、JSON 或自定义类型,便于构建多端兼容的 API 响应。

最后,参数提取器(Parameter Extractor) 从原始的 params 散列中提取数据,并将其转换为正确的类型,如整数、浮点数或字符串,为后续逻辑提供强类型的输入保障。

整体而言,接口适配器层作为系统的“翻译官”,在外部请求与内部逻辑之间建立起高效、清晰的桥梁,是实现 Clean Architecture 分层思想的重要一环。

3. 应用逻辑层:业务流转的核心引擎

在 Clean API 架构中,应用逻辑层是整个系统真正开始处理业务需求的地方。它承接来自接口适配器层的请求,并协调数据验证、权限控制、外部调用以及最终的业务执行。

对于 GET 请求这类读取型端点,请求一旦进入该层,首先由服务类(Service)进行处理。服务对象负责确保输入参数的有效性,验证用户是否有权限访问目标资源,并通过 Repo(用于数据库操作)Adapter(用于外部 API 调用)实体逻辑层获取所需数据。

在数据获取完成后,服务对象将结果封装为一个由 Result 对象返回。这种设计不仅统一了成功与失败的返回结构,也便于上层(如控制器)根据结果类型做出相应的响应决策。

而对于 POST、PUT 和 DELETE 等写入型请求,应用逻辑的处理流程类似,但引入了异步机制以提升性能和可靠性。服务对象仍然负责验证输入、授权用户,并准备写入所需的数据。不同之处在于,这些变更操作会被包装并提交到我们的**任务队列(基于 Amazon SQS)中排队,交由后台的作业(Job)**或异步服务来执行真正的数据写入操作。这种方式既减轻了主流程的压力,也增强了系统的容错能力和可扩展性。

此外,作业还承担着触发副作用的职责。例如,在数据持久化完成之后,作业可以通过 Relay 模块向客户端发送 WebSocket 消息,实时通知状态变更,实现前后端之间的即时反馈。

值得一提的是,在本架构中,Service 类还会组合一组专门的 Validator 类,对请求内容进行语义级别的验证。这意味着我们在系统中构建了双层验证机制

  • 语法验证

    发生在请求层,确保传入的数据格式正确;

  • 语义验证

    则在应用逻辑层进行,确保数据在业务规则下是合理且合法的。

这种分层验证策略显著提升了系统的健壮性,避免了无效或非法数据对核心业务逻辑造成干扰,同时也使代码更具可测试性和可维护性。

4. 实体逻辑层:业务规则与数据交互的核心

实体逻辑层(Entity Logic Layer) 是系统中最具通用性和复用价值的部分。它不仅服务于当前 API 端点,也为其他多个接口和业务流程提供基础能力支撑。这一层承载了系统的核心业务规则以及与外部存储系统的交互逻辑。

在这一层级中,我们实现对持久化数据库(如 MySQL 或 PostgreSQL)的访问,封装了数据的读取、写入和转换逻辑;同时,Adapter 类 则负责对接各类外部服务 API,例如 AWS 提供的 S3(对象存储)、ElastiCache(缓存服务)等,使得系统能够灵活集成多种基础设施资源。

与上层(如应用逻辑层)中为特定端点定制的服务类不同,实体逻辑层中的类设计强调高内聚、低耦合广泛复用性。它们通常不依赖于具体的请求或业务场景,而是围绕领域模型构建稳定的数据访问和业务处理能力。

简而言之,实体逻辑层是整个 Clean API 架构中最接近“不变”的部分——它屏蔽了外部变化的影响,确保系统核心逻辑稳定可靠,同时也为上层模块提供了统一、可测试、可替换的数据交互接口。

5. 数据层:存储抽象与适配的关键一环

数据层(Data Layer) 是整个 Clean API 架构中最底层的一环,其核心职责是为上层模块提供统一的数据访问接口,并屏蔽具体存储实现的细节。理想情况下,这一层应保持高度简洁和可替换,专注于连接数据库、缓存、文件系统或其他持久化机制。

为了实现跨平台一致性,我们在不同技术栈中(例如 Android 或 iOS 开发)也为数据存储层建立了统一接口。通过依赖注入(Dependency Injection) 技术,我们可以在测试时轻松替换真实的数据源为内存中的模拟实现(Mock)。例如,在本地运行单元测试时,可以使用基于 SQLite 的内存数据库代替实际的文件系统或远程服务,从而提高测试效率并减少外部依赖的影响。

在 Web 服务器环境中,我们通常将云服务(如 Redis、Memcached、MySQL 等)抽象为单例对象,并根据部署环境动态指向不同的实际资源。例如,在开发阶段,这些服务可以指向本地运行的 Docker 容器;而在生产环境中,则连接真实的云服务实例。

支撑数据层的各类存储系统——如 MySQL 和 Postgres——通常以进程级别的单例形式存在,并通过依赖注入或配置管理进行初始化和替换。像 ActiveRecord 这样的 ORM 会维护自己的连接池,而 Redis 和 Memcached 等服务也需要类似的全局访问控制机制来管理连接资源。

对于基于 HTTP 的无状态服务(如 S3、DynamoDB 等),我们通常采用模拟双(Instance Doubles)或覆盖连接参数的方式来隔离外部环境。这使得测试过程更加可控,同时也能保证代码逻辑在不同环境下的一致性。

总之,数据层不仅是系统与外部世界交互的桥梁,更是实现可测试性、可维护性和可扩展性的关键所在。通过良好的抽象设计与灵活的注入策略,它确保了我们的业务逻辑不受底层存储细节的牵制,真正做到“一次编写,多环境运行”。

6. 这是否过度设计?让我们通过一个简单的示例来探讨

为了更好地理解各层架构的实际应用,我们来看一个最基础的 API 示例:将文件添加到收藏夹。即使在这样一个看似简单的操作中,每一层的设计理念依然得到了体现。

假设我们要创建一个允许用户将某个文件添加到其收藏夹的功能。在这个过程中,尽管表面上看只需要一个简单的数据库操作,但实际上,这个功能隐式地依赖于我们之前定义的每一层架构。

请求(Request)

请求参数直接从 HTTP 请求中提取,包含 target_id(目标文件的ID)和 creator_id(执行该操作的用户ID)。这些未经处理的原始参数构成了一个隐式的请求对象。

Params: { "target_id": 123, "creator_id": 456 }

控制器(Controller)

由于此场景下没有复杂的验证或表示逻辑需求,因此无需专门编写控制器代码。这意味着我们可以跳过这一步骤,直接进入服务层处理业务逻辑。

服务(Service)

服务层在此处承担了主要职责,它接收来自请求的 target_idcreator_id,并查找或创建相应的领域对象 Favorite。这一过程确保了输入的有效性和用户的授权状态,并协调后续的数据处理步骤。

实体逻辑(Entity Logic)

实体逻辑层负责与持久化存储交互,这里使用了一个特殊的 ActiveRecord 方法 first_or_create 来检查是否存在符合条件的记录,若不存在则创建新记录。这种方法不仅简化了数据访问逻辑,还保证了数据的一致性。

数据(Data)

在数据层,Favorite 模型充当了与底层数据库交互的角色,提供了对特定对象的操作接口。它封装了所有与数据库相关的细节,如连接管理、查询构建等,使得上层代码可以专注于业务逻辑而非技术实现。

通过这个简单的例子可以看出,即使是看似微不足道的功能,Clean API 的分层设计也能够提供清晰的结构划分,确保每个部分专注于自己的职责。这样的设计虽然初看起来可能显得有些复杂,但它极大地提高了代码的可维护性、测试性和扩展性。随着系统规模的增长,这种架构的优势将会更加明显。

网络安全学习资源分享:

给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包,需要点击下方链接即可前往获取

读者福利 | 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

在这里插入图片描述

👉1.成长路线图&学习规划👈

要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
在这里插入图片描述

在这里插入图片描述

👉2.网安入门到进阶视频教程👈

很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。(全套教程文末领取哈)
在这里插入图片描述

在这里插入图片描述

👉3.SRC&黑客文档👈

大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录

SRC技术文籍:

在这里插入图片描述

黑客资料由于是敏感资源,这里不能直接展示哦!(全套教程文末领取哈)

👉4.护网行动资料👈

其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

在这里插入图片描述

👉5.黑客必读书单👈

在这里插入图片描述

👉6.网络安全岗面试题合集👈

当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。
在这里插入图片描述
所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~

读者福利 | 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值