没有合适的资源?快使用搜索试试~ 我知道了~
微信Android模块化架构重构实践
1 下载量 43 浏览量
2021-02-25
15:04:23
上传
评论 1
收藏 492KB PDF 举报
温馨提示
试读
12页
微信Android诞生之初,用的是常见的分层结构设计。这种架构简单、清晰并一直沿袭至今。这是微信架构的v1.x时代。图1-架构演进到了微信架构的v2.x时代,随着业务的快速发展,消息通知不及时和Android2.3版本之前webview内存泄露问题开始突显。由于代码、内存、apk大小都在增长,对系统资源的占用越来越多,导致微信进程容易被系统回收。因此微信开始转向多进程架构,独立的通信进程保持长连接的稳定性,独立的webview进程也阻隔了内存泄露导致的问题。时间继续推进,我们也遇到了65535问题和LinearAlloc问题。这时的微信已经具备了许多功能像朋友圈、摇一摇、附近的人等等,分离核心
资源推荐
资源详情
资源评论
微信微信Android模块化架构重构实践模块化架构重构实践
微信Android架构历史
微信Android诞生之初,用的是常见的分层结构设计。这种架构简单、清晰并一直沿袭至今。这是微信架构的v1.x时代。
图1-架构演进
到了微信架构的v2.x时代,随着业务的快速发展,消息通知不及时和Android 2.3版本之前webview内存泄露问题开始突显。由
于代码、内存、apk大小都在增长,对系统资源的占用越来越多,导致微信进程容易被系统回收。因此微信开始转向多进程架
构,独立的通信进程保持长连接的稳定性,独立的webview进程也阻隔了内存泄露导致的问题。
时间继续推进,我们也遇到了65535问题和LinearAlloc问题。这时的微信已经具备了许多功能像朋友圈、摇一摇、附近的人等
等,分离核心功能和其他业务模块变得越发重要。为此,微信开启了第三次架构改造(v3.x)。我们对各种产品功能进行解耦并
拆分到相互独立的p_xxx工程中,这是微信第一次进行模块化架构的重构。经过几个月的努力,微信拆出了几十个p工程,它
们都通过基础组件访问网络、存储等服务,互相独立并行。新的p工程架构支撑了微信更快速的业务发展,配合多分支开发模
式的改进,能够支持团队多分支多team的并行开发。
图2 - 架构图
为何再次重构微信
原本好好的架构出了什么问题?
从上个架构之后的两年多时间里,微信Android基本没有大的架构改动。配合gradle的编译,以及git的多分支并行开发,微信
的模块工程数量不断增多,支撑了游戏、支付等大功能,可以说这段时间里原有架构起到了很好的作用。
然而随着代码继续膨胀,一些问题开始突显出来。首先出问题的是基础工程libnetscene和libplugin。基础工程一直处于不断膨
胀的状态,同时主工程也在不断变大。同时基础工程存在中心化问题,许多业务Storage类被附着在一个核心类上面,久而久
之这个类已经没法看了。此外当初为了平滑切换到gradle避免结构变化太大以及太多module,我们将所有工程都对接到一个
module上。缺少了编译上的隔离,模块间的代码边界出现一些劣化。虽然紧接着开发了工具来限制模块间的错误依赖,但这
段时间里的影响已经产生。在上面各种问题之下,许多模块已经称不上“独立”了。所以当我们重新审视代码架构时,以前良好
模块化的架构设计已经逐渐变了样。
图3 - 架构逐渐的变化
“君有疾在腠理,不治将恐深”,在我们还在犹豫到底要不要重构的时候,硬件同学向我们提出了需求。希望将微信Android代
码移植到类似微信相册这样产品中。这样就可以快速跟进微信业务最新的支撑组件、协议、安全性、后台服务等能力,而且代
码要尽可能精简,可以选择和定制模块,可以移植模块来实现原型尝试。但就之前的情况来说,微信一时难以满足。这下定
了,还得重构。
于是我们回过头仔细看之前的设计,找找问题究竟是怎么来的。
问题出在哪
先寻找代码膨胀的原因。
翻开基础工程的代码,我们看到除了符合设计初衷的存储、网络等支持组件外,还有相当多的业务相关代码。这些代码是膨胀
的来源。但代码怎么来的,非要放这?一切不合理皆有背后的逻辑。在之前的架构中,我们大量适用Event事件总线作为模块
间通信的方式,也基本是唯一的方式。使用Event作为通信的媒介,自然要有定义它的地方,好让模块之间都能知道Event结
构是怎样的。这时候基础工程好像就成了存放Event的唯一选择——Event定义被放在基础工程中;接着,遇到某个模块A想使
用模块B的数据结构类,怎么办?把类下沉到基础工程;遇到模块A想用模块B的某个接口返回个数据,Event好像不太适合?
那就把代码下沉到基础工程吧……
就这样越来越多的代码很“自然的”被下沉到基础工程中。
我们再看看主工程,它膨胀的原因不一样。分析一下基本能确定的是,首先作为主干业务一直还有需求在开发,膨胀在所难
免,缺少适当的内部重构但暂时不是问题的核心。另一部分原因,则是因为模块的生命周期设计好像已经不满足使用需要。之
前的模块生命周期是从“Account初始化”到“Account已注销”,所以可以看出在这时机之外肯定还有逻辑。放在以前这不是个大
问题,刚启动还不等“Account初始化”就要执行的逻辑哪有那么多。而现在不一样,再简单的逻辑堆积起来也会变复杂。此
时,在模块生命周期外的逻辑基本上只能放主工程。
此外的问题,模块边界破坏、基础工程中心化,都是代码持续劣化的帮凶。
总之在模块化上我们忽视了一些重要的问题,必须重塑。
重塑模块化
重塑模块化,我们分解为三个目标:
1.改变通信方式
2.重新设计模块
3.约束代码边界
改变通信方式
前面讲过,我们使用Event总线作为模块间通信的媒介,这种设计很常见。然而当回顾整体代码时能发现,Event并非所有通
信需要的最佳形式。它的特点适合一对多的广播场景,依赖关系弱。一旦遇到需要一组业务接口时,用Event写起来那是十分
痛苦的。也正因如此,这种情况下大家都跳过了Event的使用,直接将代码下沉到了基础工程,共享代码,进而导致基础工程
的不断膨胀。
所以选个合适的通信方式很有必要,我们希望兼顾考虑开发的便利性和协议的约束性。
Event不合适。协议通信如何?
我们理解的协议通信,是指跨平台/序列化的通信方式,类似终端和服务器间的通信或restful这种。现在这种形式在终端内很常
见了。协议通信具备一种很强力解耦能力,但也有不可忽视的代价。无论什么形式的通信,所有的协议定义需要让通讯两方都
能获知。通常为了方便会在某个公共区域存放所有协议的定义,这情况和Event引发的问题有点像。另外,协议如果变化了,
两端怎么同步就变得有点复杂,至少要配合一些框架来实现。在一个应用内,这样会不会有点复杂?用起来好像也不那么方
便?更何况它究竟解决多少问题呢。
所以我们想要简单点。经过权衡,我们决定用模块提供“SDK”的方式作为它与其他模块进行通信的手段。
通常“SDK”提供的是什么,是接口 + 数据结构。这种方式好处明显:实现简单也能解决问题,IDE容易补全、调用接口方便,
不用配合工具,协议变化直接反映在编译上,维护接口也简单了。
其实想想,用协议的方式在终端内作为通信手段,开发效率低,也容易出错。因此可能会诞生各种框架和工具来提升这里损失
的效率。到头来,是不是大家都实现了一套类似RPC这样的封装。其实本地的通信,能用接口就挺好,不能用的时候,再用
协议封装也来得及。
确定了方案,实现起来就很简单。我们的注册方式和接口访问都很简单。用接口注册,再用接口访问,不暴露实现细节。如下
图。
图4 - 注册接口
图5 - 访问接口
接下来,怎么暴露接口更方便?
模块暴露“SDK”的方式无非就是新建个“SDK”工程,剥离接口和数据结构到该工程里面,然后让其他模块引用编译。但这样有
点麻烦,能不能再方便点?
当然有办法。我们实现了另一种接口暴露的形式——“.api化”。
使用方式和思路都很简单。对于java文件,将工程里想要暴露出去的接口类后缀名从“.java”改成“.api”,就可以了。
而且并不只是java文件,其他文件如果也想暴露,在文件名后增加”.api”,也一样可以。
图6 - “.api化”
当然,要让工程支持这样的方式,gradle文件肯定会有一点改变。
settings.gradle
剩余11页未读,继续阅读
资源评论
weixin_38527978
- 粉丝: 5
- 资源: 900
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- pta题库答案c语言之排序4统计工龄.zip
- pta题库答案c语言之树结构7堆中的路径.zip
- pta题库答案c语言之树结构3TreeTraversalsAgain.zip
- pta题库答案c语言之树结构2ListLeaves.zip
- pta题库答案c语言之树结构1树的同构.zip
- 基于C++实现民航飞行与地图简易管理系统可执行程序+说明+详细注释.zip
- pta题库答案c语言之复杂度1最大子列和问题.zip
- 三维装箱问题(Three-Dimensional Bin Packing Problem,3D-BPP)是一个经典的组合优化问题
- 以下是一些关于Linux线程同步的基本概念和方法.txt
- 以下是一个简化的示例,它使用pygame库来模拟烟花动画的框架.txt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功