代码生成会提高代码质量吗?


12

争论代码生成,我正在寻找一些提高代码质量的方法示例。为了阐明代码生成的含义,我只能谈论我的一个项目:

我们使用XML文件描述数据库架构中的实体关系,因此它们可帮助我们生成ORM框架和HTML表单,可用于添加,删除和修改实体。

在我看来,由于减少了人为错误,它提高了代码质量。如果某些东西实现不正确,则会在模型中将其破坏,这是很好的,因为由于更多生成的代码也被破坏了,因此错误可能会更快出现。

由于要求我提供代码质量的定义,因此让我澄清一下,我的意思是软件质量

软件质量:这不是一个属性,而是相互影响的许多属性,例如效率,可修改性,可读性,正确性,健壮性,可理解性,可用性,可移植性等。


3
您对代码质量的定义是什么?
NoChance 2012年

@EmmadKareem我在原始问题上添加了简短定义。
platzhirsch 2012年

1
我认为自动代码生成将有助于提高代码的一致性和统一性。在某些情况下,确实可以提高质量,但我认为这不是万能的。
joshin4colours 2012年

Answers:


38

代码生成器不能比编写该生成器的人生成更好的代码。

我对代码生成器的经验是,只要您不必编辑生成的代码,它们就可以了。如果您能坚持该规则,那您就走了。这意味着您可以放心和快速地可靠地重新生成系统的该部分,并在需要时自动添加更多功能。我想这可以算是质量。

我曾经听过一个关于代码生成器的论点,即一个程序员每天可以生成如此多的代码行,而使用代码生成器,他们可以生成数千行!显然,这不是我们使用生成器的原因。


6
+斜体部分一千次。代码生成器的功能应类似于编译器或C ++模板机制:您永远不必手动编辑其输出。只有当您怀疑有错误时,才应该阅读输出。
2012年

1
可惜我不能再投票了……
Fabricio Araujo 2012年

@anon:Homans通常不应该编辑代码生成器或编译器的输出,但是有时建立一个包含需要通过对它进行一些修改的程序来运行一段机器生成的代码的构建过程可能是完全合理的。如果有时候需要在更改最小字节数的同时修补现场代码,那么有时可能需要人工编辑构建过程的输出,但是当以这种方式手动调整代码时,应该还存档了构建过程中的所有文件(不仅仅是源文件!)和...
supercat

...也更新源代码以匹配手工编辑的目标代码的语义。
超级猫

20

我反过来说 -假设您正在编写有趣的应用程序,代码生成会降低代码质量。代码生成的本质是奖励那些千篇一律的,过分夸张的,过度指定的框架,这些框架在不持续依赖代码生成工具来不断生成更大,更复杂,更丑陋的代码束的情况下变得很难处理。尽管它可能是一个很好的工具,但实际上不应成为包装盒中的主要工具。


3
同意,一些ORM产生的垃圾(从知道如何编写性能良好的数据库代码的人的角度出发的垃圾)就是一个很好的例子。对于不知道自己在做什么的人来说,它通常可以起到一定的作用。而且,新程序员没有掌握在生成器之外完成更难的工作的技能,因为他们不了解基本概念。
HLGEM 2011年

1
噢,+ 1或-1 ....一方面,代码生成对于删除无用的重复代码非常有用,因为在这些代码中,您将定义简单地扩展为代码,但是正确的是,它被过度使用了“节省时间”的复杂性本身就是一个反模式。
gbjbaanb 2015年

13

我认为自动代码生成和代码质量有些正交,不一定相互关联。

代码生成仅仅是解决特定技术任务的一种方式。是否提高代码质量很大程度上取决于您在做什么。

您的情况是代码生成的一个很好的例子,可以通过尽早发现潜在的错误来提高代码质量。

我可以再举一个例子,说明自动代码生成会降低代码质量。全能的ASP.NET WebForms。它通过将UI控件的层次结构转换为HTML标记来实现自动代码生成,这一切都是稳定,可预测和可管理的。

得出结论,在正确使用时,自动代码生成可以帮助提高代码质量。


11

代码生成本身并不会影响代码质量,而不会影响代码一致性

生成的代码将在生成实例之间保持一致。如果生成器被设计为发出高质量的代码,则生成的代码将始终具有良好的质量。但是,如果代码生成器发出质量差的代码,则您将始终得到错误的代码。

代码生成也可以用来更快地构建代码。然而,更快并不意味着更好。这可能意味着您可以更快地得到质量差的代码。


6

如果满足以下条件,则代码生成很好:

  • 生成的代码不应该被编辑
  • 代码生成器为您提供了足够的灵活性来执行所需的操作
  • 代码生成器的输入语言比其他方式要好(例如,DRY)
  • 即使是罗creates的代码生成器,也可以创建无需担心的良好可靠的代码

在这种情况下,您需要考虑的质量代码就是输入到生成器的代码。

对于质量的典型更改,质量的一个简单衡量标准是您需要执行多少手动编辑。越少越好。


并且生成的代码透明地映射回原始代码,因此您不必调试生成的代码。

@Thorbjørn:我同意。在我必须维护的一个应用程序上,生成了Fortran。多年来,人们一直无法进行调试,而我是唯一一个仍然愚蠢到仍然无法进行服务电话咨询的人:)
Mike Dunlavey 2012年

我不同意代码生成器应该灵活。它需要有针对性-做好一件事情,不要做很多事情。它应该需要一个很小的,定义明确的输入,并为您编写大量代码。当开始成为程序时,它将走向失败。
gbjbaanb 2015年

@gbjbaanb:我同意。这就是为什么我说足够的灵活性。对我来说,问题不在于代码生成器本身,而是用作其输入的领域特定语言。如果DSL太灵活,则用户必须四处游动。如果不够具体,则用户必须解决其局限性。我可以举一些例子。
Mike Dunlavey 2015年

4

由于DRY(不重复自己),因此提高了代码质量。

代码生成规则只编写一次;它们不会针对生成的每个代码实例进行硬编码,因此,只需稍加修改即可减少在复制/粘贴内容时出现人为错误的可能性。


除非您必须编辑生成的代码-根本不是DRY...。我最近必须这样做- 否则一切都不愉快。如果必须再次手动编辑自动生成的代码库,我将收取三次费用!!!
Fabricio Araujo 2012年

1
您不必编辑该代码。编辑完成生成本身的代码,并在必要时使用其他规则对其进行扩充。编辑生成的代码应该是最后的选择。
EarlNameless 2012年

1
我想要选择。我没有。
Fabricio Araujo 2012年

2

我假设您是指专门为内部使用而使用的专有代码生成器,因为否则任何缺少机器代码的东西都是代码生成器。但是,您可以在这里:

在此处输入图片说明

我认为,与它生成的GLSL / HLSL代码(否则需要手写)相比,Blueprints中的节点图更易于维护并且更不容易出错,这是非常有争议的。

提出新的着色器的效率也更高,因为您可以实时视觉反馈更改图形时最终结果的外观。我绝对更希望以这种方式维护成千上万个用节点图表示的着色器,而不是GLSL / HLSL代码,而且我实际上比使用Blueprints更熟悉编写GLSL / HLSL。我认为,除了可能会立即捕捉到的轻微视觉故障外,实际上几乎不可能引起重大错误,因为“视觉语言”通常会以纯粹的功能样式强加合理的约束,例如,使着色器崩溃,至少是AFAIK(我当然不是蓝图专家)。

甚至没有“代码”可以维护了。您只需将节点放置在图形中并在它们之间绘制链接,瞧,它将为您生成着色器代码。谁维护着这些东西,然后说:“ 您知道,如果这是用GLSL代码而不是使用Blueprints编写的,那么我的生活会变得更加轻松,我将有更多的空闲时间。 ”可能永远不会。

就是说,我遇到了很多专有代码生成器,它们确实使生活变得更加艰难,使我学习了这种愚蠢的元语言,与使用生成的代码语言编写代码相比,它的好处是非常有限的(如果有的话)。对我来说,代码生成的一个迹象表明,它只是减少了少量样板,实际上并没有减少错误的可能性。您知道,如果它实际上引入了导致原始语言所没有的bug的新方法,那将尤其令人讨厌。但是,在某些情况下,例如上面的代码生成,生产率的提高是如此之大,以致于花费大量时间来处理细微的事情现在要花几分钱,甚至没人会回头再回头。

对我而言,对于Epic团队中的Blueprints专有开发而言,有一种比在世上为大众提供的许多多余的编程语言更合理的论点。


1

我要说的是,这可能会稍微提高质量,但会大大减少开发时间。有时,生成的代码不稳定,笨拙,或者只是很糟糕。在这些情况下,生成的代码会降低质量,并增加项目的测试/修复/回归测试时间。而且有些任务太复杂而无法轻易生成-生成器本身变成了一个完整的独立系统(可能比主项目更大,更复杂)。

代码生成器很好,但是要小心使用它们!


1

我曾经在一家非常依赖代码生成的商店里工作。在我看来,它使该项目的代码非常统一。在这方面,质量还可以。

但是,由于一切都必须通过生成器而不再允许您编写自定义代码时,我认为您失去了成为程序员的某些优势。

因此,我认为这肯定是一把双刃剑话题。是的,生成器之所以出色,是因为它们减少了错误并提高了代码标准,但是,它们也使“某些”程序员变得愚蠢,因为它们依赖于生成器而不必费心。

只是我的2美分。


3
汇编语言程序员过去常常这样谈论编译器。所以我不确定这是一个很好的论点。被迫弄脏手可能是一个很好的学习经历,但是一旦您学会了,就应该使用最有生产力的工具。
MarkJ 2012年

@MarkJ:有时候,汇编在一致性方面实际上可以比编译语言更好。例如,在某些嵌入式系统中,能够进行等效x=someValue ^ 0xFF ^ 0xFF ^ 0xFF ^ 0xFF;编码并使用四个XOR字面指令进行编码非常有用。如果代码存储介质只能写入空白(0xFF)字节,则上述构造将允许对该值进行四个任意更改。即使将表达式重写为as,x=someValue; x = x ^ 0xFF ^ 0xFF ^ 0xFF ^ 0xFF;并且编译器在运行时对所有xor进行了评估,它仍可能会使用“补全所有位” ...
supercat 2015年

...而不是立即进行异或操作。
超级猫

1

除了马丁的答案,我还要补充一点,当您逐条记录地工作时,SQL代码生成非常好(从tab1中选择*,其中tab1.pkcolumn =:parameter,更新tab1 set [任意列数],其中tab1.pkcolumn =:parameter等)。在这种情况下,您的ORM将大放异彩,因为确实需要重复生成SQL。

我主要担心的是元查询-查询对象的属性,ORM使用任何算法将其转换为SQL。非常相似的元查询可能会生成完全不同的SQL-并不能保证此生成的SQL是高性能的。

一种元查询语言,可以转换为另一种语言(SQL),该语言可以转换为查询计划以有效执行数据收集。并且生成的结果必须是对象,因此ORM必须实例化受影响的对象-这样它可以触发另一查询查询,以填充元查询本身未带来的对象的属性...


0

我完全同意那些说代码生成很好的人,只要您不必编辑(最好不必查看)生成的代码即可。

如果我们可以接受所生成的代码与手写的行数大致相同,并且可以说它没有错误,那么可能包含错误的行数就会减少。因此,代码质量应该提高了。


附录:当然,其他因素(例如执行时间)也可能起作用。

就个人而言,我已经编写了许多代码生成器,但从来没有将其作为初始方法。

一直以来,我都注意到现有代码中的重复模式,因此,生成器在添加新的但相似的代码并对其中的一些可变部分进行参数化时会使用一些现有代码。

在那种程度上,我生成的代码几乎与现有的手写代码相同(除了它倾向于更好地在视觉上布局和更统一,如果必须要看的话,我认为这有助于提高可读性)。

顺便说一句,我主张插入打开/关闭注释,这些注释指示代码已生成,包括工具及其维护者的详细信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.