【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

Kotlin 与 Java 之争

  • 2017-09-21
  • 本文字数:6600 字

    阅读完需:约 22 分钟

Kotlin

Kotlin 是一门相对比较新的 JVM 语言,JetBrains 自 2011 年以来一直在积极地开发。

多年来,该语言在 Android 社区受到的关注度越来越高,并在 Google IO 2017 大会之后成为 Android 开发领域最热门的话题。这次大会宣布,Android 正式支持 Kotlin。

遗憾的是,虽然已经有许多关于 Kotlin 的文章,但并没有多少客观信息,许多开发人员仍然在苦思冥想,迁移到 Kotlin 是否是一条正确的道路。

在本文的剩余部分,我将尝试提供一个在将 Kotlin 作为 Java 的替代项进行评估时需要考虑的更完善的事项清单。

Kotlin 与 Java 的主观比较

“Kotlin 比 Java 好”,“Kotlin 可读性比 Java 强”,“Kotlin 开发速度比 Java 快”,类似这样的陈述缺少相关准确数据的支持,所以都归为主观看法一类。

主观看法是个体开发人员在对与 Kotlin 或 Java 相关的主题作出一个或多个主观判断时形成。

开发人员的主观判断存在如下问题:

  1. 没有与主观判断相关联的量化指标。
  2. 主观判断存在很大的偏见。
  3. 主观判断的偏见在开发人员之间存在很大的差异。

由于没有与主观判断相关联的量化指标,建立在这些判断基础上的观点只是反映出了开发人员之前就有的偏见。不同的开发人员可能有着截然不同的偏见,因此,有开发人员认为 Kotlin 是不错(或糟糕)的 Java 替代者并不意味着其他开发人员也这么认为。

而且,由于没有客观指标,主观分歧就无法客观地消除,这经常会导致“口水战”。

主观判断的谬误

为了说明主观判断可能导致的误解,让我们仔细审视一个非常常见的主观看法:

Kotlin 可读性比 Java 强

——Web 上无数的文章

理论上讲,可以设法设计一个度量 Kotlin 和 Java 之间可读性差异的实验,但据我所知,没有任何人真正地开展这样一个实验。因此,截至目前,这个看法没有任何数据支撑。

Kotlin 的语法是许多开发人员称赞其可读性的一个原因。他们的逻辑如下:

Kotlin 有更好的语法,因此它的可读性更强

——Web 上无数的文章

在这句话中,“更好的语法”又是一个主观判断,本身就值得商榷,但为了避免争论,我们假设 Kotlin 的语法确实更好。但是,这就能说明 Kotlin 的可读性更强吗?

为了观察语法对可读性的影响,请阅读下这段“文本”:

开始的时候,这段“文本”很难理解,但慢慢地,读起来会越来越容易。如果你再读个两三遍,那么你根本就不会再注意它是由非标准的字母组成的。准确地说,字母的替换不是句法变化,但这确实可以说明,对于熟练的读者而言,外观很少会成为可读性的障碍。

我们也可以把这个例子扩展到自然语言。我了解三门截然不同的语言。虽然它们之间差别很大,但我发现,当我不理解文本中使用的单词时,阅读任何一种语言的文本都非常困难。一旦我认识构成文本的单词并熟悉上下文——无论它使用了哪一种语言,我读起来都不困难。

因此,对我而言,语言的选择并不会影响可读性,只要理解内容和上下文就可以了。

编程语言同样如此。

当我们开始使用一门新语言,我们会有一段时间很难理解源代码,需要认真领会每个句法结构。但是,随着我们阅读和编写特定语言的代码越来越多,我们逐渐就熟悉了那门语言的语法,到某个时候,我们就不会再注意句法结构了。

我自己在多门语言上有过这种体验:Verilog、Bash、Perl、Tcl、Lisp、Java。

根据我使用上述语言的经验,我可以告诉你:如果一个人适应了 Lisp 的代码,并且不会再注意到小括号,那么跟 Java 比起来,Kotlin 的语法完全不能对可读性产生不可忽视的影响,即使它“更好”。

既然我们在讨论这个话题,我就分享下自己对于影响源代码可读性因素的主观判断。

在读过其他开发人员使用许多语言编写的代码后(上面只罗列了我在某个阶段精通的语言;我用过的所有语言比这个多),我得出如下结论:如果开发人员使用某一门语言可以编写出可读性和可理解性都很好的代码,那么他们通常也可以使用其他语言编写出可读性和可理解性都很好的代码。

因此,我根据自己的经验作出的主观判断是,源代码的可读性和选择的语言无关,那取决于代码编写者的技能和读者的技能(编写者的技能更重要)。

如果你仍然认为主观看法具有代表性,那么至少阅读并思考下 Robert “Uncle Bob” Martin 在这篇博文中的观点。

Kotlin 与 Java 的客观比较

与主观比较相反,客观比较使用量化指标来度量或评估 Kotlin 比 Java 有优势的地方。

用一套标准客观地证明一门编程语言是否强过另一门,这种想法非常有吸引力,但是有个问题:据我所知,没有与编程语言相关的通用客观指标。

考虑到我们无法进行精确的直接比较,那我们能否客观地比较 Kotlin 和 Java 呢?能!我们仍然能评估从 Java 切换到 Kotlin 所带来的积极和消息影响的程度,然后比较结果,并讨论它们的影响。

为了评估 Kotlin 所能带来的最好结果,我们将做如下假设:

  1. 开发人员可以立即切换到 Kotlin;
  2. 切换到 Kotlin 后,开发人员不会损失任何技能(例如,有两年 Java 开发经验的开发人员可以神奇地获得两年的 Kotlin 开发经验);
  3. Kotlin 和 Java 一样稳定;
  4. Kotlin 工具和 Java 工具一样成熟。

事实上,上述假设没有一个是合理的,但在开始的时候,有一个理想化的设定便于说明。然后,我们会抛开这些假设,讨论真实世界的效应所带来的影响。

Kotlin 最佳结果估计

遵循 Steve McConnell 在 _Code Complete_ 一书中提出的模式,我们可以将软件构建活动分解成三个子活动:详细设计、编码与调试、开发测试。

Kotlin 对于详细设计子活动没什么影响(这项活动通常独立于选用的特定的面向对象编程语言),因此,在这一部分,Kotlin 和 Java 需要付出同样的努力。

据我所知,对于开发测试子活动,Kotlin 也没有提出什么革命性的东西。因此,开发测试需要付出的努力也一样。

就剩编码与调试子活动了。

如果我们用 Kotlin 替换 Java,那么我在编码与调试活动中可以节省多少工作量?这个问题很难回答,不同程序员之间这一数值会有很大差异(有些程序员使用 Java 更高效)。不过,既然我们在评估最好的情况,我们不妨假设从 Java 切换到 Kotlin 可以将开发人员在编码与调试阶段的生产力平均提高 10%。

10% 的生产力提升是一个不现实到令人吃惊的数值。即使我们在文本编辑器中手工输入所有代码,那也是不现实的。考虑到现如今 IDE 的功能,这一数值更是不现实。考虑到有些开发人员使用 Java 更高效,这个数值就毫无道理了。

我不介意使用这样一个既不现实又对 Kotlin 评估有利的数值,因为我知道,不管它对评估结果产生了怎样不切实际的积极影响,一旦我们抛开其中部分“理想的假设”,由此带来的负面影响会抵消掉那些积极影响。

那么,在编码与调试方面提升了 10%——我们把产品交付给客户的速度快了多少?

下面这张图片来自 _Code Complete_ 一书,展示了软件项目的各种活动所占的比例:

小项目以构建活动为主。大点的项目需要更多架构、集成和系统测试工作来保证项目成功。这张图没有显示需求,因为和其它活动不一样,需求工作不是直接的程序功能。(Albrecht 1979; Glass 1982; Boehm, Gray, and Seewaldt 1984; Boddie 1987; Card 1987; McGarry, Waligora, and McDermott 1989; Brooks 1995; Jones 1998; Jones 2000; Boehm et al. 2000)
Code Complete,第二版

根据来自 _Code Complete_ 的这张图片,在一个较大的软件项目中(多于 10K 行),编码和调试只占项目总工作量的不足 20%。

因此,在一个较大的软件项目中,我们所假设的编码和调试效率提升 10%,只能将完成项目所需的总工作量缩减 2%。

例如,一个需要 5 人年才可以完成的项目(这是相对比较大的 Android 项目),总工作量的 2% 为:

复制代码
5 人 - 年 * 12 * 4 * 5 * 0.02 = 24(人 - 天)

如果我们真得能够把项目工作量减少 24 人 - 天,这会是一个从 Java 切换到 Kotlin 的很好的理由。然而,我们应该还记得,上述积极评估是在理想情况下得出的,其基础是不切实际的假设。

在真实世界里,切换到另外一门编程语言会产生不可避免的影响,我们将评估这种影响,并与上述理想化评估作个比较。

开发人员准备

为了评估最好的情况,我们假设开发人员可以立即从 Java 切换到 Kotlin。

实际上,虽然 Kotlin 和 Java 非常类似,但开发人员仍然需要花一些时间来学习,然后再花一些时间来调整开发实践和工具。准备时间因人而异:有些开发人员可以三四天完成切换,其他人则需要 10 天甚至更多的时间。

让我们乐观一点,平均每个开发人员只要 5 天就可以从 Java 切换到 Kotlin。

一个需要 5 人年才能完成的项目会有 3 到 5 名开发人员(最好的情况下)。平均每个开发人员的切换时间为 5 天,这样,一个项目总计就需要 15 到 25 个人天的切换时间。

切换到 Kotlin 所节省的工作量(乐观估计)与切换所需的总工作量似乎差不多。

开发人员技能损失

使用一门特定的编程语言高效工作的能力是一项技能。

我们已经讨论了这项技能的其中一个方面(代码可读性),但还有许多其他方面。当从一门语言切换到另一门时,与旧编程语言相关的部分技能可以运用到新语言上,但该技能的其他部分会损失掉。

为了评估编程语言技能损失对项目工作量的影响,我们将使用源自 Cocomo2 评估模型的“语言与工具体验”因子:

语言与工具经验(LTEX)
该指标用于衡量开发软件系统或子系统的项目团队使用编程语言和软件工具的经验。软件开发包括借助工具完成需求、表现形式设计与分析、配置管理、文档提取、库管理、程序样式与格式化、一致性检查、计划与控制等等。除了项目编程语言经验外,项目支持工具集的经验也会影响开发工作。经验低于 2 个月会获得一个很低的评级,有 6 个月或多年的经验则会获得一个很高的评级,见下表:

Cocomo 2 模型定义手册

例如,假设我们有一个 Java 开发团队,团队成员平均有一年的经验,我们想迁移到 Kotlin。

由于 Kotlin 和 Java 非常像,与许多 Java 工具兼容。我们可以乐观地假设,在经过初步的准备后,开发人员就可以归为有 6 个月开发经验这一类(而不是低于 2 个月)。根据这个假设,为了评估技能损失所导致的额外工作,项目的额定工作总量应该乘以 1.09。

一个需要 5 人年完成的项目,配备了平均具有 1 年 Java 经验的开发人员,切换到 Kotlin 所导致的额外工作达到了令人咂舌的 108 人天。

技能损失所导致的额外工作是切换到 Kotlin 所缩减的工作的四倍。

语言和工具的稳定性和成熟度

有个普遍的说法,就是 Kotlin 是一门生产就绪的语言。这种说法也许是有道理的,因为 Kotlin 已经用在了若干项目里。

不过,与 Java 相比,Kotlin 是一门并不稳定的年轻语言。

有些开发人员认为,Kotlin 的不稳定性是个优势——语言在演进,可以更快地提供新特性,更快地改进。在我看来,他们对于这件事的看法过于简单。

下面是 Kotlin 1.1.4 发布说明里的第一句话(写这篇文章时的最新版本):

修复 IntelliJ IDEA 的一项重大性能衰退
——Kotlin 1.1.4 发布说明

我不知道这是什么样的衰退,有多少项目受到了影响,但我的大脑自动将“重大性能衰退”这个搭配翻译成了“浪费了许多小时的开发时间。”

此外,如果你读一遍发布说明的评论,你就会注意到,许多人遇到了迁移问题。在 1.1.2 版本的评论里,甚至有人指出,这个“补丁”发布引入了破坏性(向后不兼容)的修改。

相比之下,如果你读一遍 Oracle JDK8 的发布说明,你就会发现,它比较稳定。大多数修改都是安全改进方面的。

因此,与 Java 相比,Kotlin 是一门不稳定且不成熟的语言——迁移到 Kotlin 会对项目产生怎样的影响?为了回答这个问题,我将使用来自 Cocomo 2 评估模型的“平台波动性”工作因子:

平台波动性(PVOL)

这里使用“平台”一词指代软件产品执行任务时调用的复杂硬件和软件(OS、DBMS 等)。如果开发的软件是一个操作系统,那么平台就是计算机硬件。如果开发的是数据库管理系统,那么平台就是硬件和操作系统。如果开发的是网络文本浏览器,那么平台就是网络、计算机硬件、操作系统和分布式信息库。平台包括支撑软件系统开发所需的编译器或装配器。如下表所示,如果平台每 12 个月才有一次重大变更,则评级就会很低,如果每 2 周有一次重大变更,则评级就会很高:

Cocomo 2 模型定义手册

你可能已经注意到,编程语言并没有直接出现在该工作因子的描述里,但出现了编译器和装配器。在我看来,这段描述没有显式包含编程语言,是因为得出 Cocomo 2 模型的所有项目都使用了稳定的语言。

由于编译器和装配器属于这个工作因子,所以我们也可以推断出编程语言及相关工具。

根据平台波动性的这种评级范围,Java 的评级应该是“very low”,而 Kotlin 的评级应该是“low”或更高。Kotlin 的评级可能会更高,因为它内部依赖于其它工具,增加了出现兼容性问题的风险。

由于“very low”没有提供工作因子,所以我们需要估计。

看下该因子从“very high”到“low”的评分递减规律,我认为,我们可以放心的假设,“very low”的评分不高于 0.82。

基于这些假设(有利于 Kotlin),如果一个项目需要 5 人年的额定工作量,那么使用 Kotlin,工作量就变成了 1044 人天,而使用 Java 的总工作量是 984 人天。

选择使用 Kotlin 而不是 Java 实现这样一个项目会使总工作量增加 60 人天。

语言和工具不稳定所导致的额外工作是切换到 Kotlin 所缩减的工作的 2 倍多。

综合所有因素

我当成例子来讨论的项目需要 5 人年的额定工作量。

根据上述评估,如果该项目由平均具备 1 年 Java 开发经验的开发人员使用 Java 实现,则总工作量为:

复制代码
5 人 - 年 * LTEX(Java) * PVOL(Java) = 984 (人 - 天)

如果同样的项目由几乎没有 Kotlin 开发经验的开发人员使用 Kotlin 实现,则总工作量为:

复制代码
5 人 - 年 * LTEX(Kotlin) * PVOL(Kotlin) * 0.98 + T_ramp_up = 1115 + 5 * N_developers (人 - 天)

据估计,选择 Kotlin 替换 Java 所导致的额外工作量为131 + 5 * N_developers (人 - 天)

评估注意事项

在评估讨论的过程中,我们得出了与 Kotlin 和 Java 相关的、便利的工作量单点值。

但实际上,单点值根本不是估计——它们只是猜测。真正的估计必须有一个相关联的不确定性。换句话说,估计表示可能性的范围,而不是单点值。

我们最终使用单点值代替了范围,那是因为我从估算范围里选择了最有利于 Kotlin 的值,将所有的估计都转换成了单点值。

例如,当讨论 Kotlin 对编码与调试活动的影响时,我从估计出的可能性范围 [-5%,10%] 中选择了最大的生产力提升值 10%。在其他情况下,当我们讨论开发人员切换到 Kotlin 的平均时间时,我从估计的可能性范围 [5 天,21 天] 中选择了最小的 5 天。

此外,我们使用了 Cocomo 2 估计模型专用的工作因子。这些因子并不是放之四海而皆准的真理,在最一般的情况下,应该也有相关联的不确定性。我赋给 Kotlin 的评级高于我实际上认为它应得的评级,我希望通过这种方式消除这种不确定性。

不用说,我们获得的单点值并不是百分百正确。为了得出更完整的估计,我们可以利用真正的估计进行 Monte Carlo 仿真。通过这项技术,我们可以观察可能结果的分布,弄清楚哪种结果最可能出现。

请记住,由于我们将估计压缩成了对 Kotlin 而言最为有利的单点值,所以其他可能的结果会显示出更大的 Kotlin 切换开销。因此,在所有可能的结果中,我们在上文描述的单点值是最有利于 Kotlin 的。

小结

在文章开头部分,我们展示了一些可能会对开发人员比较编程语言造成误导的主观判断。

接下来,我们讨论了客观比较编程语言存在的困难,并进行了一系列的估计,以便弄清楚 Kotlin 栈与 Java 栈完成软件项目所需的总工作量。在执行估计时,我们一直使用估计范围里最有利于 Kotlin 的值。

通过我们的分析,从 Java 切换到 Kotlin 似乎会导致完成软件项目所需的总工作量增加。

更多的工作意味着企业切换到 Kotlin 需要花更多的钱才能获得同样的功能,而用户需要等待更长的时间才能获得产品。

有些开发人员可能会吃惊,觉得这个结果不容易接受。

在考虑了所有的情况之后,谷歌最终决定支持 Kotlin Anroid 开发。对此,谷歌可能需要相当大的投入——谷歌云平台团队是不是没有人可以做类似的分析,从而弄清楚切换到一门新语言所带来的负面影响?

我认为,谷歌员工都是非常聪明的人,我相信他们在决定支持 Kotlin 之前已经进行了非常深入的分析。

在下一篇博文中,我们将讨论谷歌为什么要支持 Kotlin,即使是在通过简单的分析就可以知道那不利于 Android 社区的情况下。

查看英文原文 Kotlin vs Java The Whole Story


感谢覃云对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-09-21 19:0017055
用户头像

发布了 1008 篇内容, 共 374.0 次阅读, 收获喜欢 340 次。

关注

评论

发布
暂无评论
发现更多内容

C语言自定义类型 | AI工程化部署

AIWeker

c AI工程化部署

Wireshark中的ARP协议包分析

小魏写代码

测试用例设计方法六脉神剑——第一剑:入门试招,等价边界初探 | 京东物流技术团队

京东科技开发者

测试 测试用例 测试 单元测试

“软件赋能·链接未来”世亚国际软件产品博览会(世亚软博会)

AIOTE智博会

软件展会

拥抱未来:大语言模型解锁平台工程的无限可能

SEAL安全

平台工程 12 月 PK 榜 大语言模型

电子竞技将引发LED屏幕行业新一轮竞争

Dylan

电竞 电竞产业 LED显示屏 全彩LED显示屏 led显示屏厂家

用友电子凭证综合服务平台2.0重磅发布!

用友BIP

电子凭证

SQL 也能搞复杂时序查询?-使用 SQL 在 GreptimeDB 上做 Range 查询

Greptime 格睿科技

数据库 sql 时序数据库

哈工大副校长刘挺访问度小满 推进人工智能等方面技术合作

科技热闻

代购系统独立站的未来发展前景

Noah

探索 Tokio Runtime丨Fabarta 技术专栏

Fabarta

人工智能 rust 图数据库 rust开发者大会 ​Rust

数据库面试题从浅入深高频必刷「2024版」

王中阳Go

MySQL 数据库 后端 面试题 面经

专家观点∣用未来思考今天,ERP国产化价值替代的“五识”进阶能力

用友BIP

国产化价值替代

微软远程管理Microsoft Remote Desktop怎么样?好用吗?

Rose

Mac远程控制软件 microsoft remote desktop mac破解软件下载 微软远程管理

时间复杂度为 O(n^2) 的排序算法 | 京东物流技术团队

京东科技开发者

算法 排序算法 O(n^2)

ios-class-guard - iOS代码混淆与加固实践

雪奈椰子

springboot集成activiti工作流实际项目(自定义工作流)

金陵老街

企业服务大模型扎根生产一线,用友BIP为中国智造“再续新篇”!

用友BIP

企业大模型

高精度时序分析工具PP-TSv2!一站式解决电力负荷预测、设备异常检测等多场景任务

飞桨PaddlePaddle

人工智能 开发者 开发工具 技术干货 时序分析工具

springboot如何用jar包启动,同时为不同机房设置不同的配置文件 | 京东云技术团队

京东科技开发者

Java spring 后端 spring-boot jar包

如何在 Mac 上创造一个纯 Windows 环境

Rose

Parallels Desktop

高效会议指南:九种让你的会议更有价值的方法

PingCode

团队 会议

石磊:以人为本,精细运营 ,企业招聘管理的下半场

用友BIP

智能招聘

企业业务场景如何实现自动化连接?

RestCloud

AppLin 自动化连接

TinyVue 组件库助力赛意信息获得工业软件种子奖

OpenTiny社区

开源 前端 组件库

每日一题:LeetCode-41. 缺失的第一个正数

半亩房顶

面试 算法 数组 LeetCode 哈希表

关于组态图和组态图设计

2D3D前端可视化开发

组态软件 组态 组态图库 组态界面 组态工具

聊点技术|数据爆炸性增长,Bonree ONE存储如何做到稳如泰山

博睿数据

去哪儿“技术债”偿还实践:如何高效、低风险砍掉50%无用代码?

TakinTalks稳定性社区

云起无垠CEO沈凯文博士获评“2023年度技术突破者”奖

云起无垠

基于机器深度学习的交通标志目标识别

3D建模设计

人工智能 机器学习 目标检测 目标识别 虚幻引擎合成数据生成

Kotlin与Java之争_Java_谢丽_InfoQ精选文章