58同城从进入移动互联网行列开始,已历经以下几个阶段:早期单团队单APP阶段,后期发展到多团队并行研发阶段,以及现在的多APP阶段,每一个阶段都有着不同时代诉求,也使产品研发能顺应各阶段的要求。
1、 单团队单APP
早在2010年58同城诞生第一版iOS客户端,按照传统的MVC模式去设计,纯native页面单工程,这时的功能比较简单,架构也很简单,从上到下分为UI展现、业务逻辑、数据访问三层,如图1所示,为单团队单APP架构。和同期其它公司一样,APP出发点是为了快速抢占市场,采取“短平快”的方式开发。纯Native的APP在早期业务量不是太大的情况下,能满足业务的需求。1.2 多团队并行研发
随着58APP用户量的剧增,各业务线业务迅速增长,各自组建了自己的团队去单独维护58APP中对应的业务。这种情况下就需要将房产、二手、二手车、黄页、招聘等业务线的代码从原工程里面剥离出来,每个业务线独立维护自己的工程,从而形成多团队并行研发的架构。如下图所示,为58APP的多团队并行研发架构,主业务层已经从物理上划分出各业务线和无线各自维护的业务模块,每个业务模块为一个独立工程,无线为各业务线提供平台支持。1.3 支持多APP
当今互联网行业竞争异常激烈,各大公司不仅有自己的主APP,还在主APP相关的垂直细分领域发力,竞相推出自己的垂直创新APP。甚至更大型公司直接并购一些细分领域的业务,也是很常见的事,并购之后,需要进行资源整合,进而节省人力成本,提高研发效率。如58先后并入赶集、安居客等,对于细分领域的创新APP有同镇、同城招聘、同城租房等,从而APP架构设计上由原来只考虑单APP,扩展到要支持多APP情况。
1.3.1 目标
标准化能力是实现app工厂的基础,标准化能力与app业务代码无耦合关系,比如React Native SDK,网络库、缓存库等。同一套代码,根据配置,能按需生成不同app所需的代码。针对独立app的公共业务代码,定义为垂直业务,业务平移即一套业务代码,能在两个或多个独立app上运行。马甲包、极速包与app工厂(58app)是一个子集与全集的关系,而类似安居客app与58app是两个独立app,有交集(公共底层代码或某些业务代码),业务代码集合不一样。1.3.2 架构和依赖准则
基于多APP的APP工厂架构主要分为两层,上层为入口工程,下层为工程池,工程池中存放着各种组件,为各入口工程提供具体业务模块和通用服务,如下图所示。iOS中pod特指用cocoapods管理起来的工程,cocoapods是对OC或swift Cocoa 工程的依赖管理。主要负责对app工厂生成的app所需代码进行配置。指具体的业务模块,如各业务线的工程、垂直业务工程,其中,各业务线模块可以为创新APP提供业务支持,垂直业务工程可以为多APP间垂直业务平移提供业务支持。与业务强相关的中间件,在某一个独立app中通用。由于对当前app其它功能的过多依赖,所以不适用于其他独立app。与业务弱相关的中间件,不仅在某一个独立app中通用,在其它独立app中也通用,与app中的业务弱相关。最常见的是标准版的RNSDK。对其它pod不产生依赖的独立库,如三方库和58集团内自封装的sdk。(1)上层可以依赖下层,但下层不可以依赖上层。比如上层中的业务pod中的首页(MainPage)可以依赖业务中间件中的生命周期组件,但反之不能依赖。(2)可以隔层依赖。比如业务pod可以依赖基础库pod;(3)业务pod间不能产生依赖。比如房产pod不能依赖招聘pod。(4)中间件pod和三方库pod可以单向依赖。比如RN所在pod可以对登录服务所在pod产生单向依赖。制定上述依赖准则,是为了在生产app时或者进行垂直业务平移时可以按需配置所需pod。有关APP工厂架构更详细的阐述,请阅读彭飞发表的文章《App工厂在58集团App中的实践(iOS视角)》。对于单pod的APP,如果要实现APP工厂,首先需要有多个pod组件。按照我们前面设计的APP工厂架构方案,单pod的APP要实现一个包含基础库、标准中间件、业务中间件、业务这样一个pod池,就需要先明确这个APP的层级架构。2.1.1 调整目录与APP工厂架构对应
对于单pod的APP,各业务各功能模块都是以目录的方式存在,需要先对目录进行分类。如下图所示,先大概分为业务和非业务两大类,然后在业务中区分纯业务和通用业务,所谓纯业务如房产业务线业务,对应APP工厂的业务组件,而通用业务如列表详情可适用于所有业务线,对应APP工厂架构中的业务中间件。而对于非业务类,可分为三方库这样的基础库和通用服务,所谓通用服务,如网络、hybrid框架,对应APP工厂的标准中间件。目录分类完后,按照分类对目录进行调整,便于功能模块的快速定位,如果已经是按照这样归类目录的,那就不需要调整。如果是要产出垂直领域的马甲包或者是垂直业务平移,则需要明确这个垂直业务模块所在的业务目录,先可以不用考虑这个业务依赖的其它功能目录;如果是要产出一些底层基础库,则需要在通用服务目录下确定所需底层库所在目录。2.1.2 上层业务拆分出来
如果是要产出马甲包或支持垂直业务平移,则需要将垂直业务代码拆分出来创建单独的业务pod,拆分的准则是只拆分出这个垂直业务内部代码,如我们我拆分出房产业务pod,就需要将房产的大类列表详情聊天页面、房产内个性化的一些工具类和一些房产定制的UI库等,而不要将依赖的一些底层文件拆进去,这个也有标准,如判断某个功能是否需要一块拆出去,检测这个功能是否在其它业务中调用,如果有调用说明这个是通用功能,否则可以拆到业务pod中。拆出去的业务pod需要满足两个条件,一是这个pod不能依赖平行业务,二是所有pod不管是拆出去的还是没拆出去的pod都不能对拆出去的这个pod有依赖,这里的依赖指有明确的import关系。对于第一个条件如拆出去的房产不能依赖招聘业务代码,虽然招聘还没有拆分出去。对于第二个条件如有一个拆出去的pod如招聘不能依赖并行拆出去的房产pod,再如还没拆出去的其它功能列表详情不能依赖房产pod。如果有一个条件不满足,则要对这个拆出去的pod以及依赖这个pod的业务功能进行解耦。2.1.3 分析上层业务的依赖关系
除了上层业务要拆分出去外,它所依赖的底层所有功能也需要拆出成pod。因此,我们先需要分析出来这个拆出去的pod依赖了哪些底层功能,这个可以写一个专门的工具,58也做了一个这样的依赖分析工具,能快速分析出来上层业务依赖的所有底层功能。由于分析出来的底层依赖都在原pod剩下的功能目录中,之前我们有对原pod目录进行重新调整,将分析出来的依赖对应到调整的目录下,如依赖了通用列表页面,我们就需要将列表业务pod范围确定好,需要将列表业务完整的目录包含进来,确定范围的标准与上述业务pod拆出一致,即只有列表才用的文件或目录包含进来,而有多处用到的功能不能携带过来。2.1.4 解耦拆分出依赖组件
确定了拆分业务依赖的所有功能以及依赖每个功能的代码范围后,我们就需要对所有的依赖功能拆出成单独的组件pod,拆出的业务和底层组件都不能依赖APP原来的Pod。依赖的功能组件拆出后我们需要进行解耦,具体每个组件的依赖准则需要参考该组件在APP工厂的定位,我们APP中的所有目录和APP工厂架构层级是对应关系,如果这个组件是标准中间件,则只能依赖三方库,其它的依赖关系都需要解除,而如果这个是业务中间件,则可以依赖标准中间件,尽量避免依赖其它的业务中间件。具体方案实施细节请阅读王晓晖同学的文章《App工厂,我们是如何快速生产创新App的》,这里就不赘述了。2.1.5 接入APP工厂
这样就将原来单pod的APP转换成了多pod的APP,接入方式参考下面的单APP多pod方案。2.2 单APP多Pod实现APP工厂
2.2.1 创建pod池
在逻辑上我们可以创建一个pod池,池里包含着APP工厂架构当中的4层组件,池中的pod来自单APP的各pod组件解耦拆分。需要明确的是APP中已有的pod不一定是能直接放到pod池中的,有可能粒度不够细,还需要再拆成更小的pod,也有可能有着复杂的依赖关系,需要进一步解耦。我们先可以将APP底层的基础库和一些通用的标准中间件如网络库拆分出来放入pod池中,而业务和业务中间件pod先为空,这些pod主是随着业务的迭代不断丰富的。2.2.2 需求驱动pod池不断丰富
如果是要生成马甲包,则需要对马甲包业务需求进行分析,产出结果是马甲包业务需要用到主APP的哪些功能模块列表。接下来我们需要根据这份功能列表到主APP的pod池中进行查找,如果池中有就直接用,否则需要到主APP中去查找是否有该功能,如果有,则将这部分功能拆分解耦出来创建新的pod组件,并加到pod池中,这个功能有可能是在别的pod中,说明这个pod所涉及的职责过多,需要将这个功能从pod中解耦出来,如果没有说明这是马甲包个性化功能,需要额外开发,不需要加到pod池。2.3 多APP多Pod实现APP工厂
多个APP有可能是主APP和马甲包关系,也有可能是一开始完全不相干的两个APP,如58同城与安居客、以前的美团与大众点评。马甲包情况可以考虑上面的单APP多pod的方案,这里主要讨论垂直业务平移的实现。2.3.1 多APP分析垂直业务依赖功能
垂直业务通常是在至少两个APP间进行,先对各APP中需要平移的垂直业务进行功能分析,产出底层依赖的基础库和标准中间件,那说明这些基础库和标准中间件需要在多个APP间都有,且必须是统一的实现。2.3.2 统一基础库和标准中间件
如果两个APP间是不相干的话,两APP间对同一功能的标准中间件的实现通常不同的,如网络库、hybrid框架、RN框架、路由等,需要两APP间进行沟通取舍,用统一的一套,如hybrid框架如果两端不一致会导致垂直业务平移后在宿主APP中无法注册和响应action事件,而hybrid框架不仅是需要native端统一action注册、响应的处理逻辑,也需要FE端的统一,下发相同的数据协议。再如路由协议通常两APP间是不同的,这就需要在两APP间的垂直业务使用统一的路由协议。为了在58APP和安居客APP间进行租房和二手房业务垂直业务平移,两端进行了多个标准中间件的统一。2.3.3 统一公共业务接口
如果两APP间的垂直业务存在公共的业务,需要两端实现上统一接口。如租房和二手房垂直业务都存在收藏,拨打记录和浏览记录功能,并且两端APP这些数据模型以及存取实现都是不同的,这就需要两端对历史记录数据模型进行兼容统一,并且数据存取接口进行统一,上层通过接口进行调用。2.3.4 统一请求公参
通常来说两APP间请求的参数也是不同的,尤其是对于一些必填参数,如标识用户是否登录的PPU,一旦业务平移,在宿主APP中,必须获取到原APP相应的参数请求才能返回正确的数据。如果有宿主APP中获取不到相应的参数,就需要将原APP中的参数值获取逻辑实现也平移过去。2.3.5 支持多APP垂直业务架构
垂直业务解耦后只依赖两端统一的标准中间件和三方库。对于业务上的依赖,需要两端统一一套业务接口供垂直业务调用,两端各自去实现这套业务协议。通过以上统一标准中间件、基础库、公共业务/公参协议后,对原APP架构改进后如下所示。2.4 按需生成APP
这里说的按需生成APP就是,公司内维护一套自己的组件池,这些组件包括基础库、业务无关服务组件、业务相关组件、以及纯业务组件,并通过在组件池中按需选择组件进行组装产出一个新APP,或者将选择的垂直业务接入到已存在的成熟APP。2.4.1按需pod配置
先要根据当前APP的需求选择APP工厂架构中业务层相应的业务pod,如支持垂直业务平移的APP,需要将垂直业务pod选入,再如58同城招聘创新APP中,需要将招聘业务pod选入,在Podfile文件中通过pod的方式导入。这里并不需要关注我们选择的业务pod会依赖pod池中的哪些中间件或基础库,因为我们会进行依赖配置,会将它依赖的底层pod自动引入。2.4.2 各pod对其它pod的依赖配置
各入口工程中配置Podfile,Podfile中配置了依赖的业务pod,业务pod及其依赖的所有pod,依次向下,如果有向下依赖pod,则在相应podspec文件中添加dependency,而dependency需要配置依赖的pod名、和对应的分支,这里对于指定的pod名,有可能是源码或者Lib库,引入库主要是用来提升研发效率。整个pod依赖配置如下图所示。Podfile比较简单,直接配置业务pod即可,如招聘创新包,只需要配置招聘业务线pod和其个性化的业务pod。由于在招聘业务pod和个性化业务pod中均有配置各自依赖的pod,在执行pod install时自动会根据配置将依赖的底层中间件pod都引入进来。是一个外部传入的pod列表,是用来说明列表中的pod是需要用源码的,如果PodA所依赖的其它PodB没在这个列表中,则dependency需要接PodB的库,即PodBLib,否则dependency的是PodB源码。我们在入口工程维护一个总的分支配置json文件,一是为了确保同一pod(如PodA)被各pod(如PodB和PodC)依赖的是同一分支,二是不用在每个上层依赖pod中维护一份自己所依赖的各pod对应分支,如果这样当被依赖的pod(PodA)版本有更新时,需要修改所有依赖PodA的pod(如PodB和PodC)。
其中表明,PodA、PodB和PodC用xxx分支,而PodD和PodE用yyy分支,Ohters表示剩下的所有pod如PodF都用zzz,这样有一个好处就是,如果pod过多,不需要一一枚举出来,便于维护。需要注意的是,配置文件中所有的pod名都是按源码pod名,即便是需要用到Lib库的pod,方便维护。对于pod池中的业务层和业务中间件层的pod,内部都维护了一个该pod依赖外部pod的列表文件,如下所示的PodA.json维护的是PodA所依赖的pod列表。该文件表明PodA对PodB、PodC、PodD这3个pod有代码上的依赖调用关系。对于这份文件的更新,需要借助我们研发的pod依赖工具。podspec文件中配置当前pod所依赖的其它pod,主要是dependency的配置,而在dependency配置过程中需要确定依赖的pod名和对应分支,如下图所示。对于pod名的确定,需要用到前面的源码/Lib pod列表和 pod内对外依赖配置,通过这两项确定所依赖的pod是用源码还是Lib库。对于分支的确定,需要用到所有pod分支配置文件。需要注意的是,如果当前pod用的是Lib库,需要按照源码pod名来去分支配置文件中查找。3.1 依赖分析工具
APP工厂落地过程中有一项很重要的工作,就是解耦,为解耦我们首先要知道当前的这些组件间的依赖关系。如果要手工去分析这么多组件的依赖关系,工作量是很巨大的,因此,我们开发了一个依赖分析工具。1. 扫描指定目录下所有pod的,对于每一个pod,扫描pod目录下的所有代码文件,并将扫描的列表和pod名保存到文件podFilesDict中。2. 扫描podFilesDict中的所有代码文件内容中的import行,分析出import中的头文件,过滤系统头和SDK头文件,取出分析出的头文件,到podFilesDict中去搜索,找到这个头文件对应的pod名,并在结果文件podDependDic中保存下来。3. 由podDependDic文件去更新各个pod中维护的依赖配置文件。如下图14所示,是通过工具分析后产出的通用详情页组件Detail依赖关系,其中,item1是Detail依赖的所有pod,用于更新Detail这个pod中的依赖配置文件,而item2中显示了其对所有pod的依赖,具体到依赖和被依赖的文件名。3.2 依赖污染检测工具
对于pod工程池里面处于底层的标准中间件,如网络库,这些基本都会被每个业务模块调用,并且也会在多APP中共享,因此,像这种中间件,不能有对某个APP平台业务,中间件中的代码不能对外产生依赖关系。那么,我们有必要产出一种方案去保证这些中间件不会被污染,就算被污染,也需要能及时检测出来。中间件中一般import的方式有三种,即”A.H”、”<XXX/A.h>”、”<A.h>”,其中系统库和三方库对三种方式都有引用,而如果是对外部工程引用则通常只会用”A.H”、”<XXX/A.h>”两种方式,但不排除异常使用情况。因此,可以通过对”A.H”、”<XXX/A.h>”、”<A.h>”三种方式进行判断分析是否有代码耦合为了达到依赖污染检测的目的,我们APP工厂中研发了一个检测工具,具体方案如下:扫描中间件中的代码文件,查找import引用,分别对”A.H”、”<XXX/A.h>”、”<A.h>”三种方式进行判断,具体方案步骤如下:1)扫描中间件工程中所有的头文件,将结果存在一个头文件列表中;2)扫描中间件中的每一个文件,查找import :2.1) 如果是“A.h”形式引用,则在1)中的头文件列表中查找,如果没有找到,则记录当前文件路径和A.h到异常文件中;否则继续;2.2) 如果是”<XXX/A.h>”形式引用,则取XXX,在白名单中搜索,如果没有,则同样记录到异常文件中;否则继续;2.3) 如果是”<A.h>”形式引用,则直接取A.h在白名单中搜索,如果没有,则同样记录到异常文件中;否则继续。对于白名单,由于所有中间件在最初始的时候都是可以编译成功的,也就是所有中间件中不会有import外部工程的情况,也就是没有代码耦合,产生的代码耦合都是在后续的业务版本迭代中发生的。因此,可以在最开始的时候通过扫描所有中间件的”<XXX/A.h>”、”<A.h>”import引用方式来获取到。后续对于白名单的维护,通常情况不会有减少,只会在原来的基础上进行追加系统和三方库。业务中间件的定位是可以对标准中间件或其它的业务中间件有单向依赖关系。这里主要检测对其它业务中间件的依赖,通常来说是可以增加对标准中间件和三方库系统库的依赖,而不应该增加对业务中间件的依赖。通过对每个业务中间件的代码文件进行分析,分析每个文件的import情况,提供一个公共的外部头文件/库/标准中间件白名单,称为公共白名单(为方便表述,以下均用此名称),公共白名单可以适时更新,并且为每个业务中间件配置一个对其它业务中间件依赖的白名单,称为私有白名单(为方便表述,以下均用此名称),私有白名单有可能是空的。如果在公共白名单中或者在本中间件中文件中则忽略,否则如果也不在私有白名单中,则视为有代码耦合。扫描业务中间件中的代码文件,查找import引用,分别对”A.h”、”<XXX/A.h>”、”<A.h>”三种方式进行判断,具体方案步骤如下:- 针对每个业务中间件,生成中间件头文件列表BizPodXXXHeaders.txt和私有白名单,BizPodXXX为中间件名称;
- 扫描中间件中的每一个文件,查找import,根据import获取其中的三方库/系统库/标准中间件名XXX,或者是头文件名A.h;
- 如果是头文件名A.h,则在当前中间件头文件列表BizPodXXXHeaders.txt中,如果没有找到,则进入2.2;否则继续扫下一个头文件;
- 如果是库名XXX或者头文件A.h,则在公共白名单中查找,如果没有,则进入2.3;否则继续扫下一个头文件;
- 如果是库名XXX或者头文件A.h,则在中间件私有白名单中查找,如果没有,则记录到异常文件中;否则继续扫下一个头文件;
由于业务中间件可以对其它的业务中间件进行依赖,就有可能会出现一个循环依赖的问题,一旦出现了循环依赖,一是破坏了APP工厂的依赖准则,项目进行中会携带过多的代码到目标APP中;二是由于在各组件的podspec文件中会通过dependency属性来设置对其它业务中间件依赖,当通过Cocoapods进行pod install时会出现如“There is a circular dependency between XXX and YYY”这样的错误。因此,有必要检测我们的业务中间件是否存在这样的依赖环,具体方案如下:- 通过依赖检测工具生成各业务中间件的对外依赖关系,产出可以是一个json文件形式;
- 通过1)中产出的依赖关系设计成一个有向图数据结构模型;
- 通过2)中的有向图进行深度优先遍历(DFS算法),即可遍历出所有环中的组成结点,输出即可。
在APP工厂项目中,涉及APP和业务线业务是极为复杂和繁多的,业务和底层组件工程数量较大,每个工程都有对应的静态库工程,每次都要对所有源码工程生成一遍。但是有可能某个工程一直都没变,但每次生成静态库时都会重新生成一遍相同的文件,这样既增加了整个生成库的时间,同时也浪费了服务器资源,做了一些无用功。如果不变的工程量比较大时,如在基础架构中会存在大量的组件如网络、缓存、路由等功能组件代码基本是多年不变的,也有些是多个版本不变的,如一些基础的服务组件如列表详情。这就需要有一个工具只需要对有更新的组件进行编译更新静态库。1) 维护一个全局的列表文件,保存工程名和对壳工程,初始为空。2) 通过cocoapods来集成所有工程,获取源码工程,这些源码工程通常是外部输入的。3) 对2中获取到的源码工程进行遍历,取下一个源码工程。3.1) 读取本地列表文件中当前工程的commitid1。3.2) 从服务器请求当前工程最新commitid2。3.3) 对比commitid1和commitid2,如果commitid1== commitid2,将当前工程从源码工程列表中删除继续执行3;否则,继续执行3。3.4) 将<当前工程名:commitid2>写入或更新到列表文件,继续执行3。5) 编译完成后生成所有在3处理后的所有源码工程的静态库。6) 修改本地的列表文件,将3处理后的源码工程以及对应的commitid2写入列表文件。7) 将本地修改完的列表文件同步到远程服务器,即在另外的静态库生成服务器上也能同步到其它任何一台生成库服务器的增量信息。4.1安居客与租房垂直业务平移
4.1.1 背景和目标
58同城和安居客中都有租房和二手房业务,为了实现资源合并,提高开发和维护成本,于是租房和二手房被确定为垂直业务。58内部需要实现安居客app的二手房和58同城app的租房在两个APP上都能运行,即一套代码,同时运行在58app和安居客app上。1. 58app和安居客app共用垂直业务所依赖的底层代码(中间件代码+基础库代码);2. 垂直业务代码及所依赖的底层代码对58app或安居客app中的独有代码没有任何耦合,这样就不会携带一些无关的不需要的代码,有利于控制包大小。垂直业务代码及所依赖的底层代码必须满足App工厂架构中的分层原则和依赖原则,这样架构扩展性会比较灵活。4.1.2 落地方案
要实现两个APP之间垂直业务相互平移,首先就需要将58同城租房、安居客二手房从原有app中拆分出来。而要实现拆出,先要分别分析并处理租房和二手房业务对下层组件的依赖关系,以达到最大限度的降低携带代码。为支持两端垂直业务平移,底层标准中间件进行了统一,在APP工厂Pod池中添加以下标准中间件。 | |
| |
| 封装了同城App内涉及到的包括城市列表、地铁列表、商圈数据、历史浏览记录、足迹信息的存储与读取的接口。 |
| 封装了Hybrid交互功能,action分发功能以及一些标准化的actions |
| 封装了RN基础功能,包括载体页、热更新、性能优化以及一些标准化的Modules |
| |
| |
| |
| 提供给支持跨平台业务调用底层具体实现的协议(Protocol)部分,具体实现由不同平台各自实现 |
| 封装了部分公共参数的生成与获取API,直接接入即可自动获取到58同城App内请求头、Cookie、以及其他公共参数 |
4.1.3 平移效果
租房垂直业务,如图18所示,左边为58 app,右边为安居客app:二手房垂直业务,如图19所示,左边为58 app,右边为安居客app:4.2 58创新APP
现各大厂除了主APP外多少都有一些业务垂直领域的创新包和极速包,如淘宝系的聚划算、口碑、阿里健康、闲鱼,头条系的抖音、西瓜视频、火山小视频,腾讯系的腾讯微视、腾讯直播、腾讯动漫等。58同城招聘属于58同城的垂直领域创新APP,和58APP的关系是的有业务上的交集,也有个性化的业务。研发总体方案如下,具体方案实施细节请阅读王晓晖同学的文章《App工厂,我们是如何快速生产创新App的》。- 分析创新APP功能需求,确定需要哪些通用的和业务相关的服务列表。
- 将分析出的服务列表在APP工厂pod池中查找,选择对应的标准中间件和业务中间件。如果pod池中有对应功能的中间件,则直接选择;否则,看主APP中是否有该功能,如果有,则从主APP中解耦拆分出来成标准中间件或业务中间件,并加入到pod池中;否则属于创新APP中个性化功能,单独开发。
- 研发创新APP中的个性化业务,通常这部分工作需要垂直领域业务线去完成。
目前通过APP工厂产出的创新包有58同城招聘、58同城租房、58同城二手车、同城服务平台。图20 APP工厂创新包APP工厂主要为有着垂直平移关系或者是垂直细分领域的创新APP提供了一套在多次实践中验证的解决方案,为上层各APP的研发提供了基础服务的支持,让上层APP更高效地专注业务的研发。随着更多的APP加入到APP工厂,由业务驱动APP工厂架构不断完善,pod池中的中间件会日益丰富,APP工厂的优越性就能更有效的发挥出来,同时也会带来更多的挑战。在APP工厂项目的推进过程中,涉及到跨部门和异地沟通协作,在各部门领导和同学的积极配合下,此项目才能顺利地进行,为此,要感谢租房、安居客、招聘、二手车、同镇、ASO团队的大力支持。曾庆隆、彭飞、王晓辉:用户价值增长部-iOS技术部
58App Android新首页改版历程
如何利用App工厂支持创新App
租房业务APP后端服务重构之路
58App-Android端的动态化框架实践与思考
“暗黑模式”之58 同城 iOS App深色模式适配实践