网上有许多讲组件化开发、模块化开发的文章,但你们通常都是将这两个概念混为一谈的,并无加以区分。并且实际上许多人对于组件、模块的区别也不甚明了,甚至于许多博客文章专门解说这几个概念都有些谬误。架构
想分清这两个概念我以为结合一下软件的渐进式开发场景更容易理解。可是下面的篇幅会比较长,因此我先说结论,不耐烦的同窗能够先看:框架
类别 | 目的 | 特色 | 接口 | 成果 | 架构定位 |
---|---|---|---|---|---|
组件 | 重用、解耦 | 高重用、松耦合 | 无统一接口 | 基础库、基础组件 | 纵向分层 |
模块 | 隔离/封装 | 高内聚、松耦合 | 统一接口 | 业务框架、业务模块 | 横向分块 |
由于从代码组织层面上来区分,组件化开发是纵向分层,模块化开发是横向分块,因此模块化并无要求必定组件化。也就是说你能够只作模块化开发,而不作组件化开发。那这样的结果是什么样的呢?就是说你的代码彻底不考虑代码重用,只是把相同业务的代码作内聚整合,不一样模块之间仍是存在大量的重复代码。这样的成果也算是作到了模块化,只不过咱们通常不会这样而已。模块化
和组件模块近似的一对概念是库和框架。库的概念偏近于代码的堆集,是分层的概念,因此对应组件化。框架是结构化的代码,因此应用于模块化。框架是骨,模块化是肉。
好比,ReactiveCocoa是库,只是提供了响应式编码能力,而基于此的MVVM具体实现成果才叫框架,由于框架自己就有架构思想在里面。组件化
下面咱们举例来讲明。
组件化就好比公共的alert框,最初在许多页面都有使用,后面提取出一份相同的代码,其实就是基于代码复用的目的。编码
模块化就好比一个资讯功能,它自己只在这一个地方使用,没有复用的需求,但系统启动的时候要初始化它的数据,首页显示的时候要展现它的数据,显示红点的时候要拉取它的未读数。这样一来应用中就有不少地方涉及到它的代码。若是咱们将它看作一个总体,那么资讯模块和主应用的耦合性就很是高了。因此咱们也要把它封装成模块,把相关的代码放到独立的单元文件里,并提供公共方法,这就是高内聚的要求。模块化开发
固然这几个概念在服务端开发和客户端开发领域有些微差异,我下面的例子就从移动端开发的角度上进行辨析。接口
首先咱们定义一个虚拟的产品——一款知识类应用,包含咨询、问答、学院、直播等功能。路由
接下来咱们逐步拆分这个产品。开发
若是开发时没有考虑任何组件化模块化开发,那么此应用的全部功能都是堆积在一块儿的,总结起来就是高耦合,低内聚,无重用。博客
那么代码重构的第一步是什么呢?
将重复的代码合并成为一份,也就是重用。
咱们来看组件化开发的定义,它的着重点就是重用,那这一步最后的结果就是提炼出一个个组件给不一样的功能使用。
这里咱们能够看一下依赖关系,是具体功能依赖提炼出来的组件,组件自己之间可能也有依赖关系,但通常很少。因此咱们总结组件化开发的原则就是高重用,低依赖。固然这只是相对而言。
基于这样的认识,咱们甚至于能够把资讯、问答、学院、直播等功能封装成组件,只不过这些组件比较大,依赖可能多些,不过本质上没有多少区别,并且实际上网上许多文章说所的模块化开发其实就是这种组件化的“模块”。
下面再说模块,按照模块的定义,它是以关注点进行划分的,关注点说到底就是功能,也就是说根据咱们上面的例子,资讯、问答、学院、直播能够分红不一样的模块。
咱们最开始定义这个虚拟产品的时候说,它有三个特色——高耦合、低内聚、无重用。而第一点组件化开发主要是解决了重用问题,提高了部份内聚,而耦合问题则没有涉及。
因此说咱们上面能够将这个产品在逻辑上划分为资讯、问答、学院、直播四个模块,但在代码层面上它们却不是四个模块,由于它们的代码都是混杂在一块儿的。好比产品首页,可能推荐了部分资讯、显示了热门问答、推送了目前的直播,而这些功能的代码则是写在一块儿的;再好比程序启动的时候,这四个模块都须要初始化一些数据,而初始化数据的代码也是写在一块儿的;再好比程序须要显示未读消息数,而这几个模块都有本身的未读消息数逻辑。
若是未进行模块化开发的拆分,那么不少时候不一样模块的同一类的代码都是直接写在一块儿的,好比系统启动的时候,咱们会在启动方法里直接写多个模块的初始化代码。
而模块化开发就是为了解决这一问题,即提升内聚,将分属同一模块代码放到一块儿;下降耦合,将不一样模块间的耦合程度弱化。
高内聚是目标,可是现状是有许多地方会用到多个模块,好比启动的时候会调用四个模块,首页会展现三个模块的界面。若是要高内聚,那么必然须要这些模块为不一样的场景提供相同的方法,这就是说全部模块要实现同一套多个接口。这样主应用和模块之间的重耦合就变成了主应用和接口耦合,接口和模块耦合这样的松耦合。
但这样的简单模块只是轻模块,统一接口较少。而统必定义的接口越多,模块和统一接口的耦合就越高,也即是重模块。
而咱们通常讲的路由问题其实只是解决模块间耦合的问题,并非模块化开发的必然需求,更多时候是基于产品上的动态化要求,只不过咱们通常都会在这个时间考虑这一事情而已,就像咱们不会只作模块化开发同时不作组件化开发同样。