您的代码是多余的,请继续使用!

本文介绍了必要的和不可避免的代码冗余,并讨论了代码冗余模型,该模型有助于理解为什么源代码生成器执行其工作,以及为什么完全需要它们。

介绍

您用Java或其他任何语言编写的代码是多余的。 并非按如下定义(每个Wikipedia页面https://en.wikipedia.org/wiki/Redundant_code ):

在计算机编程中,冗余代码是计算机程序中不必要的源代码或已编译代码,例如…

这样,您的代码也可能是多余的,但这与我现在和现在想要谈论的是另一种故事。 如果是这样,请对其进行修复,并提高您的编码技能。 但是,事实并非如此,因为您是一名优秀的程序员。 您代码中肯定存在的冗余不一定是不必要的。 冗余的来源不同,某些冗余是必要的,其他冗余是不必要的,但不可避免。

在这种情况下,我们需要的冗余的实际定义更像是信息理论上的冗余定义(根据Wikipedia页面https://en.wikipedia.org/wiki/Redundancy_(information_theory)

在信息论中,冗余度度量集合X的熵H(X)与其最大可能值log(| A_X |)之间的分数差。

UPPPS…不要停止阅读!!!

对于我们来说,这是一个非常精确但非常不可用的定义。 幸运的是,页面继续并显示:

非正式地,它是用于传输某些数据的浪费“空间”的数量。 数据压缩是减少或消除不必要的冗余的一种方法。

换句话说,以某种形式编码的某些信息如果可以压缩,则是多余的。

例如,下载和压缩古典英语小说《白鲸记》的文本会将其大小缩小到原始文本的40%。 用Apache Commons Lang的源代码做同样的事情,我们得到20%。 绝对不是因为这个“不必要的计算机程序代码”。 这是其他一些“必要的”冗余。 英语和其他语言是多余的,编程语言是多余的,事实就是这样。

如果我们分析这种冗余,我们可以看到存在六个级别的冗余。 我将在这里写的关于这六层的知识不是众所周知的,也不是公认的理论。 随时挑战它。

此模型和分类有助于建立一种思考代码生成的方式,即何时生成代码,为何生成代码。 毕竟,当我想到Java :: Geci框架时,我想出了这个模型,并且我想着为什么当有许多其他代码生成工具时,我为此花了一年的业余时间。 这种冗余模型给出了我以前只是感觉到的正确原因。

冗余级别

然后,下一个问题是这些(英语和编程语言)是否是冗余的唯一原因。 答案是,我们可以确定六个不同级别的冗余,包括已经提到的那些。

0自然

这是英语或其他任何自然语言的冗余。 这种冗余是很自然的,我们已经习惯了。 冗余随着语言的发展而发展,因此需要它来帮助理解嘈杂的环境。 我们不想消除这种冗余,因为如果这样做,我们最终可能会读取一些二进制代码。 对于我们大多数人来说,这并不是很吸引人。 这就是人类和程序员的大脑工作方式。

1种语言

编程语言也是多余的。 它比它所基于的自然语言还要多余。 额外的冗余是因为关键字的数量非常有限。 这使得压缩率从60%上升到Java的80%。 其他语言,例如Perl,则密度更高,可惜它们的可读性更差。 但是,这也是我们不愿战斗的冗余。 减少来自编程语言冗余的冗余肯定会降低可读性,从而降低可维护性。

2结构

冗余的另一个来源已经与语言无关。 这是代码结构冗余。 例如,当我们有一个带有一个参数的方法时,则调用此方法的代码片段也应使用一个参数。 如果方法更改了更多参数,则调用该方法的所有位置也必须更改。 这是来自程序结构的冗余,这不仅是我们不希望避免的事情,而且在不丢失信息和那样的代码结构的情况下也无法避免。

3域诱导

当业务域可以以简洁明了的方式描述但编程语言不支持这种描述时,我们谈论的是域引起的冗余。 编译器就是一个很好的例子。 此示例是大多数程序员都熟悉的技术领域。 可以使用BNF格式以清晰美观的形式编写无上下文语法语法。 如果我们用Java创建解析器,肯定会更长。 由于BNF形式和Java代码的含义相同,并且Java代码明显更长,因此从信息论的角度来看,我们可以确定Java代码是多余的。 这就是为什么我们有用于此示例域的工具,例如ANTLR,Yacc和Lex以及其他一些工具的原因。

另一个示例是Fluent API。 可以对流利的API进行编程,以实现多个接口,这些接口可以指导程序员完成链式方法调用的可能顺序。 编写流畅的API是一种漫长而又难以维护的方法。 同时,流利的API语法可以用正则表达式很好地描述,因为流利的API用有限状态语法描述。 正则表达式列出了描述替代方案,序列,可选调用和重复方法的方法,比同一种Java实现更易读,更短且冗余更少。 这就是为什么我们拥有诸如Java :: Geci Fluent API生成器之类的工具的原因,这些工具将方法调用的正则表达式转换为fluent API实现。

在这个区域中,减少冗余可能是理想的,并且可能导致更易于维护和更易读的代码。

4语言演变

语言演化冗余类似于域诱导的冗余,但是它独立于实际的编程域。 这种冗余的来源是编程语言的弱点。 例如,Java不会自动为字段提供getter和setter。 如果您查看C#或Swift,它们就会显示。 如果我们需要Java语言的代码,则必须为其编写代码。 这是样板代码,是语言的弱点。 另外,在Java中,没有声明性的方法来定义equals()hashCode()方法。 可能会有更高版本的Java为该问题提供一些帮助。 查看Java的过去版本,创建匿名类肯定比编写lambda表达式要多余。 Java不断发展,并将其引入了该语言。

语言进化始终是一个敏感的问题。 一些语言运行很快,并引入了新功能。 其他语言(例如Java)较为宽松,或者可以说是保守的。 正如Brian Goetz在回应催促新功能的推文中写道:

“这取决于。 您宁愿早点获得错误的功能,而不得不永远使用它吗?”

@BrianGoetz回复@joonaslehtinen和@java 10:43 PM·2019年9月16日

域引起的冗余和语言演变引起的冗余之间的主要区别在于,虽然不可能用通用编程语言解决所有编程领域,但是语言进化肯定会消除语言短缺带来的冗余。 随着语言的发展,我们在IDE和Lombok等程序中都有代码生成器来解决这些问题。

5程序员诱导

这种冗余与代码冗余的经典含义相关。 这是程序员无法生成足够好的代码,并且程序中存在不必要和过多的代码结构甚至复制粘贴代码的时候。 典型的例子是前面提到的“不合格开发者的传说”。 在这种情况下,代码生成可能是一个折衷方案,但通常是一个错误的选择。 从项目经理的角度来看,在较高的水平上可能还可以。 他们关心开发商的成本,因此他们可能决定只雇用便宜的开发商。 另一方面,在程序员级别,这是不可接受的。 如果您选择生成代码或编写更好的代码,则必须选择后者。 您必须学习和发展自己,以便可以开发更好的代码。

奥托罗

…或外卖。

当我第一次开始写有关Java :: Geci框架的文章时,有人评论说“为什么要使用另一个代码生成工具”? 这个问题当然是正确的。 如本文所述,有许多类似的工具。

但是,如果我们查看代码冗余分类,那么我们可以看到Java :: Geci可用于管理域诱导的冗余,并且可能是语言演进引起的冗余。 在后者的情况下,存在许多并发程序,而Java :: Geci则无法与之抗衡,例如,易于使用IDE内置代码生成。

有许多生成器可解决某些特定域并使用代码生成来管理额外的冗余。 Java :: Geci是我所知的唯一一个提供通用框架的框架,该框架可使特定于域的代码生成器的创建变得简单。

要认识到真正的用例是针对特定于域的生成器,上述冗余模型很有帮助。

翻译自: https://www.javacodegeeks.com/2019/09/your-code-is-redundant-live-with-it.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值