组件和依赖管理
构建系统的三个维度:部署流水线,分支和组件
解决什么问题
持续集成:解决在保障持续集成的前提下,进行大型重构和添加复杂新功能;
代码解耦:解决单体应用代码,在功能激增后的管理问题;
保证应用可发布
实际持续集成要求主干分支开发,详情见(持续交付2-版本控制).同时开发中如何保证服务的随时处于可发布状态非常重要,因为开发布状态是软件交付的关键.实际保证应用可发布的常用方式有如下几种:
- 创建新分支.分支具备天然的修改隔离性,它可以并行开发,不影响其他分支的可发布状态
- 主干分支开发,通过频繁提交来快速解决冲突,用效率来缩短应用不可用时间.
直观上大家认为分支方式比较好,这也是分支的特性引起的.但实际上分支只是掩盖了当前冲突,它会在分支合并时集中体现.持续集成主张主干分支开发,不怕有问题,通过快速解决问题来保证应用的可用性.因为不管采用哪种方式,问题会依旧存在,这时能分解并快速解决应该是推荐的方式.
怎么做
- 暂时隐藏新功能.解决的是跨版本修改及版本周期较长的情形.通过隐藏功能的方式来避免新建分支.实际隐藏包括访问按钮隐藏,路由控制等方式.
- 拆解大修改为小需求,增量式修改,保证每次修改都是可发布的.大修改的难点在于对现有代码调整大,采用小步快跑的方式可以很好的与现有代码共生.实现边走边评估的效果.
- 通过抽象虚拟分支进行大型重构.实际设计代码架构层级调整时,需求拆解的方式并不是很好用,引入本身你要做的就是替换原来的内容,共生反而不现实.这时通过抽取代码层级的方式实现代码内分支切换.
- 组件化.进行应用解耦.
这里讨论的是主干分支如何进行新功能开发及进行复杂重构.
- 通过抽象虚拟分支进行大型重构.
实际设计代码架构层级调整时,需求拆解的方式并不是很好用,引入本身你要做的就是替换原来的内容,共生反而不现实.这时通过抽取代码层级的方式实现代码内分支切换.抽象虚拟分支具体实现:
- 在修改的部分代码上创建抽象层
- 重构代码,让现有代码使用抽象层
- 创建新的实现代码
- 使用新代码
- 移除原有代码
- 可以考虑移除抽象层
直观可能感觉调整比较大,但是如果一部分代码一直处于监控下,它的使用风险就会越来越小.同时很多时候感觉无法进行抽象虚拟分支的原因是代码没有进行组件化,单次抽取虚拟分支调整的代码边界无法确定,这时你首先应该做的就是进行代码组件化.
组件
组件:指应用程序中的一个规模相当大的代码结构,它具有一套定义良好的API,而且可以被另一种实现方式代替.代码库按业务进行模块化,每个模块通过个数有限的定义良好的接口提供服务,与其他模块进行有限交互.
组件化价值
- 它将问题分成更小且更达意的代码块
- 不同组件的变化率,生命周期不同
- 情形的业务边界,便于理解和维护
- 自由组合,优化构建和部署过程.
进行组件化的场景:
- 代码库的一部分需要独立部署
- 希望增加服务内部的灵活性或扩展性
- 组件通过接口提供外部服务(已经具备拆分能力,便于拆分)
- 代码的编译和链接时间太长
- 开发环境打开项目时间太长
- 团队代码库太大
组件化不建议按团队进行组件维护划分.因为需求不会按组件的边界来分;单独组件无法实现和测试需求,团队沟通成本会增加,同时也不利于整体理解需求;推荐团队按需求进行任务划分(轮岗,实际大公司做的比较好,对个人能力也有很大提升),每个团队都可以修改所有组件内容,还推荐定期交换团队人员,通过灵活性来减少团队沟通成本.这样也保证了问题所有人共同负责,防止扯皮现象.
组件流水线化
组件化后,原本的单一流水线部署可能就要调整,原因如下:
- 组件生命周期不同
- 组件功能领域不同,被特定团队负责
- 组件使用不同的技术和构建流程
- 存在共享组件
- 组件相对文档,不用频繁修改
- 组件构建更便捷
组件流水线的构建流程要一致,都要进行同样的测试,验证,部署流程.组件流水线构建完之后,就到了集成流水线环节.
集成流水线
流程:整合组件二进制包->部署到类生产环境.
感觉组件化就是现在微服务模式,不同的服务可以通过restful访问,不存在内嵌的情形.集成流水线很多时候只是一种理论.
依赖
应用依赖是构建或运行时,软件的一部分依赖于另一部分的关系.具体依赖方式分为组件和库.
组件(component)和库(library):库是团队就有选择权,没有控制权的软件包,它们通常很少更新;组件是应用程序所依赖的不放呢软件块,它通常是公司内部开发,更新也较频繁.
构建时依赖和运行时依赖:它是根据依赖关系出现的时点来划分.构建时依赖是应用程序编译和链接时出现;运行时依赖是应用运行时出现.
依赖的管理也是需要考虑的事情,因为依赖管理不好会出现循环依赖问题,依赖版本问题.
实际依赖的管理通过库管理式:1 提交到版本管理中 2 显示声明(代表就是maven)
依赖版本管理
如果没有依赖版本管理,你就无法重现构建,程序随时都面临外部依赖造成的无法运行问题,同时你还无法定位是哪个依赖造成的.
做法:
- 构建依赖图
- 为依赖图建立流水线.当上游依赖修改后,触发下游服务构建,执行对应测试,获取修改相关可执行文件.构建频率需要和成本进行一个比较.
二进制文件管理
二进制文件是每次构建完成并完成测试的可交付产品.它的管理可以通过两种方式:
- 共享目录方式管理
它的存储需要通过一个版本标识可以和版本库关联.构建系统构建时生成一个短标识,最好包含版本库中该版本的标识.
文件下生成索引文件,记录版本和二进制包状态
定期清理二进制文件
- 通过其他软件管理,如maven