Kotlin与Java的主客观对比分析

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相关的主题作出一个或多个主观判断时形成。

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

没有与主观判断相关联的量化指标。
主观判断存在很大的偏见。
主观判断的偏见在开发人员之间存在很大的差异。
由于没有与主观判断相关联的量化指标,建立在这些判断基础上的观点只是反映出了开发人员之前就有的偏见。不同的开发人员可能有着截然不同的偏见,因此,有开发人员认为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所能带来的最好结果,我们将做如下假设:

开发人员可以立即切换到Kotlin;

切换到Kotlin后,开发人员不会损失任何技能(例如,有两年Java开发经验的开发人员可以神奇地获得两年的Kotlin开发经验);
Kotlin和Java一样稳定;
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个月或多年的经验则会获得一个很高的评级,见下表:

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

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

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

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

平台波动性(PVOL)

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

Cocomo2模型定义手册

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

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

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

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

看下该因子从“veryhigh”到“low”的评分递减规律,我认为,我们可以放心的假设,“verylow”的评分不高于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天。

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

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

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

小结

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

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

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

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

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

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

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

以上就是本文关于Kotlin与Java的主客观对比分析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出!

(0)

相关推荐

  • Kotlin 基础教程之注解与java中的注解比较

    Kotlin 的注解完全兼容 Java 的注解. 声明注解 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION) @Retention(AnnotationRetention.SOURCE) @MustBeDocumented annotation class Fancy 可以通过向注解类添加元注解(meta

  • Kotlin与Java的主客观对比分析

    Kotlin Kotlin是一门相对比较新的JVM语言,JetBrains自2011年以来一直在积极地开发. 多年来,该语言在Android社区受到的关注度越来越高,并在Google IO 2017大会之后成为Android开发领域最热门的话题.这次大会宣布,Android正式支持Kotlin. 遗憾的是,虽然已经有许多关于Kotlin的文章,但并没有多少客观信息,许多开发人员仍然在苦思冥想,迁移到Kotlin是否是一条正确的道路. 在本文的剩余部分,我将尝试提供一个在将Kotlin作为Java

  • java协程框架quasar和kotlin中的协程对比分析

    目录 前言 快速体验 添加依赖 添加javaagent 线程VS协程 协程代码 多线程代码 协程完胜 后记 前言 早就听说Go语言开发的服务不用任何架构优化,就可以轻松实现百万级别的qps.这得益于Go语言级别的协程的处理效率.协程不同于线程,线程是操作系统级别的资源,创建线程,调度线程,销毁线程都是重量级别的操作.而且线程的资源有限,在java中大量的不加限制的创建线程非常容易将系统搞垮.接下来要分享的这个开源项目,正是解决了在java中只能使用多线程模型开发高并发应用的窘境,使得java也能

  • Kotlin 与 Java基本语法对比

    Kotlin 与 Java基本语法对比 Kotlin比Java更年轻,但它是一个非常有前途的编程语言,它的社区不断增长. 每个人都在谈论它,并说它很酷. 但为什么这么特别? 我们准备了一系列文章,分享我们在Kotlin开发Android应用程序的经验. 我们将讨论Kotlin与Java在语法,可用性,UI性能和异步性方面的区别,以便您可以决定哪种语言最适合您. 让我们从一些基本的语法差异开始. 这是第一个: 1. 使用Kotlin,你可以用更少的代码做更多 Kotlin的一个主要优点是它的简洁.

  • Python和Java的语法对比分析语法简洁上python的确完美胜出

    Python是一种广泛使用的解释型.高级编程.通用型编程语言,由吉多·范罗苏姆创造,第一版发布于1991年.可以视之为一种改良(加入一些其他编程语言的优点,如面向对象)的LISP.Python的设计哲学强调代码的可读性和简洁的语法(尤其是使用空格缩进划分代码块,而非使用大括号或者关键词).相比于C++或Java,Python让开发者能够用更少的代码表达想法.不管是小型还是大型程序,该语言都试图让程序的结构清晰明了. Java是一种广泛使用的计算机编程语言,拥有跨平台.面向对象.泛型编程的特性,广

  • Java Long类型对比分析

    Java Long类型对比 在开发的到一个很基础的问题 在代码中,两个Long类型数据比较用"==",结果有时候true有时候false,原本以为Long会自动转long然后再比较,不会是这里的错,找来找去实在找不到其他原因了,我就打印这两个Long类型出来看,果然是不相等,于是脸黑了一阵...... 去查了一下资料,原来是这样: Java 基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character: 这5种包装类默认创建了数值[-

  • kotlin改善java代码实例分析

    序 本文主要举几个kotlin如何改善java代码的例子 字符串字面值及模板 字符串字面值 @Test fun testStringLiterals(){ val a = """if(a > 1) { | return a |}""".trimMargin() println(a) val b = """Foo Bar""".trimIndent() println(b) } 有了

  • kotlin和Java的相互调用示例详解

    前言 互操作就是在Kotlin中可以调用其他编程语言的接口,只要它们开放了接口,Kotlin就可以调用其成员属性和成员方法,这是其他编程语言所无法比拟的.同时,在进行Java编程时也可以调用Kotlin中的API接口. 1.在kotlin中调用Java方法 Kotlin和Java是两种不同的语言,所以在互相调用的时候,会有一些特殊的语法.kotlin中对象属性默认就带有setter和getter方法,所以在kotlin中调用Java时直接变量名点属性就可获取到属性的setter和getter的一

  • 最好的Java 反编译工具的使用对比分析

    前言 Java 反编译,一听可能觉得高深莫测,其实反编译并不是什么特别高级的操作,Java 对于 Class 字节码文件的生成有着严格的要求,如果你非常熟悉 Java 虚拟机规范,了解 Class 字节码文件中一些字节的作用,那么理解反编译的原理并不是什么问题. 甚至像下面这样的 Class 文件你都能看懂一二. 一般在逆向研究和代码分析中,反编译用到的比较多.不过在日常开发中,有时候只是简单的看一下所用依赖类的反编译,也是十分重要的. 恰好最近工作中也需要用到 Java 反编译,所以这篇文章介

  • java原生序列化和Kryo序列化性能实例对比分析

    简介 最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括: 专门针对Java语言的:Kryo,FST等等 跨语言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等 这些序列化方式的性能多数都显著优于hessian2(甚至包括尚未成熟的dubbo序列化).有鉴于此,我们为dubbo引入Kryo和FST这 两种高效Java序列化实现,来逐步取代hessian2.其中,Kryo是一种非常成熟的序列化实现,已经在Twitter.Group

  • 一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)

    楼主是一名asp.net攻城狮,最近经常跑java组客串帮忙开发,所以最近对java的一些基础知识特别上心.却遇到需要将一个对象深拷贝出来做其他事情,而原对象保持原有状态的情况.(实在是不想自己new一个出来,然后对着一堆字段赋值......好吧,再此之前我没有关心是否项目框架有深拷贝的方法),然后就想着用反射实现吧....接下来 是我自己的原因,还是真的不存在这样的纯用反射实现的深拷贝方式....(c#是有纯反射实现的) 但也不能算自己白忙活吧,也找到了其他实现深拷贝的方式(但是每种方式我都觉

随机推荐