当前位置: 首页 > 科技观察

我承认,我不得不放弃使用Lombok!

时间:2023-03-15 17:23:36 科技观察

我承认Lombok是一个非常优秀的Java库。它可以让你写更少的代码,同时玩得更酷。几个简单的注释可以杀死大量的模板代码。ImageviaPexels但所有的源代码都花了大量时间阅读而很少花时间执行(你可以细细品味这句话)。一年前,我和大多数人都认为Lombok的出现会让Java编码体验更好,并在我的团队中强烈推荐Lombok。一年后,我开始担心这个问题,尤其是当我准备为开源博客系统Una-Boot升级Java版本时,我意识到Lombok自己掉进了陷阱。在我进一步分析它的源代码并了解相关注解的工作原理后,我发现我不需要使用非标准的第三方库来将Java转换成一门简洁酷炫的语言。引入Lombok让我的项目立竿见影,但即时幸福的代价是随着项目的进展,技术债务开始积累。接下来,我将用几个熟悉的场景来重现我是如何落入龙目岛的诡计陷阱的。爱的开始,恨的起源面对Lombok提供的众多“神位”,你不介意给IDE加个新插件。IntelliJIDEA玩家只需搜索“LombokPlugin”即可找到此神器并安装。爱上Lombok从安装Lombok插件开始,恨之入骨。在使用Lombok之前,我们的源代码看起来是这样的:Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicintgetGender(){returngender;}publicvoidsetGender(intgender){this.gender=gender;}@Overridepublicbooleanequals(Objecto){if(this==o){returntrue;}if(o==null||getClass()!=o.getClass()){returnfalse;}MyObjectobj=(MyObject)o;returnage=obj.age&&gender=obj.gender&&Objects.equals(id,obj.id)&&Objects.queals(name,obj.name);}@OverridepublicinthashCode(){returnObjects.hash(id,name,age,gender);}@OverridepublicStringtoString(){return"MyObject{"+"id="+id+"name="+name+"age="+age+"gender="+gander+"}";}}每个JavaBean都会像上面说的那样填充getters和setters,equals,hashCode和toString模板代码,看起来像个胖子(不得不承认Java是一门有缺陷的编程语言)。当我们安装Lombok插件时,IDE可以识别出它很酷的注解,使用Lombok的@Getter和@Setter注解,代码看起来会像这样苗条:@Getter@SetterpublicclassMyObject{privateLongid;privateStringname;privateintage;privateintgender;@Overridepublicbooleanequals(Objecto){if(this==o){returntrue;}if(o==null||getClass()!=o.getClass()){returnfalse;}MyObjectobj=(MyObject)o;returnage=obj.age&&gender=obj.gender&&Objects.equals(id,obj.id)&&Objects.queals(name,obj.name);}@OverridepublicinthashCode(){returnObjects.hash(id,name,age,gender);}@OverridepublicStringtoString(){return"MyObject{"+"id="+id+"name="+name+"age="+age+"gender="+gander+"}";}}代码现在看起来更好了吗?但这还不是最酷的时候。现在其他方法已被替换,让我们也删除toString方法。如你所愿,可以使用@ToString注解去掉对应的方法:@Getter@Setter@EqualsAndHashCodepublicclassMyObject{privateLongid;privateStringname;privateintage;privateintgender;@OverridepublicStringtoString(){return"MyObject{"+"id="+id+"name="+name+"age="+age+"gender="+gander+"}";}}经过Lombok的trick之后,相比起最初的代码是不是显得酷酷的,苗条的,性感的?你觉得结束了吗?远不止于此,你会发现类名上大量的注解看起来很别扭。Lombok提供了一个组合注解@Data,你可以把类名头上那个天鹅一样的东西换掉:@DatapublicclassMyObject{privateLongid;privateStringname;privateintage;privateintgender;}现在,Lombok是不是把你的对象做到了你认为的完美呢?魔鬼的“身影”,冷艳脱俗。Lombok还有一些其他的注解,比如@Slf4j、@NoArgsConstructor、@AllArgsConstructor等,Lombok的用法介绍不是本文的重点。上面代码行数的变化过程,可能是无数程序员爱上Lombok的主要原因。就像一个肥胖的人逐渐变成一个苗条的人。同时也让你看到一个现象:你觉得程序员懒惰吗?有时他们甚至比你想象的还要懒惰。虽然很酷,但它也为代码种下了诅咒。扭曲的审美,爱情隐患扭曲的审美导致被检查对象处于亚健康状态。使用Lombok插件后,我们的代码也处于“亚健康”状态。回到最开始的那句话:所有的源代码,大量的时间是用来阅读的,只有少量的时间是用来执行的。本质上,我们都在寻求减少程序中的样板代码,使其代码更加简洁明了,从而提高代码的可读性和可维护性。但是龙目岛并没有实现我们追求的愿景。它只是利用Java语言在编译期的间隙期,用一种巧妙的方式,将我们需要的方法注入(写)到当前类中。在中,这个过程很像破解我们的代码,只是一个看起来很酷的技巧。这种trick并不聪明也不安全,反而会破坏Java代码已有的特性和代码的可读性。下面结合自己使用Lombok后的感受,谈谈Lombok带来的几大痛点。JDK版本问题当我想将现有项目的JDK从Java8升级到Java11时,我发现Lombok无法正常工作。所以只好把项目源码中的Lombok注解去掉,使用IDE自带的函数生成getter/setter、equals、hashCode、toString、constructor等方法。这个过程你也可以使用Delombok工具,但毕竟会消耗你很多时间。强制使用当你在你的源代码中使用Lombok,而你的代码正好被其他人使用,那么那些依赖你代码的人也必须安装Lombok插件(不管他们喜欢与否),并花时间去了解Lombok注释的使用,如果你不这样做,你的代码将无法工作。在使用了Lombok之后,我发现这是一个非常流氓的行为。可读性差Lombok隐藏了JavaBean封装的细节。如果使用@AllArgsConstructor注解,它会提供一个巨大的构造函数,让外界有机会在对象初始化时修改类中的所有属性。首先,这是极不安全的,因为我们不想修改类中的某些属性;另外,如果一个类中有几十个属性,就会有一个包含几十个参数的构造函数被删除。Lombok被注入到类中,这是不合理的行为。其次,构造函数参数的顺序完全由Lombok控制,我们无法操纵。只有当你需要调试的时候,你才发现有一个陌生的“小强”在等着你。最后,在运行代码之前,JavaBean中的所有方法你只能想象它们的样子,你是看不到的。增加代码耦合当你使用Lombok编写某个模块的代码时,其他依赖该模块的代码需要引入Lombok依赖,同时你还需要在IDE中安装Lombok插件。Lombok的依赖包虽然不大,但是因为其中一个使用了Lombok,其他所有的依赖都要强制加入Lombok的Jar包。这是一种侵入式耦合。如果再出现JDK版本问题,那就惨了。使用Lombok得不偿失,一时觉得爽,但污染了你的代码,破坏了Java代码的完整性、可读性和安全性,同时也增加了团队的技术债。这是一种弊大于利的做法。毫无价值的操作。如果你真的想让你的代码更简洁,同时兼顾可读性和编码效率,你还不如使用主流的Scala或Kotlin这种基于JVM的语言。总结Lombok本身就是一个优秀的Java代码库。它使用一种巧妙的语法糖来简化Java编码,并提供一种简化Java代码的方法。但是,在使用这个代码库的时候,需要了解Lombok并不是一个标准的Java库。使用Lombok会增加团队的技术债,降低代码的可读性,增加代码的耦合和调试难度。Lombok虽然在一定程度上减少了样板代码的编写,但也带来了一些未知的风险。如果你是参与团队项目(或大型项目),考虑后续升级扩容考虑是否使用Lombok,请与你的团队沟通三思。作者:ramostear编辑:陶家龙来源:https://www.toutiao.com/a6820517160964588044/