贝贝的组件化之路

来源:互联网 发布:商务无忧软件代理加盟 编辑:程序博客网 时间:2024/04/28 15:56


为了更好满足各种业务快速迭代

解决代码依赖和构建速度慢的问题

提升产品的质量

贝贝组件化系统应运而生

贝贝技术团队 范超、朱佳骏、李旭明

贝贝APP组件化的好处


组件化的实现不仅给我们带来开发上的便利,也让我们的业务模式发生了巨大的变化。


  1. 按月迭代加快到按周迭代,可以采取火车头方式进行发布版本,迭代速度更快,不再因为业务耦合情况,在发版时候,由于互相等待而迟迟不能发布版本。

  2. 稳定的公共模块采用依赖库方式,提供给各个业务线使用,减少重复开发和维护工作量。

  3. 迭代频繁的业务模块采用组件方式,各业务线研发可以互不干扰、提升协作效率,并控制产品质量。

  4. 为新业务随时集成提供了基础,所有业务可上可下,灵活多变。

 

贝贝组件化的诞生


随着贝贝的迅猛扩张,我们也不再满足于单一模式,业务与日俱增,业务间的关系日趋庞杂。

贝贝原始工程结构


模块的数量越来越多,代码也越来越多,千丝万缕的相互依赖,长达8分钟的代码构建时间,困扰着贝贝的工程师,也极大的限制了贝贝工程师的开发效率。

 

为了更好满足各种业务快速迭代,解决令人头疼的代码依赖和构建速度慢的问题,并提升产品的质量,贝贝组件化系统应运而生。


贝贝组件化系统简介


贝贝组件化系统由代码业务模块、自动构建系统、配置文件管理、Maven库四个部分组成。



贝贝“火车头”开发模式


其中Maven库用于存储组件模块,配置系统用来以“火车头”的形式进行版本的发布。


不同模块的代码在自动构建系统中以aar的形式生成中间包,代码以模块的形式插入贝贝的壳工程中,以事件总线的方式将不同的模块集合在一起,组合形成不同的待发布的贝贝版本(其中贝贝壳工程为必选组件)。



    贝贝组件化系统


贝贝事件总线


按业务拆分之前,各个业务之间不同页面之间页面跳转、页面之间的数据传递就成了首要解决的问题,而为此我们也经历了比较痛苦的过程。

1臃肿时代

在这个时期,所有的页面都在同一个项目中。


  1. 页面跳转:   

    所有的跳转都是通过直接的Class类型来进行跳转

    Intent intent = newIntent(this, xxxx.class);


  2. 数据传递:

    直接页面startActivityForResult返回获取, 间接页面通过存储或者变量 。


优点:方便,简洁

缺点:目标页面接收的参数需要看代码(没有文档化),每一个目标页面

的跳转都需要跟开发人员沟通,沟通成本过高。

2拆SubModule时

此时贝贝的业务已经有3~6个了,在Project下面已经各自拆分成了submodule, 不同的业务开发人员进入自己所属的业务中。


  1. 页面跳转:

    通过公共的BeiBeiSdk(被业务引用)里面建立一个IntentUtils文件来处理,由于此时已经在各个业务模块里面加入了host, name,如下图


    打开通过url打开

  2. 数据传递:

页面之间通过EventBus来传递数据

优点:android,iOS与H5客户端可以通过一些简单的url来实现跳转了,通                   过文档来约束各个页面的参数。

      缺点:多个业务组的人共同改同一个文件,导致文件的冲突率异常高,经常                 两端data不一致导致H5只能跳转到android或者iOS.

3组件化

此时已经通过各个业务组输出aar deploy进主工程了,主工程不用感知各个业务的具体变化,并且各个业务已经是不透明的了,无法通过上面的方式来做页面跳转或者数据传递。


为了统一客户端的所有跳转,做了统一URL的动作

bb     /  base/ product

[app]   [业务名]    [页面]

 

目前支持的URL如下,H5页面可以通过URL跳转到任何页面

beibei://bb/base/product

beibei://product

http://www.beibei.com?Beibeiapp={"target":"product", "desc":"desc"}  

beibei://action?target=product

4新总线的调用方法:
  1. 页面跳转:booleanresult = HBRouter.open(this, “beibei://bb/base/product?name=zs”);

  2. 数据获取:Object  o=HBAction.open(this, “beibei://bb/base/product?name=zs”);


如何设置TargetURL 与页面(Activity, Controller)的对应关系,我们设计了一套Router系统,

当时考虑了两种建立关联的方式:

  1. 每个业务初始化时注册一个服务,在运行的时候让 url与页面建立关联。

  2. 在页面编译的时候让URL与页面建立关联。

 

由于第一种会存在业务人员同时改同一个文件的问题,以及文档维护性的问题;最后选择了第二种,通过编译时与页面建立关联,通过在页面上写编译时注解让每个业务人员只需要关心自己的页面,并且通过服务器公共JSON文档来约束以及生成测试Router来判断业务人员是否写入正确。


页面注解以及服务注解(获取某一业务的数据)格式


页面注解:注解添加在页面上(Activity)业务组的开发人员通过后台的文档确定页面的URL,通过HBRouter.open(url)来打开其他业务的页面



服务注解:注解添加在对应的Action类上,类似于数据的API库,里面实现各个服务的具体逻辑。


优点:业务之间相互不影响,每个业务都可以很happy的开发了,想获取数据,想进入页面,进入后台看api文档。

缺点:页面暂时不支持fragment级别的,只能传入进去。


贝贝拆包之路

1拆分标准


贝贝拆包设计原则

横向按照业务粒度, 纵向依照复用依赖

2如何整合

每个业务打包成aar(依赖一个BeiBeiSDK),在APP层做集成。

3如何管理业务库

开发中使用snapshot快速集成;集成测试前转成版本号迭代,git tag标记具体版本号,兼顾版本开发和持续集成。

Jenkins提供模板,各业务搭建各自的2个任务(dev分支的snapshot版本, master上tag的稳定版本)。

APP层,通过共同编辑的各个aar版本号文件,做整体打包,制作最终apk。

4优点

业务之间界限清晰,隔离修改,使review实施简单。

App编译速度提高;各业务嵌入到APP开发时,不需要编译其它业务源码。

每个版本的发布组合可控,每个子业务的改动在开发阶段不互相感知,在集成阶段简单可控。


贝贝自动构建系统


现在贝贝的完成了组件的分拆,将贝贝APP拆成了许多独立的业务组件,也完成完成了业务之间的通信标准和方案,那剩下的问题就是我们如何使这套系统运转起来。最简单的方案是基于我们已有的Jenkins系统改起,建立一套简单易用的构建系统。


该系统自动构建流程如下:

  1. 子模块自动构建aar包。

  2. 子模块通过gradle内的task自动上传aar包(或者aar-snapshot包)到Maven库。

  3. 主工程通过配置系统决定将那个版本的tag打入主工程。


版本配置文件管理模块

   

版本的配置文件管理模块由配置文件和配置文件管理两个部分组成,配置文件决定了壳工程将要集成的每个子模块的版本,在开发工程上配置使用snapshot配置。


Maven库


用于存储组件的aar文件,为私有仓库。


我们是如何解决构建速度问题的


阶段

优化前

组件化后

实时更新snapshot

组件化后

不实时更新snapshot

交易线构建时间

8

1分40秒

1分钟以内,最快12秒

贝贝代码编译速度对比


到此为止组件化系统已经完成,那我们是如何将开发代码的编译速度由8分钟提升到1分钟以内的呢?


答案就在上面的整个系统中,我们在实际开发业务代码的时候只会修改一个模块并且只编译该模块的代码,所需依赖的模块直接从Maven库获取并通过aar-snapshot的形式进行更新。

0 0
原创粉丝点击