在上一篇《团贷网Android客户端架构演进之路(上)》中,我们为大家介绍了架构演进、业务重构的过程。在本篇中,我们会从CI出发,在新架构背景下,如何提高研发效率和质量,如何做好架构的维护与复用。

从 CI 到 DevOps

在上篇我们也给大家简单的介绍了一下,CI:持续集成,简单的理解就是将本地编译、构建、发布的过程放在远程服务器多次的自动执行。短短一句话,信息量其实很大。里面有编译构建、发布、远程服务器、多次、自动几个关键词。我们逐个来理解一下:

  • 编译构建:通过gradle脚本编译构建出目标文件,如jar文件、aar文件、apk文件等
  • 发布:后端程序一般就部署到docker,而我们移动端就发布到nexus,或者上传apk安装包
  • 远程服务器:部署了持续集成工具
  • 多次:允许多次重复地执行
  • 自动:通过某些特定条件触发执行,而不需人手操作

在这几个关键词里面,持续集成工具才是核心所在,我们首先得有一个CI工具,才能做上面说的这些工作,不然都是纸上谈兵。CI工具市面上有很多,比较成熟的如Jenkins、Fastlane、Gitlab、Travis CI等等,我们选用的是最流行的Jenkins作为我们CI平台的核心工具。

CI与基础库

刚开始的时候,我们对Jenkins的理解也只是停留在构建打包的层面,但前面也已经提到,这一步操作也已经为我们的基础库工程发布效率带来了很大的提升。我们通过Gitlab将基础库工程和CI关联起来,当基础库工程完成Merge Request之后,就自动触发CI构建、打包,并自动发布到nexus上,这样为我们测试和发布都带来很大的便捷。

CI与团贷项目

在我们慢慢地对jenkins有了更深入的了解之后,我们又逐步地将团贷项目的构建、打包接入了jenkins,尤其在我们在团贷项目里面加入热修复之后,对分支的管理、基准包的备份和补丁包打包效率这些问题,单靠人手已经远远跟不上节奏,jenkins的接入使得这一些都有了效率和质量上的保证。

DevOps?

其次我们又在jenkins上接入了SonarQube代码质量检测、单元测试、UI测试、app内部分发平台等等。

当我们往这个方向去推进的时候,回过头来发现原来我们所做的已经慢慢地超过了CI的范畴,从需求、代码管理、构建、测试、发布整个链路下来,我们都已经慢慢地往自动化的方向去建设,实际上这是敏捷开发上最近今年比较流行的体系——DevOps。

可能我们经常提及的DevOps就是研发+运维,而更多的也只在后台开发、部署上线,并且结合Docker来讨论的。实际上,我们移动端的DevOps也在不断的发展和完善。能用工具解决的问题,没必要浪费人力成本。将移动端的工作流往DevOps方向建设,不单可以为我们带来质量保证,还有效率的提升。

CI和DevOps将是我们后面重构的一个重心,这里暂时不做多的展开,涉及的点和面都比较多,后面有一篇文章会单独地去详细给大家介绍,讲解团贷网移动端DevOps平台的建设。

新架构的挑战

我们花了大概4个多月的时间,基本上把基础库内80%使用率高的基础设施重构好,而子业务的拆解和重构也在稳定地推进当中,由于每个同事的对新架构的认识存在一定的差异,可能每个模块重构出来的质量和效果都不一,但在保证没有重大Bug的前提下,这些参差我们是可以接受的,毕竟重构不是一朝一夕的事情,在后期我们还需要做深度的优化。

多工程复用

就在我们稳步推进业务重构的时候,我们项目新架构迎来了一个更大的考验——业务模块需要在不同项目之间复用。组件化分层,业务模块化解耦,MVP框架等等这些,很大一方面也正是为了应付这种情况的出现,app之间的模块复用,理论上按照我们设计的架构是很容易实现的。但在我们多次讨论之后,依然还是有几个大的问题需要解决:

  1. 业务只重构了三分之二,还有三分之一的业务未重构,包括1到2个核心的业务,如投资、投资记录等模块
  2. 不同项目之间,子业务如何复用?拷贝代码,还是使用Maven依赖?
  3. 公共业务层如何拆解,如何维护多个项目之间的通用模块和差异模块

实际上,这些问题也是我们重构后期需要思考和解决的,只是没想到这么快就要走上这一步。业务未重构完,只能是加快重构的速度,争取在拆分App上线之前完成提测、合并。而真没法赶上发布的模块,不同项目之间也只能拷贝这部分代码,而这部分代码我们也已经归总到一个独立的Module,只需要复制一份即可。

而已经重构好的子模块,则按照开发新手版的方式增删所依赖的模块。问题在于不同项目工程之间复用的模块是要以源码方式依赖,还是Maven方式依赖,而复用又需要如何体现其差异化的部分呢?

多项目复用架构

经过我们重构小组多次讨论之后,我们基本确定了新的项目架构,如下图所示。

基本上与原来的组件化分层是类似的,为了配合其他项目部分功能的定制化,我们加入了一个子工程-公共业务层,存放其他项目特有的内容,如请求域名管理、ARouter跳转路径、服务实现类等等。而对于团贷网项目,由于CommonBiz本身的抽离就是针对团贷网项目的,所以在时间紧迫的情况下,我们并没有急着增加td_commonbiz层,而放在日后当项目之间差异足够大的前提下,我们再抽离出子工程-公共业务层。

MVP分层复用

对于子业务层的各个业务模块来说,如果要做好两端代码的复用和维护,将公共部分(Common)抽离成独立的子工程是最好的做法,这样能真正做到边界的约束和统一的管理,而差异化的部分则交由两个项目独立维护。实际上这是一种MVP分层复用的结构。

这种分层结构是一种比较优雅的设计,即能达到核心代码的复用,也能解决两端差异化的问题,发挥MVP框架最大的价值。但这种架构模型也存在一定的弊端,就是设计成本比较高,要求开发者对两端的业务都非常熟悉,才能做好公共部分的抽离和差异部分的设计,否则可能差异化部分依然会有一些重复的代码。而这种架构后期的维护成本也比较高,尤其对于两端项目逐渐差异化的发展,可能公共部分的内容会越来越少,最终导致整个架构失控。调试也是一个痛点,将Common部分抽离成一个子工程,这导致一个功能需要在两个工程上面调试,这无疑是会拉低我们研发的效率。

碍于这些问题的存在,我们并没有将Common部分独立为一个子工程,否则我们20个模块,需要维护20个子工程,这是一个不敢想象的事情,起码就目前的团队规模来说还不需要有这样的操作。我们再次调整重构的思路,将子模块进行MVP分层之后,将公共部分源码交由两个项目维护,在观察后期两个项目的发展,再决定是否需要针对个别模块进行统一的复用管理。

父类的定制化

子模块代码复用了,意味着其父类也需要复用,我们两端项目依赖于CommonBiz公共业务层,所以基类复用的问题是可以解决的。但这里存在另外一个问题,基类封装了如标题栏、加载进度框之类的一些UI样式,而我们不同项目对UI设计有不同的要求,主题也不一致。这个问题,我们准备了两个解决方案:

  1. 修改基类Activity,采用注解或者动态代理方式去定制
  2. 采用上层资源覆盖的方式,替换默认样式

第一种方案比较灵活,但需要花一定的时间去修改和做好性能测试,毕竟改动的是底层基类。第二种方式比较粗暴,在不修改底层代码的前提下,利用apk编译打包的一个机制——上层同名资源会覆盖底层的资源,做到样式的修改。目前我们大部分样式定制采用的是第二种方案,第一种方案还在调研测试阶段。

现在与未来

说到这里,Android客户端重构的整个技术体系实际过程也介绍得差不多了,这一年时间我们做的可能远远不止上面所说的这些,踩过的坑也还有很多上面没提及的,下面再简单罗列下其他涉猎的部分:

  1. 引入微信开源的Tinker热修复框架,并对Tinker做深入研究
  2. 定期组织Code Review会议,共同审核代码、分享经验
  3. 开发简易版的基础库
  4. 研究Groovy,通过gradle脚本提升编译速度
  5. App瘦身研究
  6. 维护wiki,定期输出原创文章、技术文档
  7. 适配性研究,如沉浸式状态栏、全面屏适配、原生Api版本兼容性
  8. Mock服务研究、自动化UI测试研究、云测平台搭建等等…

还有一些我们依然未解决的问题:

  1. 使用Maven依赖,不利于开发同事在源码和远程仓库之前切换调试
  2. BI统计对代码侵入比较严重,还没有比较好的封装方案
  3. MVP分层复用的模式难以推广,还需要寻求一种更优的业务复用方案
  4. 重构后代码,在质量和性能上的验收和把控
  5. 多工程联合打包还没完全自动化,在CI建设方面需继续推广落实

最后附上一张我们目前整个Android客户端的技术图谱

回到刚开始说的,这篇文章并不是一个结束,只能说是我们第一次全面重构的总结与分享,后面依然还有很长的路要走,如果在这里能给到同样在这条路上的你一些启发,那是我们的荣幸。后面的路,我们会把重点放在CI、自动化、DevOps建设方向继续推进,同样我们架构的优化、质量与性能的提高是另外的大重点。

写在最后

最后,送三句话给大家,也算是这一段时间的工作体验和心里话了:

  1. 感到快乐就忙东忙西,感到累了就放空自己——这是《没那么简单》的歌词。正如这首歌的歌名一样,重构的过程没那么简单。在我们快乐的时候就忙东忙西,专心努力地去干;但我们累了——无论因为工作原因、还是家庭原因,就放空一下自己,停下来,歇一歇。不用过于逼迫自己去做一些事,尤其在自己已经很疲惫的状态之下,否则最后得到的结果可能并不是我们所想要的。
  2. 当你手上有一把锤子,看所有的东西都是钉子。——我们需要对自己有足够的信心,如果我们所写的代码,连自己都不相信,如果让我们的伙伴相信自己。架构的选择和建设,不是一个人所能做成的,是一个技术团队奋斗的目标,只有彼此都有信心,才能发挥团队最大的作用。
  3. 没有任何一个方案可以获得每个人的赞同。——这是在美团架构演进文章里面看到的一句话。也许也正是我们每个人思考的角度不同、认识的方向不一样,才能让我们设计有更多的碰撞。重构是一个不断演进的过程,也许我们前进3步,最后还是需要后退2步,但我们不能因为这种“后退”而否定我们这个过程,毕竟我们比原来已经前进了1步。

写在最后的最后

有个前面的前面,再加个最后的最后吧。当你正在努力拼搏冲刺之际,大厦突然崩塌,戛然而止,这种感觉实在是太难受了。但也给了自己一个停下来歇息和喘气的机会吧,把之前落下的基础补一下,把这段时间做的事情沉淀一下,把停了1年多的Blog更一下。
收拾心情,重新上路!

团贷网Android客户端架构演进之路(下)相关推荐

  1. 团贷网Android客户端架构演进之路(上)

    写在前面的前面 到草稿箱里翻看一下:2018年5月18日,这一篇博文已经在草稿箱里躺了快整整一年了.5月份,恰好是项目第一次重构完成的时间节点,当时趁着总结汇报之际抽时间把项目演进历程写了一下,不知不 ...

  2. 抖音、美团等大厂千万级用户的Android客户端架构演进之路—

    在移动开发中,对开发者来说不同的人具有不同的能力.就像读一本书一样,一千个读者,有一千个哈姆雷特.但不管怎样,只要你是个软件开发者你就必须学习windows或Linux等操作系统的运行原理.Andro ...

  3. 微信Android客户端架构演进之路

    去年7月,笔者在InfoQ举办的ArchSummit深圳2014的架构师峰会上,分享了微信Android客户端的架构演进史.可以说,这是一个典型的Android应用在从小到大的成长过程中的" ...

  4. 人人车Android客户端架构演进实录

    前言 对于大多数创业公司而言, 初版开发时采用的简单架构,在历经数次快速迭代后,已经成为了一个"大泥球"(源于Brian Footer和Joseph Yonder的论文<大泥 ...

  5. 微信Android客户端架构演进及其对开发流程的影响

    微信Android客户端架构演进及其对开发流程的影响 http://www.infoq.com/cn/presentations/android-client-architecture-evoluti ...

  6. 精华阅读第 9 期 |滴滴出行 iOS 客户端架构演进之路

    「架构都是演变出来的,没有最好的架构,只有最合适的架构!」最近,滴滴出行平台产品中心 iOS 技术负责人李贤辉接受了 infoQ 的采访,阐述了滴滴的 iOS 客户端架构模式与演变过程.李贤辉也是移动 ...

  7. 滴滴android架构演进,滴滴出行iOS客户端架构演进之路

    自从蘑菇街的李忠老师在移动前线群里做了一次关于iOS组件化的分享之后,大家对于iOS客户端的架构非常感兴趣,展开了热烈的讨论.我很认同一句话,架构都是演变出来的,没有最好的架构,只有最合适的架构,刚好 ...

  8. [2016.10.17日更新]各大互联网公司架构演进之路汇总

    大型网站架构演化历程 大型网站架构技术一览 Web 支付宝和蚂蚁花呗的技术架构及实践 支付宝的高可用与容灾架构演进 聚划算架构演进和系统优化 (视频+PPT) 淘宝交易系统演进之路 (专访) 淘宝数据 ...

  9. 各大互联网公司架构演进之路汇总

    大型网站架构演化历程 大型网站架构技术一览 Web 支付宝和蚂蚁花呗的技术架构及实践 聚划算架构演进和系统优化 (视频+PPT) 淘宝交易系统演进之路 (专访) 淘宝数据魔方技术架构解析 淘宝技术发展 ...

最新文章

  1. shell访问php文件夹,Shell获取某目录下所有文件夹的名称
  2. linux 端口 流量统计,Linux下如何对端口流量进行统计
  3. 字节跳动推荐平台技术公开,项亮:底层架构有时比上层算法更重要
  4. 操作系统(三十三)内存管理
  5. 用户体验岗如何说服其他部门_为什么我们应该说服用户更新他们的浏览器-这是双赢的。...
  6. 德勤预判:2022技术七大趋势
  7. 进入职场,为什么都需要了解办公软件,了解它对我们有什么作用?
  8. 分治法的关键特征_经典算法思想2——分治(Divide-and-Conquer)
  9. 菜鸟学习笔记:Java基础篇3(面向对象思想、程序执行过程内存分析、面向对象重要概念)
  10. linux下常用vim命令
  11. 输入一个十六进制的字符串,输出其相应的十进制数。
  12. little endian c语言,endian.h这个头文件里面的宏可以直接用么?
  13. 地方麻将吉林过蛋玩法算法
  14. 【WZOI】2019愚人节比赛题目分析
  15. 地鼠君黑盒测试--小白功能测试避雷经验分享
  16. 计算机网络应用技术技能大赛
  17. windows下气象grib/grib2数据转Tiff格式输出
  18. VMware虚拟机禁止防火墙启动
  19. c语言有趣代码,分享一段有趣的小代码
  20. 转贴:定式中的“纳什均衡”与“有限理性”

热门文章

  1. 算法笔记-问题 A: 【字符串】最长回文子串
  2. Android如何适配不同屏幕分辨率
  3. 阿里云,华为云,腾讯云三大公有云厂商,香港地区主机测评
  4. 欢乐水杯(happy glass)的流体实现! Cocos Creator!
  5. 批改网作文提交时分析不出来_推荐收藏:作文如何批阅更有效(附作文批改评语范例)...
  6. 硬盘也能双动力?混合硬盘游戏实际体验
  7. 东芝杀入硬盘大战中 推混合硬盘产品
  8. IC设计基础系列之芯片设计流程3:国内IC设计公司没技术含量?海思员工第一个不服
  9. 深度之眼 - Python学习笔记——第八章 文件、异常和模块
  10. 【other】idea格式化快捷键ctr+alt+L与qq锁定冲突