在AnDevCon的尾声, Doug Bateman主持了一个小组专注于如何才能开发一个扩展到全球数百万用户的Android应用程序。内容包含团队管理、测试和可测性设计、功能和发布管理、支持、开源贡献和可选架构等等。
该活动是由NewCircle Training组织并分享了以下专家的见解:Howard Harte from Cyanogen, Inc.; Jake Wharton from Square; Ty Smith from Twitter’s Fabric team; Juan Gomez from Eventbrite; Mike Hines from Amazon; Larry Schiefer from HiQES; and Dave Smith from Possible Mobile.
你是如何管理团队来支持大量的功能开发?
Ty简短地描述了Twitter Fabric团队从最初15人到Twitter收购Crashlytics后增长到60人如何负责许多的功能开发。总之,他们的组织保持不变是基于围绕独立功能创建较小的团队,然后确保这些团队至少每周进行交流。Juan强调自动化测试等过程的重要性,以确新团队成员提交的代码不破坏任何东西。
在将新功能推向海量用户之前你们是如何进行测试的?
根据Mike的说法,你不必将一组更新一次性地推向所有用户。你可以将一个更新推向一小部分用户。亚马逊使用一个内部框架来做A/B测试并能够找出哪些功能使用率下降,通过它就能确定将哪些功能推向所有用户。Ty,从另一方面来说,在开发SDK的时候A/B测试不是一个好的选择,因为开发人员期望更多地是稳定性,他们不喜欢新功能推送多来后一段时间后被取消。所以,从这方面讲,这完全决定于开发人员的反馈、与开发人员合作和重点人群等等。
你们的测试策略是什么?你们使用哪些工具?
在Howard的情况下,考虑到CyanogenMod支持一百多种设备,重度测试依赖于用户在自己的设备上使用它并进行反馈。Jack解释说,在Squre进行三种测试:在提交到主仓库之前要进行单元测试(数千个),通过异步运行慢速的机器测试来检测app的各个流程,最后是手动测试。有趣的是,Square的开发人员尝试使用他们的app模拟所有咖啡和午餐的购买。Juan再次强调了自动化测试的重要性,尽管他们也依赖于专门的QA团队。他们曾经使用Robotium作为工具,而是现在切换到了Espresso。
在回答观众提出的一个问题时,Jake提出了自己对于Robotium的看法,它是围绕基本的Android Instumention API的包装,所以它并没有解决你在测试异步操作时的基本问题。例如你不应该进行一个新的测试直到确保所有与前一个相关的任务已经完成。Espresso,从另一方面来看,采用了一种新的方式,即在清除了主循环的所有消息之后就可以进行一个新的测试。除此之外,他还说,如果你使用了与网络相关的library,你可以这样说:不要进行新的测试,直到没有网络活动。Espresso还有一些明确的API来使得你能够进行更高级别的测试。
在Fabric,Ty说,他们正在从JUnit迁移到Robolectric。Robolectric提供了不需要与Android框架进行深度交互的最快的方式去进行测试。在Android Framework是必须的地方,它通过创建shadow classes来和contexts和activities进行交互从而更好地完成工作。Robolectric能使得测试运行地很快,因为它运行在本地VM上,这非常重要因为Fabric团队在CI流程内的每次提交都进行单元测试。在设计方面,Ty介绍了他们在代码架构方面的努力,代码的高可测试性正是归功于它,基本上遵循单一职责原则,mocking classes,例如网络访问classes,从而使得基本可对一切独立测试。
Jake插入再次说,他们在一些必须和bundle或者intent再或者一些UI Views交互的情况下同样使用Robolectric。在这样的情况下,通常的做法是将核心代码包装进interface,由此就可以被JUnit测试。Robolectric,相反,使得能够通过shadow classes直接调用该代码。Square,Jake继续说,一直在接触Robolectric并在将要发布的下一个版本中减少shadow classes的数量,目的是使用尽可能多的真实Android代码。它主要的优点是更接在Android设备上真实地操作。最后,Jake提出了人们为何总是想方设法使用Robolectric在JVM进行所有的测试,因为它很快,但是这不是Robolectric的初衷。对于Jake来说,最大的优点是它提供了一个安全网和一些代码位所以你能够轻松地通过一些Android superclass运行你的代码。
你如何设计你的程序的可测试性?
Juan说,理想的情况是,你想要通过架构一些东西使得通过一些mocking的帮助就可以进行自动测试。有一些设计模式和libraries能够帮助解耦你的代码使得它有更高的可测性。在Eventbrite,他们用自己的框架做mocking和依赖注入,同时他们也在调研Mockito。Juan说,有时候,当有地方与Android framework交互的时候得到一个干净的单元用来测试并非易事,但有办法使这个过程不那么痛苦。
Ty接着说,在编写一个SDK时,他们不能使用依赖注入模式,基本上是由于要保持尽可能轻量化的意图,使用像Dagger这样的依赖注入工具不符合需求。当有与Android activities或fragments进行交互时,Fabric的开发人员正在尝试将业务逻辑与activities本身解耦,因此前者可以在隔离中进行测试。根据Ty的说法,你要尽可能地将activities排除在测试之外,这就是他们通过一个单例controller将activities和它们的依赖绑定在一起的意图。
最后,Jake提供一个稍微不同的观察角度,可测性设计是重要的,但也需要在你用来测试的抽象、它们的数量、mocks和最终的目的也就是发布你的app之间找到平衡。所以你也想做一些简单的事情将事情完成。你想抽象,你想要一个干净的分离,但有时你只是把一些代码放在那里去使用,也许你可以返回来再提高它。因此,可测性设计可以看作是一个渐进的过程。
如何在嵌入式级别进行测试?
Larry说,如果你在嵌入式级别工作,使用内核级别的驱动程序,或HAL,你不会有和在JVM中可用的相同的框架或模式。在他的公司,他们尝试使用相同的模块化原则来构建驱动程序或libraries并抽象成组件使得能够提取到一个专有的测试框架。对于驱动程序,他们把它们放在内核空间,并依赖于一系列的应用空间测试,所以他们知道的驱动程序在内核空间是可靠的。
你在使用什么替代的设计方法?
Jake讲述他们如何跳上使用fragments的行列来管理自己的用户界面,但发现它试图为太多人做太多的事情,对于如何做事它没有足够的“能力”,同时它很复杂并由许多毛病。最后,当他们明白自己实际上在通过试图使用一个单独的activity来管理一堆fragments来滥用这个系统的时候,他们移除了它。这限制了系统,所以他们决定执行自己的代码来管理视图。事实上,fragments只是一种管理你的视图的方式,驱动它们显示或隐藏。这使得Square工程师可以简化他们的代码,每一个新的版本可以让他们看到他们的崩溃率下降,这得感谢摆脱了fragments。Jake说,当你在一段时间中只需处理几个的时候,fragments可能是合适的。
有人在开发apps的时候使用反应式编程或者reactive java?
Jake再次率先表达了他使用RxJava的感受。简单地说,问题是,RxJava是一个框架,而不是一个library,这意味着你要在你的app中做很多工作来整合其API,你几乎绝对不希望它在你的activities、views和services中,因为它实在是太多了。在Square,他们使用内部helpers也使用RxAndroid,它的部分属于RxJava。RxAndroid将使RxJava的异步观察模型更容易接入Android的世界。
当你有世界范围的用户时,你如何适配Android?
关于通过本土化与国际化来支持全球用户的使用的重要性,Mike给出他的观点。这到头来体现在准备好例如从右到左书写支持,或像德语一样可以有非常长的词语能够让任何用户界面无效。抽象并使用资源文件也很重要。Mike说支撑起一个庞大用户基础的有趣的一面是支持人员和工程师之间的互动。支持人员通常可以为你所开发的功能提出有趣的用户故事,但随着规模的增加,他们也会建议使用从未想到的一些功能。但有时,那些新的故事真的很棒!
对Ty来说,当支持一个全球用户基础,设备和操作系统碎片化成为一个重要的因素,因为你会希望你的SDK支持最广泛的设备,但是你没有选择他们。因此,能够逐步降低你的功能同时使用最小量的资源来运行是很重要的,特别是对于新兴市场。Juan强调了同样地概念,他总是给应用程序在低分辨率或缓慢的设备留有余地,因为很多美国以外的用户就是这样的。此外,Howard说,通常哪些地方的设备没有太多内存。
你能介绍一下你的组织如何与开源社区进行交流吗?
Mike说,在亚马逊,他们有一个小组负责处理开源贡献和回馈开源社区。会有一个程序,工程师将他们想要回馈提交的代码提交给亚马逊的律师,所以他们可以检查任何涉及的知识产权。Mike说,这是一个非常棘手的业务,所以不要让工程师当律师!
Jake提供了相当不同的观点:在Square,这个过程完全是工程师驱动的。他们也有一个合法或许可审查,但没有人会说:“嘿,这看起来不错,你应该开源。”Square没有正式的程序,除了为了开源使用共同审查以评估代码,最终,如果它被认为是适当的,就会被提交到开源仓库。Square和开放源社区之间的关系是紧密的,既是由于Square有许多贡献,也由于外部用户提交的pull requests。杰克说,他们甚至为了感谢一些人的pull requests而雇佣了他们。
Howard说,Cyanogen也与开源社区有很好的关系,约有9000人有来自社区的贡献。关于开源社区的一个好处是你可以审查它以确保它是安全的并且不是为了牟利而开源。
你认为什么是不可缺少的开源库?
Dave解释说,他的公司没有贡献大量的开源代码,虽然他们使用了很多。当然,他们很注重代码的许可证,所以有时候他们不匹配许可证就不得不重新实现。Dave说,他们的大量使用一些Square的libraries例如Picasso、Retrofit和Dagger。
Larry认为,让客户了解可能使用一个给定的开源库是很重要的,所以他们明白有什么含义,并给他们一个机会去决定什么对他们是最好的。
如何分析有助于开发更好的apps?
Ty指出,有很多不同的分析方法。例如前面提到A/B测试可以让你对产品的功能做出重要的决定。Ty说,Fabric是一个强大的分析平台,虽不像Google Analytics那样灵活,但会为高层次的决定提供足够的信息,例如,用户数,崩溃数等等。
对Jake来说,app的分析显然是有好处的,但对他来说,收集他们用作运维也很重要。他解释说,为调查运维调用,他们记录了每个功能调用的频率,所以当他们检测到一个给定功能的高调用率,他们可以尝试提高它,从而提高应用程序和运维。这种方法也有助于在一个应用程序的用户基数增长的时候保持运维水平不变,并且不需要雇用更多的运维人员。
最后Dave增加了他的观点,观察分析对他们的客户是非常重要的,基本上是因为分析帮助推动收入,他们经常在一些应用程序种使用最多七个分析包。分析是他们决定apps应该向哪个方向走的数据来源。
你最喜欢的学习安卓的资源是什么?
Ty说,Android文档是非常棒,并且还有很多杰出的书籍,他最喜欢的一本是“The Busy Coder’s Guide to Android Development”。Haward说,网上也有几个主题的丰富的介绍。
对于杰克来说,很难找到很好的高级内容。他说,对于初学者来说有很多好东西,但有时也没有太多关于新框架的信息或者更深入的资料。所以,当你到达一个中间的水平,很难找到资料来更进一步提高自己。
Larry、Mike和Dave都同意导师帮助新手快速进步的重要性。在他们的公司会配对初级开发人员与高级开发人员从而得到快速提高。
怎样才能让我们的设计师了解Android?他们似乎只了解iOS…
Dave有一个相当激进的方法,建议设计部门的几个人使用Android手机一段时间。他认为这是设计师理解交互模型而不只是看截图的唯一方式。另一方面,Juan强调开发人员努力给设计师提供正确的信息的重要性。他回忆起一个例子,他买了几本谷歌的material设计书,并给了他们的设计师。
这里有线上的小组讨论记录完整版。
关于作者
Sergio de Simone是一名iOS独立开发者和顾问。Sergio作为软件工程师在不同的项目和公司中工作超过了15年,包括不同的工作环境例如Siemens、HP和小的初创公司。目前,他专注于移动平台的开发和相关的技术。
查看英文原文:Lessons Learned by Scaling Android Apps - AnDevCon Panel Summary
全能程序员交流QQ群290551701,群内程序员都是来自,百度、阿里、京东、小米、去哪儿、饿了吗、蓝港等高级程序员 ,拥有丰富的经验。加入我们,直线沟通技术大牛,最佳的学习环境,了解业内的一手的资讯。如果你想结实大牛,那 就加入进来,让大牛带你超神!