在2017年在线技术峰会——阿里开源项目最佳实践上,天猫的戴鹏带来了BeeHive,分享iOS大型项目的脱钩方案。他从多人开发的问题出发,介绍了三种模块方案,比较了传统的Init和BeeHiveModule,分析了BeeHive架构,并详细介绍了模块管理器和模块的实现。
iOS大型项目中需要优化的对应地方如何优化,多人协同开发中如何避免冲突?本文给你详细解答。
背景
2015年上半年开始参与天猫iPad的开发,负责我的天猫和主页上的一些程序框架的东西。2015年下半年后开始参与天猫iPhone的开发,主要负责直播项目。
多人发展模式中的问题
多人发展模式涉及沟通与合作。在代码依赖层面,函数调用繁琐,函数相互依赖,底层函数反过来依赖上层业务。在协同开发层面,合并冲突需要花费时间和精力,界面不稳定且频繁更新。在定量分析层面,代码耦合很难分析性能和单元测试。在性能优化层面,每个库都侵入App生命周期,难以区分库初始化的必要性,导致启动卡顿。
严酷的发展环境就像面条逻辑文化。有经验的开发人员也怕自己的手脚,因为整个迭代周期过程包括开发过程和bug修复过程。如果这些操作是在严重的耦合情况下进行的,可能会引入更多的错误。如果整个项目没有适当的分类,业务和基本逻辑就会交织在一起,可维护性就会降低。
多人发展的小目标
在开发过程中,为了支持业务的快速发展,没有认真考虑整个应用的特点。所有的应用都必须具备以下三个特点:可维护性,支持多人持续开发;可用性好,性能好,功能齐全;可分析性,支持优化和用户行为分析。
行业模块化解决方案
URLRouter可以参考JRRoute这种开源领域的成熟方案,以一个URL的形式把每个模块作为一个独立的边界。URLRouter需要在内存中维护一个URL表作为实现相应推送或者调用相应模块的关键。它在传递参数的过程中不能像对象一样传递数据,只能像String一样传递数据。
TargetAction也是基于苹果的原生Runtime的优势,它最大的优势是不需要加载内存,调用时没有相关的依赖关系。调用的缺陷是你只能知道运行池中是否存在对应的组件,如果不存在就会导致对应的崩溃。
Protocolclass是利用原类和对应协议使用的Serviceinterface实现的,接口是分开的,这样大部分业务方只需要基于协议调用接口即可。在这个过程中,会涉及到内存占用的问题。
蜂巢实践之路
BeeHive相当于蜂巢。我们希望每个模块能够像六边形蜂窝一样独立存在,同时能够与外界有良好的接口。
应用程序的层次关系
iOS分层有几层:CoreOS层,上面有CoreServices和MediaLayer,CocoaTouch对开发者来说是相对黑盒的。而且独立的应用也是以插件的形式插入系统的。最高的应用生命周期是管理和控制平台。
传统初始化和调试模块
传统的Init有三个级别。在这个过程中,Init分辨不好,一些耗时的操作是不必要的。对应的BeeHivemodule将每个模块划分成细粒度的模块,以ModuleManager的形式分配整个应用生命周期。每个模块在回调过程中只需遵循moduleprotocol就可以感知整个应用生命周期,并在不同的场景下做出相应的程序响应。
模块管理器
模块管理器不仅分割了应用程序的生命周期,还扩展了生命周期。从上图的对比可以知道,BeeHive增加了三个进程,分别是ModuleSetup、ModuleInit和ModuleSplash,对于大多数模块的初始化来说已经足够了。在这个过程中,还支持用户自定义的ModuleEvent,可以在一个App的任何一个生命链接中进行插件回调,方便在某些场景中显示一个业务功能的定制内容。
模块
Module存在的意义在于:在主项目中拆解联轴器;分发状态;定义应用状态;定量分析模块耗时;支持横向扩展能力。
在模块设置和模块设置中,记录模块的时间消耗。ModuleMonitor可以记录时间消耗,检查主线程占用情况,记录加载相应模块的顺序。ModuleMonitor也作为插件嵌入到BeeHive中。
从BeeHive中的工程可以看到模块交易模块、用户购买点、企业主页和商店的加载情况。这些数据可以支持未来的性能优化。
BeeHive架构
在BeeHiveCore中,每个模块的业务调度都以插件的形式存在。BeeHive以几种形式提供模块注册和服务注册:用plist编写、注释和动态调用。上下文主要包含一些全局内容,比如服务器返回的整个App环境,全局可读状态也存储在Config中,方便整个模块共享资源。
几个主要的业务并行调用流程
在上图中,三个不同的服务在调用过程中涉及四个基本的库模块。可以看出,这些关联很多都是不必要的。例如,日志库到网络库和网络库到日志库只需要单点依赖。
调整呼叫流程
BeeHive处理ServiceModule,ServiceManager控制ServiceProtocol的实现,比如管理单个或者多个案例。所有服务不再直接依赖于各种库,而是通过Interface的形式,服务只需要以切片的形式关心业务流程,大大提高了工作效率。
服务阻止模块之间的依赖关系
如上图所示,Service blocking模块之间的依赖关系,将无序的面条业务耦合变成了一种集中耦合的新形式。服务具有这样的特点:服务吸收了SpringService的开发理念,以AOP的形式存在;Register like Module有三种模式:静态注册、代码注册和注释注册。单个案例和多个案例是否与SpringService一致。
协议类对编译性能的影响
在大型项目的开发过程中,Xcode会运行的非常慢,可能只修改了几个小文件,但是编译打包这些文件的耗时过程还是相当严重的。一方面可以买新电脑提高编译速度,或者多开Xcode线程提高性能。协议类可以从三个方面提高编译速度:分配和分离接口和实现,通过协议划分不同的模块来划分代码之间的直接依赖关系;服务合并和编译也可以提高相应的速度,因为单个模块中提供的一些服务可以合并成一个大的整体ModuleService,文件少可以提高编译效率;业务中引入较少的头文件也会提高编译速度。
在BeeHive环境下开发3DTouch
在非BeeHive环境下开发3DTouch功能的步骤如上图所示。各种需求带来模块参考。首先,动态需要引入相关的配置内容,前后切换和个性化QuickAction涉及本地存储,进一步的个性化使用与用户的嵌入有关的东西。由于各种数据需要在外部记录,一些服务需要在外部提供,而不需要服务器的合作。
在BeeHive环境下开发这样的功能,有几点需要注意。不需要引入这样的module,只需要引入一个Module就可以关注它在整个生命周期中想要知道的东西。预期的服务只依赖于相应的服务接口。外部提供的服务也由BeeHive的服务管理器转移。
模块+服务架构的特点
每个模块都是一个独立的模块,享有全局Context和ServiceInterface,并有插件开发进行横向扩展。引入新的服务将是非常独立的,没有耦合。对于移植来说,只要是以Module的形式存在,并且新项目是基于BeeHive的,那么就可以开箱即用。
BeeHive的前景与问题
支持App秒智能调度逻辑,简单记录Module的负载分析,无法完成智能加载过程。需要支持更多的服务调用形式。服务依赖和调度逻辑也有一些问题。
BeeHive的框架带来一定的学习成本,只有在一定的复杂情况下,BeeHive的价值才能体现出来。复杂度守恒原理也提到了分离服务之间的耦合会造成BeeHive内部的复杂度,通过对一些线程的保护避免了一些快速的情况。BeeHive希望以基本库的形式管理整个应用周期和相应的外部插件。
1.《beehive BeeHive:大型iOS项目解耦实践》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《beehive BeeHive:大型iOS项目解耦实践》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/jiaoyu/891593.html