作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《EffectiveJava》独家解析》专栏作者。
热门文章推荐:
- (1)《为什么很多人工作 3 年 却只有 1 年经验?》
- (2)《从失望到精通:AI 大模型的掌握与运用技巧》
- (3)《AI 时代,程序员的出路在何方?》
- (4)《如何写出高质量的文章:从战略到战术》
- (5)《我的技术学习方法论》
- (6)《我的性能方法论》
- (7)《AI 时代的学习方式: 和文档对话》
一、前言
相信很多人都听说过 David Wheeler 的一个非常著名的论断:“计算机科学领域的任何问题,都是可以通过增加一个间接的中间层来解决的。”
所谓:“内行人看门道,外行人看热闹”。在我看来很多人以为自己懂了,但还停留在“看热闹”的层面,并不能真正理解“中间层”思想的含义,更难以做到“知行合一” 进行泛化运用。
那么,中间层思想的含义究竟是什么?有哪些你意想不到的中间层思想的运用场景? 中间层思想又能给我们带来哪些启发? 中间层真的可以解决一切问题吗?本文将为你揭晓!
二、“中间层” 思想是什么?
2.1 解释
“计算机科学中的所有问题都可以通过增加一个额外的间接层来解决”,是对计算机科学和软件工程中间接层(Indirection Layer)重要性的一种幽默表述。间接层可以帮助解决多种问题,比如组织、优化和复用代码。
下面是这句话含义的几个方面:
- 解耦:
通过添加间接层,可以将系统的不同部分分离,使它们之间的依赖关系降到最低。这样,如果一个部分发生变化,它不会直接影响到其他部分。 - 抽象:
间接层可以提供一个抽象,使得开发者可以在不必关心底层实现细节的情况下工作。例如,数据库管理系统(DBMS)为开发者提供了一个查询和管理数据的抽象,而不需要关心底层的数据存储和检索机制。 - 可扩展性:
间接层可以帮助设计可扩展的系统。例如,通过添加一个负载均衡层,可以将来自客户端的请求分发到多个服务器,从而提高系统的处理能力。 - 复用和模块化:
通过间接层,可以创建可复用和模块化的代码。这使得开发者可以在不同的项目或系统中重用相同的代码,从而提高开发效率和代码质量。 - 错误处理和安全:
间接层还可以用于错误处理和安全控制。例如,通过在网络通信中添加一个错误检测和重传层,可以确保数据的正确传输。 - 优化:
间接层可以用于优化性能,例如,通过添加一个缓存层来减少对底层资源的访问,从而提高系统的响应速度。
2.2 案例
操作系统通过增加中间层,连接软件和硬件; Java 虚拟机是通过增加虚拟机层实现 Java 的跨平台;分布式缓存通过增加中间的缓存层,实现不同的应用之间的缓存共享;分布式锁,通过增加中间层的锁机制,实现跨机器的并发控制;分库分表中间件,通过增加中间层封装分库分表逻辑,降低复杂度;消息队列通过中间层实现削峰、异步的功能;代理服务通过中间层代理,来实现访问目标服务器的功能;中介者模式,则是通过增加中介者中间层,来降低对象之间的直接通信,减少对象耦合、提高系统灵活性和可维护性;领域驱动,则是通过增加中间的领域层实现核心业务的稳定性,提高内聚降低耦合。
在软件工程领域,通过中间层来解决问题的例子还有很多很多。
生活中能够体现“中间层”的例子也比比皆是。比如通过支付宝实现支付,通过淘宝实现购物,通过滴滴实现打车,通过饿了么实现购买外卖,通过翻译软件或翻译人员实现不同语言之间的交流,通过熟人介绍对象等等。
最近 ChatGPT 官网上 GPT-4 也支持调用 DALL·E3 通过自然语言进行绘图,这也体现了“中间层”的思想。
中文用户可以通过简单的中文自然语言描述生成比较满意的图形。
ChatGPT 作为 “中间层”,可以将用户相对简答的中文的自然语言提示词,转换为 DALL·E3 模型所需的英文的专业的复杂提示词,降低用户的使用门槛,对用户非常友好。
三、为什么"中间层"思想那么有效?
在我看来,“中间层” 和“任务分解” 有异曲同工之妙。
“中间层” 是采用 “任务分解” 将复杂的问题分解为更简单、更具体的子任务,降低问题的复杂度,提高问题解决的效率和质量的一个具体运用。
“中间层”能够降低复杂度主要是因为它起到了“隔离”和“桥梁”的作用,让不同层次或组件之间有了清晰的边界和互动方式。
四、我们该怎么做?
4.1 学以致用
只有能够“学以致用”,能够将所学的知识用来解决实际的问题,我们学习的知识才有价值。
4.1.1 辅助理解知识
由于“中间层”思想在计算机领域得到了非常广泛的应用,我们在学习或重温一些计算机专业基础、学习中间件、设计模式时,需要主动思考当前所学的知识是否是通过“中间层”来解决问题的,或许在某个瞬间能够想到本质儿“豁然开朗”。
比如,当我们学习领域驱动时,我们会发现和“中间层”思想颇为一致。就可以思考,通过它采用中间层的思想解决了什么问题,带来了哪些好处。
领域驱动解决的问题:
- 解耦:领域层使得业务逻辑从其他层(如UI层、数据访问层)中分离出来,降低了各层之间的耦合度。
- 可维护性:业务逻辑集中在领域层,使得代码更易于维护和测试。
- 可重用性:领域层中的业务逻辑可以在不同的应用或系统中重用。
- 易于理解:通过使用领域特定的语言(Ubiquitous Language),使得业务逻辑更易于理解。
领域驱动带来的好处:
- 敏捷开发:由于业务逻辑与其他层解耦,更容易适应需求变化。
- 团队协作:使用领域特定语言有助于提高开发者和业务人员之间的沟通效率。
- 高质量代码:领域层强调软件质量,如代码的可测试性和可扩展性。
- 提高生产效率:通过模式和设计原则(如工厂模式、策略模式等)的应用,领域层可以更快地进行开发。
再比如我们学习“装饰器” 设计模式时,也可以按照这种模式进行思考。学习适配器模式、代理模式、中介者模式等,亦然。
装饰器模式解决的问题:
- 开闭原则:装饰器模式使得你可以在不修改原有类的代码的情况下,对其添加新的功能。
- 单一职责原则:每个装饰器只关心一种特定的功能扩展,使得类的设计更加模块化。
- 灵活性:可以动态地、运行时地添加或移除功能。
装饰器模式带来的好处:
- 可维护性:由于新的功能是通过添加新的装饰器类来实现的,因此更容易进行单元测试和维护。
- 可复用性:装饰器是独立的对象,可以在不同的场景和对象上重复使用。
- 可扩展性:新的功能可以通过添加新的装饰器来轻松实现,而不需要修改现有代码。
- 粒度控制:装饰器模式提供了一种粒度更细的功能扩展方式,你可以选择只对某个特定对象进行装饰,而不是整个类。
装饰器设计模式通过引入装饰器“中间层”,在保持原有对象不变的同时,提供了一种灵活和可扩展的方式来增加对象的功能。这不仅有助于保持代码的整洁和可维护性,还提高了代码的可复用性和可扩展性。
再比如我们学习 API 网关时,也可以按照这种模式进行思考。
API 网关体现了“中间层”思想,因为它位于微服务架构(或者其他服务端架构)与客户端之间,作为一个中介层来管理和路由请求。API网关通常提供一系列功能,包括请求路由、负载均衡、身份验证、授权、缓存等。
API 网关解决的问题:
- 解耦:API网关使得客户端和服务端的交互更加解耦,客户端不需要知道后端服务的具体位置和实现细节。
- 集中管理:所有进出的请求都会经过API网关,方便进行监控、日志记录、安全控制等。
- 协议转换:API网关可以负责将外部的HTTP/REST请求转换为内部使用的其他协议(如gRPC, MQTT等)。
- 灵活性:可以根据需要动态地更改路由规则、添加新服务或者进行版本控制。
API 网关带来的好处:
- 简化客户端:由于API网关提供了统一的入口,客户端的实现会更加简单。
- 提高安全性:集中进行身份验证和授权,更容易对系统进行安全控制。
- 提高可维护性:集中管理使得代码和配置更容易维护。
- 性能优化:API网关通常包括缓存、限流、熔断等功能,有助于提高系统的整体性能。
通过这种思考模式,更容易抓住问题的本质,更好地理解对应的概念。
4.1.2 辅助解决问题
当我们理清需求,需要设计技术方案,遇到难以理解的问题时,可以主动思考是否可以通过增加“中间层”来解决当下的问题,有时候会有“奇效”。
4.2 没有银弹
计算机科学家弗雷德·布鲁克斯(Fred Brooks)在他的经典论文《没有银弹:软件工程的本质性与附属性工作》中提出了“没有银弹”的概念。即没有一种单一的技术或方法可以解决软件工程中的所有问题,也不能在短时间内显著提高软件工程的生产力。软件工程是一项复杂而困难的工作,需要综合运用多种技术和方法来解决各种问题。
《解决问题的艺术》中也提到“解决一个问题可能会导致其他问题的产生或者原有问题的恶化”。
因此“中间层”思想并不是“银弹”,并不是万能的,我们在运用“中间层”思想来解决问题时,需要思考“带来了什么副作用”,权衡好利弊。
五、总结
本文介绍了“中间层”的概念,并从软件工程和生活领域给出了诸多能够体现出“中间层”思想的例子以便帮助大家理解这个概念。希望大家能够真正做到学以致用,通过“中间层”思想辅助我们理解知识,通过“中间层”思想辅助我们解决问题。另外我们还需要谨记“没有银弹”,凡事“有利就有弊”,在运用“中间层”思想解决问题时,还需要权衡利弊,做出最佳选择。
创作不易,如果本文对你有帮助,欢迎点赞、收藏加关注,你的支持和鼓励,是我创作的最大动力。