借用李宗盛的一句歌词:
女:为何你不懂
男:别说我不懂
女:只要有爱就有痛
男:有爱就有痛
女:有一天你会知道,人生没有我并不会不同
男:没有你会不同
我个人的背景和基本立场:
1、十余年的程序员,极客,用过二十多门编程语言,终身学习者。
2、轮子大王,喜欢微创新,众多开源项目作者和参与者。
3、项目开发经理、技术经理、公司级架构师,主抓工程效率、质量和可维护性。
Lombok和Kotlin实际上都是“语法糖”,既然是糖,当然有甜头,语法层面(本文只做简单点评),我认为大部分语法改进是好的,但是像Kotlin移除了原生static变量和方法,改用伴生对象(companion object),这种做法有些激进。
实际上,任何语法都是一把“双刃剑”,语法不是越多越好,也不是越简单越好,比如@Data、@RequiredArgsConstructor这种大家觉得很常用的功能,为什么Java语言不直接官方支持,如果你是编程语言的作者,你会怎么考虑?一门大众语言,要考虑易学、易用、通用、兼容性、受众面以及底层大家看不到的东西(跨平台、性能、复杂度、破坏性、可维护性),剑走偏锋,不是一门成熟语言的性格。在我的另一篇文章《浅论各种编程语言》中有更为详细的说明。
在此,我只强调两点:
一、语法必须要考虑的基本问题
1、易用:大部分语法的第一设计原则就是让原本很难实现的编程,用更简单的方式来实现。
2、受众多寡:针对一个很小众的功能,通常不会从语法层面去改进它的易用性。
3、通用性:针对99.99%甚至100%的相似用例和场景,都应该有相同的语法,且不需要额外配置,否则会降低易用性。
4、统一性:针对相似用例和场景,通常的写法只有一种(最多可接受两种),不存在两种以上功能重叠的语法。
5、易学:语法概念简单、直观,一看就懂,语法通用性、统一性好,不存在针对不同情况的各种变异用法或配置。判断标准:一个语法的教程一段话就能说完,语法的变种或配置不超过两个。
像lombok、kotlin这样的语法,在Java这种成熟语言的基础上做文章,盯上的主要是上面的第1、2点进行扩展,在一些受众比较大的、使用频繁的地方,做一些更易用的语法。但是它们在第3、4、5项上,做得就不如原生Java语言那样周全。
举几个例子,例如:
@ToString(onlyExplicitlyIncluded=true, includeFieldNames=true, callSuper=true) @Data(staticConstructor = "of") public class Point { final int x, y; } @Builder(toBuilder=true) @AllArgsConstructor(onConstructor=@__({@Annotations})) @NoArgsConstructor public class Point { final int x, y; }
为什么lombok要支持多种配置?还不是因为它想支持更多的功能,它想做得更通用、更统一、更强大。但是一旦它变得更强大,支持了丰富的配置和更多的语法,它的易用性、易学习性、易维护性甚至兼容性就会降低。一个200行的Java程序,我们完全可以通过类似lombok这种方式,把代码精简到100行,甚至更狠,精简到10行!但是我们怎么做到同时兼顾上面所说的那5个语法基本要求:受众广、通用性高、统一性高、易学易用?
还有一个灵魂拷问:即便是你觉得这个语法糖很好,你觉得简单、直观、不复杂,你认为上面那5个要求全都满足,但是你认为你的同事(包括初级的程序员)和将来入职的新同事,都能直接上手维护你的代码吗?如果他们做不到,那你认为是什么原因呢?
二、语法是否能融入、兼容已有的广大生态
比如,Java语言,有编辑器的代码“语法高亮”插件,有Eclipse、IdeaJ等成熟的开发工具(支持热编译、Debug),有Checkstyle、FindBugs、PMD等代码扫描工具,甚至还有很多直接生成Java代码、生成UML类图等生态工具。那么,一旦你把Java代码换成了Kotlin、Lombok代码之后,上述的那些工具还能用吗、会不会有很大的坑?
这么说吧,Kotlin都发布10年了,至今它的生态都不太完善。Android是官方支持它的,然而还是会有不完善的地方。
举个例子,在Android Studio中,编写如下Java代码:
public class Test { public static void main(String[] args) { System.out.println(KotlinClass.STATIC_VAR); System.out.println(JavaClass.STATIC_VAR); } }
其中 KotlinClass.kt 是 kotlin格式代码,JavaClass.java 是 java格式代码。
如果修改了 JavaClass.STATIC_VAR 这个变量的定义,编译器就能实时地识别到引用关系,提示报错。
但是修改了 KotlinClass.STATIC_VAR这个变量的定义,编译器就不会实时识别到引用关系,不会提示报错。
大家都知道,写代码时,如果没有报错提醒,直到手动编译时才知道报错,那种体验会有多糟糕。
想一想,要放弃一个成熟的生态,去拥抱一个不成熟的生态,需要多勇敢。很多语言刚出来那时候,甚至连打断点调试的功能都没有,代码检查和语法高亮功能也没有,个人小项目无所谓,复杂的项目以及多人协作的项目,可能就需要更成熟的考虑。
顺便
说一下我看好的几门语言:
Java(企业级应用NO.1)
C(底层软件)
HTML、CSS(网页霸主)
TypeScript(新一代JS)
Python(易学易用的万金油)
Golang(新宠,介于C和Java之间,国内外大厂支持,已成气候)
C++等
咱们拭目以待!