g代码生成器 源代码
手动地
这是标题中设置的问题的答案。 如果有可能,您必须手动生成代码。 一年前,我已经写了一篇有关代码生成的文章 ,但我没有改变主意。
除非确实需要,否则不应生成代码。
奇怪的说法,尤其是当我推广完全针对Java代码生成的FOSS工具时。 我知道并且仍然声明??,您必须手动编写所有代码。 不幸的是,或者出于我的小工具的考虑,在很多情况下无法选择手动代码生成,或者至少自动代码生成似乎是一个更好的选择。
为什么要手动生成
我已经在引用的文章中讨论了它,但是在这里我们再次进行。 如果最好的选择是生成源代码,那么系统中就会出现错误或至少不是最优的。
代码生成主要可能发生:
- (BC)编译前
- (DC)编译期间
- (DT)在测试阶段
- (DCL)在类加载期间
- (DRT)在运行时
在下文中,我们将讨论这些不同的情况。
(BC)编译前
常规阶段是在编译之前。 在这种情况下,代码生成器将读取某些配置或可能的源代码,并通常将Java代码生成到与手册源代码分开的特定目录中。
在这种情况下,生成的源代码不是进入版本控制系统的代码的一部分。 代码维护必须处理代码生成,并且几乎不能选择从流程中省略代码生成器并继续手动维护代码。
代码生成器无法轻松访问Java代码结构。 如果生成的代码必须以任何方式使用,扩展或补充已经存在的手动代码,则它必须分析Java源代码。 可以逐行或使用某些解析器来完成。 无论哪种方式,这都是一项任务,稍后将由Java编译器再次完成,并且还有很小的机会Java编译器和用于解析代码生成器代码的工具可能不是100%兼容的。
(DC)编译期间
Java使创建由编译器调用的所谓注释处理器成为可能。 它们可以在编译阶段生成代码,并且编译器将编译生成的类。 这样,代码生成便成为了编译阶段的一部分。
在此阶段运行的代码生成器无法访问已编译的代码,但是它们可以通过Java编译器为注释处理器提供的API访问已编译的结构。
可以生成新的类,但不能修改现有的源代码。
(DT)在测试阶段
首先,它似乎有点偏离。 为什么有人要在测试阶段执行代码生成但是,我在这里尝试“出售”的FOSS确实做到了这一点,我将详细介绍此阶段代码生成的可能性,优点和缺点。
(DCL)在类加载期间
在类加载期间也可以修改代码。 执行此操作的程序称为Java代理。 它们不是真正的代码生成器。 它们在字节码级别上工作,并修改已编译的代码。
(DRT)在运行时
一些代码生成器在运行时工作。 其中许多应用程序直接生成Java字节码,并将代码加载到正在运行的应用程序中。 也可以生成Java源代码,编译代码并将结果字节加载到JVM中。
在测试阶段生成代码
这是Java :: Geci(Java GEnerate代码内联)生成代码的时间和地点。 为了帮助您理解在单元测试期间执行代码生成的怪异想法(当为时已晚:代码已经编译)让我告诉您另一个故事。 这个故事是虚构的,它从未发生过,但并没有使解释的能力相形见.。
我们有一个包含几个数据类的代码,每个数据类都有几个字段。 我们必须为每个这些类创建和方法。 最终,这意味着代码冗余。 当类更改时,添加或删除了一个字段,则方法也必须更改。 删除字段不是问题:编译器不会编译引用不存在的字段的或方法。 另一方面,编译器不介意这种方法不引用新的现有字段。
我们时不时地忘记更新这些方法,我们试图发明越来越多的复杂且更好的方法来抵消容易出错的人类编码。 最奇怪的想法是创建字段名称的MD5值,并将其作为注释插入到和方法中。 如果字段发生更改,则测试可以检查源代码中的值是否与根据字段名称计算出的值不同,然后发出错误消息:单元测试失败。 我们从未实施过。
甚至更怪异的想法,也并不是那么怪异,最终导致了Java :: Geci实际上是在测试期间从通过反射获得的可用字段中创建预期的和方法测试,并将其与已经在代码中了。 如果它们不匹配,则必须重新生成它们。 但是,此时的代码已经重新生成。 唯一的问题是它在JVM的内存中,而不在包含源代码的文件中。 为什么只发出错误信 并告诉程序员重新生成代码测试为什么不回写更改毕竟,我们应该告诉计算机应该怎么做,而不是相反!

这就是导致Java :: Geci的顿悟。
Java :: Geci体系结构
Java :: Geci在编译,部署和执行生命周期的中间生成代码。 在构建阶段运行单元测试时,将启动Java :: Geci。
这意味着手册和先前生成的代码已经被编译,并且可以通过反射用于代码生成器。
在测试阶段执行代码生成还有另一个优势。 以后运行的任何代码生成都应仅生成与手动代码功能正交的代码。 这是什么意思从产生的代码不应以任何方式修改或干扰单元测试可能发现的现有手动创建的代码的意义上说,它必须是正交的。 这样做的原因是,在以后的任何阶段发生的代码生成已经在单元测试执行之后进行,因此不可能测试生成的代码是否以任何不希望的方式影响代码的行为。
在测试过程中生成代码可以考虑手册以及生成的代码对整个代码进行测试。 本身不应该对生成的代码本身进行测试(这是对代码生成器项目进行测试的任务),但是程序员编写的手动代码的行为可能取决于生成的代码以及测试的执行可能取决于生成的代码。
为确保生成的代码对所有测试都可以,在生成任何新代码的情况下,应再次执行编译和测试。 为了确保这一点,从测试中调用代码生成,并且在生成新代码的情况下测试失败。
为了更正此问题,通常会调用Java :: Geci中的代码生成
来自具有以下结构的三行单元测试:
对的调用是配置框架和生成器的方法调用链,当框架执行时,将确定所生成的代码是否与现有代码不同。 如果代码更改,它将Java代码写回到源代码,但是如果生成的代码没有更改,则将代码保留完整。
方法是代码链中的最终调用
代返回 ,如果任何代码被更改,并写回
源代码。 这将使测试失败,但是如果我们再次运行测试 使用已修改的源,则测试应该可以正常运行。
此结构对生成器有一些约束:
- 如果生成器在相同的源和类上执行,则生成的代码应完全相同。 通常这不是一个严格的要求,代码生成器通常不会生成随机源。 一些代码生成器可能希望在代码中插入时间戳作为注释:他们不应该这样做。
- 生成的代码成为源代码的一部分,它们不是编译时工件。 所有将代码生成到现有类源中的代码生成器通常都是这种情况。 Java :: Geci可以生成单独的文件,但是它主要是为内联代码生成而设计的(因此得名)。
- 生成的代码必须保存到存储库中,手动源以及生成的代码必须处于不需要进一步生成代码的状态。 这样可以确保开发中的CI服务器可以使用原始工作流程:提取–编译–测试–将工件提交到存储库。 代码生成已经在开发人员机器上完成,并且CI上的代码生成器仅确保它确实完成了(否则测试失败)。
请注意,代码是在开发人员机器上生成的事实
不违反构建应独立于机器的规则。
如果存在任何机器依赖性,那么代码生成将 导致CI服务器上的代码不同,因此构建将中断。
代码生成API
代码生成器应用程序应该很简单。 框架必须执行与大多数代码生成器相同的所有任务,并应提供支持,否则框架的职责是什么
Java :: Geci为代码生成器做了很多事情:
- 它处理文件集的配置以查找源文件
- 扫描源目录并找到源代码文件
- 读取文件,如果文件是Java源代码,则有助于查找与源代码相对应的类
- 支持反射调用以帮助确定性代码生成
- 统一配置处理
- Java源代码生成方式不同
- 仅在更改时修改源文件并写回更改
- 提供功能齐全的示例代码生成器。 其中之一是成熟的Fluent API生成器,仅此一个就可以是一个整个项目。
- 支持Jamal模板和代码生成。
摘要
在接下来的几周中,我计划就Java :: Geci中遵循的设计注意事项和实际解决方案撰写更多文章。
我们鼓励您与我联系,以获取代码,然后在Twitter上创建票证,链接为whatnot。 很好玩。
翻译自: https://www.javacodegeeks.com/2019/04/generate-source-code.html
g代码生成器 源代码
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91338 人正在系统学习中 相关资源:孤狼电脑易用快捷助手V1.0免费绿色版-其它代码类资源-CSDN文库
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!