整洁架构or整洁代码?或许需要一个整洁的API!
【引】你可能读过《clean architecture》一书, 也读过《clean code》,如果缺了些什么? 那可能就是 Clean API 了。本文译自“https://medium.com/perry-street-software-engineering/clean-api-architecture”。
在软件架构领域,网上讨论最广泛的架构之一是整洁架构(Clean Architecture)。它通过将项目划分为多个层级,实现关注点分离,从而提升代码的可维护性和可扩展性。

每一层都遵循单一职责原则,确保每个类只负责一部分逻辑,不仅使系统结构更清晰,也极大地方便了单元测试的编写与执行。
整洁架构的核心理念可以概括为:
依赖关系向内指向“业务核心”,外层可以依赖内层,但内层绝不可以反向依赖外层。
换句话说,没有哪一层可以看到比它更高层的细节。它们可以引用自己的子层,但从不允许跨层依赖或反向耦合。
这种设计思想不仅适用于整体系统架构,在具体场景如 API 开发中同样具有重要价值。那么,如何将 Clean Architecture 的理念应用到 API 端点的设计中?这就引出了“Clean API 架构”这一实践模式:

它将接口层、应用服务、领域逻辑和数据访问等模块清晰隔离,使 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_id和 creator_id,并查找或创建相应的领域对象 Favorite。这一过程确保了输入的有效性和用户的授权状态,并协调后续的数据处理步骤。
实体逻辑(Entity Logic)
实体逻辑层负责与持久化存储交互,这里使用了一个特殊的 ActiveRecord 方法 first_or_create 来检查是否存在符合条件的记录,若不存在则创建新记录。这种方法不仅简化了数据访问逻辑,还保证了数据的一致性。
数据(Data)
在数据层,Favorite 模型充当了与底层数据库交互的角色,提供了对特定对象的操作接口。它封装了所有与数据库相关的细节,如连接管理、查询构建等,使得上层代码可以专注于业务逻辑而非技术实现。
通过这个简单的例子可以看出,即使是看似微不足道的功能,Clean API 的分层设计也能够提供清晰的结构划分,确保每个部分专注于自己的职责。这样的设计虽然初看起来可能显得有些复杂,但它极大地提高了代码的可维护性、测试性和扩展性。随着系统规模的增长,这种架构的优势将会更加明显。
网络安全学习资源分享:
给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
题外话
黑客&网络安全如何学习
今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。
1.学习路线图

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。
2.视频教程
网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我们和网安大厂360共同研发的的网安视频教程,之前都是内部资源,专业方面绝对可以秒杀国内99%的机构和个人教学!全网独一份,你不可能在网上找到这么专业的教程。
内容涵盖了入门必备的操作系统、计算机网络和编程语言等初级知识,而且包含了中级的各种渗透技术,并且还有后期的CTF对抗、区块链安全等高阶技术。总共200多节视频,200多G的资源,不用担心学不全。

因篇幅有限,仅展示部分资料,需要见下图即可前往获取
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
3.技术文档和电子书
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
4.工具包、面试题和源码
“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。
还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。
这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。
参考解析:深信服官网、奇安信官网、Freebuf、csdn等
内容特点:条理清晰,含图像化表示更加易懂。
内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
————————————————
本文转自 https://blog.youkuaiyun.com/yy1715713348/article/details/148946519?spm=1001.2014.3001.5502,如有侵权,请联系删除。

1952

被折叠的 条评论
为什么被折叠?



