本文为读书笔记,对书中内容进行重点概括,并将书中的模块化结合微服务、Java9 Jigsaw谈谈理解。
本书概括
以Java软件系统为例,重点讲解了应用架构中的物理设计问题,即如何将软件系统拆分为模块化系统。所以内容组织包括为什么需要模块化,围绕如何实现模块化讲述了模块化模式,最后在模块化基础上使用OSGi技术实现动态模块化。
内容总结
模块化定义
先谈谈应用架构的逻辑设计和物理设计。
逻辑设计是关于语言结构的,指类、方法之间的关系,组织结构。物理设计是关于软件中的物理实体,即部署单元和他们之间的关系,是关于如何将系统拆分为模块系统的。
模块定义:
软件模块是独立可部署的、可管理的、进程内可重用的、无状态的软件单元。可管理即模块可以安装、卸载和更新。
在Java中,模块就是jar包。
与分布式服务不同的是,这里的模块是进程内重用,需要与想用其功能的进程一起部署,而服务是一次部署被多个client使用。
模块化的理由
- 仅关注高层抽象是不够的,只强调代码质量也是不够的,模块化能填补高层架构与底层代码之间的空白,增加设计的灵活性,帮助实现高适应性、高可维护性的系统架构。
- 模块是内聚的,变化将局限在模块的实现细节中,即能封装变化,所以能减小复杂性,降低维护成本。
- 模块化提供了指导和规律,让我们可以在最小化依赖的同时又能最大化重用的潜能,帮助我们平衡模块的重量级和粒度。这里粒度指一个系统要拆分的各个部分的范围大小,重量级指模块对其他环境依赖的程度。最大化重用会使得可用复杂化,设计软件时,围绕模块的重量级和粒度的权衡是很重要的因素,对系统的模块化都是与项目上下文相关并且要符合当时的情况。一些特定级别的重用已经很成熟了,如ORM框架,Netty框架等。
- 跨应用重用是服务的最佳用武之地,但通常是粗粒度的,即所做的事情超出我们的需要,如果需要跨应用重用一些需要的行为呢?没有模块的情况下,我们的选择是将其暴露为服务或者复制类的代码,两者都不理想,模块化就是另一种选择,在粒度上,模块是比服务更小的单元且是部署单元。
模块化模式
-
基本模式
- 管理关系:设计模块之间的关系
- 模块重用:强调模块级别的重用
- 模块内聚:模块的行为应该只服务于一个目的
-
依赖模式
- 非循环关系:模块之间的关系非循环依赖
- 等级化模块:模块关系是等级化的,物理分层旨在为组成应用的分层创建多个模块,更多是与职责相关,而等级与理解系统的结构和关系更为密切,比分层更为细粒度,一个分层可能会有多个等级。
- 物理分层:模块关系不影响物理分层,如展现、领域、DAO。
- 容器独立:模块不依赖于具体容器,采用轻量级容器,如Spring
- 独立部署:模块可独立部署
-
可用性模式
- 发布接口:暴露API
- 外部配置:使用独立的配置文件用于不同的上下文。外部化配置增加了模块的重用行,但降低的易用性。如一个提供连接池的模块,user,password通过配置文件配置而不是硬编码在模块中,这就方便重用,但会使得易用性降低,因为使用之前必须配置对应的上下文
- 默认实现:为模块接口提供默认实现,并提供扩展机制,默认实现有助于在重用和易用之间取得平衡。如dubbo的扩展点机制
- 模块门面:为底层细粒度模块创建一个门面,提供高层API协调一组细粒度模块的行为
-
扩展性模式
- 抽象化模块:依赖于抽象而不是具体,典型的例子如通过Spring注入具体实现,bean里面依赖的属性是接口
- 实现工厂:通过实现工厂建立适当的对象引用,如Spring的装配
- 分离抽象:将抽象类与实现类放在各自的模块中,从而能用新的实现替换已有的实现,帮助创建灵活和可扩展的系统
-
通用模式
- 就近异常:异常定义应该接近抛出他们的模块
- 等级化构建:按照模块的等级构建
- 测试模块:每个模块应该有一个对应的测试模块
模块化与OSGi
OSGi是Java平台中的动态模块系统,定义了一个模块化单元,称之为bundle,是一个jar文件。bundle会在同一个JVM中进行部署和交互,在进程内跨bundle交互,并且可动态部署bundle。
OSGi只是提供一个运行时环境,使得在Java平台中实现模块化成为可能。
书中好词好句
自上而下的架构
架构的目标是减少变化的成本和影响
软件倾向于随着时间变得腐化,随着时间流逝,变化会悄然发生并以难以预料的方式考验着设计
技术债用来描述为了满足进度或用户期望而做出的设计让步,与财务债一样,也需要支付利息,在将来的开发中要付出额外的努力。我们可以选择继续支付利息或用更好的设计重构来偿还本金,尽管偿还本金需要成本,但是会降低将来要支付的利息。
复杂性阻止我们以优雅的方式使软件系统适应需求的变化。
最大化重用会使得可用复杂化。即软件模块的可重用性越高,则其易用性越差。
模块化与微服务
通过上文的描述,我们已经了解了模块化思想,那与如今的微服务是什么关系呢?
微服务也是可独立部署于容器的,每个微服务仅关注于完成一件任务并很好地完成该任务,每个任务代表着一个小的业务能力。各个微服务之间通过轻量级协议(RESTful API接口, 轻量级消息机制)交互通信。与模块化强调的进程内重用不同,微服务属于分布式服务,通过RPC协议在进程间重用。
相似点:
两者都是可独立部署的,重视逻辑的可复用性,强调一个大的软件系统需要拆分为各个部分,保持高内聚低耦合,实现更好的软件架构。
个人理解:
微服务架构更胜一筹于模块化架构思想。提出模块化架构的本书(中文版)发版于2013年,微服务的概念源于2014年,两者目的相似,现如今已有大量企业对已有系统进行改造或实施微服务架构,开发人员对微服务的认知逐渐深入,大的市场环境已经采用了微服务架构。又微服务已经是一个较小且完整的业务部署单元,不会将其拆分为多个模块化单元在同一进程中部署,就算拆分也是将其拆分为更细粒度的微服务。
虽然实施微服务需要具备完善的基础设施,如容器化、服务注册发现、配置管理、监控等DevOps开发运维一体化设施,但随着应用云化的日益普及,相关设施不断完善,如SpringCloud,其实施的门槛已经较低了。
且动态模块化技术如OSGi尚未普及,所以,个人认为微服务架构比模块化架构更优。
模块化与Java9 Jigsaw
Java 9Java 平台模块化项目(Jigsaw )参考 https://mp.weixin.qq.com/s/Sr...
参考
微服务相关:
https://www.ibm.com/developer...
https://martinfowler.com/micr...