前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何解决架构与业务发展冲突?讯飞输入法Android架构演进

如何解决架构与业务发展冲突?讯飞输入法Android架构演进

作者头像
IT大咖说
发布2018-06-04 16:09:19
8840
发布2018-06-04 16:09:19
举报
文章被收录于专栏:IT大咖说IT大咖说

内容来源:2017 年 12 月 3 日,科大讯飞应用研发经理程坤在“IAS2017互联网架构峰会”进行《讯飞输入法Android架构演进与实践》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:3031 | 8分钟阅读

摘要

本次演讲将分享讯飞输入法Android版从最初开发到逐步发展成熟的过程中所面临的各种挑战以及经验,还有架构的逐步演进过程。最后提到了团队在组件化架构中的一些实践。

嘉宾演讲视频及PPT回顾:http://suo.im/5qUJXn

架构演进历程

架构演进概览

讯飞输入法初期采用的是简单MVC,2012年3月份进行了分层重构,2014年12月份做了多进程的架构,最后2015年12月份开始尝试组件化相关的工作。

架构如何演进

当架构与业务发展不匹配的时候就需要考虑改变当前架构,让架构去适应业务。无论是组织架构还是软件架构都需要面对业务问题,而如何解决这一问题是架构的核心目标。

软件架构也要与组织架构相匹配,它们之间应该是一一映射的关系,也就是说系统设计的架构所对应的设计结构和组织结构是相等的。

架构的演进的关键在于平衡性,架构设计人员经常会追求完美,比如设计非常好的扩展性,追求极致的架构,一股脑的将最新最酷的技术放到架构中。这些做法是不是业务所需求的其实并不一定 ,所以架构的可靠性、扩展性包括安全性等是要做一定平衡的,考虑时间和成本上的问题。

产品初期

讯飞输入法的项目于2010年7月份启动,当时的开发人员仅有两人。在2010年10月份的语音云发布会上讯飞输入法要作为演示型产品展示,因此对产品的要求是非常高的。可以看到开发的时间其实只有短短的三个多月,而且当时很多功能都是首创并无产考。

简单MVC

基于产品初期的这些挑战,我们在开发的时候其实是没有使用架构,而是优先考虑如何快速稳定的实现功能。下图展示的是开发前的设计图,上面是展现层,包含各种功能模块,右边是业务逻辑,中间是拼音手写和语音输入的引擎,最下面是数据存储。

根据项目开发过程中的经验来看,当你不能判断产品发布出去后是否能存活或者能否达到预期的情况下,不要花太多的精力去做一个非常好架构,如何快速稳定的发布产品才是核心目的,因此我们的建议是尽量复用。

产品快速发展前期

在产品的快速发展时期我们的主要工作就是补齐功能、优化效果,这时的开发人员也由原来的2人增加到了4人。开发过程中也出现了一些问题,由于当时都是各写各的代码,导致代码的重用性很差,新功能开发成本高,维护起来困难。

基于这方面的问题我们向产品人员提出了放慢产品发布节奏的要求,因此有了三个月的时间进行产品的重构。

分层重构

这次重构对产品进行了抽象分层,主要目的是为了复用。下面两层与业务无关,工具层包含常用的工具类,框架封装的是业务无关的通用业务能力。服务层和业务层则是和业务相关的,比如服务层的日志应用了框架层日志的能力,并融合了业务上的策略。

分层架构后开发效率获得极大的提升,将原先比较差或不好维护的模块重新进行了梳理和优化,同时还封装了很多了公共初始模块。

产品快速发展中期

产品经过迭代后功能越来越多,代码也越来越复杂,这时传统的分层架构已无法满足需求。因此我们将现有的10人团队,分成了业务组和架构组,架构组主要负责性能和稳定性上的优化。

多进程架构

在架构组进行优化的过程中,我们将原先的架构调整成多进程架构。原先的输入法只有一个进程,启动的速度非常缓慢,进程崩了输入法就无法使用。因此我们将输入法分成5个进程,将用户不常用的功能放在单独的进程中,用完后立刻杀掉,也就是即用即走。另一点就是隔离,把原先后台的一些功能,比如日志、下载、推送等单独剥离出来独立成一个进程,那么当这部分出现问题的时候就不会影响到主进程。

多进程的调用是非常麻烦的,因此我们摒弃了原先的单例模式,简化了调用。

产品快速发展后期

产品发展后期团队已经达到了20多人,管理起来很不方面,因此整个团队被分成了4个业务团队,4个架构团队。这时需要考虑的是什么样架构才能匹配各个团队的例行开发,同时还要支持更快的产品迭代。

为了保证快速迭代的过程中的产品稳定性,我们开始往组件化的架构上发展。

组件化的架构

目前开源的组件化框架非常多,要想实现这样的框架其实没有什么成本。当时我们的关注点在并行开发上,做到团队之间是隔离的,开发人员开发完功能后可以自行上线、测试、验证。另一个关注点是动态更新,保证上线的时候框架支持动态更新能力。

这个过程我们发现组件化架构坑实在是太多了,还没有或者准备做这方面的人员要想清楚是否一定要使用组件化架构。这里有两个概念,一个是并行开发,一个是并行发布,可以根据自身的情况选择做到哪一点为止。并行开发相对来说比较容易的,但是并行发布难度就不一样了,它涉及的不仅是客户端,还有服务端、大数据、版本的管理和兼容等各方面的问题。

组件化架构实践

为什么重复造轮子

较早的组件化框架有Atlas/ACDD、DynamicLoadApk、DynamicApk、Small,最近又出了两个新的框架VirtualAPK、Replugin。虽然考察了众多的框架,但是我们综合考虑后还是决定自己动手实现,这是由于输入法业务有其独特性。输入法不同于普通的App,它在键盘方面有着非常高的要求,而这恰恰是其他开源框架无法满足的。

兼容性

由于安卓系统的碎片化问题兼容性上的处理非常麻烦,比如会出现手机在切换到横屏状态时输入法显示一半的情况,后来发现是因为屏幕切换的时候资源没有刷新,获取到的还是原来的屏幕宽度,于是我们在ActivityThread内做了Hook。Hook本身的机制就是利用java的反射机制将API固有的实现替换成我们自己的。

启动性能

启动性能的问题主要出现在键盘启动变慢,空间不足导致崩溃上。框架的启动相比于原先做的事情更多了,花费的时间也更多。另外老用户在进行升级的时候,组件启动过程中会有一个配置文件,列出组件清单配置组件启动的优先级,然后对它进行解压再压缩最后拷贝到相应的地方。可以看到因为要腾出另外的空间将组件提取出来进行解压优化,这样对于老款的ROM空间不够的手机就很不友好。

基于以上的问题我们将原先的清单文件改成class文件,将应用启动相关的部分归为一个Dex,不相关的归为另外的Dex,这样启动速度就能得到提升,因为在安装时Dex就做了优化。

多进程

我们在进程的相互调用间添加了封装层,像使用本地能力一样使用跨进程的能力,包括远程接口转本地接口、远程拉起、重连和状态恢复。另外为了保证各组件能力能够正常运行,让组件自适应选择进程。

工程结构

这里的壳工程无任何代码,仅有脚本及配置文件,且只有唯一分支,一般不做修改。另外壳工程仅集成打包、集成调试时使用,不使用repo、git submodule。

业务组件中的Bundle可独立编译调试,打包产物有:测试apk、组件apk和aar,这些产物都会被上传到Nexus私服。

有问题可以在评论区讨论,以上为所有分享内容,谢谢大家!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT大咖说 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档