随想录:探索从模块化到组件化的转变之路

2024-11-17 0 946

   

现在我们来聊聊组件化开发。以下高能,请做好心理准备。

模块化和组件化

模块化

组件化不是个新概念,其在各行各业都一直备受重视.至于组件化什么时候在软件工程领域提出已经无从考究了,不过呢可以确认的是组件化最早应用于服务端开发,后来在该思想的指导下,前端开发和移动端开发也产生各自的开发方式.

在了解组件化之前,先来回顾下 模块化 的定义

Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.

简单来说,模块化就是将一个程序按照其功能做拆分,分成相互独立的模块,以便于每个模块只包含与其功能相关的内容。模块我们相对熟悉,比如登录功能可以是一个模块,搜索功能可以是一个模块,汽车的发送机也可是一个模块.

组件化

现在来看看"组件化开发",这里我们看一下其 定义 :

Component-based software engineering (CBSE), also known as component-based development (CBD), is a branch of software engineering that emphasizes the separation of concerns in respect of the wide-ranging functionality available throughout a given software system. It is a reuse-based approach to defining, implementing and composing loosely coupled independent components into systems. This practice aims to bring about an equally wide-ranging degree of benefits in both the short-term and the long-term for the software itself and for organizations that sponsor such software.

通俗点就是:组件化就是基于可重用的目的,将一个大的软件系统按照分离关注点的形式,拆分成多个独立的组件,已较少耦合。

咋样一看还是非常抽象,说了这么多好像还是不明白.什么是组件呢?组件可以是模块、web资源,软件包,比如汽车的发动机是一个模块,也是一个组件,再或者前端中的一个日历控件是一个模块,也一个组件.

模块化 vs 组件化

当你看到这的时候,想必心理一阵恶寒:模块化?组件化?到底是什么鬼?有啥区别.

有这种感觉才是对的,模块化和组件化本质思想是一样的,都是"大化小",两者的目的都是为了重用和解耦,只是叫法不一样.如果非要说区别,那么可以认为模块化粒度更小,更侧重于重用,而组件化粒度稍大于模块,更侧重于业务解耦.

组件化优缺点

组件化开发的好处是显而易见:系统级的控制力度细化到组件级的控制力度,一个复杂系统的构建最后就是组件集成的结果.每个组件都有自己独立的版本,可以独立的编译,测试,打包和部署

产品组件化后能够实现完整意义上的按需求进行产品配置和销售,用户可以选择使用那些组件,组件之间可以灵活的组建.

配置管理,开发,测试,打包,发布完全控制到组建层面,并带来很多好处.比如一个组件小版本进行升级,如果对外提供的接口没有发生任何变化,其他组件完全不需要再进行测试.

但是组件化的实施对开发人员和团队管理者提出了更高水平的要求.相对传统方式,在项目的管理和组织上难度加大,要求开发人员对业务有更深层次上的理解.

进军Android 项目

为什么要在Android中实行组件化开发

为什么要在Android中实行组件化开发呢,其根本原因在于业务的增长提高了项目的复杂性,为了更好的适应团队开发,提高开发效率,实行组件化乃大势所趋.

为了更好的帮助大家理解上面这句话,我将从最早的Android 项目开发方式说起.

简单开发模型

所谓的简单开发模型是最基础的开发方式,工程中没有所谓的模块,没有所谓的规划,常见于初学者学习阶段或者是个人学习过程所写的demo,其结构大概如下:

随想录:探索从模块化到组件化的转变之路

这里写图片描述

不难发现,往往是在一个界面中存在着大量的业务逻辑,而业务逻辑中充斥着各种各种网络请求,数据操作等行为,整个项目中没有所谓的模块的概念,项目组成的基本单位不是模块,而是方法级的.

关于这种开发模型没什么需要介绍的,我们早期都经历过,现在除了很少非常古老的项目以及初学者练手之作,已经很少见到.

单工程开发模型

该种开发模型已经有了明确的模块划分,并且通过逻辑上的分层呈现出较好结构,该模型最为我们所熟悉,通常用于早期产品的快速开发,团队规模较小的情况下.该种开发模型结构如下:

随想录:探索从模块化到组件化的转变之路

这里写图片描述

随着产品的迭代,业务越来越复杂,随之带来的是项目结构复杂度的极度增加,此时我们面临着几个问题:

  1. 实际业务变化非常快,但是工程之前的业务模块耦合度太高,牵一发而动全身.
  2. 对工程所做的任何修改都必须要编译整个工程
  3. 功能测试和系统测试每次都要进行.
  4. 团队协同开发存在较多的冲突.不得不花费更多的时间去沟通和协调,并且在开发过程中,任何一位成员没办法专注于自己的功能点,影响开发效率.
  5. 不能灵活的对工程进行配置和组装.比如今天产品经理说加上这个功能,明天又说去掉,后天在加上.

在面临这些问题的前提下,我们重新来思考组件化,看看它是否能解决我们在Android 项目开发中所遇到的难题.

主工程多组件开发模型

借助组件化这一思想,我们在"单工程"模型的基础上,将业务层中的各业务抽取出来,封装成相应的业务组件,将基础库中各部分抽取出来,封装成基础组件,而主工程是一个可运行的app,作为各组件的入口(主工程也被称之为壳程序).这些组件或以jar的形式呈现,或以aar的形式呈现.主工程通过依赖的方式使用组件所提供的功能.

随想录:探索从模块化到组件化的转变之路

这里写图片描述

(需要注意这是理想状态下的结构图,实际项目中,业务组件之间会产生通信,也会产生依赖,关于这一点,我们在下文会谈)

不论是jar还是aar,本质上都是Library,他们不能脱离主工程而单独的运行.当团队中成员共同参与项目的开发时,每个成员的开发设备中必须至少同时具备主工程和各自负责组件,不难看出通过对项目实行组件化,每个成员可以专注自己所负责的业务,并不影响其他业务,同时借助稳定的基础组件,可以极大减少代码缺陷,因而整个团队可以以并行开发的方式高效的推进开发进度.

不但如此,组件化可以灵活的让我们进行产品组装,要做的无非就是根据需求配置相应的组件,最后生产出我们想要的产品.这有点像玩积木,通过不同摆放,我们就能得到自己想要的形状.

对测试同学而言,能有效的减少测试的时间:原有的业务不需要再次进行功能测试,可以专注于发生变化的业务的测试,以及最终的集成测试即可.

到现在为止,我们已经有效解决了"单工程开发模型"中一些问题,对于大部分团队来说这种已经可以了,但是该模型仍然存在一些可以改进的点:每次修改依赖包,就需要重新编译生成lib或者aar.比如说小颜同学接手了一个项目有40多个组件,在最后集成所有组件的时候,小颜同学发现其中某组件存在问题,为了定位和修改该组件中的问题,小颜同学不断这调试该组件.由于在该模型下,组件不能脱离主工程,那么意味着,每次修改后,小颜同学都要在漫长的编译过程中等待.更糟糕的是,现在离上线只有5小时了,每次编译10分钟,为改这个bug,编译了20次,恩....什么也不用干了,可以提交离职报告了

如何解决这种每次修改组件都要连同主工程一起编译的问题?下面我们来看主工程多子工程开发模型是如何解决该问题的.

主工程多子工程开发模型

该种开发模型在"主工程多组件"开发模型的基础上做了改进,其结构图如下:

随想录:探索从模块化到组件化的转变之路

这里写图片描述

不难发现,该种开发模型在结构上和"主工程多组件"并无不同,唯一的区别在于:所有业务组件不再是mouble而是作为一个子工程,基础组件可以使moudle,也可以是子工程,该子工程和主工程不同:Debug模式下下作为app,可以单独的开发,运行,调试;Release模式下作为Library,被主工程所依赖,向主工程提供服务.

在该种模型下,当小颜同学发现某个业务组件存在缺陷,会如何做呢?比如是基础组件2出现问题,由于在Debug模式下,基础组件2作为app可以独立运行的,因此可以很容易地对该模块进行单独修改,调试.最后修改完后只需要重新编译一次整个项目即可.

不难发现该种开发模型有效的减少了全编译的次数,减少编译耗时的同时,方便开发者进行开发调试.

对测试同学来说,功能测试可以提前,并且能够及时的参与到开发环节中,将风险降到最低.

到现在,我们在理论层次上讲明了采用组件化开发给我们带来的便利,空口无凭是没有说服力的,在下面的一小节中,我们来谈谈如何组件化在Android中的实施过程.

组件化过程中遇到的问题

组件划分

组件化首要做的事情就是划分组件.如何划分并没有一个确切的标准,我建议早期实施组件化的时候,可以以一种"较粗"的粒度来进行,这样左右的好处在于后期随着对业务的理解进行再次细分,而不会有太大的成本.当然,我建议划分组件这一工作有团队架构人员和业务人员协商定制.

子工程工作方式切换

在"主工程多子工程模型"中,我们提到子工程在Debug模式下做为单独的Application运行,在Release模式下作为Library运行,如何去动态修改子工程的运行模式呢?我们都知道采用Gradle构建的工程中,用 apply plugin: 'com.android.application' 来标识该为Application,而 apply plugin: 'com.android.library' 标志位Library.因此,我们可以在编译的是同通过判断构建环境中的参数来修改子工程的工作方式,在子工程的gradle脚本头部加入以下脚本片段:

  if (isDebug.toBoolean()) {      apply plugin: 'com.android.application'  } else {      apply plugin: 'com.android.library'  }

在软件开发领域,组件化开发成为了一个热门的讨论焦点。这其中,所涉及的复杂情况及应对策略,极具研究价值。无论是面对不同运行模式下的子工程XML文件问题,还是探讨组件间的通信、依赖关系以及资源引用等问题,都值得我们深入研究和思考。

子工程的.xml文件情况

随想录:探索从模块化到组件化的转变之路

子工程在运行方式不同时,其.xml文件也会有所区别。因此,我们需在子工程的src目录下创建如debug等特定目录,以便存放相应的.xml文件。以实际项目为例,在APP测试和正式上线阶段,由于运行环境的不同,.xml文件的内容会有较大差异。明确.xml文件的功能,如配置工程信息、资源管理等,十分关键。针对不同的运行方式,单独配置.xml文件,有助于确保工程稳定高效地运行。这涉及到开发过程中的规划问题,如何合理布局这些.xml文件,对整个工程架构至关重要。

这也意味着开发者必须对项目的全过程有透彻的了解,不能随意地创建。你的项目里,是否也遇到了管理类似.xml文件时的麻烦?

  android {      sourceSets {          main {              if(isDebug.toBoolean()) {                  manifest.srcFile 'src/debug/AndroidManifest.xml'              } else {                  manifest.srcFile 'src/release/AndroidManifest.xml'              }          }      }  }

业务组件通信的现实问题

在主工程的多组件理想模型中,业务组件本应独立运作,无需相互交流或依赖。然而,实际情况并非如此。例如,业务组件1和业务组件3会同时向业务组件2提供支持,从而形成了错综复杂的依赖链。在众多大型软件项目中,这种现象相当普遍,不同功能模块间频繁调用和交换数据。这种现象显著提升了项目的复杂程度,不仅降低了开发效率,还增加了后续维护的难度。

随想录:探索从模块化到组件化的转变之路

为了解决这一问题,我们可以在工程实践中借鉴操作系统的总线机制,增设组件总线。借助组件总线,业务组件能够实现双向通信,其通信协议与HTTP协议相似,采用URL作为通信方式。然而,文中并未对实现细节进行详述,这为我们的探索和思考提供了广阔的空间。

解决组件间的重复依赖

使用aar格式输出项目时,构建过程中会保留最新的aar版本。通过aar格式提供的依赖不会产生重复,然而,若直接提供依赖,在打包过程中就可能出现代码重复的情况。这一点往往容易被开发者忽视。比如,在开发一款大型办公软件时,若对依赖方式不加注意,众多模块便可能产生重复代码。

随想录:探索从模块化到组件化的转变之路

目前存在两种处理方法。首先,针对纯粹的代码库或jar包,仅在项目最终执行阶段使用;其次,在编译过程中,对依赖包进行检测,若已存在依赖,则不再添加重复依赖。只有采取恰当的措施,才能有效避免开发过程中因重复依赖引发的问题。

组件合并中的资源引用冲突

合并多个组件至主工程时,可能会出现资源引用的冲突现象。举例来说,若两个组件拥有同名资源,便会产生冲突。最简单的解决方法是规定资源名称前缀。若设定为“ve”,则所有资源名称都必须添加此前缀。例如,在开发一款集地图和购物功能于一体的APP时,组件合并阶段就遇到了图像资源名称重复的问题,通过采用这种策略,问题得以顺利解决。

随想录:探索从模块化到组件化的转变之路

开发组件时需事先制定资源命名规范,否则日后修改将面临高昂的成本。

Debug与Release模式下的注意事项

在调试模式与发布模式中,需留意是否符合个人需求,以防出现强制转换异常。软件开发过程中的测试期(调试模式)与正式发布期(发布模式),数据格式、运行环境等方面可能存在不同。以游戏开发为例,测试期间可能为了便于测试而开启特定权限或使用简易加密算法,但正式上线时则需作出相应调整,否则极易引发强制转换异常,进而影响软件的正常运行。

组件化开发的思考

组件化开发并非无所不能。作者在广告SDK工作中接触到了这一概念,并据此撰写了现在的文章。在项目实施前,必须先考虑其适用性。并非所有业务复杂的情况都能通过组件化开发得到有效解决。开发团队需根据自身技术能力和项目具体需求来做出判断。对于“组件化开发是万能的”这一说法,您是否认同?欢迎点赞、分享,并在评论区展开讨论。

  andorid{      ...        buildTypes{          ...      }        resourcePrefix "moudle_prefix"    }

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

七爪网 行业资讯 随想录:探索从模块化到组件化的转变之路 https://www.7claw.com/2795926.html

七爪网源码交易平台

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务