我不讨厌Java……

我爱咖啡……

我不讨厌Java……

在我的其他一些帖子中,人们可能会对我“讨厌” Java(作为编程语言或开发生态系统或两者兼而有之)产生印象。

我不。

Java是一种相对简单的编程语言,具有大量已编写,易于使用且经过良好测试的代码。 这样一来,合格的开发人员就可以为集群和分布式环境编写软件,而无需了解部署后如何工作的每个细节。

这并不是说它很简单,而是它尽可能地接近简单而又不比可能简单。 学习Java的大部分困难来自大量的框架和库。 最初来自.NET世界的那些人通常不知所措。

这套特别有用的工具的最新增加包括WSO2的MSF4J,这是一个使用OSGi的Java Web服务框架,在SpringBoot的十分之一时间和Express.js的五分之一启动了相同的服务,从而使原子微服务更加可行。 Payara Micro,基于Glassfish的Eclipse MicroProfile实现,可在70 MB的运行时中提供大部分Java EE。 Java EE 8和Glassfish 5; Apache River 3.0.0,是对JINI 2.1的长期延迟更新,增加了一些模块化(尽管在Apache的防御中,JINI 2.1并没有多大错误); 当然,还有Java 9,尽管要使某些程序兼容需要一些工作。

仅仅在基础上的Jigsaw模块化就大大提高了语言的速度,特别是在启动时,同时还提高了可靠性。

这些保护伞中的技术数量向那些不熟悉Java生态系统的人们表明了可用的丰富技术以及其中许多技术的质量。

要成为Java 专家很困难,在许多方面要比在通常认为困难的语言中要困难得多。 但是,大多数Java开发人员不需要那种专业知识。 通常,该级别的开发人员正在着手解决更难解决的问题,而这些问题几乎可以定义为利基市场,而不是人们在日常情况下使用的应用程序。

用Java编写的代码量加上问题或行业特定技术的必要性,以最低限度地支持Java,自然使它成为大多数系统的最佳集成平台。 随着许多围绕集成的最佳Java技术的出现,它变得毫不费力。

这些技术中的许多在网上论坛上讨论不多,因为它们并不旨在引起人们的注意,并且它们只是在起作用。 “吱吱作响的轮子”效应不会区分生态系统中的技术和不同生态系统中的技术。

当任何工具丢失或损坏时,它都会变得更加突出。

没有大量的集成工作,我们将没有有用的系统。 很少有人会对在家中拥有计算机感兴趣,直到可以写电子邮件,聊天,看电影等成为可能,而所有这些都需要大量的集成。

对于开发人员或围观者来说,这不是最有趣的问题,总的来说,这是理所当然的,虽然有些遗憾构成了大多数管理人员,但是引入新内容几乎总是必要的。 我们所依赖的系统中的某些核心代码早于Java,但是这些系统中的许多组件都是用Java编写的。

在使用Java编写应用程序时,我感到有些烦恼和耐心,其中有一些是特定于语言的,主要是语法隐藏了语言的对象性质而不是使用语言,但更多情况是它几乎没有或与语言本身无关。

从角度来看,几乎所有开发人员都会承认,与Java相比,COBOL,BASIC或Pascal更胜一筹,而且更令人愉悦,无论他们偏爱哪种语言,环境和生态系统。 在C ++中要做很多工作所需的受虐情绪是最好的一种变态。

在GitHub上的代码研究中发现的导致集成问题的第一大原因是Google的V8 JavaScript引擎,这显然是由于其在维护网络连接方面的脆弱性,这对于源自Web浏览器的技术而言有点奇怪。 不要指望您的Electron non-app会说话,或者至少不会保持一致。

当JavaScript技术获得了久违的历史时,在JavaScript世界中令人兴奋的程度更加令人讨厌。 您好AngularJSF,很高兴再次认识您。

就像奥斯卡·王尔德(Oscar Wilde)在一次演讲中所说的那样,我还没有听到关于Node.js的讨论。 我听见

它仍然是碰巧具有异步I / O的单线程语言,并且网络I / O至少看起来不能很好地工作。 当使JavaScript应用程序协同工作的唯一方法是在它们之间放置Java应用程序时,作为集成工具,这并不是一个开始。

明年它可能会赶上Windows 1.0,即Electron非应用程序将“运行”超过5分钟。

无论如何,回到Java时,当Java生态系统中有针对该项目的更好选择时,最常见的问题与选择特定项目的框架和库时所做出的决定有关。 但是,正如我在上面指出的那样,众多的选择可能使评估所有可能性变得困难。

当您发现自己试图“修复”应用程序问题时,发现它正在JBoss Java EE容器中的18个不同Tomcat Java SE Web容器中运行。 在这种情况下,导致问题的不是选择,而是非选择。

语言对愚蠢无能为力。

阿维塔尔·隆内尔(Avital Ronell)指出:“愚蠢是我们对无限性的最普遍体验,而智力始终是有限的”。 在上述情况下,在编写一行代码之前,情报似乎已被切断并扔回垃圾箱。

但是,它确实为面食主义者提供了飞行意大利面条怪兽存在的充分证据。

对于某些Java技术而言,其预期用途的某些方面很复杂。 同时,在不真正需要它们的时候使用它们比使用不熟悉的东西或需要额外的工作来集成更为方便。

Java Collections Framework是一个很好的例子。 对于每种集合类型都要求三个类似乎有点过头了:集合类型本身,用于对其进行排序的比较器以及用于对其进行导航的迭代器。 尽管Java 5中引入的语法更改确实使这变得更容易,但是假设您已经知道,则使用Eclipse集合仍然更加容易和快捷。

在编写高度并发的集群或分布式应用程序时,JCF的工作方式通常是完成所需工作的最简单方法。

同时支持这种应用程序更常见的应用程序类型的需求驱使诸如JDBC和JPA之类的技术使用JCF。 然后,将JCF用于大多数Java应用程序变得更加容易,因为相关技术已经在使用它。

相反,某些框架和库试图过分简化,在尝试超出其能力范围时会引起问题,并给特定系统的其他领域带来额外的复杂性。

“保持简单”的口头禅太简单了。 它通常只会导致应用程序中其他地方的过于复杂。

其他问题不仅限于Java,在某些情况下,Java至少有一些解决方案。

大多数远程API隐藏了以下事实:远程调用远程调用。 多数形式的RPC或RMI是主要示例。

如果VM内的本地呼叫未返回响应,则您的应用程序可能比没有响应的麻烦要大得多。 另一方面,由于网络环境中的各种问题,远程呼叫通常不返回响应。

隐藏了调用是远程的事实,这使得开发人员在时间限制下(谁不是?)不太可能考虑无响应,结果是运行时异常终止了应用程序。

JINI(即现在的Apache River)是为数不多的广泛使用远程调用的技术之一,同时在需要考虑无响应的远程调用时很明显。

很少有人意识到像JINI这样的技术的普遍性,因为它们可以可靠地工作,而使用它们编写的代码通常也可以可靠地工作。 例如,新型汽车中手机等设备的“自动”集成完全依赖于JINI。 它隐蔽地工作,很少有人考虑到实际的困难,这是一个真正好的工具的标志。

不幸的是,语言并非无法避免产生类似的效果。 当Java没有功能时,它突然变得很重要,除非以前只有Java的语言是Smalltalk,Haskell或LISP。 诸如闭包,lambda,递归列表函数,原子函数等之类的东西似乎并没有激发任何人,直到他们意识到Java缺少它们。

由于JVM运行用Java以外的语言编写的代码,因此要实现这些类型的功能并不容易。 在运行时为它们提供支持会破坏这些语言,例如Clojure,Scala,Ceylon,NetREXX和Groovy等。

javac为使lambdas之类的东西工作而执行的某些扭曲是相当惊人的,但是有点荒谬。 它们也使调试程序更加困难。 考虑到其中大多数功能只不过是将代码缩短了几行而已,所以仅仅因为它突然流行而添加它似乎是没有意义的。

当前使用Scala改善并发性的趋势(例如Apache Storm和Spark等应用程序就是很好的例子)以相反的方式将其带入另一种JVM语言中。 Scala中的语言构造所隐含的并行性,或Ceylon中非常强大的类型所隐含的可靠性,在很大程度上已被转换为JVM字节码。

当Java代码使用Java流API和Java并发包时,至少在Scala中,结果看起来与Java字节码非常相似。 当运行时不使用,遵循或服从它们时,语法,语言结构和代码限制不会给您带来很多好处。

添加功能会使字节码不必要地变得复杂,从而产生一个相关的问题,即调试中使用的堆栈跟踪不再类似于编写的代码,当问题仅在生产中或仅在生产中出现时,它们通常是开发人员仅有的东西之一。该公司最大的客户。

相反,在一种在语法和语言结构方面具有明显优势的语言中,大多数语言通常会被预编译器删除,以在针对缺少它们的语言而设计的环境中运行。 两种语言都有相同的问题,不过堆栈跟踪与代码不一样。

由于上述原因,以及在用另一种语言编写VM,解释器或编译器时难以用一种语言进行思考,除了最初的引导程序之外,所有语言都是用语言本身编写的,这几种语言要么源自许多此类功能,或添加它们并不那么困难。 一旦使用这些语言保存了代码,就隐式地更改了运行该代码的状态机以支持该代码。

在Java,JavaScript,Clojure,Scala之前,LISP,Smalltalk或Haskell中都存在Lambda,闭包,原型,反射,自省,递归,具有安全动态转换的强类型,特征(有时被称为其他语言的mixins)和多态性。或大多数其他其中一些语言。

此外,以解释器/编译器的语言编写解释器/编译器时,生成的汇编器会隐式遵循这些限制并继承该语言的结构,结果是,在处理器上运行的实际代码会受益于以下限制:使用危险的指示以及结构和隐喻提供的力量。

毫不奇怪,Java的JIT编译器的原型是由Sun在Smalltalk VM中编写的,之后将其开源为“ Strongtalk”。 同样,IBM的一种基于VM的语言可以扩展的概念证明是用于Squeak / Pharo开源Smalltalk的VM,它可以扩展到接近线性的1024 CPU(IBM没有更大的机器可以看到它可以扩展多远)。 。

最初,这种类型的语言更难编写,并且花费更长的时间,但是一旦编写了基础语言,添加内容就变得容易得多,因为不需要以语义等效的方式在多种位置以不同的语言添加内容。

像Java这样的语言所涉及的困难必须克服,并且仍然需要大量工作来升级,对于依赖于该语言和/或运行时的大量应用程序,更是如此,这需要一些聪明的人付出巨大的努力。 。

剩下的最大问题是事件在全球范围内的传播,大多数事件的通用性质(尤其是在UI框架中,但不仅限于它们)意味着太多的对象要花费时间来消耗它们,却发现它们无关紧要。

一个非常明显的例子是Eclipse中的Dali JPA库。 尽管Dali在对复杂数据库进行逆向工程方面比其他JPA框架做得更好,但是由于它发出的事件数量和使用者数量,花了300多个CPU小时并向JVM分配了16 GB来修改ERP数据库。 /回应者。 在某一时刻,队列中有超过850,000个未处理的事件。

JavaScript有相同的问题,尽管许多库实现了stopPropagation(),还有一些库也实现了stopImmediatePropagation()API(jQuery是一个示例)。 很少有JS程序员实际上将它们称为。

再次回到Java(到目前为止,您可能已经发现我非常讨厌JavaScript或我通常所说的EczemaScript)。 它的外观和工作方式就像是一家公司在几周内迫于其新产品的使用而编写的。 再说一遍

幸运的是,Java中有一些惊人的库,框架和应用程序,并且大多数Java程序都做得很好。

与Java相比,很难解决LISP或Haskell中业务和用户应用程序中常见的许多要求。 就像在使用map / reduce函数或对象图迭代的数据库中将众所周知的SQL解决方案转换为通用需求时遇到的困难一样,许多已经用该语言解决了通用问题的人也变得更加容易。

虽然像LISP,Haskell或Prolog等深奥的语言一样,地图/归约和对象图数据库具有用例,它们是必要的,或者只是更好,但这些用例相对较少。

而且它仍然比COBOL更好…