19 仓库&版本管理:如何从物理边界上规范依赖?
你好,我是黄俊彬。
前面我们完成了Sharing项目的组件化架构改造,但是在仓库与版本管理上,依旧还是与改造前一致,采用的是单体仓库以及组件源码依赖的方式。
当代码以及团队达到一定的规模以后,这会给项目仓库和版本的管理带来诸多问题。我总结了一张常见问题的表格,你不妨“对号入座”,看看自己的项目有没有“中招”。
那么怎么来解决上面这些问题呢?今天我们将一起来学习如何对组件做代码仓库管理以及二进制版本管理,让组件能更加独立地迭代演进,从物理上规范好组件之间的依赖。
仓库管理
首先,我们先了解一下代码仓库管理的模式,常见的有单仓模式和多仓模式。
单仓模式
单仓模式指的是所有的组件代码统一在一个版本仓库中管理,团队成员基于一个代码仓库来完成日常的开发活动,就像后面图里画得这样。
这种仓库管理的方式的优点是简单,所有的代码在一起维护,团队所有成员能共享产品的所有代码。由于所有代码都在一个仓库,所以代码集成方便,也便于团队统一代码规范。团队之间能共享到所有人的代码,方便大家了解项目的整体代码情况以及学习其他组件架构及代码设计。
但单仓库的缺点就是当代码及团队规模庞大时,会带来后面的问题。
1.开发人员容易受到干扰,不能专注在自己所属的组件代码上。
2.如果缺少有效的架构守护以及代码检视,因为代码都在一起,开发人员都有权限修改,就非常容易导致架构腐化。
多仓模式
多仓模式指的是各个组件在独立的代码仓库中维护,团队成员基于自己负责的组件仓库开发,不需要拉取自己不关心的组件代码。
多仓模式的优点是开发人员能够专注在自己维护的组件的代码开发上,不用每次更新所有的仓库的代码。并且仓库的代码量及复杂性是可控的,不同团队可以维护自己的仓库,职责清晰。
但是缺点是需要依赖拆分的组件足够独立,新增需求不用涉及跨组件修改,避免一个开发人员需要同时基于多个组件仓库开发。如果经常出现跨仓开发及修改代码,这样反而会降低开发效率。
在实际项目中,具体采用哪种仓库管理策略,我们需要综合团队、代码规模和工程管理能力来考量。对于组件化架构来说,建议组件化项目初期采用单仓模式,等组件逐步稳定及团队规模达到一定的程度时,再考虑分离,即采用多仓模式。
版本管理
接下来,我们一起来看组件的版本管理。前面Sharing项目的所有组件都是采用源码依赖的方式,对于各个组件来说,直接都是依赖最新的代码,而并没有版本的概念。
所以我们先来比较一下二进制依赖和之前源码依赖有什么不同,然后再一起动手对Sharing项目做二进制依赖改造,进一步加深理解。
二进制依赖
二进制依赖指的是组件之间不直接依赖源码,而是依赖组件编译生成的二进制文件,并且对这些二进制文件做版本管理,就像后面这样。
相比较源码依赖,在集成编译时,由于所有的依赖已经被编译成二进制的格式,所以可以有效提高版本的编译速度。这点是对于遗留系统改造的一个非常明显的收益。
在之前的咨询项目中,我们见过大量的大型遗留系统,一次完整的编译都需要十几分钟。可以设想一下,如果开发每次修改代码都需要等待这么长的编译时间,那么就不会愿意频繁去触发编译来验证功能。想要解决这个问题,采用组件化分而治之十分有效。
另外,由于依赖的组件都是二进制格式,我们只能调用而无法修改原有组件的内容,这样能够减少代码被随意修改的风险。
最重要的是,由于使用二进制依赖,我们可以对组件做二进制的版本管理,这样就能够更灵活组合各个组件的功能,而且当版本有问题时,我们也可以快速回滚集成之前的版本,重新发布。
当然,二进制依赖在带来灵活的版本管理时,也需要我们做一些额外的投入,主要是三个方面。
第一,我们需要搭建二进制版本管理服务器,例如搭建Maven服务器来统一存放二进制组件以及管理组件的版本。
第二,在组件的迭代上,我们也需要规划好组件各个版本的需求,并且做好组件的兼容性。
第三,我们还需要注意,在组件的二进制发布方面,我们也要结合持续集成流水线让组件发布的过程自动化。不然以前依赖源码的时候,我们只需要改代码马上就能验证。但是如果是二进制依赖的形式,我们改完代码以后还需要发布新的版本,然后调用的地方依赖新的版本才能验证,这也会影响开发的效率。
Sharing组件版本管理改造
下面我们以Sharing项目的日志组件为例,一起来看看如何做组件版本管理的改造。
我们会使用Maven来管理组件二进制制品,为了方便演示,我们会使用本地Maven来配置,生成的制品会存储在本地的工程目录中。但在实际项目中,你只需要把本地路径地址设置为自己搭建的Maven服务器的地址,就可以将制品发布到远程的服务中。
这里我们的改造目标是,将日志组件发布到Maven仓库中,并将其他组件对日志组件的源码依赖调整为二进制依赖。
第一步,我们需要先在日志组件的gradle配置文件中引入Maven的插件,然后配置对应发布二进制组件所需要的Maven服务地址、组件名称以及版本号等信息,具体的配置代码是这样。
//日志组件所在目录的build.gralde 文件配置
apply plugin: 'maven'
group = 'com.jkb.junbin.sharing.library'
archivesBaseName = 'log'
version = '1.0.0'
repositories.mavenCentral()
uploadArchives {
repositories.mavenDeployer {
repository(url: 'file:'+ rootDir.getPath()+'/lib')
}
}
//根目录的build.gralde 文件配置
allprojects {
repositories {
maven{
url 'file:'+ rootDir.getPath()+'/lib'
}
}
}
配置完成后,我们就可以使用gradle命令来触发二进制制品的发布,代码是后面这样。
成功执行完该命令以后,我们就可以在配置的本地地址目录下,找到对应生成的二进制文件,像后面这样。
最后一步,我们需要将之前依赖log组件源码的地方,调整为依赖生成的二进制制品。
当所有的调整完成以后,可以运行./gradlew testDUT命令运行之前所有的测试,保证调整没有破坏架构规则以及业务功能。
总结
今天我们一起学习了组件的仓库管理以及二进制版本管理实践。
对于仓库管理来说,有2种常用的模式,分别为单仓模式以及多仓模式。我梳理了一张表,方便你对比这2种分仓模式。
在实际项目中,你可以根据代码以及团队成员的规模来选择合适的仓库管理模式,建议组件化项目初期采用单仓模式,等组件逐步稳定及团队规模达到一定的程度时采用分仓模式。
对于版本管理来说,采用二进制依赖的方式相比源码依赖能有效提高编译的效率。另外,使用二进制依赖后,我们可以做组件的版本管理,这样可以更灵活地组合版本的功能。在项目中,我们可以使用Maven来管理二进制制品的发布以及版本管理,具体你可以参考课程里Sharing项目的改造示例。
如果组件已经是独立的仓库管理,而且组件间也都是二进制的依赖,那么日常开发中很重要的一项工作就是确保组件可以独立编译调试,避免每次都需要集成才能测试和验收。下节课我们一起来学习组件独立编译调试的3种技巧,帮助你快速调试组件和实现功能验证,敬请期待。
思考题
感谢你学完了今天的内容,今天的思考题是这样的:你了解git的subtree子仓库功能吗?使用这个功能有什么优点?
欢迎你在留言区与我交流讨论,也欢迎你把它分享给你的同事或朋友,我们一起来高效、高质量交付软件!
- 我的video 👍(0) 💬(1)
老师可以介绍一下monorepo吗
2023-04-10 - peter 👍(0) 💬(1)
请教老师几个问题: Q1:安卓APP现在可以接入chatGPT吗?市场上有APP使用chatGPT的案例吗? Q2:屏幕适配问题,如果自己实现(不用框架),字体用sp、距离用dp可以实现适配吗?(或者说,sp、dp会存在适配问题吗?)
2023-03-24