InfoQ最近采访了Pinterest核心UI团队的Android工程师Christina Lee,讨论了Pinterest对Kotlin的采用情况、Pinterest在采用过程中面临的挑战、从中总结的主要经验教训、从Java过渡到Kotlin的技巧,以及她即将在KotlinConf 2018上进行的演讲主题Representing State: the Kotlin Edition。
InfoQ:请你简单介绍一下自己和你在Pinterest的角色(特别是在支持采用Kotlin方面)。
Christina Lee:我是Christina,Pinterest核心UI团队的一名Android工程师。几年前,我所在公司被Pinterest收购,我也因此加入了Pinterest。在之前那家公司,我有多年完全自由使用Kotlin的经验。因此,当我开始加入Pinterest时,很自然地将这种经验和热情带入我的新工作中。在Pinterest的几个星期内,我被授权在我当时负责的功能上试用Kotlin(Android的视频支持)。这项工作以及一些相关的内部倡导工作,最终导致我们的Android应用程序大量使用Kotlin。今年,我们的新策略是将Kotlin作为Android的首选开发环境。
InfoQ:Kotlin的哪些方面促使你成为Kotlin倡导者?
Lee:Kotlin并没有彻底偏离Java,因为它们都为JVM生成字节码。它之所以如此好用,是因为它本质上是内置了最好的编程实践的另一个Java版本,用它做对事情比做错事更容易。开发人员能够快速、自信地进行编码,并消除了使用Java时所需的大量工作。因为编码就像写作一样,是一种富有表现力的艺术形式,有了这样的工具,你就可以清楚、快速、准确地表达自己的想法。当你将其与行业领先的语言工具和互操作性以及JetBrains团队表现出的全面而深思熟虑的语言领导力相结合时,很难不爱上它。
InfoQ:Pinterest在采用Kotlin期间面临了哪些组织层面的挑战?Pinterest是如何克服这些挑战的?
Lee:在采用Kotlin期间我们遇到的最大挑战之一是持续出现的Kapt(Kotlin注解处理器)和其他与构建相关的问题。CI构建环境经常出现错误,并且在本地切换分支时经常出现构建失败,因为构建状态未能被正确清除。因为这些问题的存在,有些高级工程师甚至提议放弃这门语言。采用一门年轻的编程总是会伴随着日益增长的痛点——Kapt本身存在固有的big——而这些bug不是我们自己能够解决的。随着Kapt和相关构建工具得到改进,这类问题也得到了解决,但在很多工程师的心目中,Kotlin已经与构建不稳定性联系在了一起,他们对这门语言有了偏见。
不过,有一部分原因是第一次采用新技术时都不可避免会出现的盲点。这些是我们有能力在内部解决的问题,我们通过培训来解决这些问题。比如,我们在编译时会遇到的一个常见的问题,即开发人员会忘记导入语句或者犯了一些与Kotlin无关的错误,但Kapt在Android Studio中输出信息的方式导致很难在构建输出中找到这些错误。教会他们可以在哪里找到真正的编译时错误,这样以后他们就可以自己找到这些错误。为了解决这类问题,我们的团队专门设立了几个Slack频道,专门用于询问有关Kotlin或构建的问题,并开创了一个先例,即欢迎提出任何问题,这些问题都会得到回应。向团队讲授Kapt等新组件的工作原理、有用的错误信息类型以及从哪里开始寻找解决方案,这对缓解Kotlin的痛点大有裨益。
InfoQ:你是如何说服你的团队使用Kotlin重新构建整个Android代码库的?
Lee:在Pinterest,我们的策略是优先使用Kotlin,但并不是只能用Kotlin。也就是说,所有的Pinterest Android开发人员必须知道如何阅读、编写和理解Kotlin,因为它是我们公司主要的Android开发语言,所有新代码都必须使用Kotlin编写。不过,我们也强调,不要去转换那些没有合理理由去转换的现有Java代码。这背后有双重的逻辑。首先,“如果没有bug,就不要去修复它”。如果某些代码可以正常运行,而你修改了它,可能会破坏现有的行为。除非将代码转换为Kotlin有明显的ROI,否则最好让工作组件继续不受干扰,直到有必要引入其他变更。其次,将Pinterest代码库中的每个文件都转换为Kotlin需要大量的时间,这是一笔巨大的投入。在我们看来,花费开发人员这么多时间可能得不偿失。
InfoQ:Pinterest在采用Kotlin时学到的最大教训是什么?
Lee:作为一个正常人,我也有一点叛逆性格。我不喜欢别人告诉我要做什么,所以我认为,在决定是使用Kotlin还是Java时,每个Pinterest的开发人员都应该参与做出决定。从技术角度来看,由于Kotlin与Java之间卓越的互操作性,这完全是有可能的,但它并未考虑到人性。人们不喜欢不确定性,当一个团队很容易形成不同的阵营(Java团队、Kotlin团队),那么有关API设计或可空性模式等问题的对话就很容易变成“我们与他们”之间的对立。通过让语言在公司内部有机地传播,我们最终达到了一个平衡点,大部分热衷于尝试使用新语言的开发人员都采用了这门语言,其他不感兴趣的开发人员可以选择退出。
如果时间足够,这种有机路径最终可能会改变所有开发人员,但在很长一段时间内,团队将处于分裂状态。当我们的平台负责人Sha Sha Chu(与其他工程主管一起)决定将Kotlin作为首选语言时,我们担心人们会因为他们的选择被忽略而感到不安。我们针对这一过程进行了讨论,但在政策推出后,团队凝聚力和幸福感似乎大幅提升。根据这一经验,我认为Pinterest最大的经验教训是在探索的早期阶段要提供明确和直接的指导,以最大限度地减少团队处在分裂状态的时间。作为一个团队,我认为我们已经更加深入地意识到进行全面测试的价值,然后迅速回归单一的路径(要么完全放弃,要么全力以赴)。
另一个重要的经验是Kotlin(尤其是早期)的构建有点不稳定,直到我们分配了足够的资源来监控和解决出现的问题(特别是与CI和Kapt相关的问题)。这些问题都不是不可克服的,但它们确实需要一些深思熟虑的调查,这些都需要占用工程师的时间。我们在开始时没有为此分配适当的资源,导致早期在诊断构建失败原因时所花的时间超过了预期。在为这个问题分配了专用的资源之后,我们就能够在相对较短的时间内修复问题。针对待命工程师的投入带来了巨大的回报,在未来推出新的框架部署时,我们可能会尝试做类似的事情。
InfoQ:关于从Java到Kotlin的转换,你有哪些有用的技巧可以分享?
Lee:关于Kotlin的入门(包括来自Huyen Tue Dao和我的演讲)现在有很多资源可参考,几乎任何学习方式都应该能够找到能够简化从Java过渡到Kotlin的内容。除了各种免费讲座和教程之外,IntelliJ系列IDE也是最好的学习工具。它们提供了复制和粘贴Java代码并将其自动转换为Kotlin的功能。这样就可以粗略地知道Java概念将会被翻译成什么样的新语言,就像在学习新语言时,Google Translate可以为你提供粗略的语言翻译。编辑器可能会给出一些不正确的建议,但这些建议仍然会带有有用的错误信息,可以在StackOverflow上轻松查找问题的答案。
此外,代码评审很关键。与大多数编程语言一样,在Kotlin中也有很多方法可以完成代码评审任务。随着人们逐渐加入Kotlin的行列,我们指定了特定的Kotlin评审人员检查来自新手的拉取请求。他们的作用不是判断底层代码的技术健全性,而是关注语言的使用方式以及它们是否符合最佳实践和我们推荐的风格指南。这些代码评审促进了组织学习的传播——写代码的人收到了建议,评审人员在提出问题和意见时必须更深入地思考语言本身,讨论内容被记录下来,其他团队成员可以阅读或参考它们。
InfoQ:你在KotinConf 2018的演讲内容是什么?你为什么要选择这个主题?
Lee:我今年在KotlinConf上的演讲是关于Kotlin语言特性如何让我们能够更轻松、更准确地定义应用程序的离散状态。我对这种定义良好的数据结构主题充满热情,因为它在代码评审和架构讨论中经常被忽略,但却是无数问题和错误的根源。要保持一间干净的房间的整洁是相对容易的,与之类似,在项目开始时投入时间来设置和维护逻辑数据结构可以更容易让代码做正确的事情,这对开发者来说是速度方面的胜利,对用户来说是稳定性方面的胜利。
InfoQ:感谢你抽出宝贵时间接受我们的采访。你还有什么想与InfoQ读者分享的吗?
Lee:Kotlin最吸引我的是我不记得有哪个开发人员在彻底采用这门语言后有感到后悔的。我使用Swift的经历告诉我,人们喜欢这门语言,但由于构建时间、互操作性或语言版本迁移方面的问题,导致他们对切换到Swift感到遗憾。根据我的经验,批评Kotlin的声音主要来自那些尚未开始使用这门语言的人,而只有极少数是来自那些已经深入使用这门语言的人。有几个人跟我争论好几个月是否要采用Kotlin,但是在转向Kotlin几个星期后,他们来到我的办公桌前,告诉我说,Kotlin让他们再次激起了他们开发Android的热情。我知道,最初不愿意采用Kotlin的开发人员现在在抱怨他们需要切换回Java维护旧代码。在我看来,这种能够吸引最不情愿的开发人员的能力是对语言本身、围绕它的工具以及引导采用这门语言的团队的最好佐证。
有关Pinterest采用Kotlin的更多信息,请访问Pinterest工程博客。读者还可以访问InfoQ Java主页,了解所有与Java相关的新闻。