首页 体育 教育 财经 社会 娱乐 军事 国内 科技 互联网 房产 国际 女人 汽车 游戏

高德APP全链路源码依赖分析工程

2019-12-25

高德 App 经过多年的开展,其代码量已达到数百万行等级,支撑了高德地图杂乱的事务功用。但与此一同,跟着团队的扩张和事务的杂乱化,越来越碎片化的代码以及代码之间杂乱的依靠联系带来许多保护性问题,较为杰出的问题包含:

不敢容易修正或下线对外露出的接口或组件,因为不知道有什么当地对自己有依靠、会受到影响,所以代码变得臃肿,包巨细也变得越来越大;

模块在没有改变的状况下,发布到新版别的客户端时,需求全量回归测验整个功用,因为不知道所依靠的模块是否有改变;

难以判别 Native 从事务完成转变为底层支撑的趋势是否合理,管理是否有用;

这些问题现已达到了咱们有必要开端管理的程度了,而处理此类问题的关键在于需求了解代码间的依靠联系。

为了消除一些疑问,在评论依靠剖析的完成前,先简略阐明一下高德 APP 的渠道架构,以便对一些名词和场景有一些布景了解。

高德 APP 从言语渠道上能够分为 4 个部分,JS 层首要担任事务逻辑和 UI 结构;中心有 C++层做高性能烘托,一同完成了一些切面 API,这样能够在双端只保护一套逻辑了;Android 和 iOS 层首要作为适配层,做一些操作体系接口的对接和双端差异化的抹平。

这儿的切面是指 JS 层与 Native/C++ 层的分界线,这儿会完成一些切面 API,也就是 JS 层与 Native/C++ 层交互的一系列接口,如蓝牙接口、体系信息接口等,由 Native/C++ 层来完成接口,然后往 JS 层露出,由 JS 层调用。

整个项目最根本也是最重要的数据就是依靠联系。所谓依靠联系,最简略的比如就是文件 A 依靠文件 B 的某个办法。

要将这个联系查出来,一般来说需求经过两个过程。

遍历一切源码,经过语法剖析,生成笼统语法树。以 JS 扫描器为例,我选用了 typeScript 模块作为编译器,它一同支撑 JS、TS,经过 ts.createSourceFile 来生成 AST。除 JS 外,iOS 选用的是 CLang,Android 选用的是字节码剖析,C++ 选用的是符号表剖析。

从 AST 上咱们能够找到一切的引证和露出表达式,以 JS 为例就是 import/ require 和 export/ module.exports。寻觅表达式的办法就是递归地遍历一切语法节点,在 JS 中我选用了 TypeScript 编译器供给的 ts.forEachChild 来进行遍历,经过 ts.SyntaxKind 进行语法节点类型的辨认。

找到表达式后,经过依靠途径找到详细的依靠文件。以 JS 为例,咱们能够经过 const { identifierName } = require 的方法引证其它模块的某个文件的某些标识符,咱们就需求依据这表达式来定位到详细的标识符。

跨切面的依靠会需求多做一步,需求将切面 API 分为调用侧和声明侧,在 JS 层经过 AST 剖析出调用侧数据,在 Native/C++ 层剖析出声明侧数据,将调用侧和声明侧数据经过版别号相关到一同,即可完成全依靠链路贯穿。

咱们把这个联系以及一些元数据保存下来,就能够作为源数据来作数据剖析了。

全体项目架构如下:

咱们运用 Node.js 和集团的 egg.js 结构搭建了本依靠剖析工程服务,而且考虑到数据运用场景的多变性和多样性,我选用了 GraphQL 作为查询接口,输出咱们界说的数据类型,由上层运用自行封装,假如呈现多个上层运用一同需求相似的数据,咱们也会进行整合复用。

其间数据加工模块是独立模块,由 Node.js 编写,支撑其它项目复用,未来管帐划在 IDE 等项目复用。

左边是咱们的数据消费方,这儿只列举了几个;右侧是咱们的数据库,用于贮存剖析成果;下侧是四端扫描器和触发器,四端分别对自己渠道的源码进行源数据出产,触发器支撑发布流程触发事情触发、守时触发、前端触发和人工触发等。

全链路依靠联系的运用场景有无量的想象力,这儿挑几个来举例。

影响规模判别

第一个咱们能想到的运用场景就是影响规模判别,这也是咱们这个项目的第一个抓手。咱们都能想到,假如保护一个接口,咱们会发现当越来越多当地用的时分,迭代它的危险会随之而越来越高,咱们需求清晰地知道究竟有哪些当地调用了这个接口,以确认究竟要回归测验多少功用、要怎么做发布、怎么做兼容等。而这就需求进行逆向依靠剖析了。

逆向依靠是相对扫描器中剖析出来的依靠联系的,扫描器剖析出来的咱们称之为正向依靠,它首要表明「此模块依靠了哪些其他模块」;而逆向依靠则指的是「此模块被哪些模块依靠了」。所以很自然地,咱们的逆向依靠就是依据正向依靠联系做的数据加工。

依据逆向依靠数据,结合多个版别的数据,咱们还能算出「接连未被引证的版别数」,以衡量下线接口的安全性。

组件库、结构和切面 API 的保护者是这个才能的重度用户,这个才能为他们带来了数据支撑,清晰了自己的修正将会影响多少的其它模块,然后进行改变、发布决议计划和回归测验。

版别间改变剖析

版别提测时,咱们能够对两个版别进行依靠链比对,剖析出文件的改变及其整个影响链路,为 QA 供给一些数据支撑,能更精确地知道有哪些功用要进行回归测验,有哪些不需求。

版别间改变剖析有许多场景,除了正常的版别迭代的场景之外,还有一个常见的场景:模块在未改变的状况下被集成到新版别的高德 APP 中,那就会呈现「发布代码不变,而所依靠的其它模块有改变」的状况,特别有是 Native/C++ 和共用模块。测验环境需求知道的是,当时模块所依靠的其它模块究竟有哪些改变、这些改变对此模块的影响是什么、需求回归测验哪些功用点等。

这个数据的首要消费方是 QA 同学,他们使用这个数据能够进步测验功率,也能发现漏考虑的回归点。

趋势改变判别

前面也提到过,因为高德 APP 时刻跨度很大,以及之前未进行约束,所以咱们有部分事务逻辑代码仍然是经过 Native 来完成的,咱们希望逐步迁移到 JS 或 C++ 层完成,Native 仅作适配。

而要判别这个管理的进展和作用,需求从两个方面的数据来支撑,一是各渠道代码行数,这个咱们还有专门的服务做,暂时不提;二是接口趋势。接口趋势也分为调用侧和声明侧两种,依照咱们管理的方向,咱们希望的作用应该是:一条 Native 事务切面 API 的调用量按版别/时刻不断削减的曲线,当一些 API 的调用量为 0 后就能够把 API 下线掉,这样就会随之呈现另一条曲线——Native 事务切面 API 的声明量也不断削减。

进行架构管理、切面 API 管理的同学是这些数据的首要消费方,有了这些数据他们就能确认架构管理的趋势是否合理、是否能下线某切面 API 等。

包巨细优化——无用、重复文件查找

咱们也为包巨细优化作了奉献。依据依靠联系数据,咱们能够找出一些没有被引证或许内容彻底相同的文件,这些文件也占用了不少体积。

咱们使用依靠剖析工程找出了上千张这样的图片,@1x @2x @3x 文件是重灾区,有许多伪装自己是另一个清晰度的图片被咱们揪出来了。

以上就是高德全链路依靠剖析工程的根本概述,在详细的完成傍边,会有很多的细节需求处理,如各种前史遗留问题、多级版别处理发生指数级的代码快照、改变剖析发生指数级的剖析成果等,其间也涉及到不少编译原理、数据结构与算法等常识,十分检测编程才能和权衡才能,以及最重要的——耐性。欢迎咱们一同评论,一同爆发新的主意、新的场景!

热门文章

随机推荐

推荐文章